Ejemplo n.º 1
0
        // This finds and adds visible sectors
        private void ProcessSidedefCulling(Sidedef sd)
        {
            VisualSector vs;

            // Find the visualsector and make it if needed
            if (allsectors.ContainsKey(sd.Sector))
            {
                // Take existing visualsector
                vs = allsectors[sd.Sector];
            }
            else
            {
                // Make new visualsector
                vs = CreateVisualSector(sd.Sector);
                if (vs != null)
                {
                    allsectors.Add(sd.Sector, vs);
                }
            }

            if (vs != null)
            {
                // Add to visible sectors if not added yet
                if (!visiblesectors.ContainsKey(sd.Sector))
                {
                    visiblesectors.Add(sd.Sector, vs);
                    visiblegeometry.AddRange(vs.FixedGeometry);
                }

                // Add sidedef geometry
                visiblegeometry.AddRange(vs.GetSidedefGeometry(sd));
            }
        }
Ejemplo n.º 2
0
        // This reads a single sidedef and connects it to the given linedef
        private void ReadSidedef(MapSet map, UniversalCollection sc, Linedef ld,
                                 bool front, Dictionary <int, Sector> sectorlink, int index)
        {
            // Read fields
            string where = "linedef " + ld.Index + (front ? " front sidedef " : " back sidedef ") + index;
            int    offsetx = GetCollectionEntry <int>(sc, "offsetx", false, 0, where);
            int    offsety = GetCollectionEntry <int>(sc, "offsety", false, 0, where);
            string thigh   = GetCollectionEntry <string>(sc, "texturetop", false, "-", where);
            string tlow    = GetCollectionEntry <string>(sc, "texturebottom", false, "-", where);
            string tmid    = GetCollectionEntry <string>(sc, "texturemiddle", false, "-", where);
            int    sector  = GetCollectionEntry <int>(sc, "sector", true, 0, where);

            // Create sidedef
            if (sectorlink.ContainsKey(sector))
            {
                Sidedef s = map.CreateSidedef(ld, front, sectorlink[sector]);
                if (s != null)
                {
                    s.Update(offsetx, offsety, thigh, tmid, tlow);

                    // Custom fields
                    ReadCustomFields(sc, s, "sidedef");
                }
            }
            else
            {
                General.ErrorLogger.Add(ErrorType.Warning, "Sidedef references invalid sector " + sector + ". Sidedef has been removed.");
            }
        }
Ejemplo n.º 3
0
 // Disposer
 internal void Dispose()
 {
     reflexlink = null;
     eartiplink = null;
     vertslink  = null;
     sidedef    = null;
 }
Ejemplo n.º 4
0
        // This sets the Lower Unpegged flag
        public virtual void ApplyBottomAlignment(bool set)
        {
            if (!set)
            {
                // Remove flag
                mode.CreateUndo("Remove bottom-aligned setting");
                mode.SetActionResult("Removed bottom-aligned setting.");
                Sidedef.SetFlag(General.Map.FormatInterface.WallFlags.AlignImageToBottom, false);
            }
            else
            {
                // Add flag
                mode.CreateUndo("Set bottom-aligned setting");
                mode.SetActionResult("Set bottom-aligned setting.");
                Sidedef.SetFlag(General.Map.FormatInterface.WallFlags.AlignImageToBottom, true);
            }

            // Update sidedef geometry
            VisualWallParts parts = Sector.GetSidedefParts(Sidedef);

            parts.SetupAllParts();

            // Update other sidedef geometry

            /*if(Sidedef.Other != null)
             * {
             *      BaseVisualSector othersector = (BaseVisualSector)mode.GetVisualSector(Sidedef.Other.Sector);
             *      parts = othersector.GetSidedefParts(Sidedef.Other);
             *      parts.SetupAllParts();
             * }*/
        }
        // Insert middle texture
        public virtual void OnInsert()
        {
            // No middle texture yet?
            if (!Sidedef.MiddleRequired() && (string.IsNullOrEmpty(Sidedef.MiddleTexture) || (Sidedef.MiddleTexture[0] == '-')))
            {
                // Make it now
                mode.CreateUndo("Create middle texture");
                mode.SetActionResult("Created middle texture.");
                General.Settings.FindDefaultDrawSettings();
                Sidedef.SetTextureMid(General.Settings.DefaultTexture);

                // Update
                Sector.Changed = true;

                // Other side as well
                if (string.IsNullOrEmpty(Sidedef.Other.MiddleTexture) || (Sidedef.Other.MiddleTexture[0] == '-'))
                {
                    Sidedef.Other.SetTextureMid(General.Settings.DefaultTexture);

                    // Update
                    VisualSector othersector = mode.GetVisualSector(Sidedef.Other.Sector);
                    if (othersector is BaseVisualSector)
                    {
                        (othersector as BaseVisualSector).Changed = true;
                    }
                }
            }
        }
Ejemplo n.º 6
0
        // This adds the matching, unmarked sidedefs from a vertex for texture alignment
        private static void AddSidedefsForFloodfill(BaseVisualMode mode, Stack <Tools.SidedefFillJob> stack, Vertex v, bool forward, HashSet <long> texturelongnames)
        {
            foreach (Linedef ld in v.Linedefs)
            {
                Sidedef side1 = (forward ? ld.Front : ld.Back);
                Sidedef side2 = (forward ? ld.Back : ld.Front);

                // [ZZ] don't iterate the same linedef twice.
                //
                if ((side1 != null && side1.Marked) ||
                    (side2 != null && side2.Marked))
                {
                    continue;
                }

                if ((ld.Start == v) && (side1 != null) && !side1.Marked)
                {
                    if (SidedefTextureMatch(mode, side1, texturelongnames))
                    {
                        stack.Push(new Tools.SidedefFillJob {
                            forward = forward, sidedef = side1
                        });
                    }
                }
                else if ((ld.End == v) && (side2 != null) && !side2.Marked)
                {
                    if (SidedefTextureMatch(mode, side2, texturelongnames))
                    {
                        stack.Push(new Tools.SidedefFillJob {
                            forward = forward, sidedef = side2
                        });
                    }
                }
            }
        }
        public BuildWall(Sidedef src)
        {
            Flags = new Dictionary <string, bool>(src.Flags);

            var v = (src.IsFront ? src.Line.Start : src.Line.End);

            StartX = (int)v.Position.x;
            StartY = (int)v.Position.y;

            // These must be set separately...
            NextWallIndex    = -1;
            OtherWallIndex   = -1;
            OtherSectorIndex = -1;

            OffsetX         = src.OffsetX;
            OffsetY         = src.OffsetY;
            RepeatX         = src.RepeatX;
            RepeatY         = src.RepeatY;
            TileIndex       = src.TileIndex;
            MaskedTileIndex = src.MaskedTileIndex;
            Shade           = src.Shade;
            PaletteIndex    = src.PaletteIndex;

            HiTag = src.HiTag;
            LoTag = src.LoTag;
            Extra = src.Extra;
        }
Ejemplo n.º 8
0
        //mxd. This calculates wall brightness level with doom-style shading
        public int CalculateBrightness(int level, Sidedef sd)
        {
            if (level < 253 && sd != null)
            {
                bool evenlighting   = General.Map.Data.MapInfo.EvenLighting;
                bool smoothlighting = General.Map.Data.MapInfo.SmoothLighting;

                //check for possiburu UDMF overrides
                if (General.Map.UDMF)
                {
                    if (sd.IsFlagSet("lightabsolute") && sd.Fields.ContainsKey("light"))
                    {
                        evenlighting = true;
                    }
                    else
                    {
                        if (sd.IsFlagSet("nofakecontrast"))
                        {
                            evenlighting = true;
                        }
                        if (sd.IsFlagSet("smoothlighting"))
                        {
                            smoothlighting = true;
                        }
                    }
                }

                if (!evenlighting)
                {
                    //all walls are shaded by their angle
                    if (smoothlighting)
                    {
                        float ammount  = Math.Abs((float)Math.Sin(sd.Angle));
                        int   hAmmount = (int)((1.0f - ammount) * General.Map.Data.MapInfo.HorizWallShade);
                        int   vAmmount = (int)(ammount * General.Map.Data.MapInfo.VertWallShade);

                        level = General.Clamp(level - hAmmount - vAmmount, 0, 255);
                    }
                    else                     //only horizontal/verticel walls are shaded
                    {
                        switch ((int)Angle2D.RadToDeg(sd.Angle))
                        {
                        // Horizontal wall
                        case 90:
                        case 270:
                            level = General.Clamp(level + General.Map.Data.MapInfo.HorizWallShade, 0, 255);
                            break;

                        // Vertical wall
                        case 180:
                        case 0:
                            level = General.Clamp(level + General.Map.Data.MapInfo.VertWallShade, 0, 255);
                            break;
                        }
                    }
                }
            }

            return(CalculateBrightness(level));
        }
Ejemplo n.º 9
0
        private static int GetExpectedOffsetY(Sidedef source, Sidedef target, string texturename, int textureheight, double texturescaley, double linescaley, Rectangle partsize, out VisualGeometryType matchingparttype)
        {
            if (target.MiddleTexture == texturename &&
                partsize.IntersectsWith(BuilderModesTools.GetSidedefPartSize(target, VisualGeometryType.WALL_MIDDLE)))
            {
                matchingparttype = VisualGeometryType.WALL_MIDDLE;
                int partheight = (int)Math.Round(((target.Sector.CeilHeight - source.Sector.CeilHeight) / texturescaley) * linescaley);
                return(((int)Tools.GetSidedefMiddleOffsetY(target, target.OffsetY + GetSidedefValue(target, matchingparttype, "offsety", 0f), linescaley, false) + partheight) % textureheight);
            }

            if (target.HighTexture == texturename &&
                partsize.IntersectsWith(BuilderModesTools.GetSidedefPartSize(target, VisualGeometryType.WALL_UPPER)))
            {
                matchingparttype = VisualGeometryType.WALL_UPPER;
                int partheight = (int)Math.Round(((target.Sector.CeilHeight - source.Sector.CeilHeight) / texturescaley) * linescaley);
                return(((int)Tools.GetSidedefTopOffsetY(target, target.OffsetY + GetSidedefValue(target, matchingparttype, "offsety", 0f), linescaley, false) + partheight) % textureheight);
            }

            if (target.LowTexture == texturename &&
                partsize.IntersectsWith(BuilderModesTools.GetSidedefPartSize(target, VisualGeometryType.WALL_LOWER)))
            {
                matchingparttype = VisualGeometryType.WALL_LOWER;
                int partheight = (int)Math.Round(((target.Sector.CeilHeight - source.Sector.CeilHeight) / texturescaley) * linescaley);
                return(((int)Tools.GetSidedefBottomOffsetY(target, target.OffsetY + GetSidedefValue(target, matchingparttype, "offsety", 0f), linescaley, false) + partheight) % textureheight);
            }

            matchingparttype = VisualGeometryType.UNKNOWN;
            return(int.MinValue);
        }
        private static int GetExpectedOffsetY(Sidedef source, Sidedef target, string texturename, int textureheight, double texturescaley, double linescaley, Rectangle partsize, out VisualGeometryType matchingparttype)
        {
            if (target.MiddleTexture == texturename &&
                partsize.IntersectsWith(BuilderModesTools.GetSidedefPartSize(target, VisualGeometryType.WALL_MIDDLE)))
            {
                matchingparttype = VisualGeometryType.WALL_MIDDLE;
                int partheight = (int)Math.Round(((target.Sector.CeilHeight - source.Sector.CeilHeight) / texturescaley) * linescaley);
                return(((int)Tools.GetSidedefMiddleOffsetY(target, target.OffsetY + GetSidedefValue(target, matchingparttype, "offsety", 0f), linescaley, false) + partheight) % textureheight);
            }

            // Only check upper and lower textures if the sidedef as an other side. See https://github.com/jewalky/UltimateDoomBuilder/issues/533
            if (target.Other != null && target.HighTexture == texturename &&
                partsize.IntersectsWith(BuilderModesTools.GetSidedefPartSize(target, VisualGeometryType.WALL_UPPER)))
            {
                matchingparttype = VisualGeometryType.WALL_UPPER;
                int partheight = (int)Math.Round(((target.Sector.CeilHeight - source.Sector.CeilHeight) / texturescaley) * linescaley);
                return(((int)Tools.GetSidedefTopOffsetY(target, target.OffsetY + GetSidedefValue(target, matchingparttype, "offsety", 0f), linescaley, false) + partheight) % textureheight);
            }

            if (target.Other != null && target.LowTexture == texturename &&
                partsize.IntersectsWith(BuilderModesTools.GetSidedefPartSize(target, VisualGeometryType.WALL_LOWER)))
            {
                matchingparttype = VisualGeometryType.WALL_LOWER;
                int partheight = (int)Math.Round(((target.Sector.CeilHeight - source.Sector.CeilHeight) / texturescaley) * linescaley);
                return(((int)Tools.GetSidedefBottomOffsetY(target, target.OffsetY + GetSidedefValue(target, matchingparttype, "offsety", 0f), linescaley, false) + partheight) % textureheight);
            }

            matchingparttype = VisualGeometryType.UNKNOWN;
            return(int.MinValue);
        }
Ejemplo n.º 11
0
        //mxd
        private static void SetUDMFLight(Sidedef sd, Label label, Label value, bool highlight)
        {
            if (sd.Fields.ContainsKey("light"))
            {
                int light = (int)sd.Fields["light"].Value;

                if (sd.Fields.GetValue("lightabsolute", false))
                {
                    value.Text = light + " (abs.)";
                }
                else
                {
                    value.Text = light + " (" + Math.Min(255, Math.Max(0, (light + sd.Sector.Brightness))) + ")";
                }

                value.Enabled = true;
                label.Enabled = true;
            }
            else
            {
                value.Text    = "-- (" + sd.Sector.Brightness + ")";
                label.Enabled = highlight;
                value.Enabled = highlight;
            }

            label.ForeColor = (highlight ? SystemColors.HotTrack : SystemColors.WindowText);
            value.ForeColor = label.ForeColor;
        }
Ejemplo n.º 12
0
		// Fix a single side
		public override bool Button1Click(bool batchMode)
		{
			// On which side can we fix?
			if(copysidedeffront != null)
			{
				// Front
				if(!batchMode) General.Map.UndoRedo.CreateUndo("Create front sidedef");
				Sidedef newside = General.Map.Map.CreateSidedef(line, true, copysidedeffront.Sector);
				if(newside == null) return false;
				copysidedeffront.CopyPropertiesTo(newside);
			}
			else if(copysidedefback != null)
			{
				// Back
				// Because the line is single-sided, we make the sidedef on the front.
				// We will then flip it to make sure to ends up in the right position.
				if(!batchMode) General.Map.UndoRedo.CreateUndo("Create front sidedef");
				Sidedef newside = General.Map.Map.CreateSidedef(line, true, copysidedefback.Sector);
				if(newside == null) return false;
				copysidedefback.CopyPropertiesTo(newside);
				line.FlipVertices();
			}
			
			line.ApplySidedFlags();
			General.Map.Map.Update();
			return true;
		}
Ejemplo n.º 13
0
        // This returns all selected sidedefs, no doubles
        public List <Sidedef> GetSelectedSidedefs()
        {
            Dictionary <Sidedef, int> added    = new Dictionary <Sidedef, int>();
            List <Sidedef>            sidedefs = new List <Sidedef>();

            foreach (IVisualEventReceiver i in selectedobjects)
            {
                if (i is BaseVisualGeometrySidedef)
                {
                    Sidedef sd = (i as BaseVisualGeometrySidedef).Sidedef;
                    if (!added.ContainsKey(sd))
                    {
                        sidedefs.Add(sd);
                        added.Add(sd, 0);
                    }
                }
            }

            // Add highlight?
            if ((selectedobjects.Count == 0) && (target.picked is BaseVisualGeometrySidedef))
            {
                Sidedef sd = (target.picked as BaseVisualGeometrySidedef).Sidedef;
                if (!added.ContainsKey(sd))
                {
                    sidedefs.Add(sd);
                }
            }

            return(sidedefs);
        }
Ejemplo n.º 14
0
 // This adds the matching, unmarked sidedefs from a vertex for texture alignment
 private static void AddSidedefsForAlignment(Stack <SidedefAlignJob> stack, Vertex v, bool forward, float offsetx, long texturelongname)
 {
     foreach (Linedef ld in v.Linedefs)
     {
         Sidedef side1 = forward ? ld.Front : ld.Back;
         Sidedef side2 = forward ? ld.Back : ld.Front;
         if ((ld.Start == v) && (side1 != null) && !side1.Marked)
         {
             if (SidedefTextureMatch(side1, texturelongname))
             {
                 SidedefAlignJob nj = new SidedefAlignJob();
                 nj.forward = forward;
                 nj.offsetx = offsetx;
                 nj.sidedef = side1;
                 stack.Push(nj);
             }
         }
         else if ((ld.End == v) && (side2 != null) && !side2.Marked)
         {
             if (SidedefTextureMatch(side2, texturelongname))
             {
                 SidedefAlignJob nj = new SidedefAlignJob();
                 nj.forward = forward;
                 nj.offsetx = offsetx;
                 nj.sidedef = side2;
                 stack.Push(nj);
             }
         }
     }
 }
Ejemplo n.º 15
0
        //mxd. Useful when debugging...
        public override string ToString()
        {
            Sidedef side   = (front ? line.Front : line.Back);
            Sector  sector = (side != null ? side.Sector : null);

            return(line + " (" + (front ? "front" : "back") + ")" + (sector != null ? ", Sector " + sector.Index : ", no sector"));
        }
        // Fix both sides
        public override bool Button2Click(bool batchMode)
        {
            if (!batchMode)
            {
                General.Map.UndoRedo.CreateUndo("Create sidedefs");
            }

            // Front
            Sidedef newside = General.Map.Map.CreateSidedef(line, true, copysidedeffront.Sector);

            if (newside == null)
            {
                return(false);
            }
            copysidedeffront.CopyPropertiesTo(newside);

            // Back
            newside = General.Map.Map.CreateSidedef(line, false, copysidedefback.Sector);
            if (newside == null)
            {
                return(false);
            }
            copysidedefback.CopyPropertiesTo(newside);

            line.ApplySidedFlags();
            General.Map.Map.Update();
            return(true);
        }
Ejemplo n.º 17
0
 // Constructor
 public ResultUnknownTexture(Sidedef sd, SidedefPart part)
 {
     // Initialize
     this.side = sd;
     this.part = part;
     this.viewobjects.Add(sd);
     this.description = "This sidedef uses an unknown texture. This could be the result of missing resources, or a mistyped texture name. Click the Remove Texture button to remove the texture or click on Add Default Texture to use a known texture instead.";
 }
 // This gets the geometry list for the specified sidedef
 public List <VisualGeometry> GetSidedefGeometry(Sidedef sd)
 {
     if (sidedefgeometry.ContainsKey(sd))
     {
         return(sidedefgeometry[sd]);
     }
     return(new List <VisualGeometry>());
 }
Ejemplo n.º 19
0
 // Constructor
 public ResultMissingTexture(Sidedef sd, SidedefPart part)
 {
     // Initialize
     this.side = sd;
     this.part = part;
     this.viewobjects.Add(sd);
     this.description = "This sidedef is missing a texture where it is required and could cause a 'Hall Of Mirrors' visual problem in the map. Click the Add Default Texture button to add a texture to the line.";
 }
Ejemplo n.º 20
0
        // Constructor
        public VisualMiddleDouble(BaseVisualMode mode, VisualSector vs, Sidedef s) : base(mode, vs, s)
        {
            // Set render pass
            this.RenderPass = RenderPass.Mask;

            // We have no destructor
            GC.SuppressFinalize(this);
        }
Ejemplo n.º 21
0
    void Start()
    {
        map = WADReader.LoadMap("E1M1");

        vertices = new List <Vector3>();
        List <CombineInstance> floorCIs = new List <CombineInstance>();

        foreach (SubSector ssector in map.subsectors)
        {
            List <Vector3> floorVerts = new List <Vector3>();
            //SubSector ssector = map.subsectors[0];
            for (int i = 0; i < ssector.num; i++)
            {
                Seg     seg     = map.segs[ssector.start + i];
                Vertex  vertS   = map.vertexes[seg.start];
                Vertex  vertE   = map.vertexes[seg.end];
                Linedef line    = map.linedefs[seg.linedef];
                Sidedef sideR   = map.sidedefs[line.right];
                Sector  sectorR = map.sectors[sideR.sector];
                if (line.left >= 0)
                {
                    Sidedef sideL   = map.sidedefs[line.left];
                    Sector  sectorL = map.sectors[sideL.sector];
                }
                Vector3 vStart = new Vector3(vertS.x, 0, vertS.y) * scale;
                Vector3 vEnd   = new Vector3(vertE.x, 0, vertE.y) * scale;
                /*if (!floorVerts.Contains(vStart))*/ floorVerts.Add(vStart);
                /*if (!floorVerts.Contains(vEnd))*/ floorVerts.Add(vEnd);
            }

            List <int> floorTris = new List <int>();
            int        p0        = 0;
            int        pHelper   = 1;
            for (int i = 2; i < floorVerts.Count; i++)
            {
                int pTemp = i;
                floorTris.AddRange(new int[] { p0, pHelper, pTemp });
                pHelper = pTemp;
            }

            CombineInstance ci   = new CombineInstance();
            Mesh            mesh = new Mesh();
            mesh.vertices  = floorVerts.ToArray();
            mesh.triangles = floorTris.ToArray();
            mesh.RecalculateNormals();
            ci.mesh      = mesh;
            ci.transform = transform.localToWorldMatrix;
            floorCIs.Add(ci);
        }

        Mesh combinedFloor = new Mesh();

        combinedFloor.CombineMeshes(floorCIs.ToArray());

        meshFilter.sharedMesh = combinedFloor;

        inited = true;
    }
Ejemplo n.º 22
0
 public SidedefProperties(Sidedef s)
 {
     hightexture   = s.HighTexture;
     middletexture = s.MiddleTexture;
     lowtexture    = s.LowTexture;
     offsetx       = s.OffsetX;
     offsety       = s.OffsetY;
     fields        = new UniFields(s.Fields);
 }
Ejemplo n.º 23
0
 public static LuaSidedef NearestSidedef(LuaVector2D pos)
 {
     Sidedef side = MapSet.NearestSidedef(General.Map.Map.Sidedefs, pos.vec);
     if (side == null)
     {
         return null;
     }
     return new LuaSidedef(side);
 }
Ejemplo n.º 24
0
    // Copy constructor
    internal EarClipVertex(EarClipVertex v)
    {
        // Initialize
        this.pos     = v.pos;
        this.sidedef = v.sidedef;

        // We have no destructor
        GC.SuppressFinalize(this);
    }
        // Constructor
        public VisualMiddle3D(BaseVisualMode mode, VisualSector vs, Sidedef s) : base(mode, vs, s)
        {
            //mxd
            geometrytype = VisualGeometryType.WALL_MIDDLE_3D;
            partname     = "mid";

            // We have no destructor
            GC.SuppressFinalize(this);
        }
Ejemplo n.º 26
0
    // Constructor
    internal EarClipVertex(Vector2 v, Sidedef sidedef)
    {
        // Initialize
        this.pos     = v;
        this.sidedef = sidedef;

        // We have no destructor
        GC.SuppressFinalize(this);
    }
Ejemplo n.º 27
0
 // Constructor
 public ResultUnusedTexture(Sidedef sd, SidedefPart part)
 {
     // Initialize
     this.side = sd;
     this.part = part;
     this.viewobjects.Add(sd);
     this.hidden      = sd.IgnoredErrorChecks.Contains(this.GetType());        //mxd
     this.description = "This sidedef uses an upper or lower texture, which is not required (it will never be visible ingame). Click the Remove Texture button to remove the texture (this will also reset texture offsets and scale in UDMF map format).";
 }
Ejemplo n.º 28
0
        // Constructor
        public VisualUpper(BaseVisualMode mode, VisualSector vs, Sidedef s) : base(mode, vs, s)
        {
            //mxd
            geometrytype = VisualGeometryType.WALL_UPPER;
            partname     = "top";

            // We have no destructor
            GC.SuppressFinalize(this);
        }
Ejemplo n.º 29
0
        private readonly Dictionary <string, bool> flags;        //mxd

        public SidedefProperties(Sidedef s) : base(s.Fields, MapElementType.SIDEDEF)
        {
            hightexture   = s.HighTexture;
            middletexture = s.MiddleTexture;
            lowtexture    = s.LowTexture;
            offsetx       = s.OffsetX;
            offsety       = s.OffsetY;
            flags         = s.GetFlags();     //mxd
        }
Ejemplo n.º 30
0
        // This performs an accurate test for object picking
        public override bool PickAccurate(Vector3D from, Vector3D to, Vector3D dir, ref float u_ray)
        {
            u_ray = pickrayu;

            // Check on which side of the nearest sidedef we are
            Sidedef sd   = MapSet.NearestSidedef(Sector.Sector.Sidedefs, pickintersect);
            float   side = sd.Line.SideOfLine(pickintersect);

            //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 (!BuilderPlug.Me.AlphaBasedTextureHighlighting || !Texture.IsImageLoaded || extrafloor == null || RenderPass == RenderPass.Solid || (!Texture.IsTranslucent && !Texture.IsMasked))
                {
                    return(true);
                }

                // Some textures (e.g. HiResImage) may lie about their size, so use bitmap size instead
                Bitmap image = Texture.GetBitmap();

                lock (image)
                {
                    // 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 * image.Width) % image.Width;
                    o.y = (o.y * image.Height) % image.Height;

                    // Make sure coordinates are inside of texture dimensions...
                    if (o.x < 0)
                    {
                        o.x += image.Width;
                    }
                    if (o.y < 0)
                    {
                        o.y += image.Height;
                    }

                    // Make final texture coordinates...
                    int ox = General.Clamp((int)Math.Floor(o.x), 0, image.Width - 1);
                    int oy = General.Clamp((int)Math.Floor(o.y), 0, image.Height - 1);

                    // Check pixel alpha
                    return(image.GetPixel(ox, oy).A > 0);
                }
            }

            return(false);
        }