diff --git a/Build/Configurations/Includes/GZDoom_things.cfg b/Build/Configurations/Includes/GZDoom_things.cfg index 37fc550..185892c 100644 --- a/Build/Configurations/Includes/GZDoom_things.cfg +++ b/Build/Configurations/Includes/GZDoom_things.cfg @@ -40,7 +40,7 @@ gzdoom_lights 9801 { title = "Pulse Light"; - fixedrotation = true; + fixedrotation = true; arg0 { title = "Red"; @@ -70,7 +70,7 @@ gzdoom_lights 9802 { title = "Flicker Light"; - fixedrotation = true; + fixedrotation = true; arg0 { title = "Red"; @@ -124,7 +124,7 @@ gzdoom_lights 9804 { title = "Random Light"; - fixedrotation = true; + fixedrotation = true; arg0 { title = "Red"; @@ -178,7 +178,7 @@ gzdoom_lights 9811 { title = "Additive Pulse Light"; - fixedrotation = true; + fixedrotation = true; arg0 { title = "Red"; @@ -208,7 +208,7 @@ gzdoom_lights 9812 { title = "Additive Flicker Light"; - fixedrotation = true; + fixedrotation = true; arg0 { title = "Red"; @@ -262,7 +262,7 @@ gzdoom_lights 9814 { title = "Additive Random Light"; - fixedrotation = true; + fixedrotation = true; arg0 { title = "Red"; @@ -316,7 +316,7 @@ gzdoom_lights 9821 { title = "Subtractive Pulse Light"; - fixedrotation = true; + fixedrotation = true; arg0 { title = "Red"; @@ -346,7 +346,7 @@ gzdoom_lights 9822 { title = "Subtractive Flicker Light"; - fixedrotation = true; + fixedrotation = true; arg0 { title = "Red"; @@ -400,7 +400,7 @@ gzdoom_lights 9824 { title = "Subtractive Random Light"; - fixedrotation = true; + fixedrotation = true; arg0 { title = "Red"; @@ -427,10 +427,10 @@ gzdoom_lights default = 64; } } - 9825 = "Vavoom Light"; + 9825 = "Vavoom Light (obsolete)"; 1502 { - title = "Vavoom Light "; + title = "Vavoom Light"; arg0 { title = "Radius"; diff --git a/Build/Configurations/Includes/ZDoom_linedefs.cfg b/Build/Configurations/Includes/ZDoom_linedefs.cfg index ed6e721..03ae512 100644 --- a/Build/Configurations/Includes/ZDoom_linedefs.cfg +++ b/Build/Configurations/Includes/ZDoom_linedefs.cfg @@ -3957,7 +3957,8 @@ zdoom arg1 { - title = "Translucency Amount"; + title = "Opacity"; + default = 128; } arg2 { diff --git a/Documents/udmf_zdoom.txt b/Documents/udmf_zdoom.txt index d501cb8..611a667 100644 --- a/Documents/udmf_zdoom.txt +++ b/Documents/udmf_zdoom.txt @@ -27,7 +27,8 @@ II. Implementation Semantics II.A : Storage and Retrieval of Data ------------------------------------ -No changes. +Any TEXTMAP lump in the described namespaces must be encoded in ISO 8859-1 which +as of this writing is the only character encoding supported by ZDoom. ----------------------------------- II.B : Storage Within Archive Files @@ -202,7 +203,18 @@ Note: All fields default to false unless mentioned otherwise. // sound sequence thing in the sector will override this property. hidden = ; // if true this sector will not be drawn on the textured automap. waterzone = ; // Sector is under water and swimmable - moreids = ; // Additional sector IDs/tags, specified as a space separated list of numbers (e.g. "2 666 1003 4505") + moreids = ; // Additional sector IDs/tags, specified as a space separated list of numbers (e.g. "2 666 1003 4505") + damageamount = ; // Amount of damage inflicted by this sector, default = 0. If this is 0, all other damage properties will be ignored. + // Setting damage through these properties will override any damage set through 'special'. + // Setting damageamount to a negative value will create a healing sector. + damagetype = ; // Damage type for sector damage, Default = "None". (generic damage) + damageinterval = ; // Interval in tics between damage application, default = 32. + leakiness = ; // Probability of leaking through radiation suit (0 = never, 256 = always), default = 0. + damageterraineffect = ; // Will spawn a terrain splash when damage is inflicted. Default = false. + damagehazard = ; // Changes damage model to Strife's delayed damage for the given sector. Default = false. + floorterrain = ; // Sets the terrain for the sector's floor. Default = 'use the flat texture's terrain definition.' + ceilingterrain = ; // Sets the terrain for the sector's ceiling. Default = 'use the flat texture's terrain definition.' + * Note about dropactors @@ -376,6 +388,10 @@ Changed language describing the DIALOGUE lump to mention USDF as an option. 1.25 19.04.2015 Added 'moreids' for linedefs and sectors. +1.26 05.01.2016 +added clarification about character encoding +added sector damage properties. + =============================================================================== EOF =============================================================================== diff --git a/Source/Core/Data/ImageData.cs b/Source/Core/Data/ImageData.cs index afb5e3d..8e95d87 100644 --- a/Source/Core/Data/ImageData.cs +++ b/Source/Core/Data/ImageData.cs @@ -53,8 +53,9 @@ namespace CodeImp.DoomBuilder.Data protected string shortname; //mxd. Name in uppercase and clamped to DataManager.CLASIC_IMAGE_NAME_LENGTH protected string virtualname; //mxd. Path of this name is used in TextureBrowserForm protected string displayname; //mxd. Name to display in TextureBrowserForm - protected bool isFlat; //mxd. if false, it's a texture - protected bool istranslucent; //mxd + protected bool isFlat; //mxd. If false, it's a texture + protected bool istranslucent; //mxd. If true, has pixels with alpha > 0 && < 255 + protected bool ismasked; //mxd. If true, has pixels with zero alpha protected bool hasLongName; //mxd. Texture name is longer than DataManager.CLASIC_IMAGE_NAME_LENGTH protected bool hasPatchWithSameName; //mxd protected int level; //mxd. Folder depth of this item @@ -97,7 +98,8 @@ namespace CodeImp.DoomBuilder.Data public string DisplayName { get { return displayname; } } //mxd public bool IsFlat { get { return isFlat; } } //mxd public bool IsTranslucent { get { return istranslucent; } } //mxd - public bool HasPatchWithSameName { get { return hasPatchWithSameName; } } //mxd + public bool IsMasked { get { return ismasked; } } //mxd + public bool HasPatchWithSameName { get { return hasPatchWithSameName; } } //mxd internal bool HasLongName { get { return hasLongName; } } //mxd public bool UseColorCorrection { get { return usecolorcorrection; } set { usecolorcorrection = value; } } public Texture Texture { get { lock(this) { return texture; } } } @@ -364,7 +366,8 @@ namespace CodeImp.DoomBuilder.Data // Also check alpha if(cp->a > 0 && cp->a < 255) istranslucent = true; - } + else if (cp->a == 0) ismasked = true; + } // Update glow data int br = (int)(r / numpixels); @@ -395,9 +398,9 @@ namespace CodeImp.DoomBuilder.Data bitmap.UnlockBits(bmpdata); } } - //mxd. Check if the texture is translucent - else - { + //mxd. Check if the texture is translucent + else if (!loadfailed) + { BitmapData bmpdata = null; try { bmpdata = bitmap.LockBits(new Rectangle(0, 0, bitmap.Size.Width, bitmap.Size.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); } catch(Exception e) { General.ErrorLogger.Add(ErrorType.Error, "Cannot lock image '" + this.filepathname + "' for translucency check. " + e.GetType().Name + ": " + e.Message); } @@ -409,13 +412,10 @@ namespace CodeImp.DoomBuilder.Data for(PixelColor* cp = pixels + numpixels - 1; cp >= pixels; cp--) { - // Check alpha - if(cp->a > 0 && cp->a < 255) - { - istranslucent = true; - break; - } - } + // Check alpha + if (cp->a > 0 && cp->a < 255) istranslucent = true; + else if (cp->a == 0) ismasked = true; + } // Release the data bitmap.UnlockBits(bmpdata); diff --git a/Source/Core/Windows/MainForm.cs b/Source/Core/Windows/MainForm.cs index 03815d4..58db55d 100644 --- a/Source/Core/Windows/MainForm.cs +++ b/Source/Core/Windows/MainForm.cs @@ -1042,7 +1042,7 @@ namespace CodeImp.DoomBuilder.Windows if(General.Colors != null) e.Graphics.Clear(Color.FromArgb(General.Colors.Background.ToInt())); else - e.Graphics.Clear(SystemColors.AppWorkspace); + e.Graphics.Clear(SystemColors.ControlDarkDark); } } } diff --git a/Source/Plugins/BuilderModes/General/BuilderModesTools.cs b/Source/Plugins/BuilderModes/General/BuilderModesTools.cs index be36247..92e63e6 100644 --- a/Source/Plugins/BuilderModes/General/BuilderModesTools.cs +++ b/Source/Plugins/BuilderModes/General/BuilderModesTools.cs @@ -627,7 +627,7 @@ namespace CodeImp.DoomBuilder.BuilderModes #region ================== Sectors // This gets sectors which surround given sectors - internal static IEnumerable GetSectorsAround(IEnumerable selected) + internal static IEnumerable GetSectorsAround(BaseVisualMode mode, IEnumerable selected) { HashSet processedsectors = new HashSet(); HashSet verts = new HashSet(); @@ -651,12 +651,40 @@ namespace CodeImp.DoomBuilder.BuilderModes { result.Add(l.Front.Sector); processedsectors.Add(l.Front.Sector.Index); - } + + // Add extrafloors as well + SectorData sd = mode.GetSectorDataEx(l.Front.Sector); + if (sd != null && sd.ExtraFloors.Count > 0) + { + foreach (Effect3DFloor effect in sd.ExtraFloors) + { + if (!processedsectors.Contains(effect.Linedef.Front.Sector.Index)) + { + result.Add(effect.Linedef.Front.Sector); + processedsectors.Add(effect.Linedef.Front.Sector.Index); + } + } + } + } if(l.Back != null && l.Back.Sector != null && !processedsectors.Contains(l.Back.Sector.Index)) { result.Add(l.Back.Sector); processedsectors.Add(l.Back.Sector.Index); - } + + // Add extrafloors as well + SectorData sd = mode.GetSectorDataEx(l.Back.Sector); + if (sd != null && sd.ExtraFloors.Count > 0) + { + foreach (Effect3DFloor effect in sd.ExtraFloors) + { + if (!processedsectors.Contains(effect.Linedef.Front.Sector.Index)) + { + result.Add(effect.Linedef.Front.Sector); + processedsectors.Add(effect.Linedef.Front.Sector.Index); + } + } + } + } } } diff --git a/Source/Plugins/BuilderModes/VisualModes/BaseVisualMode.cs b/Source/Plugins/BuilderModes/VisualModes/BaseVisualMode.cs index 24d5275..883e34e 100644 --- a/Source/Plugins/BuilderModes/VisualModes/BaseVisualMode.cs +++ b/Source/Plugins/BuilderModes/VisualModes/BaseVisualMode.cs @@ -708,9 +708,15 @@ namespace CodeImp.DoomBuilder.BuilderModes return sectordata[s]; } - - // This requests a things's extra data - internal ThingData GetThingData(Thing t) + + //mxd. This requests a sector's extra data or null if given sector doesn't have it + internal SectorData GetSectorDataEx(Sector s) + { + return (sectordata.ContainsKey(s) ? sectordata[s] : null); + } + + // This requests a things's extra data + internal ThingData GetThingData(Thing t) { // Make fresh sector data when it doesn't exist yet if(!thingdata.ContainsKey(t)) @@ -2251,7 +2257,7 @@ namespace CodeImp.DoomBuilder.BuilderModes else { // Get next higher floor or ceiling from surrounding unselected sectors - foreach(Sector s in BuilderModesTools.GetSectorsAround(ceilings.Keys)) + foreach(Sector s in BuilderModesTools.GetSectorsAround(this, ceilings.Keys)) { if(s.FloorHeight < targetCeilingHeight && s.FloorHeight > maxSelectedHeight) targetCeilingHeight = s.FloorHeight; @@ -2284,7 +2290,7 @@ namespace CodeImp.DoomBuilder.BuilderModes else { // Get next higher floor or ceiling from surrounding unselected sectors - foreach(Sector s in BuilderModesTools.GetSectorsAround(floors.Keys)) + foreach(Sector s in BuilderModesTools.GetSectorsAround(this, floors.Keys)) { if(s.FloorHeight > maxSelectedHeight && s.FloorHeight < targetFloorHeight && s.FloorHeight <= minSelectedCeilingHeight) targetFloorHeight = s.FloorHeight; @@ -2451,7 +2457,7 @@ namespace CodeImp.DoomBuilder.BuilderModes else { // Get next lower ceiling or floor from surrounding unselected sectors - foreach(Sector s in BuilderModesTools.GetSectorsAround(floors.Keys)) + foreach(Sector s in BuilderModesTools.GetSectorsAround(this, floors.Keys)) { if(s.CeilHeight > targetFloorHeight && s.CeilHeight < minSelectedHeight) targetFloorHeight = s.CeilHeight; @@ -2484,7 +2490,7 @@ namespace CodeImp.DoomBuilder.BuilderModes else { // Get next lower ceiling or floor from surrounding unselected sectors - foreach(Sector s in BuilderModesTools.GetSectorsAround(ceilings.Keys)) + foreach(Sector s in BuilderModesTools.GetSectorsAround(this, ceilings.Keys)) { if(s.CeilHeight > targetCeilingHeight && s.CeilHeight < minSelectedHeight && s.CeilHeight >= maxSelectedFloorHeight) targetCeilingHeight = s.CeilHeight; diff --git a/Source/Plugins/BuilderModes/VisualModes/VisualCeiling.cs b/Source/Plugins/BuilderModes/VisualModes/VisualCeiling.cs index 5c4e537..d789db9 100644 --- a/Source/Plugins/BuilderModes/VisualModes/VisualCeiling.cs +++ b/Source/Plugins/BuilderModes/VisualModes/VisualCeiling.cs @@ -480,8 +480,41 @@ namespace CodeImp.DoomBuilder.BuilderModes // Check on which side of the nearest sidedef we are Sidedef sd = MapSet.NearestSidedef(Sector.Sector.Sidedefs, pickintersect); float side = sd.Line.SideOfLine(pickintersect); - return (((side <= 0.0f) && sd.IsFront) || ((side > 0.0f) && !sd.IsFront)); - } + + //mxd. Alpha based picking. Used only on extrafloors with transparent or masked textures + if ((side <= 0.0f && sd.IsFront) || (side > 0.0f && !sd.IsFront)) + { + if (!Texture.IsImageLoaded || extrafloor == null || RenderPass == RenderPass.Solid || (!Texture.IsTranslucent && !Texture.IsMasked)) + return true; + + // Fetch ZDoom fields + float rotate = Angle2D.DegToRad(level.sector.Fields.GetValue("rotationceiling", 0.0f)); + Vector2D offset = new Vector2D(level.sector.Fields.GetValue("xpanningceiling", 0.0f), level.sector.Fields.GetValue("ypanningceiling", 0.0f)); + Vector2D scale = new Vector2D(level.sector.Fields.GetValue("xscaleceiling", 1.0f), level.sector.Fields.GetValue("yscaleceiling", 1.0f)); + Vector2D texscale = new Vector2D(1.0f / Texture.ScaledWidth, 1.0f / Texture.ScaledHeight); + + // Texture coordinates + Vector2D o = pickintersect; + o = o.GetRotated(rotate); + o.y = -o.y; + o = (o + offset) * scale * texscale; + o.x = (o.x * Texture.Width) % Texture.Width; + o.y = (o.y * Texture.Height) % Texture.Height; + + // Make sure coordinates are inside of texture dimensions... + if (o.x < 0) o.x += Texture.Width; + if (o.y < 0) o.y += Texture.Height; + + // Make final texture coordinates... + int ox = General.Clamp((int)Math.Floor(o.x), 0, Texture.Width - 1); + int oy = General.Clamp((int)Math.Floor(o.y), 0, Texture.Height - 1); + + // Check pixel alpha + return (Texture.GetBitmap().GetPixel(ox, oy).A > 0); + } + + return false; + } // Return texture name public override string GetTextureName() diff --git a/Source/Plugins/BuilderModes/VisualModes/VisualFloor.cs b/Source/Plugins/BuilderModes/VisualModes/VisualFloor.cs index dfed141..21b5b4a 100644 --- a/Source/Plugins/BuilderModes/VisualModes/VisualFloor.cs +++ b/Source/Plugins/BuilderModes/VisualModes/VisualFloor.cs @@ -432,8 +432,41 @@ namespace CodeImp.DoomBuilder.BuilderModes // Check on which side of the nearest sidedef we are Sidedef sd = MapSet.NearestSidedef(Sector.Sector.Sidedefs, pickintersect); float side = sd.Line.SideOfLine(pickintersect); - return (((side <= 0.0f) && sd.IsFront) || ((side > 0.0f) && !sd.IsFront)); - } + + //mxd. Alpha based picking. Used only on extrafloors with transparent or masked textures + if ((side <= 0.0f && sd.IsFront) || (side > 0.0f && !sd.IsFront)) + { + if (!Texture.IsImageLoaded || extrafloor == null || RenderPass == RenderPass.Solid || (!Texture.IsTranslucent && !Texture.IsMasked)) + return true; + + // Fetch ZDoom fields + float rotate = Angle2D.DegToRad(level.sector.Fields.GetValue("rotationfloor", 0.0f)); + Vector2D offset = new Vector2D(level.sector.Fields.GetValue("xpanningfloor", 0.0f), level.sector.Fields.GetValue("ypanningfloor", 0.0f)); + Vector2D scale = new Vector2D(level.sector.Fields.GetValue("xscalefloor", 1.0f), level.sector.Fields.GetValue("yscalefloor", 1.0f)); + Vector2D texscale = new Vector2D(1.0f / Texture.ScaledWidth, 1.0f / Texture.ScaledHeight); + + // Texture coordinates + Vector2D o = pickintersect; + o = o.GetRotated(rotate); + o.y = -o.y; + o = (o + offset) * scale * texscale; + o.x = (o.x * Texture.Width) % Texture.Width; + o.y = (o.y * Texture.Height) % Texture.Height; + + // Make sure coordinates are inside of texture dimensions... + if (o.x < 0) o.x += Texture.Width; + if (o.y < 0) o.y += Texture.Height; + + // Make final texture coordinates... + int ox = General.Clamp((int)Math.Floor(o.x), 0, Texture.Width - 1); + int oy = General.Clamp((int)Math.Floor(o.y), 0, Texture.Height - 1); + + // Check pixel alpha + return (Texture.GetBitmap().GetPixel(ox, oy).A > 0); + } + + return false; + } // Return texture name public override string GetTextureName() diff --git a/Source/Plugins/BuilderModes/VisualModes/VisualMiddle3D.cs b/Source/Plugins/BuilderModes/VisualModes/VisualMiddle3D.cs index 4fd828c..eca4ea6 100644 --- a/Source/Plugins/BuilderModes/VisualModes/VisualMiddle3D.cs +++ b/Source/Plugins/BuilderModes/VisualModes/VisualMiddle3D.cs @@ -346,8 +346,38 @@ namespace CodeImp.DoomBuilder.BuilderModes return base.PickFastReject(from, to, dir); } - // Return texture name - public override string GetTextureName() + //mxd. Alpha based picking + public override bool PickAccurate(Vector3D from, Vector3D to, Vector3D dir, ref float u_ray) + { + if (!Texture.IsImageLoaded || (!Texture.IsTranslucent && !Texture.IsMasked)) return base.PickAccurate(from, to, dir, ref u_ray); + + float u; + Sidedef sourceside = extrafloor.Linedef.Front; + new Line2D(from, to).GetIntersection(Sidedef.Line.Line, out u); + if (Sidedef != Sidedef.Line.Front) u = 1.0f - u; + + // Get correct offset to texture space... + float texoffsetx = Sidedef.OffsetX + sourceside.OffsetX + UniFields.GetFloat(Sidedef.Fields, "offsetx_mid") + UniFields.GetFloat(sourceside.Fields, "offsetx_mid"); + int ox = (int)Math.Floor((u * Sidedef.Line.Length * UniFields.GetFloat(sourceside.Fields, "scalex_mid", 1.0f) / Texture.Scale.x + texoffsetx) % Texture.Width); + + float texoffsety = Sidedef.OffsetY + sourceside.OffsetY + UniFields.GetFloat(Sidedef.Fields, "offsety_mid") + UniFields.GetFloat(sourceside.Fields, "offsety_mid"); + int oy = (int)Math.Ceiling(((pickintersect.z - sourceside.Sector.CeilHeight) * UniFields.GetFloat(sourceside.Fields, "scaley_mid", 1.0f) / Texture.Scale.y - texoffsety) % Texture.Height); + + // Make sure offsets are inside of texture dimensions... + if (ox < 0) ox += Texture.Width; + if (oy < 0) oy += Texture.Height; + + // Check pixel alpha + if (Texture.GetBitmap().GetPixel(General.Clamp(ox, 0, Texture.Width - 1), General.Clamp(Texture.Height - oy, 0, Texture.Height - 1)).A > 0) + { + return base.PickAccurate(from, to, dir, ref u_ray); + } + + return false; + } + + // Return texture name + public override string GetTextureName() { //mxd if((extrafloor.Linedef.Args[2] & (int)Effect3DFloor.Flags.UseUpperTexture) != 0) diff --git a/Source/Plugins/BuilderModes/VisualModes/VisualMiddleDouble.cs b/Source/Plugins/BuilderModes/VisualModes/VisualMiddleDouble.cs index 182b159..907da99 100644 --- a/Source/Plugins/BuilderModes/VisualModes/VisualMiddleDouble.cs +++ b/Source/Plugins/BuilderModes/VisualModes/VisualMiddleDouble.cs @@ -283,9 +283,9 @@ namespace CodeImp.DoomBuilder.BuilderModes //mxd. Alpha based picking public override bool PickAccurate(Vector3D from, Vector3D to, Vector3D dir, ref float u_ray) { - if(!Texture.IsImageLoaded) return base.PickAccurate(from, to, dir, ref u_ray); + if (!Texture.IsImageLoaded || (!Texture.IsTranslucent && !Texture.IsMasked)) return base.PickAccurate(from, to, dir, ref u_ray); - float u; + float u; new Line2D(from, to).GetIntersection(Sidedef.Line.Line, out u); if(Sidedef != Sidedef.Line.Front) u = 1.0f - u; @@ -309,12 +309,12 @@ namespace CodeImp.DoomBuilder.BuilderModes oy = (int)Math.Ceiling(((pickintersect.z - zoffset) * UniFields.GetFloat(Sidedef.Fields, "scaley_mid", 1.0f) / Texture.Scale.y) % Texture.Height); } - // Make sure offsets are inside of texture dimensions... - while(ox < 0) ox += Texture.Width; - while(oy < 0) oy += Texture.Height; + // Make sure offsets are inside of texture dimensions... + if (ox < 0) ox += Texture.Width; + if (oy < 0) oy += Texture.Height; - // Check pixel alpha - if(Texture.GetBitmap().GetPixel(General.Clamp(ox, 0, Texture.Width - 1), General.Clamp(Texture.Height - oy, 0, Texture.Height - 1)).A > 0) + // Check pixel alpha + if (Texture.GetBitmap().GetPixel(General.Clamp(ox, 0, Texture.Width - 1), General.Clamp(Texture.Height - oy, 0, Texture.Height - 1)).A > 0) { return base.PickAccurate(from, to, dir, ref u_ray); }