Пример #1
0
        //mxd
        private int GetLevelColor(SectorLevel src)
        {
            PixelColor brightness = PixelColor.FromInt(mode.CalculateBrightness(src.brightnessbelow));
            PixelColor color      = PixelColor.Modulate(src.colorbelow, brightness);

            return(color.WithAlpha(255).ToInt());
        }
Пример #2
0
        private Lights GetLight(int color)
        {
            PixelColor c;

            c = PixelColor.FromInt(color);
            return(new Lights(c.r, c.g, c.b, 0));
        }
Пример #3
0
        //mxd. merged from GZDoomEditing plugin
        // This applies the given values on the vertices
        private static void SetupSurfaceVertices(FlatVertex[] vertices, Sector s, ImageData img, Vector2D offset,
                                                 Vector2D scale, double rotate, int color, int light, bool absolute)
        {
            // Prepare for math!
            rotate = Angle2D.DegToRad(rotate);
            Vector2D texscale = new Vector2D(1.0f / img.ScaledWidth, 1.0f / img.ScaledHeight);

            if (!absolute)
            {
                light = s.Brightness + light;
            }
            PixelColor lightcolor = PixelColor.FromInt(color);
            PixelColor brightness = PixelColor.FromInt(General.Map.Renderer2D.CalculateBrightness(light));
            PixelColor finalcolor = PixelColor.Modulate(lightcolor, brightness);

            color = finalcolor.WithAlpha(255).ToInt();

            // Do the math for all vertices
            for (int i = 0; i < vertices.Length; i++)
            {
                Vector2D pos = new Vector2D(vertices[i].x, vertices[i].y);
                pos           = pos.GetRotated(rotate);
                pos.y         = -pos.y;
                pos           = (pos + offset) * scale * texscale;
                vertices[i].u = (float)pos.x;
                vertices[i].v = (float)pos.y;
                vertices[i].c = color;
            }
        }
Пример #4
0
        // When ceiling surface geometry is created for classic modes
        public override void OnSectorCeilingSurfaceUpdate(Sector s, ref FlatVertex[] vertices)
        {
            ImageData img = General.Map.Data.GetFlatImage(s.LongCeilTexture);

            if ((img != null) && img.IsImageLoaded)
            {
                //mxd. Merged from GZDoomEditing plugin
                if (General.Map.UDMF)
                {
                    // Fetch ZDoom fields
                    Vector2D offset = new Vector2D(s.Fields.GetValue("xpanningceiling", 0.0),
                                                   s.Fields.GetValue("ypanningceiling", 0.0));
                    Vector2D scale = new Vector2D(s.Fields.GetValue("xscaleceiling", 1.0),
                                                  s.Fields.GetValue("yscaleceiling", 1.0));
                    double rotate = s.Fields.GetValue("rotationceiling", 0.0);
                    int    color, light;
                    bool   absolute;

                    //mxd. Apply GLDEFS override?
                    if (General.Map.Data.GlowingFlats.ContainsKey(s.LongCeilTexture) &&
                        General.Map.Data.GlowingFlats[s.LongCeilTexture].Fullbright)
                    {
                        color    = -1;
                        light    = 255;
                        absolute = true;
                    }
                    else
                    {
                        color    = PixelColor.Modulate(PixelColor.FromInt(s.Fields.GetValue("lightcolor", -1)), PixelColor.FromInt(s.Fields.GetValue("color_ceiling", -1))).ToInt();
                        light    = s.Fields.GetValue("lightceiling", 0);
                        absolute = s.Fields.GetValue("lightceilingabsolute", false);
                    }

                    // Setup the vertices with the given settings
                    SetupSurfaceVertices(vertices, s, img, offset, scale, rotate, color, light, absolute);
                }
                else
                {
                    // Make scalars
                    float sw = 1.0f / img.ScaledWidth;
                    float sh = 1.0f / img.ScaledHeight;

                    // Make proper texture coordinates
                    for (int i = 0; i < vertices.Length; i++)
                    {
                        vertices[i].u = vertices[i].u * sw;
                        vertices[i].v = -vertices[i].v * sh;
                    }
                }
            }
            else // [ZZ] proper fallback please.
            {
                for (int i = 0; i < vertices.Length; i++)
                {
                    vertices[i].u = vertices[i].u / 64;
                    vertices[i].v = -vertices[i].v / 64;
                }
            }
        }
Пример #5
0
        // When no geometry has been changed and no effects have been added or removed,
        // you can call this again to update existing effects. The effects will update
        // the existing SectorLevels to match with any changes.
        public void Update()
        {
            if (isupdating || updated)
            {
                return;
            }
            isupdating = true;

            // Set floor/ceiling to their original setup
            BasicSetup();

            // Update all effects
            foreach (SectorEffect e in alleffects)
            {
                e.Update();
            }

            // Sort the levels (but not the first and the last)
            SectorLevelComparer comparer = new SectorLevelComparer(sector);

            lightlevels.Sort(1, lightlevels.Count - 2, comparer);

            // Now that we know the levels in this sector (and in the right order) we
            // can determine the lighting in between and on the levels.
            // Start from the absolute ceiling and go down to 'cast' the lighting
            for (int i = lightlevels.Count - 2; i >= 0; i--)
            {
                SectorLevel l  = lightlevels[i];
                SectorLevel pl = lightlevels[i + 1];

                // Set color when no color is specified, or when a 3D floor is placed above the absolute floor
                if ((l.color == 0) || ((l == floor) && (lightlevels.Count > 2)))
                {
                    PixelColor floorbrightness = PixelColor.FromInt(mode.CalculateBrightness(pl.brightnessbelow));
                    PixelColor floorcolor      = PixelColor.Modulate(pl.colorbelow, floorbrightness);
                    l.color = floorcolor.WithAlpha(255).ToInt();
                }

                if (l.colorbelow.a == 0)
                {
                    l.colorbelow = pl.colorbelow;
                }

                if (l.brightnessbelow == -1)
                {
                    l.brightnessbelow = pl.brightnessbelow;
                }
            }

            floorchanged   = false;
            ceilingchanged = false;
            updated        = true;
            isupdating     = false;
        }
Пример #6
0
        // This updates the overlay
        private void UpdateOverlay()
        {
            if (renderer.StartOverlay(true))
            {
                // Editing a selection?
                if (mode == ModifyMode.Adjusting)
                {
                    // Go for all sectors that are being edited
                    ICollection <Sector> orderedselection = General.Map.Map.GetSelectedSectors(true);
                    foreach (Sector s in orderedselection)
                    {
                        // We use the overlay to dim the brightness of the sectors
                        PixelColor c = PixelColor.FromInt(General.Map.Renderer2D.CalculateBrightness(s.Brightness));
                        PixelColor brightnesscolor = new PixelColor((byte)(255 - c.r), 0, 0, 0);
                        int        brightnessint   = brightnesscolor.ToInt();

                        // Render the geometry
                        FlatVertex[] verts = new FlatVertex[s.FlatVertices.Length];
                        s.FlatVertices.CopyTo(verts, 0);
                        for (int i = 0; i < verts.Length; i++)
                        {
                            verts[i].c = brightnessint;
                        }
                        renderer.RenderGeometry(verts, null, true);
                    }
                }

                if (BuilderPlug.Me.ViewSelectionNumbers)
                {
                    // Go for all sectors
                    ICollection <Sector> orderedselection = General.Map.Map.GetSelectedSectors(true);
                    foreach (Sector s in orderedselection)
                    {
                        // Render labels
                        TextLabel[] labelarray = labels[s];
                        for (int i = 0; i < s.Labels.Count; i++)
                        {
                            TextLabel l = labelarray[i];

                            // Render only when enough space for the label to see
                            float requiredsize = (l.TextSize.Height / 2) / renderer.Scale;
                            if (requiredsize < s.Labels[i].radius)
                            {
                                renderer.RenderText(l);
                            }
                        }
                    }
                }

                renderer.Finish();
            }
        }
Пример #7
0
        //mxd. This sets up the association
        public Association(IRenderer2D renderer)
        {
            this.tags = new HashSet <int> {
                0
            };
            this.renderer = renderer;

            things     = new List <Thing>();
            sectors    = new List <Sector>();
            linedefs   = new List <Linedef>();
            eventlines = new Dictionary <string, List <Line3D> >();

            try
            {
                font = new Font(new FontFamily(General.Settings.TextLabelFontName), General.Settings.TextLabelFontSize, (General.Settings.TextLabelFontBold ? FontStyle.Bold : FontStyle.Regular));
            }
            catch (Exception)             // Fallback if the font couldn't be loaded
            {
                font = ((MainForm)General.Interface).Font;
            }

            distinctcolors = new List <PixelColor>
            {
                General.Colors.InfoLine,
                PixelColor.FromInt(0x84d5a4).WithAlpha(255),
                PixelColor.FromInt(0xc059cb).WithAlpha(255),
                PixelColor.FromInt(0xd0533d).WithAlpha(255),
                // PixelColor.FromInt(0x415354).WithAlpha(255), // too dark
                PixelColor.FromInt(0xcea953).WithAlpha(255),
                PixelColor.FromInt(0x91d44b).WithAlpha(255),
                PixelColor.FromInt(0xcd5b89).WithAlpha(255),
                PixelColor.FromInt(0xa8b6c0).WithAlpha(255),
                PixelColor.FromInt(0x797ecb).WithAlpha(255),
                // PixelColor.FromInt(0x567539).WithAlpha(255), // too dark
                // PixelColor.FromInt(0x72422f).WithAlpha(255), // too dark
                // PixelColor.FromInt(0x5d3762).WithAlpha(255), // too dark
                PixelColor.FromInt(0xffed6f).WithAlpha(255),
                PixelColor.FromInt(0xccebc5).WithAlpha(255),
                PixelColor.FromInt(0xbc80bd).WithAlpha(255),
                // PixelColor.FromInt(0xd9d9d9).WithAlpha(255), // too gray
                PixelColor.FromInt(0xfccde5).WithAlpha(255),
                PixelColor.FromInt(0x80b1d3).WithAlpha(255),
                PixelColor.FromInt(0xfdb462).WithAlpha(255),
                PixelColor.FromInt(0xb3de69).WithAlpha(255),
                PixelColor.FromInt(0xfb8072).WithAlpha(255),
                PixelColor.FromInt(0xbebada).WithAlpha(255),                 // too blue/gray?
                PixelColor.FromInt(0xffffb3).WithAlpha(255),
                PixelColor.FromInt(0x8dd3c7).WithAlpha(255),
            };
        }
        // This makes sure we are updated with the source linedef information
        public override void Update()
        {
            SectorData sd = data.Mode.GetSectorData(linedef.Front.Sector);

            if (!sd.Updated)
            {
                sd.Update();
            }
            sd.AddUpdateSector(data.Sector, false);

            // Transfer ceiling brightness, keep sector color
            PixelColor lightcolor = PixelColor.FromInt(data.Sector.Fields.GetValue("lightcolor", -1));
            PixelColor brightness = PixelColor.FromInt(General.Map.Renderer3D.CalculateBrightness(sd.Sector.Brightness));

            data.Ceiling.color = PixelColor.Modulate(lightcolor, brightness).WithAlpha(255).ToInt();
        }
Пример #9
0
        //mxd. This replicates ZDoom's V_GetColorFromString method
        public static bool GetColorFromString(string name, out PixelColor color)
        {
            name = StripQuotes(name.Replace(" ", ""));

            // Check for HTML-style #RRGGBB or #RGB color string
            bool ishtmlcolor = false;

            if (name.StartsWith("#"))
            {
                ishtmlcolor = true;
                name        = name.Remove(0, 1);

                // Expand RGB to RRGGBB
                if (name.Length == 3)
                {
                    name = name[0].ToString() + name[0] + name[1] + name[1] + name[2] + name[2];
                }
                else if (name.Length != 6)
                {
                    // Bad HTML-style; pretend it's black.
                    color = new PixelColor();
                    return(true);
                }
            }

            // Probably it's a hex color (like FFCC11)?
            int ci;

            if (int.TryParse(name, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out ci))
            {
                color = PixelColor.FromInt(ci).WithAlpha(255);
                return(true);
            }

            // Probably it's a color name?
            if (!ishtmlcolor && General.Map.Data.KnownColors.ContainsKey(name))
            {
                color = General.Map.Data.KnownColors[name];
                return(true);
            }

            color = new PixelColor();
            return(false);
        }
        private void tbColor_TextChanged(object sender, EventArgs e)
        {
            if (blockupdate)
            {
                return;
            }

            int colorval;

            if (int.TryParse(tbColor.Text, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out colorval))
            {
                colorval      = General.Clamp(colorval, 0, 0xFFFFFF);
                cpColor.Color = PixelColor.FromInt(colorval).WithAlpha(255);
            }

            CheckColor();
            if (!blockevents && OnValueChanged != null)
            {
                OnValueChanged(this, EventArgs.Empty);
            }
        }
Пример #11
0
        //mxd
        private int GetLevelColor(SectorLevel src, SectorLevel target)
        {
            PixelColor brightness;

            if (lightfloorabsolute && target == floor)
            {
                brightness = PixelColor.FromInt(mode.CalculateBrightness(lightfloor));
            }
            else if (lightceilingabsolute && target == ceiling)
            {
                brightness = PixelColor.FromInt(mode.CalculateBrightness(lightceiling));
            }
            else
            {
                brightness = PixelColor.FromInt(mode.CalculateBrightness(src.brightnessbelow));
            }

            PixelColor color = PixelColor.Modulate(src.colorbelow, brightness);

            return(color.WithAlpha(255).ToInt());
        }
        public void SetValueFrom(UniFields fields, bool first)
        {
            blockevents = true;

            string colorval = String.Format("{0:X6}", UniFields.GetInteger(fields, field, defaultvalue));

            if (first)
            {
                tbColor.Text = colorval;
            }
            else if (!string.IsNullOrEmpty(tbColor.Text) && colorval != tbColor.Text)
            {
                blockupdate   = true;
                tbColor.Text  = string.Empty;
                cpColor.Color = PixelColor.FromInt(defaultvalue).WithAlpha(255);
                blockupdate   = false;

                CheckColor();
            }

            blockevents = false;
        }
Пример #13
0
        // This sets up the basic floor and ceiling, as they would be in normal Doom circumstances
        private void BasicSetup()
        {
            // Normal (flat) floor and ceiling planes
            floor.plane   = new Plane(new Vector3D(0, 0, 1), -sector.FloorHeight);
            ceiling.plane = new Plane(new Vector3D(0, 0, -1), sector.CeilHeight);

            // Fetch ZDoom fields
            int  color  = sector.Fields.GetValue("lightcolor", -1);
            int  flight = sector.Fields.GetValue("lightfloor", 0);
            bool fabs   = sector.Fields.GetValue("lightfloorabsolute", false);
            int  clight = sector.Fields.GetValue("lightceiling", 0);
            bool cabs   = sector.Fields.GetValue("lightceilingabsolute", false);

            // Determine colors & light levels
            PixelColor lightcolor = PixelColor.FromInt(color);

            if (!fabs)
            {
                flight = sector.Brightness + flight;
            }
            if (!cabs)
            {
                clight = sector.Brightness + clight;
            }
            PixelColor floorbrightness   = PixelColor.FromInt(mode.CalculateBrightness(flight));
            PixelColor ceilingbrightness = PixelColor.FromInt(mode.CalculateBrightness(clight));
            PixelColor floorcolor        = PixelColor.Modulate(lightcolor, floorbrightness);
            PixelColor ceilingcolor      = PixelColor.Modulate(lightcolor, ceilingbrightness);

            floor.color             = floorcolor.WithAlpha(255).ToInt();
            floor.brightnessbelow   = sector.Brightness;
            floor.colorbelow        = lightcolor.WithAlpha(255);
            ceiling.color           = ceilingcolor.WithAlpha(255).ToInt();
            ceiling.brightnessbelow = sector.Brightness;
            ceiling.colorbelow      = lightcolor.WithAlpha(255);
        }
        private GlowingFlatData GetGlowData(bool floor)
        {
            // Check UDMF glow properties
            if (General.Map.UDMF)
            {
                int glowcolor = data.Sector.Fields.GetValue((floor ? "floorglowcolor" : "ceilingglowcolor"), 0);

                // Glow is explicidly disabled?
                if (glowcolor == -1)
                {
                    return(null);
                }

                // Avoid black glows
                if (glowcolor > 0)
                {
                    double glowheight = data.Sector.Fields.GetValue((floor ? "floorglowheight" : "ceilingglowheight"), 0.0);
                    if (glowheight > 0f)
                    {
                        // Create glow data
                        PixelColor c = PixelColor.FromInt(glowcolor);
                        return(new GlowingFlatData
                        {
                            Color = c,
                            Height = glowheight,
                            Brightness = (c.r + c.g + c.b) / 3,
                        });
                    }
                }
            }

            // Use GLDEFS glow if available
            long texture = (floor ? data.Sector.LongFloorTexture : data.Sector.LongCeilTexture);

            return(General.Map.Data.GlowingFlats.ContainsKey(texture) ? General.Map.Data.GlowingFlats[texture] : null);
        }
Пример #15
0
        // This shows the info
        public void ShowInfo(Sector s, bool highlightceiling, bool highlightfloor)
        {
            int sheight = s.CeilHeight - s.FloorHeight;

            // Lookup effect description in config
            string effectinfo = s.Effect + " - " + General.Map.Config.GetSectorEffectInfo(s.Effect).Title;             //mxd

            // Sector info
            sectorinfo.Text  = " Sector " + s.Index + " (" + (s.Sidedefs == null ? "no" : s.Sidedefs.Count.ToString()) + " sidedefs)";            //mxd
            effect.Text      = effectinfo;
            ceiling.Text     = s.CeilHeight.ToString();
            floor.Text       = s.FloorHeight.ToString();
            height.Text      = sheight.ToString();
            brightness.Text  = s.Brightness.ToString();
            floorname.Text   = (s.FloorTexture.Length > DataManager.CLASIC_IMAGE_NAME_LENGTH ? s.FloorTexture : s.FloorTexture.ToUpperInvariant());
            ceilingname.Text = (s.CeilTexture.Length > DataManager.CLASIC_IMAGE_NAME_LENGTH ? s.CeilTexture : s.CeilTexture.ToUpperInvariant());

            //mxd. Set tags
            if (s.Tags.Count > 1)
            {
                string[] tags = new string[s.Tags.Count];
                for (int i = 0; i < s.Tags.Count; i++)
                {
                    tags[i] = s.Tags[i].ToString();
                }
                tag.Text         = string.Join(", ", tags);
                tag.Enabled      = true;
                taglabel.Enabled = true;
                taglabel.Text    = "Tags:";
            }
            else
            {
                tag.Text         = s.Tag + (General.Map.Options.TagLabels.ContainsKey(s.Tag) ? " - " + General.Map.Options.TagLabels[s.Tag] : string.Empty);
                tag.Enabled      = (s.Tag != 0);
                taglabel.Enabled = (s.Tag != 0);
                taglabel.Text    = "Tag:";
            }

            //mxd
            effect.Enabled      = (s.Effect != 0);
            effectlabel.Enabled = (s.Effect != 0);

            //mxd. Texture size
            if (s.LongFloorTexture == MapSet.EmptyLongName)
            {
                labelFloorTextureSize.Visible = false;
                General.DisplayZoomedImage(floortex, Properties.Resources.MissingTexture);
            }
            else
            {
                ImageData image = General.Map.Data.GetFlatImage(s.FloorTexture);
                DisplayTextureSize(labelFloorTextureSize, image);
                General.DisplayZoomedImage(floortex, image.GetPreview());
            }

            if (s.LongCeilTexture == MapSet.EmptyLongName)
            {
                labelCeilTextureSize.Visible = false;
                General.DisplayZoomedImage(ceilingtex, Properties.Resources.MissingTexture);
            }
            else
            {
                ImageData image = General.Map.Data.GetFlatImage(s.CeilTexture);
                DisplayTextureSize(labelCeilTextureSize, image);                 //mxd
                General.DisplayZoomedImage(ceilingtex, image.GetPreview());
            }

            //mxd
            bool showExtededFloorInfo   = false;
            bool showExtededCeilingInfo = false;

            if (General.Map.UDMF)
            {
                if (s.Fields != null)
                {
                    //sector colors
                    labelLight.Visible      = true;
                    labelFade.Visible       = true;
                    panelLightColor.Visible = true;
                    panelFadeColor.Visible  = true;

                    if (s.Fields.ContainsKey("lightcolor"))
                    {
                        panelLightColor.BackColor = PixelColor.FromInt(s.Fields.GetValue("lightcolor", 0xFFFFFF)).WithAlpha(255).ToColor();
                        labelLight.Enabled        = true;
                    }
                    else
                    {
                        panelLightColor.BackColor = SystemColors.Control;
                        labelLight.Enabled        = false;
                    }

                    if (s.Fields.ContainsKey("fadecolor"))
                    {
                        panelFadeColor.BackColor = PixelColor.FromInt(s.Fields.GetValue("fadecolor", 0)).WithAlpha(255).ToColor();
                        labelFade.Enabled        = true;
                    }
                    else
                    {
                        panelFadeColor.BackColor = SystemColors.Control;
                        labelFade.Enabled        = false;
                    }

                    //light
                    if (s.Fields.ContainsKey("lightceiling") || s.Fields.ContainsKey("lightceilingabsolute"))
                    {
                        showExtededCeilingInfo    = true;
                        ceilingLight.Enabled      = true;
                        ceilingLightLabel.Enabled = true;

                        int cl = s.Fields.GetValue("lightceiling", 0);

                        if (s.Fields.GetValue("lightceilingabsolute", false))
                        {
                            ceilingLight.Text = cl + " (abs.)";
                        }
                        else
                        {
                            ceilingLight.Text = cl + " (" + Math.Min(255, Math.Max(0, (cl + s.Brightness))) + ")";
                        }
                    }
                    else
                    {
                        ceilingLight.Text         = "--";
                        ceilingLight.Enabled      = false;
                        ceilingLightLabel.Enabled = false;
                    }

                    if (s.Fields.ContainsKey("lightfloor") || s.Fields.ContainsKey("lightfloorabsolute"))
                    {
                        showExtededFloorInfo    = true;
                        floorLight.Enabled      = true;
                        floorLightLabel.Enabled = true;

                        int fl = s.Fields.GetValue("lightfloor", 0);

                        if (s.Fields.GetValue("lightfloorabsolute", false))
                        {
                            floorLight.Text = fl + " (abs.)";
                        }
                        else
                        {
                            floorLight.Text = fl + " (" + Math.Min(255, Math.Max(0, (fl + s.Brightness))) + ")";
                        }
                    }
                    else
                    {
                        floorLight.Text         = "--";
                        floorLight.Enabled      = false;
                        floorLightLabel.Enabled = false;
                    }

                    //ceiling offsets
                    float panX = s.Fields.GetValue("xpanningceiling", 0f);
                    float panY = s.Fields.GetValue("ypanningceiling", 0f);

                    if (panX != 0 || panY != 0)
                    {
                        showExtededCeilingInfo     = true;
                        ceilingOffset.Enabled      = true;
                        ceilingOffsetLabel.Enabled = true;
                        ceilingOffset.Text         = panX.ToString(CultureInfo.InvariantCulture) + ", " + panY.ToString(CultureInfo.InvariantCulture);
                    }
                    else
                    {
                        ceilingOffset.Text         = "--, --";
                        ceilingOffset.Enabled      = false;
                        ceilingOffsetLabel.Enabled = false;
                    }

                    //floor offsets
                    panX = s.Fields.GetValue("xpanningfloor", 0f);
                    panY = s.Fields.GetValue("ypanningfloor", 0f);

                    if (panX != 0 || panY != 0)
                    {
                        showExtededFloorInfo     = true;
                        floorOffset.Enabled      = true;
                        floorOffsetLabel.Enabled = true;
                        floorOffset.Text         = panX.ToString(CultureInfo.InvariantCulture) + ", " + panY.ToString(CultureInfo.InvariantCulture);
                    }
                    else
                    {
                        floorOffset.Text         = "--, --";
                        floorOffset.Enabled      = false;
                        floorOffsetLabel.Enabled = false;
                    }

                    //ceiling scale
                    float scaleX = s.Fields.GetValue("xscaleceiling", 1.0f);
                    float scaleY = s.Fields.GetValue("yscaleceiling", 1.0f);

                    if (scaleX != 1.0f || scaleY != 1.0f)
                    {
                        showExtededCeilingInfo    = true;
                        ceilingScale.Enabled      = true;
                        ceilingScaleLabel.Enabled = true;
                        ceilingScale.Text         = scaleX.ToString(CultureInfo.InvariantCulture) + ", " + scaleY.ToString(CultureInfo.InvariantCulture);
                    }
                    else
                    {
                        ceilingScale.Text         = "--, --";
                        ceilingScale.Enabled      = false;
                        ceilingScaleLabel.Enabled = false;
                    }

                    //floor scale
                    scaleX = s.Fields.GetValue("xscalefloor", 1.0f);
                    scaleY = s.Fields.GetValue("yscalefloor", 1.0f);

                    if (scaleX != 1.0f || scaleY != 1.0f)
                    {
                        showExtededFloorInfo    = true;
                        floorScale.Enabled      = true;
                        floorScaleLabel.Enabled = true;
                        floorScale.Text         = scaleX.ToString(CultureInfo.InvariantCulture) + ", " + scaleY.ToString(CultureInfo.InvariantCulture);
                    }
                    else
                    {
                        floorScale.Text         = "--, --";
                        floorScale.Enabled      = false;
                        floorScaleLabel.Enabled = false;
                    }

                    //rotation
                    float ceilangle = s.Fields.GetValue("rotationceiling", 0f);
                    if (ceilangle != 0f)
                    {
                        showExtededCeilingInfo    = true;
                        ceilingAngle.Enabled      = true;
                        ceilingAngleLabel.Enabled = true;
                        ceilingAngle.Text         = ceilangle + "\u00B0";
                    }
                    else
                    {
                        ceilingAngle.Text         = "--";
                        ceilingAngle.Enabled      = false;
                        ceilingAngleLabel.Enabled = false;
                    }

                    float floorangle = s.Fields.GetValue("rotationfloor", 0f);
                    if (floorangle != 0f)
                    {
                        showExtededFloorInfo    = true;
                        floorAngle.Enabled      = true;
                        floorAngleLabel.Enabled = true;
                        floorAngle.Text         = floorangle + "\u00B0";
                    }
                    else
                    {
                        floorAngle.Text         = "--";
                        floorAngle.Enabled      = false;
                        floorAngleLabel.Enabled = false;
                    }
                }

                //Flags
                flags.Items.Clear();
                foreach (KeyValuePair <string, string> group in General.Map.Config.SectorFlags)
                {
                    if (s.Flags.ContainsKey(group.Key) && s.Flags[group.Key])
                    {
                        flags.Items.Add(new ListViewItem(group.Value)
                        {
                            Checked = true
                        });
                    }
                }
                foreach (KeyValuePair <string, string> group in General.Map.Config.CeilingPortalFlags)
                {
                    if (s.Flags.ContainsKey(group.Key) && s.Flags[group.Key])
                    {
                        flags.Items.Add(new ListViewItem(group.Value + " (ceil. portal)")
                        {
                            Checked = true
                        });
                    }
                }
                foreach (KeyValuePair <string, string> group in General.Map.Config.FloorPortalFlags)
                {
                    if (s.Flags.ContainsKey(group.Key) && s.Flags[group.Key])
                    {
                        flags.Items.Add(new ListViewItem(group.Value + " (floor portal)")
                        {
                            Checked = true
                        });
                    }
                }

                //mxd. Flags panel visibility and size
                flagsPanel.Visible = (flags.Items.Count > 0);
                if (flags.Items.Count > 0)
                {
                    Rectangle rect           = flags.GetItemRect(0);
                    int       itemspercolumn = 1;

                    // Check how many items per column we have...
                    for (int i = 1; i < flags.Items.Count; i++)
                    {
                        if (flags.GetItemRect(i).X != rect.X)
                        {
                            break;
                        }
                        itemspercolumn++;
                    }

                    flags.Width      = rect.Width * (int)Math.Ceiling(flags.Items.Count / (float)itemspercolumn);
                    flagsPanel.Width = flags.Width + flags.Left * 2;
                }

                //mxd. Toggle visibility
                foreach (Label label in floorinfolabels)
                {
                    label.Visible = showExtededFloorInfo;
                }
                foreach (Label label in floorlabels)
                {
                    label.Visible = showExtededFloorInfo;
                }
                foreach (Label label in ceilinfolabels)
                {
                    label.Visible = showExtededCeilingInfo;
                }
                foreach (Label label in ceillabels)
                {
                    label.Visible = showExtededCeilingInfo;
                }
            }
            else
            {
                panelFadeColor.Visible  = false;
                panelLightColor.Visible = false;
                labelFade.Visible       = false;
                labelLight.Visible      = false;
                flagsPanel.Visible      = false;
            }

            //mxd. Resize panels
            UpdateTexturePanel(ceilingpanel, ceilingname, ceilinfolabels, ceilingtex, ceilingOffsetLabel.Location.X - 1, showExtededCeilingInfo);
            UpdateTexturePanel(floorpanel, floorname, floorinfolabels, floortex, floorOffsetLabel.Location.X - 1, showExtededFloorInfo);

            //mxd. Highlight ceiling or floor?
            Color floorhighlightcolor   = (highlightfloor ? SystemColors.HotTrack : SystemColors.WindowText);
            Color ceilinghighlightcolor = (highlightceiling ? SystemColors.HotTrack : SystemColors.WindowText);

            floorpanel.ForeColor = floorhighlightcolor;
            floor.ForeColor      = floorhighlightcolor;
            labelfloor.ForeColor = floorhighlightcolor;

            ceilingpanel.ForeColor = ceilinghighlightcolor;
            ceiling.ForeColor      = ceilinghighlightcolor;
            labelceiling.ForeColor = ceilinghighlightcolor;

            // Show the whole thing
            this.Show();
            this.Update();
        }
Пример #16
0
        // This builds the geometry. Returns false when no geometry created.
        public override bool Setup(SectorLevel level, Effect3DFloor extrafloor)
        {
            WorldVertex[] verts;
            Sector        s = level.sector;
            Vector2D      texscale;

            base.Setup(level, extrafloor);

            // Fetch ZDoom fields
            float    rotate = Angle2D.DegToRad(s.Fields.GetValue("rotationceiling", 0.0f));
            Vector2D offset = new Vector2D(s.Fields.GetValue("xpanningceiling", 0.0f),
                                           s.Fields.GetValue("ypanningceiling", 0.0f));
            Vector2D scale = new Vector2D(s.Fields.GetValue("xscaleceiling", 1.0f),
                                          s.Fields.GetValue("yscaleceiling", 1.0f));

            // Load floor texture
            base.Texture = General.Map.Data.GetFlatImage(s.LongCeilTexture);
            if (base.Texture == null)
            {
                base.Texture         = General.Map.Data.MissingTexture3D;
                setuponloadedtexture = s.LongCeilTexture;
            }
            else
            {
                if (!base.Texture.IsImageLoaded)
                {
                    setuponloadedtexture = s.LongCeilTexture;
                }
            }

            // Determine texture scale
            if (base.Texture.IsImageLoaded)
            {
                texscale = new Vector2D(1.0f / base.Texture.ScaledWidth, 1.0f / base.Texture.ScaledHeight);
            }
            else
            {
                texscale = new Vector2D(1.0f / 64.0f, 1.0f / 64.0f);
            }

            // Make vertices
            ReadOnlyCollection <Vector2D> triverts = base.Sector.Sector.Triangles.Vertices;

            verts = new WorldVertex[triverts.Count];
            for (int i = 0; i < triverts.Count; i++)
            {
                // Color shading
                PixelColor c = PixelColor.FromInt(level.color);
                verts[i].c = c.WithAlpha((byte)General.Clamp(level.alpha, 0, 255)).ToInt();

                // Vertex coordinates
                verts[i].x = triverts[i].x;
                verts[i].y = triverts[i].y;
                verts[i].z = level.plane.GetZ(triverts[i]);                 //(float)s.CeilHeight;

                // Texture coordinates
                Vector2D pos = triverts[i];
                pos        = pos.GetRotated(rotate);
                pos.y      = -pos.y;
                pos        = (pos + offset) * scale * texscale;
                verts[i].u = pos.x;
                verts[i].v = pos.y;
            }

            // The sector triangulation created clockwise triangles that
            // are right up for the floor. For the ceiling we must flip
            // the triangles upside down.
            if ((extrafloor == null) || extrafloor.VavoomType)
            {
                SwapTriangleVertices(verts);
            }

            // Determine render pass
            if (extrafloor != null)
            {
                if (level.alpha < 255)
                {
                    this.RenderPass = RenderPass.Alpha;
                }
                else
                {
                    this.RenderPass = RenderPass.Mask;
                }
            }
            else
            {
                this.RenderPass = RenderPass.Solid;
            }

            // Apply vertices
            base.SetVertices(verts);
            return(verts.Length > 0);
        }
Пример #17
0
        // This builds the thing geometry. Returns false when nothing was created.
        public bool Setup()
        {
            // Find the sector in which the thing resides
            Thing.DetermineSector(mode.BlockMap);

            //mxd. If the thing is inside a sector, apply DECORATE/UDMF alpha/renderstyle overrides
            byte alpha = 255;

            if (Thing.Sector != null)
            {
                string renderstyle = info.RenderStyle;
                alpha = info.AlphaByte;

                if (General.Map.UDMF)
                {
                    if (Thing.IsFlagSet("translucent"))
                    {
                        renderstyle = "translucent";
                        alpha       = 64;
                    }
                    else if (Thing.IsFlagSet("invisible"))
                    {
                        renderstyle = "none";
                        alpha       = 0;
                    }
                    else if (Thing.Fields.ContainsKey("renderstyle"))
                    {
                        renderstyle = Thing.Fields.GetValue("renderstyle", renderstyle);
                    }

                    if ((renderstyle == "add" || renderstyle == "translucent" || renderstyle == "subtract" || renderstyle == "stencil") &&
                        Thing.Fields.ContainsKey("alpha"))
                    {
                        alpha = (byte)(General.Clamp(Thing.Fields.GetValue("alpha", info.Alpha), 0f, 1f) * 255);
                    }
                }
                else if (General.Map.HEXEN)
                {
                    if (Thing.IsFlagSet("2048"))
                    {
                        renderstyle = "translucent";
                        alpha       = 64;
                    }
                    else if (Thing.IsFlagSet("4096"))
                    {
                        renderstyle = "none";
                        alpha       = 0;
                    }
                }

                // Set appropriate RenderPass
                switch (renderstyle)
                {
                case "translucent":
                case "subtract":
                case "stencil":
                    RenderPass = RenderPass.Alpha;
                    break;

                case "add":
                    RenderPass = RenderPass.Additive;
                    break;

                case "none":
                    RenderPass = RenderPass.Mask;
                    alpha      = 0;
                    break;

                // Many render styles are not supported yet...
                default:
                    RenderPass = RenderPass.Mask;
                    alpha      = 255;
                    break;
                }
            }

            // Don't bother when alpha is unchanged, unless Additive RenderStyle is used
            if (RenderPass != RenderPass.Additive && alpha == 255)
            {
                RenderPass = RenderPass.Mask;
            }

            int sectorcolor = new PixelColor(alpha, 255, 255, 255).ToInt();

            fogfactor = 0f;             //mxd

            //mxd. Check thing size
            float thingradius = Thing.Size;         // Thing.Size has ThingRadius arg override applied

            thingheight = Thing.Height;             // Thing.Height has ThingHeight arg override applied

            if (thingradius < 0.1f || thingheight < 0.1f)
            {
                thingradius = FIXED_RADIUS;
                thingheight = FIXED_RADIUS;
                sizeless    = true;
            }
            else
            {
                sizeless = false;
            }

            Plane floor   = new Plane();           //mxd
            Plane ceiling = new Plane();           //mxd

            if (Thing.Sector != null)
            {
                SectorData sd = mode.GetSectorData(Thing.Sector);
                floor   = sd.Floor.plane;               //mxd
                ceiling = sd.Ceiling.plane;             //mxd

                if (!info.Bright)
                {
                    Vector3D    thingpos = new Vector3D(Thing.Position.x, Thing.Position.y, Thing.Position.z + sd.Floor.plane.GetZ(Thing.Position));
                    SectorLevel level    = sd.GetLevelAboveOrAt(thingpos);

                    //mxd. Let's use point on floor plane instead of Thing.Sector.FloorHeight;
                    if (nointeraction && level == null && sd.LightLevels.Count > 0)
                    {
                        level = sd.LightLevels[sd.LightLevels.Count - 1];
                    }

                    //mxd. Use the light level of the highest surface when a thing is above highest sector level.
                    if (level != null)
                    {
                        // TECH: In GZDoom, ceiling glow doesn't affect thing brightness
                        // Use sector brightness for color shading
                        int brightness = level.brightnessbelow;

                        // Level is glowing
                        if (level.affectedbyglow && level.type == SectorLevelType.Floor)
                        {
                            // Extrafloor glow doesn't affect thing brightness
                            if (level.sector == Thing.Sector)
                            {
                                float planez = level.plane.GetZ(thingpos);

                                // Get glow brightness
                                int         glowbrightness = sd.FloorGlow.Brightness / 2;
                                SectorLevel nexthigher     = sd.GetLevelAbove(new Vector3D(thingpos, planez));

                                // Interpolate thing brightness between glow and regular ones
                                if (nexthigher != null)
                                {
                                    float higherz = nexthigher.plane.GetZ(thingpos);
                                    float delta   = General.Clamp(1.0f - (thingpos.z - planez) / (higherz - planez), 0f, 1f);
                                    brightness = (int)((glowbrightness + level.sector.Brightness / 2) * delta + nexthigher.sector.Brightness * (1.0f - delta));
                                }
                            }
                        }
                        // Level below this one is glowing. Only possible for floor glow(?)
                        else if (level.type == SectorLevelType.Glow)
                        {
                            // Interpolate thing brightness between glow and regular ones
                            if (sd.Floor != null && sd.FloorGlow != null)
                            {
                                // Get glow brightness
                                float glowz  = level.plane.GetZ(thingpos);
                                float floorz = floor.GetZ(thingpos);
                                float delta  = General.Clamp((thingpos.z - floorz) / (glowz - floorz), 0f, 1f);

                                brightness = (int)((sd.FloorGlow.Brightness / 2 + sd.Floor.sector.Brightness / 2) * (1.0f - delta) + sd.Floor.sector.Brightness * delta);
                            }
                        }

                        PixelColor areabrightness = PixelColor.FromInt(mode.CalculateBrightness(brightness));
                        PixelColor areacolor      = PixelColor.Modulate(level.colorbelow, areabrightness);
                        sectorcolor = areacolor.WithAlpha(alpha).ToInt();

                        //mxd. Calculate fogfactor
                        fogfactor = VisualGeometry.CalculateFogFactor(level.sector.FogMode, brightness);
                    }
                }
                //TECH: even Bright Thing frames are affected by custom fade...
                else
                {
                    Vector3D    thingpos = new Vector3D(Thing.Position.x, Thing.Position.y, Thing.Position.z + sd.Floor.plane.GetZ(Thing.Position));
                    SectorLevel level    = sd.GetLevelAboveOrAt(thingpos);

                    if (level != null && level.sector.FogMode > SectorFogMode.CLASSIC)
                    {
                        //mxd. Calculate fogfactor
                        fogfactor = VisualGeometry.CalculateFogFactor(level.sector.FogMode, level.brightnessbelow);
                    }
                }
            }

            //mxd. Create verts for all sprite angles
            WorldVertex[][] allverts   = new WorldVertex[info.SpriteFrame.Length][];
            Vector2D[]      alloffsets = new Vector2D[info.SpriteFrame.Length];
            base.textures = new ImageData[info.SpriteFrame.Length];
            isloaded      = true;

            for (int i = 0; i < sprites.Length; i++)
            {
                Vector2D offsets = new Vector2D();

                // Check if the texture is loaded
                ImageData sprite = sprites[i];
                sprite.LoadImage();
                if (sprite.IsImageLoaded)
                {
                    base.textures[i] = sprite;

                    // Determine sprite size and offset
                    float        radius    = sprite.ScaledWidth * 0.5f;
                    float        height    = sprite.ScaledHeight;
                    ISpriteImage spriteimg = sprite as ISpriteImage;
                    if (spriteimg != null)
                    {
                        offsets.x = radius - spriteimg.OffsetX;
                        offsets.y = spriteimg.OffsetY - height;
                    }

                    // Scale by thing type/actor scale
                    // We do this after the offset x/y determination above, because that is entirely in sprite pixels space
                    radius    *= info.SpriteScale.Width;
                    height    *= info.SpriteScale.Height;
                    offsets.x *= info.SpriteScale.Width;
                    offsets.y *= info.SpriteScale.Height;

                    // Make vertices
                    WorldVertex[] verts = new WorldVertex[6];

                    //mxd. Sprite mirroring
                    float ul = (info.SpriteFrame[i].Mirror ? 1f : 0f);
                    float ur = (info.SpriteFrame[i].Mirror ? 0f : 1f);

                    if (sizeless)                    //mxd
                    {
                        float hh = height / 2;
                        verts[0] = new WorldVertex(-radius + offsets.x, 0.0f, offsets.y - hh, sectorcolor, ul, 1.0f);
                        verts[1] = new WorldVertex(-radius + offsets.x, 0.0f, hh + offsets.y, sectorcolor, ul, 0.0f);
                        verts[2] = new WorldVertex(+radius + offsets.x, 0.0f, hh + offsets.y, sectorcolor, ur, 0.0f);
                        verts[3] = verts[0];
                        verts[4] = verts[2];
                        verts[5] = new WorldVertex(+radius + offsets.x, 0.0f, offsets.y - hh, sectorcolor, ur, 1.0f);
                    }
                    else
                    {
                        verts[0] = new WorldVertex(-radius + offsets.x, 0.0f, offsets.y, sectorcolor, ul, 1.0f);
                        verts[1] = new WorldVertex(-radius + offsets.x, 0.0f, height + offsets.y, sectorcolor, ul, 0.0f);
                        verts[2] = new WorldVertex(+radius + offsets.x, 0.0f, height + offsets.y, sectorcolor, ur, 0.0f);
                        verts[3] = verts[0];
                        verts[4] = verts[2];
                        verts[5] = new WorldVertex(+radius + offsets.x, 0.0f, offsets.y, sectorcolor, ur, 1.0f);
                    }
                    allverts[i] = verts;
                }
                else
                {
                    isloaded         = false;
                    base.textures[i] = General.Map.Data.Hourglass3D;

                    // Determine sprite size
                    float radius = Math.Min(thingradius, thingheight / 2f);
                    float height = Math.Min(thingradius * 2f, thingheight);

                    //mxd. Determine sprite offsets
                    offsets.x = radius;
                    offsets.y = height / 2;

                    // Make vertices
                    WorldVertex[] verts = new WorldVertex[6];
                    verts[0]    = new WorldVertex(-radius, 0.0f, 0.0f, sectorcolor, 0.0f, 1.0f);
                    verts[1]    = new WorldVertex(-radius, 0.0f, height, sectorcolor, 0.0f, 0.0f);
                    verts[2]    = new WorldVertex(+radius, 0.0f, height, sectorcolor, 1.0f, 0.0f);
                    verts[3]    = verts[0];
                    verts[4]    = verts[2];
                    verts[5]    = new WorldVertex(+radius, 0.0f, 0.0f, sectorcolor, 1.0f, 1.0f);
                    allverts[i] = verts;
                }

                //mxd. Store offsets
                alloffsets[i] = offsets;
            }

            //mxd
            SetVertices(allverts, alloffsets /*, floor, ceiling*/);

            // Determine position
            Vector3D pos = Thing.Position;

            if (Thing.Type == 9501)
            {
                if (Thing.Sector != null)                //mxd
                {
                    // This is a special thing that needs special positioning
                    SectorData sd = mode.GetSectorData(Thing.Sector);
                    pos.z = sd.Ceiling.sector.CeilHeight + Thing.Position.z;
                }
            }
            else if (Thing.Type == 9500)
            {
                if (Thing.Sector != null)                //mxd
                {
                    // This is a special thing that needs special positioning
                    SectorData sd = mode.GetSectorData(Thing.Sector);
                    pos.z = sd.Floor.sector.FloorHeight + Thing.Position.z;
                }
            }
            else if (info.AbsoluteZ)
            {
                // Absolute Z position
                pos.z = Thing.Position.z;
            }
            else if (info.Hangs)
            {
                // Hang from ceiling
                if (Thing.Sector != null)
                {
                    SectorData sd   = mode.GetSectorData(Thing.Sector);
                    float      maxz = sd.Ceiling.plane.GetZ(Thing.Position) - info.Height;
                    pos.z = maxz;

                    if (Thing.Position.z > 0 || nointeraction)
                    {
                        pos.z -= Thing.Position.z;
                    }

                    // Check if below floor
                    if (!nointeraction)
                    {
                        float minz = sd.Floor.plane.GetZ(Thing.Position);
                        if (pos.z < minz)
                        {
                            pos.z = Math.Min(minz, maxz);
                        }
                    }
                }
            }
            else
            {
                // Stand on floor
                if (Thing.Sector != null)
                {
                    SectorData sd   = mode.GetSectorData(Thing.Sector);
                    float      minz = sd.Floor.plane.GetZ(Thing.Position);
                    pos.z = minz;

                    if (Thing.Position.z > 0 || nointeraction)
                    {
                        pos.z += Thing.Position.z;
                    }

                    // Check if above ceiling
                    if (!nointeraction)
                    {
                        float maxz = sd.Ceiling.plane.GetZ(Thing.Position) - info.Height;
                        if (pos.z > maxz)
                        {
                            pos.z = Math.Max(minz, maxz);
                        }
                    }
                }
            }

            // Apply settings
            SetPosition(pos);
            SetCageColor(Thing.Color);

            // Keep info for object picking
            cageradius2 = thingradius * Angle2D.SQRT2;
            cageradius2 = cageradius2 * cageradius2;
            pos2d       = pos;

            if (sizeless)            //mxd
            {
                boxp1 = new Vector3D(pos.x - thingradius, pos.y - thingradius, pos.z - thingradius / 2);
                boxp2 = new Vector3D(pos.x + thingradius, pos.y + thingradius, pos.z + thingradius / 2);
            }
            else
            {
                boxp1 = new Vector3D(pos.x - thingradius, pos.y - thingradius, pos.z);
                boxp2 = new Vector3D(pos.x + thingradius, pos.y + thingradius, pos.z + thingheight);
            }

            // Done
            changed = false;
            return(true);
        }
Пример #18
0
        public bool Setup(Effect3DFloor extrafloor)
        {
            Vector2D vl, vr;
            Sidedef  sourceside = extrafloor.Linedef.Front;

            this.extrafloor = extrafloor;

            int  lightvalue    = Sidedef.Fields.GetValue("light", 0);
            bool lightabsolute = Sidedef.Fields.GetValue("lightabsolute", false);

            Vector2D tscale = new Vector2D(sourceside.Fields.GetValue("scalex_mid", 1.0f),
                                           sourceside.Fields.GetValue("scaley_mid", 1.0f));
            Vector2D toffset1 = new Vector2D(Sidedef.Fields.GetValue("offsetx_mid", 0.0f),
                                             Sidedef.Fields.GetValue("offsety_mid", 0.0f));
            Vector2D toffset2 = new Vector2D(sourceside.Fields.GetValue("offsetx_mid", 0.0f),
                                             sourceside.Fields.GetValue("offsety_mid", 0.0f));

            // Left and right vertices for this sidedef
            if (Sidedef.IsFront)
            {
                vl = new Vector2D(Sidedef.Line.Start.Position.x, Sidedef.Line.Start.Position.y);
                vr = new Vector2D(Sidedef.Line.End.Position.x, Sidedef.Line.End.Position.y);
            }
            else
            {
                vl = new Vector2D(Sidedef.Line.End.Position.x, Sidedef.Line.End.Position.y);
                vr = new Vector2D(Sidedef.Line.Start.Position.x, Sidedef.Line.Start.Position.y);
            }

            // Load sector data
            SectorData sd = mode.GetSectorData(Sidedef.Sector);

            // Texture given?
            if ((sourceside.MiddleTexture.Length > 0) && (sourceside.MiddleTexture[0] != '-'))
            {
                // Load texture
                base.Texture = General.Map.Data.GetTextureImage(sourceside.LongMiddleTexture);
                if (base.Texture == null)
                {
                    base.Texture         = General.Map.Data.MissingTexture3D;
                    setuponloadedtexture = sourceside.LongMiddleTexture;
                }
                else
                {
                    if (!base.Texture.IsImageLoaded)
                    {
                        setuponloadedtexture = sourceside.LongMiddleTexture;
                    }
                }
            }
            else
            {
                // Use missing texture
                base.Texture         = General.Map.Data.MissingTexture3D;
                setuponloadedtexture = 0;
            }

            // Get texture scaled size
            Vector2D tsz = new Vector2D(base.Texture.ScaledWidth, base.Texture.ScaledHeight);

            tsz = tsz / tscale;

            // Get texture offsets
            Vector2D tof = new Vector2D(Sidedef.OffsetX, Sidedef.OffsetY);

            tof = tof + toffset1 + toffset2;
            tof = tof / tscale;
            if (General.Map.Config.ScaledTextureOffsets && !base.Texture.WorldPanning)
            {
                tof = tof * base.Texture.Scale;
            }

            // For Vavoom type 3D floors the ceiling is lower than floor and they are reversed.
            // We choose here.
            float sourcetopheight    = extrafloor.VavoomType ? sourceside.Sector.FloorHeight : sourceside.Sector.CeilHeight;
            float sourcebottomheight = extrafloor.VavoomType ? sourceside.Sector.CeilHeight : sourceside.Sector.FloorHeight;

            // Determine texture coordinates plane as they would be in normal circumstances.
            // We can then use this plane to find any texture coordinate we need.
            // The logic here is the same as in the original VisualMiddleSingle (except that
            // the values are stored in a TexturePlane)
            // NOTE: I use a small bias for the floor height, because if the difference in
            // height is 0 then the TexturePlane doesn't work!
            TexturePlane tp        = new TexturePlane();
            float        floorbias = (sourcetopheight == sourcebottomheight) ? 1.0f : 0.0f;

            tp.trb.x = tp.tlt.x + Sidedef.Line.Length;
            tp.trb.y = tp.tlt.y + (sourcetopheight - sourcebottomheight) + floorbias;

            // Apply texture offset
            tp.tlt += tof;
            tp.trb += tof;

            // Transform pixel coordinates to texture coordinates
            tp.tlt /= tsz;
            tp.trb /= tsz;

            // Left top and right bottom of the geometry that
            tp.vlt = new Vector3D(vl.x, vl.y, sourcetopheight);
            tp.vrb = new Vector3D(vr.x, vr.y, sourcebottomheight + floorbias);

            // Make the right-top coordinates
            tp.trt = new Vector2D(tp.trb.x, tp.tlt.y);
            tp.vrt = new Vector3D(tp.vrb.x, tp.vrb.y, tp.vlt.z);

            // Get ceiling and floor heights
            float fl = sd.Floor.plane.GetZ(vl);
            float fr = sd.Floor.plane.GetZ(vr);
            float cl = sd.Ceiling.plane.GetZ(vl);
            float cr = sd.Ceiling.plane.GetZ(vr);

            // Anything to see?
            if (((cl - fl) > 0.01f) || ((cr - fr) > 0.01f))
            {
                // Keep top and bottom planes for intersection testing
                top    = extrafloor.Floor.plane;
                bottom = extrafloor.Ceiling.plane;

                // Create initial polygon, which is just a quad between floor and ceiling
                WallPolygon poly = new WallPolygon();
                poly.Add(new Vector3D(vl.x, vl.y, fl));
                poly.Add(new Vector3D(vl.x, vl.y, cl));
                poly.Add(new Vector3D(vr.x, vr.y, cr));
                poly.Add(new Vector3D(vr.x, vr.y, fr));

                // Determine initial color
                int        lightlevel     = lightabsolute ? lightvalue : sd.Ceiling.brightnessbelow + lightvalue;
                PixelColor wallbrightness = PixelColor.FromInt(mode.CalculateBrightness(lightlevel));
                PixelColor wallcolor      = PixelColor.Modulate(sd.Ceiling.colorbelow, wallbrightness);
                poly.color = wallcolor.WithAlpha(255).ToInt();

                // Cut off the part above the 3D floor and below the 3D ceiling
                CropPoly(ref poly, extrafloor.Floor.plane, false);
                CropPoly(ref poly, extrafloor.Ceiling.plane, false);

                // Cut out pieces that overlap 3D floors in this sector
                List <WallPolygon> polygons = new List <WallPolygon>(1);
                polygons.Add(poly);
                foreach (Effect3DFloor ef in sd.ExtraFloors)
                {
                    // Same 3D floor and other floors that are not translucent will clip my walls
                    if ((ef.Alpha == 255) || (ef.Linedef.Front.Sector == extrafloor.Linedef.Front.Sector))
                    {
                        int num = polygons.Count;
                        for (int pi = 0; pi < num; pi++)
                        {
                            // Split by floor plane of 3D floor
                            WallPolygon p  = polygons[pi];
                            WallPolygon np = SplitPoly(ref p, ef.Ceiling.plane, true);

                            if (np.Count > 0)
                            {
                                // Split part below floor by the ceiling plane of 3D floor
                                // and keep only the part below the ceiling (front)
                                SplitPoly(ref np, ef.Floor.plane, true);

                                if (p.Count == 0)
                                {
                                    polygons[pi] = np;
                                }
                                else
                                {
                                    polygons[pi] = p;
                                    polygons.Add(np);
                                }
                            }
                            else
                            {
                                polygons[pi] = p;
                            }
                        }
                    }
                }

                // Process the polygon and create vertices
                List <WorldVertex> verts = CreatePolygonVertices(polygons, tp, sd, lightvalue, lightabsolute);
                if (verts.Count > 0)
                {
                    if (extrafloor.Alpha < 255)
                    {
                        // Apply alpha to vertices
                        byte alpha = (byte)General.Clamp(extrafloor.Alpha, 0, 255);
                        if (alpha < 255)
                        {
                            for (int i = 0; i < verts.Count; i++)
                            {
                                WorldVertex v = verts[i];
                                PixelColor  c = PixelColor.FromInt(v.c);
                                v.c      = c.WithAlpha(alpha).ToInt();
                                verts[i] = v;
                            }
                        }

                        this.RenderPass = RenderPass.Alpha;
                    }
                    else
                    {
                        this.RenderPass = RenderPass.Mask;
                    }

                    base.SetVertices(verts);
                    return(true);
                }
            }

            return(false);
        }
        public bool Setup(Effect3DFloor extrafloor)
        {
            Sidedef sourceside = extrafloor.Linedef.Front;

            this.extrafloor = extrafloor;

            //mxd. Extrafloor may've become invalid during undo/redo...
            if (sourceside == null)
            {
                base.SetVertices(null);
                return(false);
            }

            Vector2D vl, vr;

            //mxd. lightfog flag support
            int  lightvalue;
            bool lightabsolute;

            GetLightValue(out lightvalue, out lightabsolute);

            Vector2D tscale = new Vector2D(sourceside.Fields.GetValue("scalex_mid", 1.0f),
                                           sourceside.Fields.GetValue("scaley_mid", 1.0f));
            Vector2D tscaleAbs = new Vector2D(Math.Abs(tscale.x), Math.Abs(tscale.y));
            Vector2D toffset1  = new Vector2D(Sidedef.Fields.GetValue("offsetx_mid", 0.0f),
                                              Sidedef.Fields.GetValue("offsety_mid", 0.0f));
            Vector2D toffset2 = new Vector2D(sourceside.Fields.GetValue("offsetx_mid", 0.0f),
                                             sourceside.Fields.GetValue("offsety_mid", 0.0f));

            // Left and right vertices for this sidedef
            if (Sidedef.IsFront)
            {
                vl = new Vector2D(Sidedef.Line.Start.Position.x, Sidedef.Line.Start.Position.y);
                vr = new Vector2D(Sidedef.Line.End.Position.x, Sidedef.Line.End.Position.y);
            }
            else
            {
                vl = new Vector2D(Sidedef.Line.End.Position.x, Sidedef.Line.End.Position.y);
                vr = new Vector2D(Sidedef.Line.Start.Position.x, Sidedef.Line.Start.Position.y);
            }

            // Load sector data
            SectorData sd = mode.GetSectorData(Sidedef.Sector);

            //mxd. which texture we must use?
            long texturelong = 0;

            if ((sourceside.Line.Args[2] & (int)Effect3DFloor.Flags.UseUpperTexture) != 0)
            {
                if (Sidedef.LongHighTexture != MapSet.EmptyLongName)
                {
                    texturelong = Sidedef.LongHighTexture;
                }
            }
            else if ((sourceside.Line.Args[2] & (int)Effect3DFloor.Flags.UseLowerTexture) != 0)
            {
                if (Sidedef.LongLowTexture != MapSet.EmptyLongName)
                {
                    texturelong = Sidedef.LongLowTexture;
                }
            }
            else if (sourceside.LongMiddleTexture != MapSet.EmptyLongName)
            {
                texturelong = sourceside.LongMiddleTexture;
            }

            // Texture given?
            if (texturelong != 0)
            {
                // Load texture
                base.Texture = General.Map.Data.GetTextureImage(texturelong);
                if (base.Texture == null || base.Texture is UnknownImage)
                {
                    base.Texture         = General.Map.Data.UnknownTexture3D;
                    setuponloadedtexture = texturelong;
                }
                else if (!base.Texture.IsImageLoaded)
                {
                    setuponloadedtexture = texturelong;
                }
            }
            else
            {
                // Use missing texture
                base.Texture         = General.Map.Data.MissingTexture3D;
                setuponloadedtexture = 0;
            }

            // Get texture scaled size
            Vector2D tsz = new Vector2D(base.Texture.ScaledWidth, base.Texture.ScaledHeight);

            tsz = tsz / tscale;

            // Get texture offsets
            Vector2D tof = new Vector2D(Sidedef.OffsetX, Sidedef.OffsetY) + new Vector2D(sourceside.OffsetX, sourceside.OffsetY);

            tof = tof + toffset1 + toffset2;
            tof = tof / tscaleAbs;
            if (General.Map.Config.ScaledTextureOffsets && !base.Texture.WorldPanning)
            {
                tof = tof * base.Texture.Scale;
            }

            // For Vavoom type 3D floors the ceiling is lower than floor and they are reversed.
            // We choose here.
            float sourcetopheight    = extrafloor.VavoomType ? sourceside.Sector.FloorHeight : sourceside.Sector.CeilHeight;
            float sourcebottomheight = extrafloor.VavoomType ? sourceside.Sector.CeilHeight : sourceside.Sector.FloorHeight;

            // Determine texture coordinates plane as they would be in normal circumstances.
            // We can then use this plane to find any texture coordinate we need.
            // The logic here is the same as in the original VisualMiddleSingle (except that
            // the values are stored in a TexturePlane)
            // NOTE: I use a small bias for the floor height, because if the difference in
            // height is 0 then the TexturePlane doesn't work!
            TexturePlane tp        = new TexturePlane();
            float        floorbias = (sourcetopheight == sourcebottomheight) ? 1.0f : 0.0f;

            tp.trb.x = tp.tlt.x + (float)Math.Round(Sidedef.Line.Length);             //mxd. (G)ZDoom snaps texture coordinates to integral linedef length
            tp.trb.y = tp.tlt.y + (sourcetopheight - sourcebottomheight) + floorbias;

            // Apply texture offset
            tp.tlt += tof;
            tp.trb += tof;

            // Transform pixel coordinates to texture coordinates
            tp.tlt /= tsz;
            tp.trb /= tsz;

            // Left top and right bottom of the geometry that
            tp.vlt = new Vector3D(vl.x, vl.y, sourcetopheight);
            tp.vrb = new Vector3D(vr.x, vr.y, sourcebottomheight + floorbias);

            // Make the right-top coordinates
            tp.trt = new Vector2D(tp.trb.x, tp.tlt.y);
            tp.vrt = new Vector3D(tp.vrb.x, tp.vrb.y, tp.vlt.z);

            //mxd. Get ceiling and floor heights. Use our and neighbour sector's data
            SectorData sdo = mode.GetSectorData(Sidedef.Other.Sector);

            float flo = sdo.Floor.plane.GetZ(vl);
            float fro = sdo.Floor.plane.GetZ(vr);
            float clo = sdo.Ceiling.plane.GetZ(vl);
            float cro = sdo.Ceiling.plane.GetZ(vr);

            float fle = sd.Floor.plane.GetZ(vl);
            float fre = sd.Floor.plane.GetZ(vr);
            float cle = sd.Ceiling.plane.GetZ(vl);
            float cre = sd.Ceiling.plane.GetZ(vr);

            float fl = flo > fle ? flo : fle;
            float fr = fro > fre ? fro : fre;
            float cl = clo < cle ? clo : cle;
            float cr = cro < cre ? cro : cre;

            // Anything to see?
            if (((cl - fl) > 0.01f) || ((cr - fr) > 0.01f))
            {
                // Keep top and bottom planes for intersection testing
                top    = extrafloor.Floor.plane;
                bottom = extrafloor.Ceiling.plane;

                // Create initial polygon, which is just a quad between floor and ceiling
                WallPolygon poly = new WallPolygon();
                poly.Add(new Vector3D(vl.x, vl.y, fl));
                poly.Add(new Vector3D(vl.x, vl.y, cl));
                poly.Add(new Vector3D(vr.x, vr.y, cr));
                poly.Add(new Vector3D(vr.x, vr.y, fr));

                // Determine initial color
                int lightlevel = lightabsolute ? lightvalue : sd.Ceiling.brightnessbelow + lightvalue;

                //mxd. This calculates light with doom-style wall shading
                PixelColor wallbrightness = PixelColor.FromInt(mode.CalculateBrightness(lightlevel, Sidedef));
                PixelColor wallcolor      = PixelColor.Modulate(sd.Ceiling.colorbelow, wallbrightness);
                fogfactor  = CalculateFogFactor(lightlevel);
                poly.color = wallcolor.WithAlpha(255).ToInt();

                // Cut off the part above the 3D floor and below the 3D ceiling
                CropPoly(ref poly, extrafloor.Floor.plane, false);
                CropPoly(ref poly, extrafloor.Ceiling.plane, false);

                // Cut out pieces that overlap 3D floors in this sector
                List <WallPolygon> polygons = new List <WallPolygon> {
                    poly
                };
                bool translucent = (extrafloor.RenderAdditive || extrafloor.Alpha < 255);
                foreach (Effect3DFloor ef in sd.ExtraFloors)
                {
                    //mxd. Our poly should be clipped when our ond other extrafloors are both solid or both translucent,
                    // or when only our extrafloor is translucent.
                    // Our poly should not be clipped when our extrafloor is translucent and the other one isn't and both have renderinside setting.
                    bool othertranslucent = (ef.RenderAdditive || ef.Alpha < 255);
                    if (translucent && !othertranslucent && !ef.ClipSidedefs)
                    {
                        continue;
                    }
                    if (ef.ClipSidedefs == extrafloor.ClipSidedefs || ef.ClipSidedefs)
                    {
                        //TODO: find out why ef can be not updated at this point
                        //TODO: [this crashed on me once when performing auto-align on myriad of textures on BoA C1M0]
                        if (ef.Floor == null || ef.Ceiling == null)
                        {
                            ef.Update();
                        }

                        int num = polygons.Count;
                        for (int pi = 0; pi < num; pi++)
                        {
                            // Split by floor plane of 3D floor
                            WallPolygon p  = polygons[pi];
                            WallPolygon np = SplitPoly(ref p, ef.Ceiling.plane, true);

                            if (np.Count > 0)
                            {
                                // Split part below floor by the ceiling plane of 3D floor
                                // and keep only the part below the ceiling (front)
                                SplitPoly(ref np, ef.Floor.plane, true);

                                if (p.Count == 0)
                                {
                                    polygons[pi] = np;
                                }
                                else
                                {
                                    polygons[pi] = p;
                                    polygons.Add(np);
                                }
                            }
                            else
                            {
                                polygons[pi] = p;
                            }
                        }
                    }
                }

                // Process the polygon and create vertices
                if (polygons.Count > 0)
                {
                    List <WorldVertex> verts = CreatePolygonVertices(polygons, tp, sd, lightvalue, lightabsolute);
                    if (verts.Count > 2)
                    {
                        if (extrafloor.Sloped3dFloor)
                        {
                            this.RenderPass = RenderPass.Mask;                                                   //mxd
                        }
                        else if (extrafloor.RenderAdditive)
                        {
                            this.RenderPass = RenderPass.Additive;                                                         //mxd
                        }
                        else if ((extrafloor.Alpha < 255) || Texture.IsTranslucent)
                        {
                            this.RenderPass = RenderPass.Alpha;                                                                                 // [ZZ] translucent texture should trigger Alpha pass
                        }
                        else
                        {
                            this.RenderPass = RenderPass.Mask;
                        }

                        if (extrafloor.Alpha < 255)
                        {
                            // Apply alpha to vertices
                            byte alpha = (byte)General.Clamp(extrafloor.Alpha, 0, 255);
                            if (alpha < 255)
                            {
                                for (int i = 0; i < verts.Count; i++)
                                {
                                    WorldVertex v = verts[i];
                                    v.c      = PixelColor.FromInt(v.c).WithAlpha(alpha).ToInt();
                                    verts[i] = v;
                                }
                            }
                        }

                        base.SetVertices(verts);
                        return(true);
                    }
                }
            }

            base.SetVertices(null);             //mxd
            return(false);
        }
Пример #20
0
        // This builds the geometry. Returns false when no geometry created.
        public override bool Setup()
        {
            Vector2D vl, vr;

            //mxd. Apply sky hack?
            UpdateSkyRenderFlag();

            //mxd. lightfog flag support
            int  lightvalue;
            bool lightabsolute;

            GetLightValue(out lightvalue, out lightabsolute);

            Vector2D tscale = new Vector2D(Sidedef.Fields.GetValue("scalex_mid", 1.0f),
                                           Sidedef.Fields.GetValue("scaley_mid", 1.0f));
            Vector2D toffset = new Vector2D(Sidedef.Fields.GetValue("offsetx_mid", 0.0f),
                                            Sidedef.Fields.GetValue("offsety_mid", 0.0f));

            // Left and right vertices for this sidedef
            if (Sidedef.IsFront)
            {
                vl = new Vector2D(Sidedef.Line.Start.Position.x, Sidedef.Line.Start.Position.y);
                vr = new Vector2D(Sidedef.Line.End.Position.x, Sidedef.Line.End.Position.y);
            }
            else
            {
                vl = new Vector2D(Sidedef.Line.End.Position.x, Sidedef.Line.End.Position.y);
                vr = new Vector2D(Sidedef.Line.Start.Position.x, Sidedef.Line.Start.Position.y);
            }

            // Load sector data
            SectorData sd = mode.GetSectorData(Sidedef.Sector);

            // Texture given?
            if (Sidedef.LongMiddleTexture != MapSet.EmptyLongName)
            {
                // Load texture
                base.Texture = General.Map.Data.GetTextureImage(Sidedef.LongMiddleTexture);
                if (base.Texture == null || base.Texture is UnknownImage)
                {
                    base.Texture         = General.Map.Data.UnknownTexture3D;
                    setuponloadedtexture = Sidedef.LongMiddleTexture;
                }
                else
                {
                    if (!base.Texture.IsImageLoaded)
                    {
                        setuponloadedtexture = Sidedef.LongMiddleTexture;
                    }
                }
            }
            else
            {
                // Use missing texture
                base.Texture         = General.Map.Data.MissingTexture3D;
                setuponloadedtexture = 0;
            }

            // Get texture scaled size
            Vector2D tsz = new Vector2D(base.Texture.ScaledWidth, base.Texture.ScaledHeight);

            tsz = tsz / tscale;

            // Get texture offsets
            Vector2D tof = new Vector2D(Sidedef.OffsetX, Sidedef.OffsetY);

            tof = tof + toffset;
            tof = tof / tscale;
            if (General.Map.Config.ScaledTextureOffsets && !base.Texture.WorldPanning)
            {
                tof = tof * base.Texture.Scale;
            }

            // Determine texture coordinates plane as they would be in normal circumstances.
            // We can then use this plane to find any texture coordinate we need.
            // The logic here is the same as in the original VisualMiddleSingle (except that
            // the values are stored in a TexturePlane)
            // NOTE: I use a small bias for the floor height, because if the difference in
            // height is 0 then the TexturePlane doesn't work!
            TexturePlane tp        = new TexturePlane();
            float        floorbias = (Sidedef.Sector.CeilHeight == Sidedef.Sector.FloorHeight) ? 1.0f : 0.0f;

            if (Sidedef.Line.IsFlagSet(General.Map.Config.LowerUnpeggedFlag))
            {
                // When lower unpegged is set, the middle texture is bound to the bottom
                tp.tlt.y = tsz.y - (Sidedef.Sector.CeilHeight - Sidedef.Sector.FloorHeight);
            }
            tp.trb.x = tp.tlt.x + (float)Math.Round(Sidedef.Line.Length);             //mxd. (G)ZDoom snaps texture coordinates to integral linedef length
            tp.trb.y = tp.tlt.y + (Sidedef.Sector.CeilHeight - (Sidedef.Sector.FloorHeight + floorbias));

            // Apply texture offset
            tp.tlt += tof;
            tp.trb += tof;

            // Transform pixel coordinates to texture coordinates
            tp.tlt /= tsz;
            tp.trb /= tsz;

            // Left top and right bottom of the geometry that
            tp.vlt = new Vector3D(vl.x, vl.y, Sidedef.Sector.CeilHeight);
            tp.vrb = new Vector3D(vr.x, vr.y, Sidedef.Sector.FloorHeight + floorbias);

            // Make the right-top coordinates
            tp.trt = new Vector2D(tp.trb.x, tp.tlt.y);
            tp.vrt = new Vector3D(tp.vrb.x, tp.vrb.y, tp.vlt.z);

            // Get ceiling and floor heights
            float fl = sd.Floor.plane.GetZ(vl);
            float fr = sd.Floor.plane.GetZ(vr);
            float cl = sd.Ceiling.plane.GetZ(vl);
            float cr = sd.Ceiling.plane.GetZ(vr);

            // Anything to see?
            if (((cl - fl) > 0.01f) || ((cr - fr) > 0.01f))
            {
                // Keep top and bottom planes for intersection testing
                top    = sd.Ceiling.plane;
                bottom = sd.Floor.plane;

                // Create initial polygon, which is just a quad between floor and ceiling
                WallPolygon poly = new WallPolygon();
                poly.Add(new Vector3D(vl.x, vl.y, fl));
                poly.Add(new Vector3D(vl.x, vl.y, cl));
                poly.Add(new Vector3D(vr.x, vr.y, cr));
                poly.Add(new Vector3D(vr.x, vr.y, fr));

                // Determine initial color
                int lightlevel = lightabsolute ? lightvalue : sd.Ceiling.brightnessbelow + lightvalue;

                //mxd. This calculates light with doom-style wall shading
                PixelColor wallbrightness = PixelColor.FromInt(mode.CalculateBrightness(lightlevel, Sidedef));
                PixelColor wallcolor      = PixelColor.Modulate(sd.Ceiling.colorbelow, wallbrightness);
                fogfactor  = CalculateFogFactor(lightlevel);
                poly.color = wallcolor.WithAlpha(255).ToInt();

                // Cut out pieces that overlap 3D floors in this sector
                List <WallPolygon> polygons = new List <WallPolygon> {
                    poly
                };
                ClipExtraFloors(polygons, sd.ExtraFloors, false);                 //mxd

                if (polygons.Count > 0)
                {
                    // Process the polygon and create vertices
                    List <WorldVertex> verts = CreatePolygonVertices(polygons, tp, sd, lightvalue, lightabsolute);
                    if (verts.Count > 2)
                    {
                        base.SetVertices(verts);
                        return(true);
                    }
                }
            }

            base.SetVertices(null);             //mxd
            return(false);
        }
Пример #21
0
        // This builds the thing geometry. Returns false when nothing was created.
        public bool Setup()
        {
            // Find the sector in which the thing resides
            Thing.DetermineSector(mode.BlockMap);

            //mxd. If the thing is inside a sector, apply DECORATE/UDMF alpha/renderstyle overrides
            byte alpha = 255;

            if (Thing.Sector != null)
            {
                string renderstyle = info.RenderStyle.ToLowerInvariant();
                alpha = info.AlphaByte;

                if (General.Map.UDMF)
                {
                    if (Thing.IsFlagSet("translucent"))
                    {
                        renderstyle = "translucent";
                        alpha       = 64;
                    }
                    else if (Thing.IsFlagSet("invisible"))
                    {
                        renderstyle = "none";
                        alpha       = 0;
                    }
                    else if (Thing.Fields.ContainsKey("renderstyle"))
                    {
                        renderstyle = Thing.Fields.GetValue("renderstyle", renderstyle).ToLowerInvariant();
                    }

                    if ((renderstyle == "add" || renderstyle == "translucent" || renderstyle == "subtract" || renderstyle == "translucentstencil") &&
                        Thing.Fields.ContainsKey("alpha"))
                    {
                        alpha = (byte)(General.Clamp(Thing.Fields.GetValue("alpha", info.Alpha), 0.0, 1.0) * 255.0);
                    }
                    else if (renderstyle == "soultrans")
                    {
                        // Lost Soul trasparency is controlled by a CVAR (see https://zdoom.org/wiki/CVARs:Display#transsouls), let's use the default 0.75 here
                        alpha = 192;
                    }
                    else if (renderstyle == "shadow")
                    {
                        alpha        = 76;                  // about 0.3
                        stencilColor = PixelColor.FromInt(PixelColor.INT_BLACK);
                    }

                    if (renderstyle.EndsWith("stencil"))
                    {
                        stencilColor   = PixelColor.FromInt(UniFields.GetInteger(Thing.Fields, "fillcolor", 0));
                        stencilColor.a = 255; // 0xFF alpha means nothing was read. 0x00 alpha means there was a valid fillcolor.
                    }
                    else if (renderstyle != "shadow")
                    {
                        stencilColor.a = 0;
                    }
                }
                else if (General.Map.HEXEN)
                {
                    if (Thing.IsFlagSet("2048"))
                    {
                        renderstyle = "translucent";
                        alpha       = 64;
                    }
                    else if (Thing.IsFlagSet("4096"))
                    {
                        renderstyle = "none";
                        alpha       = 0;
                    }
                }

                // Set appropriate RenderPass
                switch (renderstyle)
                {
                case "translucent":
                case "subtract":
                case "soultrans":
                case "translucentstencil":
                case "shadow":
                    RenderPass = RenderPass.Alpha;
                    break;

                case "add":
                case "addstencil":
                    RenderPass = RenderPass.Additive;
                    break;

                case "none":
                    RenderPass = RenderPass.Mask;
                    alpha      = 0;
                    break;

                // Many render styles are not supported yet...
                default:
                    RenderPass = RenderPass.Mask;
                    alpha      = 255;
                    break;
                }
            }

            int sectorcolor = new PixelColor(alpha, 255, 255, 255).ToInt();

            fogfactor = 0f;             //mxd

            //mxd. Check thing size
            float thingradius = Thing.Size;         // Thing.Size has ThingRadius arg override applied

            thingheight = Thing.Height;             // Thing.Height has ThingHeight arg override applied

            if (thingradius < 0.1f || thingheight < 0.1f)
            {
                thingradius = FIXED_RADIUS;
                thingheight = FIXED_RADIUS;
                sizeless    = true;
            }
            else
            {
                sizeless = false;
            }

            if (Thing.Sector != null)
            {
                SectorData sd    = mode.GetSectorData(Thing.Sector);
                Plane      floor = sd.Floor.plane;            //mxd

                if (!info.Bright)
                {
                    Vector3D    thingpos = new Vector3D(Thing.Position.x, Thing.Position.y, Thing.Position.z + sd.Floor.plane.GetZ(Thing.Position));
                    SectorLevel level    = sd.GetLevelAboveOrAt(thingpos);

                    //mxd. Let's use point on floor plane instead of Thing.Sector.FloorHeight;
                    if (nointeraction && level == null && sd.LightLevels.Count > 0)
                    {
                        level = sd.LightLevels[sd.LightLevels.Count - 1];
                    }

                    //mxd. Use the light level of the highest surface when a thing is above highest sector level.
                    if (level != null)
                    {
                        // TECH: In GZDoom, ceiling glow doesn't affect thing brightness
                        // Use sector brightness for color shading
                        int brightness = level.brightnessbelow;

                        //mxd. Apply lightfloor value
                        // According to Graf, this is incorrect behaviour...
                        // TECH: In (G)ZDoom, this is ignored when ceiling texture is sky or a thing is below a 3D floor
                        // It's probably more involved than this, but for now let's do it only when there are no 3d floors in Thing.Sector...

                        /*if(General.Map.UDMF && sd.LightLevels.Count == 2 && Thing.Sector.CeilTexture != General.Map.Config.SkyFlatName)
                         * {
                         *      if(sd.Sector.Fields.GetValue("lightfloorabsolute", false))
                         *              brightness = UniFields.GetInteger(sd.Sector.Fields, "lightfloor");
                         *      else
                         *              brightness += UniFields.GetInteger(sd.Sector.Fields, "lightfloor");
                         * }*/

                        // Level is glowing
                        if (level.affectedbyglow && level.type == SectorLevelType.Floor)
                        {
                            // Extrafloor glow doesn't affect thing brightness
                            if (level.sector == Thing.Sector)
                            {
                                double planez = level.plane.GetZ(thingpos);

                                // Get glow brightness
                                int         glowbrightness = sd.FloorGlow.Brightness / 2;
                                SectorLevel nexthigher     = sd.GetLevelAbove(new Vector3D(thingpos, planez));

                                // Interpolate thing brightness between glow and regular ones
                                if (nexthigher != null)
                                {
                                    double higherz = nexthigher.plane.GetZ(thingpos);
                                    double delta   = General.Clamp(1.0f - (thingpos.z - planez) / (higherz - planez), 0f, 1f);
                                    brightness = (int)((glowbrightness + level.sector.Brightness / 2) * delta + nexthigher.sector.Brightness * (1.0f - delta));
                                }
                            }
                        }
                        // Level below this one is glowing. Only possible for floor glow(?)
                        else if (level.type == SectorLevelType.Glow)
                        {
                            // Interpolate thing brightness between glow and regular ones
                            if (sd.Floor != null && sd.FloorGlow != null)
                            {
                                // Get glow brightness
                                double glowz  = level.plane.GetZ(thingpos);
                                double floorz = floor.GetZ(thingpos);
                                double delta  = General.Clamp((thingpos.z - floorz) / (glowz - floorz), 0f, 1f);

                                brightness = (int)((sd.FloorGlow.Brightness / 2 + sd.Floor.sector.Brightness / 2) * (1.0f - delta) + sd.Floor.sector.Brightness * delta);
                            }
                        }

                        PixelColor areabrightness = PixelColor.FromInt(mode.CalculateBrightness(brightness));
                        PixelColor areacolor      = PixelColor.Modulate(level.colorbelow, areabrightness);

                        // [ZZ] if sector is using Doom64 lighting, apply thing color here.
                        sectorcolor = PixelColor.Modulate(sd.ColorSprites, areacolor).WithAlpha(alpha).ToInt();

                        //mxd. Calculate fogfactor
                        fogfactor = VisualGeometry.CalculateFogFactor(level.sector, brightness);
                    }
                }
                //TECH: even Bright Thing frames are affected by custom fade...
                else
                {
                    Vector3D    thingpos = new Vector3D(Thing.Position.x, Thing.Position.y, Thing.Position.z + sd.Floor.plane.GetZ(Thing.Position));
                    SectorLevel level    = sd.GetLevelAboveOrAt(thingpos);

                    if (level != null && level.sector.FogMode > SectorFogMode.CLASSIC)
                    {
                        //mxd. Calculate fogfactor
                        fogfactor = VisualGeometry.CalculateFogFactor(level.sector, level.brightnessbelow);
                    }
                }
            }

            //mxd. Create verts for all sprite angles
            WorldVertex[][] allverts   = new WorldVertex[info.SpriteFrame.Length][];
            Vector2D[]      alloffsets = new Vector2D[info.SpriteFrame.Length];
            base.textures = new ImageData[info.SpriteFrame.Length];
            isloaded      = true;

            for (int i = 0; i < sprites.Length; i++)
            {
                Vector2D offsets = new Vector2D();

                // Check if the texture is loaded
                ImageData sprite = sprites[i];
                if (!sprite.IsImageLoaded && !sprite.LoadFailed)
                {
                    sprite.LoadImageNow();
                }
                if (sprite.IsImageLoaded)
                {
                    base.textures[i] = sprite;

                    // Determine sprite size and offset
                    float        radius    = sprite.ScaledWidth * 0.5f;
                    float        height    = sprite.ScaledHeight;
                    ISpriteImage spriteimg = sprite as ISpriteImage;
                    if (spriteimg != null)
                    {
                        offsets.x = radius - spriteimg.OffsetX;
                        offsets.y = spriteimg.OffsetY - height;
                    }

                    // Scale by thing type/actor scale
                    // We do this after the offset x/y determination above, because that is entirely in sprite pixels space
                    radius    *= info.SpriteScale.Width;
                    height    *= info.SpriteScale.Height;
                    offsets.x *= info.SpriteScale.Width;
                    offsets.y *= info.SpriteScale.Height;

                    // Make vertices
                    WorldVertex[] verts = new WorldVertex[6];

                    //mxd. Sprite mirroring
                    float ul = (info.SpriteFrame[i].Mirror ? 1f : 0f);
                    float ur = (info.SpriteFrame[i].Mirror ? 0f : 1f);

                    if (sizeless)                    //mxd
                    {
                        float hh = height / 2;
                        verts[0] = new WorldVertex((float)(-radius + offsets.x), 0.0f, (float)(offsets.y - hh), sectorcolor, ul, 1.0f);
                        verts[1] = new WorldVertex((float)(-radius + offsets.x), 0.0f, (float)(hh + offsets.y), sectorcolor, ul, 0.0f);
                        verts[2] = new WorldVertex((float)(+radius + offsets.x), 0.0f, (float)(hh + offsets.y), sectorcolor, ur, 0.0f);
                        verts[3] = verts[0];
                        verts[4] = verts[2];
                        verts[5] = new WorldVertex((float)(+radius + offsets.x), 0.0f, (float)(offsets.y - hh), sectorcolor, ur, 1.0f);
                    }
                    else
                    {
                        verts[0] = new WorldVertex((float)(-radius + offsets.x), 0.0f, (float)offsets.y, sectorcolor, ul, 1.0f);
                        verts[1] = new WorldVertex((float)(-radius + offsets.x), 0.0f, (float)(height + offsets.y), sectorcolor, ul, 0.0f);
                        verts[2] = new WorldVertex((float)(+radius + offsets.x), 0.0f, (float)(height + offsets.y), sectorcolor, ur, 0.0f);
                        verts[3] = verts[0];
                        verts[4] = verts[2];
                        verts[5] = new WorldVertex((float)(+radius + offsets.x), 0.0f, (float)offsets.y, sectorcolor, ur, 1.0f);
                    }
                    allverts[i] = verts;
                }
                else
                {
                    isloaded         = false;
                    base.textures[i] = sprite;

                    // Determine sprite size
                    float radius = Math.Min(thingradius, thingheight / 2f);
                    float height = Math.Min(thingradius * 2f, thingheight);

                    //mxd. Determine sprite offsets
                    offsets.x = radius;
                    offsets.y = height / 2;

                    // Make vertices
                    WorldVertex[] verts = new WorldVertex[6];
                    verts[0]    = new WorldVertex(-radius, 0.0f, 0.0f, sectorcolor, 0.0f, 1.0f);
                    verts[1]    = new WorldVertex(-radius, 0.0f, height, sectorcolor, 0.0f, 0.0f);
                    verts[2]    = new WorldVertex(+radius, 0.0f, height, sectorcolor, 1.0f, 0.0f);
                    verts[3]    = verts[0];
                    verts[4]    = verts[2];
                    verts[5]    = new WorldVertex(+radius, 0.0f, 0.0f, sectorcolor, 1.0f, 1.0f);
                    allverts[i] = verts;
                }

                //mxd. Store offsets
                alloffsets[i] = offsets;
            }

            //mxd
            SetVertices(allverts, alloffsets /*, floor, ceiling*/);

            // Determine position
            Vector3D pos = Thing.Position;

            if (Thing.Type == 9501)
            {
                if (Thing.Sector != null)                //mxd
                {
                    // This is a special thing that needs special positioning
                    SectorData sd = mode.GetSectorData(Thing.Sector);
                    pos.z = sd.Ceiling.sector.CeilHeight + Thing.Position.z;
                }
            }
            else if (Thing.Type == 9500)
            {
                if (Thing.Sector != null)                //mxd
                {
                    // This is a special thing that needs special positioning
                    SectorData sd = mode.GetSectorData(Thing.Sector);
                    pos.z = sd.Floor.sector.FloorHeight + Thing.Position.z;
                }
            }
            else if (info.AbsoluteZ)
            {
                // Absolute Z position
                pos.z = Thing.Position.z;
            }
            else if (info.Hangs)
            {
                // Hang from ceiling
                if (Thing.Sector != null)
                {
                    SectorData sd   = mode.GetSectorData(Thing.Sector);
                    double     maxz = sd.Ceiling.plane.GetZ(Thing.Position) - info.Height;
                    pos.z = maxz;

                    if (Thing.Position.z > 0 || nointeraction)
                    {
                        pos.z -= Thing.Position.z;
                    }

                    // Check if below floor
                    if (!nointeraction)
                    {
                        double minz = sd.Floor.plane.GetZ(Thing.Position);
                        if (pos.z < minz)
                        {
                            pos.z = Math.Min(minz, maxz);
                        }
                    }
                }
            }
            else
            {
                // Stand on floor
                if (Thing.Sector != null)
                {
                    SectorData sd   = mode.GetSectorData(Thing.Sector);
                    double     minz = sd.Floor.plane.GetZ(Thing.Position);
                    pos.z = minz;

                    if (Thing.Position.z > 0 || nointeraction)
                    {
                        pos.z += Thing.Position.z;
                    }

                    // Check if above ceiling
                    if (!nointeraction)
                    {
                        double maxz = sd.Ceiling.plane.GetZ(Thing.Position) - info.Height;
                        if (pos.z > maxz)
                        {
                            pos.z = Math.Max(minz, maxz);
                        }
                    }
                }
            }

            // Apply settings
            SetPosition(pos);
            SetCageColor(Thing.Color);

            // Keep info for object picking
            cageradius2 = thingradius * Angle2D.SQRT2;
            cageradius2 = cageradius2 * cageradius2;
            pos2d       = pos;

            if (sizeless)            //mxd
            {
                boxp1 = new Vector3D(pos.x - thingradius, pos.y - thingradius, pos.z - thingradius / 2);
                boxp2 = new Vector3D(pos.x + thingradius, pos.y + thingradius, pos.z + thingradius / 2);
            }
            else
            {
                boxp1 = new Vector3D(pos.x - thingradius, pos.y - thingradius, pos.z);
                boxp2 = new Vector3D(pos.x + thingradius, pos.y + thingradius, pos.z + thingheight);
            }

            // Done
            changed = false;
            return(true);
        }
Пример #22
0
        // Constructor
        internal ConfigurationInfo(Configuration cfg, string filename)
        {
            // Initialize
            this.filename    = filename;
            this.config      = cfg;        //mxd
            this.settingskey = Path.GetFileNameWithoutExtension(filename).ToLower();

            // Load settings from game configuration
            this.name            = config.ReadSetting("game", "<unnamed game>");
            this.defaultlumpname = config.ReadSetting("defaultlumpname", "");

            // Load settings from program configuration
            this.nodebuildersave       = General.Settings.ReadSetting("configurations." + settingskey + ".nodebuildersave", MISSING_NODEBUILDER);
            this.nodebuildertest       = General.Settings.ReadSetting("configurations." + settingskey + ".nodebuildertest", MISSING_NODEBUILDER);
            this.formatinterface       = config.ReadSetting("formatinterface", "").ToLowerInvariant(); //mxd
            this.defaultscriptcompiler = cfg.ReadSetting("defaultscriptcompiler", "");                 //mxd
            this.resources             = new DataLocationList(General.Settings.Config, "configurations." + settingskey + ".resources");
            this.startmode             = General.Settings.ReadSetting("configurations." + settingskey + ".startmode", "VerticesMode");
            this.enabled = General.Settings.ReadSetting("configurations." + settingskey + ".enabled", config.ReadSetting("enabledbydefault", false));             //mxd

            //mxd. Read test engines
            testEngines = new List <EngineInfo>();
            IDictionary list = General.Settings.ReadSetting("configurations." + settingskey + ".engines", new ListDictionary());

            currentEngineIndex = Math.Max(0, General.Settings.ReadSetting("configurations." + settingskey + ".currentengineindex", 0));

            // No engine list found? Use old engine properties
            if (list.Count == 0)
            {
                EngineInfo info = new EngineInfo();
                info.TestProgram      = General.Settings.ReadSetting("configurations." + settingskey + ".testprogram", "");
                info.TestProgramName  = General.Settings.ReadSetting("configurations." + settingskey + ".testprogramname", EngineInfo.DEFAULT_ENGINE_NAME);
                info.TestParameters   = General.Settings.ReadSetting("configurations." + settingskey + ".testparameters", "");
                info.TestShortPaths   = General.Settings.ReadSetting("configurations." + settingskey + ".testshortpaths", false);
                info.CustomParameters = General.Settings.ReadSetting("configurations." + settingskey + ".customparameters", false);
                info.TestSkill        = General.Settings.ReadSetting("configurations." + settingskey + ".testskill", 3);
                testEngines.Add(info);
                currentEngineIndex = 0;
            }
            else
            {
                //read engines settings from config
                foreach (DictionaryEntry de in list)
                {
                    string     path = "configurations." + settingskey + ".engines." + de.Key;
                    EngineInfo info = new EngineInfo();
                    info.TestProgram      = General.Settings.ReadSetting(path + ".testprogram", "");
                    info.TestProgramName  = General.Settings.ReadSetting(path + ".testprogramname", EngineInfo.DEFAULT_ENGINE_NAME);
                    info.TestParameters   = General.Settings.ReadSetting(path + ".testparameters", "");
                    info.TestShortPaths   = General.Settings.ReadSetting(path + ".testshortpaths", false);
                    info.CustomParameters = General.Settings.ReadSetting(path + ".customparameters", false);
                    info.TestSkill        = General.Settings.ReadSetting(path + ".testskill", 3);
                    testEngines.Add(info);
                }

                if (currentEngineIndex >= testEngines.Count)
                {
                    currentEngineIndex = 0;
                }
            }

            //mxd. read custom linedef colors
            List <LinedefColorPreset> colorPresets = new List <LinedefColorPreset>();

            list = General.Settings.ReadSetting("configurations." + settingskey + ".linedefcolorpresets", new ListDictionary());

            //no presets? add "classic" ones then.
            if (list.Count == 0)
            {
                colorPresets.Add(new LinedefColorPreset("Any action", PixelColor.FromColor(System.Drawing.Color.PaleGreen), -1, 0, new List <string>(), new List <string>(), true));
            }
            else
            {
                //read custom linedef colors from config
                foreach (DictionaryEntry de in list)
                {
                    string        path          = "configurations." + settingskey + ".linedefcolorpresets." + de.Key;
                    string        presetname    = General.Settings.ReadSetting(path + ".name", "Unnamed");
                    bool          presetenabled = General.Settings.ReadSetting(path + ".enabled", true);
                    PixelColor    color         = PixelColor.FromInt(General.Settings.ReadSetting(path + ".color", -1));
                    int           action        = General.Settings.ReadSetting(path + ".action", 0);
                    int           activation    = General.Settings.ReadSetting(path + ".activation", 0);
                    List <string> flags         = new List <string>();
                    flags.AddRange(General.Settings.ReadSetting(path + ".flags", "").Split(LINEDEF_COLOR_PRESET_FLAGS_SEPARATOR, StringSplitOptions.RemoveEmptyEntries));
                    List <string> restrictedFlags = new List <string>();
                    restrictedFlags.AddRange(General.Settings.ReadSetting(path + ".restrictedflags", "").Split(LINEDEF_COLOR_PRESET_FLAGS_SEPARATOR, StringSplitOptions.RemoveEmptyEntries));
                    LinedefColorPreset preset = new LinedefColorPreset(presetname, color, action, activation, flags, restrictedFlags, presetenabled);
                    colorPresets.Add(preset);
                }
            }
            linedefColorPresets = colorPresets.ToArray();

            // Make list of things filters
            thingsfilters = new List <ThingsFilter>();
            IDictionary cfgfilters = General.Settings.ReadSetting("configurations." + settingskey + ".thingsfilters", new Hashtable());

            foreach (DictionaryEntry de in cfgfilters)
            {
                thingsfilters.Add(new ThingsFilter(General.Settings.Config, "configurations." + settingskey + ".thingsfilters." + de.Key));
            }

            // Make list of texture sets
            texturesets = new List <DefinedTextureSet>();
            IDictionary sets = General.Settings.ReadSetting("configurations." + settingskey + ".texturesets", new Hashtable());

            foreach (DictionaryEntry de in sets)
            {
                texturesets.Add(new DefinedTextureSet(General.Settings.Config, "configurations." + settingskey + ".texturesets." + de.Key));
            }

            // Make list of edit modes
            this.editmodes = new Dictionary <string, bool>(StringComparer.Ordinal);
            IDictionary modes = General.Settings.ReadSetting("configurations." + settingskey + ".editmodes", new Hashtable());

            foreach (DictionaryEntry de in modes)
            {
                if (de.Key.ToString().StartsWith(MODE_ENABLED_KEY))
                {
                    editmodes.Add(de.Value.ToString(), true);
                }
                else if (de.Key.ToString().StartsWith(MODE_DISABLED_KEY))
                {
                    editmodes.Add(de.Value.ToString(), false);
                }
            }
        }
        // This builds the geometry. Returns false when no geometry created.
        public override bool Setup()
        {
            //mxd
            if (Sidedef.LongMiddleTexture == MapSet.EmptyLongName)
            {
                base.SetVertices(null);
                return(false);
            }

            Vector2D vl, vr;

            //mxd. lightfog flag support
            int  lightvalue;
            bool lightabsolute;

            GetLightValue(out lightvalue, out lightabsolute);

            Vector2D tscale = new Vector2D(Sidedef.Fields.GetValue("scalex_mid", 1.0f),
                                           Sidedef.Fields.GetValue("scaley_mid", 1.0f));
            Vector2D tscaleAbs = new Vector2D(Math.Abs(tscale.x), Math.Abs(tscale.y));
            Vector2D toffset   = new Vector2D(Sidedef.Fields.GetValue("offsetx_mid", 0.0f),
                                              Sidedef.Fields.GetValue("offsety_mid", 0.0f));

            // Left and right vertices for this sidedef
            if (Sidedef.IsFront)
            {
                vl = new Vector2D(Sidedef.Line.Start.Position.x, Sidedef.Line.Start.Position.y);
                vr = new Vector2D(Sidedef.Line.End.Position.x, Sidedef.Line.End.Position.y);
            }
            else
            {
                vl = new Vector2D(Sidedef.Line.End.Position.x, Sidedef.Line.End.Position.y);
                vr = new Vector2D(Sidedef.Line.Start.Position.x, Sidedef.Line.Start.Position.y);
            }

            // Load sector data
            SectorData sd  = mode.GetSectorData(Sidedef.Sector);
            SectorData osd = mode.GetSectorData(Sidedef.Other.Sector);

            if (!osd.Updated)
            {
                osd.Update();
            }

            // Load texture
            if (Sidedef.LongMiddleTexture != MapSet.EmptyLongName)
            {
                base.Texture = General.Map.Data.GetTextureImage(Sidedef.LongMiddleTexture);
                if (base.Texture == null || base.Texture is UnknownImage)
                {
                    base.Texture         = General.Map.Data.UnknownTexture3D;
                    setuponloadedtexture = Sidedef.LongMiddleTexture;
                }
                else if (!base.Texture.IsImageLoaded)
                {
                    setuponloadedtexture = Sidedef.LongMiddleTexture;
                }
            }
            else
            {
                // Use missing texture
                base.Texture         = General.Map.Data.MissingTexture3D;
                setuponloadedtexture = 0;
            }

            // Get texture scaled size
            Vector2D tsz = new Vector2D(base.Texture.ScaledWidth, base.Texture.ScaledHeight);

            tsz = tsz / tscale;

            // Get texture offsets
            Vector2D tof = new Vector2D(Sidedef.OffsetX, Sidedef.OffsetY);

            tof = tof + toffset;
            tof = tof / tscaleAbs;
            if (General.Map.Config.ScaledTextureOffsets && !base.Texture.WorldPanning)
            {
                tof = tof * base.Texture.Scale;
            }

            // Determine texture coordinates plane as they would be in normal circumstances.
            // We can then use this plane to find any texture coordinate we need.
            // The logic here is the same as in the original VisualMiddleSingle (except that
            // the values are stored in a TexturePlane)
            // NOTE: I use a small bias for the floor height, because if the difference in
            // height is 0 then the TexturePlane doesn't work!
            TexturePlane tp        = new TexturePlane();
            float        floorbias = (Sidedef.Sector.CeilHeight == Sidedef.Sector.FloorHeight) ? 1.0f : 0.0f;
            float        geotop    = Math.Min(Sidedef.Sector.CeilHeight, Sidedef.Other.Sector.CeilHeight);
            float        geobottom = Math.Max(Sidedef.Sector.FloorHeight, Sidedef.Other.Sector.FloorHeight);
            float        zoffset   = Sidedef.Sector.CeilHeight - Sidedef.Other.Sector.CeilHeight;    //mxd

            // When lower unpegged is set, the middle texture is bound to the bottom
            if (Sidedef.Line.IsFlagSet(General.Map.Config.LowerUnpeggedFlag))
            {
                tp.tlt.y = tsz.y - (geotop - geobottom);
            }

            if (zoffset > 0)
            {
                tp.tlt.y -= zoffset;                                      //mxd
            }
            tp.trb.x = tp.tlt.x + (float)Math.Round(Sidedef.Line.Length); //mxd. (G)ZDoom snaps texture coordinates to integral linedef length
            tp.trb.y = tp.tlt.y + (Sidedef.Sector.CeilHeight - (Sidedef.Sector.FloorHeight + floorbias));

            // Apply texture offset
            tp.tlt += tof;
            tp.trb += tof;

            // Transform pixel coordinates to texture coordinates
            tp.tlt /= tsz;
            tp.trb /= tsz;

            // Left top and right bottom of the geometry that
            tp.vlt = new Vector3D(vl.x, vl.y, Sidedef.Sector.CeilHeight);
            tp.vrb = new Vector3D(vr.x, vr.y, Sidedef.Sector.FloorHeight + floorbias);

            // Make the right-top coordinates
            tp.trt = new Vector2D(tp.trb.x, tp.tlt.y);
            tp.vrt = new Vector3D(tp.vrb.x, tp.vrb.y, tp.vlt.z);

            // Keep top and bottom planes for intersection testing
            top    = sd.Ceiling.plane;
            bottom = sd.Floor.plane;

            // Create initial polygon, which is just a quad between floor and ceiling
            WallPolygon poly = new WallPolygon();

            poly.Add(new Vector3D(vl.x, vl.y, sd.Floor.plane.GetZ(vl)));
            poly.Add(new Vector3D(vl.x, vl.y, sd.Ceiling.plane.GetZ(vl)));
            poly.Add(new Vector3D(vr.x, vr.y, sd.Ceiling.plane.GetZ(vr)));
            poly.Add(new Vector3D(vr.x, vr.y, sd.Floor.plane.GetZ(vr)));

            // Determine initial color
            int lightlevel = lightabsolute ? lightvalue : sd.Ceiling.brightnessbelow + lightvalue;

            //mxd. This calculates light with doom-style wall shading
            PixelColor wallbrightness = PixelColor.FromInt(mode.CalculateBrightness(lightlevel, Sidedef));
            PixelColor wallcolor      = PixelColor.Modulate(sd.Ceiling.colorbelow, wallbrightness);

            fogfactor  = CalculateFogFactor(lightlevel);
            poly.color = wallcolor.WithAlpha(255).ToInt();

            // Cut off the part below the other floor and above the other ceiling
            CropPoly(ref poly, osd.Ceiling.plane, true);
            CropPoly(ref poly, osd.Floor.plane, true);

            // Determine if we should repeat the middle texture
            repeatmidtex = Sidedef.IsFlagSet("wrapmidtex") || Sidedef.Line.IsFlagSet("wrapmidtex");             //mxd
            if (!repeatmidtex)
            {
                // First determine the visible portion of the texture
                float textop;

                // Determine top portion height
                if (Sidedef.Line.IsFlagSet(General.Map.Config.LowerUnpeggedFlag))
                {
                    textop = geobottom + tof.y + Math.Abs(tsz.y);
                }
                else
                {
                    textop = geotop + tof.y;
                }

                // Calculate bottom portion height
                float texbottom = textop - Math.Abs(tsz.y);

                // Create crop planes (we also need these for intersection testing)
                topclipplane    = new Plane(new Vector3D(0, 0, -1), textop);
                bottomclipplane = new Plane(new Vector3D(0, 0, 1), -texbottom);

                // Crop polygon by these heights
                CropPoly(ref poly, topclipplane, true);
                CropPoly(ref poly, bottomclipplane, true);
            }

            //mxd. In(G)ZDoom, middle sidedef parts are not clipped by extrafloors of any type...
            List <WallPolygon> polygons = new List <WallPolygon> {
                poly
            };

            //ClipExtraFloors(polygons, sd.ExtraFloors, true); //mxd
            //ClipExtraFloors(polygons, osd.ExtraFloors, true); //mxd

            //if(polygons.Count > 0)
            //{
            // Keep top and bottom planes for intersection testing
            top    = osd.Ceiling.plane;
            bottom = osd.Floor.plane;

            // Process the polygon and create vertices
            List <WorldVertex> verts = CreatePolygonVertices(polygons, tp, sd, lightvalue, lightabsolute);

            if (verts.Count > 2)
            {
                // Apply alpha to vertices
                byte alpha = SetLinedefRenderstyle(true);
                if (alpha < 255)
                {
                    for (int i = 0; i < verts.Count; i++)
                    {
                        WorldVertex v = verts[i];
                        v.c      = PixelColor.FromInt(v.c).WithAlpha(alpha).ToInt();
                        verts[i] = v;
                    }
                }

                base.SetVertices(verts);
                return(true);
            }
            //}

            base.SetVertices(null);             //mxd
            return(false);
        }
Пример #24
0
        // This sets up the basic floor and ceiling, as they would be in normal Doom circumstances
        private void BasicSetup()
        {
            //mxd
            if (sector.FloorSlope.GetLengthSq() > 0 && !float.IsNaN(sector.FloorSlopeOffset / sector.FloorSlope.z))
            {
                // Sloped plane
                floor.plane = new Plane(sector.FloorSlope, sector.FloorSlopeOffset);
            }
            else
            {
                // Normal (flat) floor plane
                floor.plane = new Plane(new Vector3D(0, 0, 1), -sector.FloorHeight);
            }

            if (sector.CeilSlope.GetLengthSq() > 0 && !float.IsNaN(sector.CeilSlopeOffset / sector.CeilSlope.z))
            {
                // Sloped plane
                ceiling.plane = new Plane(sector.CeilSlope, sector.CeilSlopeOffset);
            }
            else
            {
                // Normal (flat) ceiling plane
                ceiling.plane = new Plane(new Vector3D(0, 0, -1), sector.CeilHeight);
            }

            // Fetch ZDoom fields
            int color = sector.Fields.GetValue("lightcolor", -1);

            lightfloor           = sector.Fields.GetValue("lightfloor", 0);
            lightfloorabsolute   = sector.Fields.GetValue("lightfloorabsolute", false);
            lightceiling         = sector.Fields.GetValue("lightceiling", 0);
            lightceilingabsolute = sector.Fields.GetValue("lightceilingabsolute", false);
            if (!lightfloorabsolute)
            {
                lightfloor = sector.Brightness + lightfloor;
            }
            if (!lightceilingabsolute)
            {
                lightceiling = sector.Brightness + lightceiling;
            }

            // Determine colors & light levels
            // [ZZ] Doom64 lighting
            //
            // ceiling/floor
            ColorCeiling    = PixelColor.FromInt(sector.Fields.GetValue("color_ceiling", PixelColor.INT_WHITE));
            ColorFloor      = PixelColor.FromInt(sector.Fields.GetValue("color_floor", PixelColor.INT_WHITE));
            ColorSprites    = PixelColor.FromInt(sector.Fields.GetValue("color_sprites", PixelColor.INT_WHITE));
            ColorWallTop    = PixelColor.FromInt(sector.Fields.GetValue("color_walltop", PixelColor.INT_WHITE));
            ColorWallBottom = PixelColor.FromInt(sector.Fields.GetValue("color_wallbottom", PixelColor.INT_WHITE));

            PixelColor floorbrightness   = PixelColor.FromInt(mode.CalculateBrightness(lightfloor));
            PixelColor ceilingbrightness = PixelColor.FromInt(mode.CalculateBrightness(lightceiling));
            PixelColor lightcolor        = PixelColor.FromInt(color);
            PixelColor floorcolor        = PixelColor.Modulate(ColorFloor, PixelColor.Modulate(lightcolor, floorbrightness));
            PixelColor ceilingcolor      = PixelColor.Modulate(ColorCeiling, PixelColor.Modulate(lightcolor, ceilingbrightness));

            floor.color             = floorcolor.WithAlpha(255).ToInt();
            floor.brightnessbelow   = sector.Brightness;
            floor.colorbelow        = lightcolor.WithAlpha(255);
            ceiling.color           = ceilingcolor.WithAlpha(255).ToInt();
            ceiling.brightnessbelow = sector.Brightness;
            ceiling.colorbelow      = lightcolor.WithAlpha(255);

            //mxd. Store a copy of initial settings
            floor.CopyProperties(floorbase);
            ceiling.CopyProperties(ceilingbase);

            //mxd. We need sector brightness here, unaffected by custom ceiling brightness...
            ceilingbase.brightnessbelow = sector.Brightness;
            ceilingbase.color           = PixelColor.FromInt(mode.CalculateBrightness(sector.Brightness)).WithAlpha(255).ToInt();

            //mxd
            glowingflateffect.Update();
        }
 private void bReset_Click(object sender, EventArgs e)
 {
     cpColor.Focus();             // Otherwise the focus will go to cpColor's textbox, which is not what we want
     cpColor.Color = PixelColor.FromInt(defaultvalue).WithAlpha(255);
     cpColor_ColorChanged(this, EventArgs.Empty);
 }
Пример #26
0
        // This builds the geometry. Returns false when no geometry created.
        public override bool Setup()
        {
            Vector2D vl, vr;

            int  lightvalue    = Sidedef.Fields.GetValue("light", 0);
            bool lightabsolute = Sidedef.Fields.GetValue("lightabsolute", false);

            Vector2D tscale = new Vector2D(Sidedef.Fields.GetValue("scalex_mid", 1.0f),
                                           Sidedef.Fields.GetValue("scaley_mid", 1.0f));
            Vector2D toffset = new Vector2D(Sidedef.Fields.GetValue("offsetx_mid", 0.0f),
                                            Sidedef.Fields.GetValue("offsety_mid", 0.0f));

            // Texture given?
            if ((Sidedef.MiddleTexture.Length > 0) && (Sidedef.MiddleTexture[0] != '-'))
            {
                // Left and right vertices for this sidedef
                if (Sidedef.IsFront)
                {
                    vl = new Vector2D(Sidedef.Line.Start.Position.x, Sidedef.Line.Start.Position.y);
                    vr = new Vector2D(Sidedef.Line.End.Position.x, Sidedef.Line.End.Position.y);
                }
                else
                {
                    vl = new Vector2D(Sidedef.Line.End.Position.x, Sidedef.Line.End.Position.y);
                    vr = new Vector2D(Sidedef.Line.Start.Position.x, Sidedef.Line.Start.Position.y);
                }

                // Load sector data
                SectorData sd  = mode.GetSectorData(Sidedef.Sector);
                SectorData osd = mode.GetSectorData(Sidedef.Other.Sector);
                if (!osd.Updated)
                {
                    osd.Update();
                }

                // Texture given?
                if ((Sidedef.MiddleTexture.Length > 0) && (Sidedef.MiddleTexture[0] != '-'))
                {
                    // Load texture
                    base.Texture = General.Map.Data.GetTextureImage(Sidedef.LongMiddleTexture);
                    if (base.Texture == null)
                    {
                        base.Texture         = General.Map.Data.MissingTexture3D;
                        setuponloadedtexture = Sidedef.LongMiddleTexture;
                    }
                    else
                    {
                        if (!base.Texture.IsImageLoaded)
                        {
                            setuponloadedtexture = Sidedef.LongMiddleTexture;
                        }
                    }
                }
                else
                {
                    // Use missing texture
                    base.Texture         = General.Map.Data.MissingTexture3D;
                    setuponloadedtexture = 0;
                }

                // Get texture scaled size
                Vector2D tsz = new Vector2D(base.Texture.ScaledWidth, base.Texture.ScaledHeight);
                tsz = tsz / tscale;

                // Get texture offsets
                Vector2D tof = new Vector2D(Sidedef.OffsetX, Sidedef.OffsetY);
                tof = tof + toffset;
                tof = tof / tscale;
                if (General.Map.Config.ScaledTextureOffsets && !base.Texture.WorldPanning)
                {
                    tof = tof * base.Texture.Scale;
                }

                // Determine texture coordinates plane as they would be in normal circumstances.
                // We can then use this plane to find any texture coordinate we need.
                // The logic here is the same as in the original VisualMiddleSingle (except that
                // the values are stored in a TexturePlane)
                // NOTE: I use a small bias for the floor height, because if the difference in
                // height is 0 then the TexturePlane doesn't work!
                TexturePlane tp        = new TexturePlane();
                float        floorbias = (Sidedef.Sector.CeilHeight == Sidedef.Sector.FloorHeight) ? 1.0f : 0.0f;
                float        geotop    = (float)Math.Min(Sidedef.Sector.CeilHeight, Sidedef.Other.Sector.CeilHeight);
                float        geobottom = (float)Math.Max(Sidedef.Sector.FloorHeight, Sidedef.Other.Sector.FloorHeight);
                if (Sidedef.Line.IsFlagSet(General.Map.Config.LowerUnpeggedFlag))
                {
                    // When lower unpegged is set, the middle texture is bound to the bottom
                    tp.tlt.y = tsz.y - (float)(geotop - geobottom);
                }
                tp.trb.x = tp.tlt.x + Sidedef.Line.Length;
                tp.trb.y = tp.tlt.y + ((float)Sidedef.Sector.CeilHeight - ((float)Sidedef.Sector.FloorHeight + floorbias));

                // Apply texture offset
                tp.tlt += tof;
                tp.trb += tof;

                // Transform pixel coordinates to texture coordinates
                tp.tlt /= tsz;
                tp.trb /= tsz;

                // Left top and right bottom of the geometry that
                tp.vlt = new Vector3D(vl.x, vl.y, (float)Sidedef.Sector.CeilHeight);
                tp.vrb = new Vector3D(vr.x, vr.y, (float)Sidedef.Sector.FloorHeight + floorbias);

                // Make the right-top coordinates
                tp.trt = new Vector2D(tp.trb.x, tp.tlt.y);
                tp.vrt = new Vector3D(tp.vrb.x, tp.vrb.y, tp.vlt.z);

                // Keep top and bottom planes for intersection testing
                top    = sd.Ceiling.plane;
                bottom = sd.Floor.plane;

                // Create initial polygon, which is just a quad between floor and ceiling
                WallPolygon poly = new WallPolygon();
                poly.Add(new Vector3D(vl.x, vl.y, sd.Floor.plane.GetZ(vl)));
                poly.Add(new Vector3D(vl.x, vl.y, sd.Ceiling.plane.GetZ(vl)));
                poly.Add(new Vector3D(vr.x, vr.y, sd.Ceiling.plane.GetZ(vr)));
                poly.Add(new Vector3D(vr.x, vr.y, sd.Floor.plane.GetZ(vr)));

                // Determine initial color
                int        lightlevel     = lightabsolute ? lightvalue : sd.Ceiling.brightnessbelow + lightvalue;
                PixelColor wallbrightness = PixelColor.FromInt(mode.CalculateBrightness(lightlevel));
                PixelColor wallcolor      = PixelColor.Modulate(sd.Ceiling.colorbelow, wallbrightness);
                poly.color = wallcolor.WithAlpha(255).ToInt();

                // Cut off the part below the other floor and above the other ceiling
                CropPoly(ref poly, osd.Ceiling.plane, true);
                CropPoly(ref poly, osd.Floor.plane, true);

                // Determine if we should repeat the middle texture
                if (Sidedef.Fields.ContainsKey("wrapmidtex"))
                {
                    repeatmidtex = Sidedef.Fields.GetValue("wrapmidtex", false);
                }
                else
                {
                    repeatmidtex = Sidedef.Line.IsFlagSet("wrapmidtex");
                }

                if (!repeatmidtex)
                {
                    // First determine the visible portion of the texture
                    float textop, texbottom;

                    // Determine top portion height
                    if (Sidedef.Line.IsFlagSet(General.Map.Config.LowerUnpeggedFlag))
                    {
                        textop = geobottom + tof.y + tsz.y;
                    }
                    else
                    {
                        textop = geotop + tof.y;
                    }

                    // Calculate bottom portion height
                    texbottom = textop - tsz.y;

                    // Create crop planes (we also need these for intersection testing)
                    topclipplane    = new Plane(new Vector3D(0, 0, -1), textop);
                    bottomclipplane = new Plane(new Vector3D(0, 0, 1), -texbottom);

                    // Crop polygon by these heights
                    CropPoly(ref poly, topclipplane, true);
                    CropPoly(ref poly, bottomclipplane, true);
                }

                if (poly.Count > 2)
                {
                    // Keep top and bottom planes for intersection testing
                    top    = osd.Ceiling.plane;
                    bottom = osd.Floor.plane;

                    // Process the polygon and create vertices
                    List <WorldVertex> verts = CreatePolygonVertices(poly, tp, sd, lightvalue, lightabsolute);
                    if (verts.Count > 0)
                    {
                        // Apply alpha to vertices
                        byte alpha = SetLinedefRenderstyle(true);
                        if (alpha < 255)
                        {
                            for (int i = 0; i < verts.Count; i++)
                            {
                                WorldVertex v = verts[i];
                                PixelColor  c = PixelColor.FromInt(v.c);
                                v.c      = c.WithAlpha(alpha).ToInt();
                                verts[i] = v;
                            }
                        }

                        base.SetVertices(verts);
                        return(true);
                    }
                }
            }

            return(false);
        }
Пример #27
0
        //mxd
        public bool Setup(SectorLevel level, Effect3DFloor extrafloor, bool innerside)
        {
            Sector   s = level.sector;
            Vector2D texscale;

            this.innerside = innerside;

            base.Setup(level, extrafloor);

            // Fetch ZDoom fields
            float    rotate = Angle2D.DegToRad(s.Fields.GetValue("rotationfloor", 0.0f));
            Vector2D offset = new Vector2D(s.Fields.GetValue("xpanningfloor", 0.0f),
                                           s.Fields.GetValue("ypanningfloor", 0.0f));
            Vector2D scale = new Vector2D(s.Fields.GetValue("xscalefloor", 1.0f),
                                          s.Fields.GetValue("yscalefloor", 1.0f));

            //Load floor texture
            if (s.LongFloorTexture != MapSet.EmptyLongName)
            {
                base.Texture = General.Map.Data.GetFlatImage(s.LongFloorTexture);
                if (base.Texture == null || base.Texture is UnknownImage)
                {
                    base.Texture         = General.Map.Data.UnknownTexture3D;
                    setuponloadedtexture = s.LongFloorTexture;
                }
                else if (!base.Texture.IsImageLoaded)
                {
                    setuponloadedtexture = s.LongFloorTexture;
                }
            }
            else
            {
                // Use missing texture
                base.Texture         = General.Map.Data.MissingTexture3D;
                setuponloadedtexture = 0;
            }

            // Determine texture scale
            if (base.Texture.IsImageLoaded)
            {
                texscale = new Vector2D(1.0f / base.Texture.ScaledWidth, 1.0f / base.Texture.ScaledHeight);
            }
            else
            {
                texscale = new Vector2D(1.0f / 64.0f, 1.0f / 64.0f);
            }

            // Determine brightness
            int color = PixelColor.FromInt(level.color).WithAlpha((byte)General.Clamp(level.alpha, 0, 255)).ToInt();

            //mxd. Top extrafloor level should calculate fogdensity
            //from the brightness of the level above it
            int targetbrightness;

            if (extrafloor != null && extrafloor.VavoomType && !level.disablelighting)
            {
                targetbrightness = 0;
                SectorData sd = mode.GetSectorData(this.Sector.Sector);
                for (int i = 0; i < sd.LightLevels.Count - 1; i++)
                {
                    if (sd.LightLevels[i] == level)
                    {
                        targetbrightness = sd.LightLevels[i + 1].brightnessbelow;
                        break;
                    }
                }
            }
            else
            {
                targetbrightness = level.brightnessbelow;
            }

            //mxd. Determine fog density
            fogfactor = CalculateFogFactor(targetbrightness);

            // Make vertices
            ReadOnlyCollection <Vector2D> triverts = Sector.Sector.Triangles.Vertices;

            WorldVertex[] verts = new WorldVertex[triverts.Count];
            for (int i = 0; i < triverts.Count; i++)
            {
                // Color shading
                verts[i].c = color;                 //mxd

                // Vertex coordinates
                verts[i].x = triverts[i].x;
                verts[i].y = triverts[i].y;
                verts[i].z = level.plane.GetZ(triverts[i]);

                // Texture coordinates
                Vector2D pos = triverts[i];
                pos        = pos.GetRotated(rotate);
                pos.y      = -pos.y;
                pos        = (pos + offset) * scale * texscale;
                verts[i].u = pos.x;
                verts[i].v = pos.y;
            }

            // The sector triangulation created clockwise triangles that
            // are right up for the floor. For the ceiling we must flip
            // the triangles upside down.
            if ((extrafloor != null) && !extrafloor.VavoomType && !innerside)
            {
                SwapTriangleVertices(verts);
            }

            // Determine render pass
            if (extrafloor != null)
            {
                if (extrafloor.Sloped3dFloor)                //mxd
                {
                    this.RenderPass = RenderPass.Mask;
                }
                else if (extrafloor.RenderAdditive)                //mxd
                {
                    this.RenderPass = RenderPass.Additive;
                }
                else if (level.alpha < 255)
                {
                    this.RenderPass = RenderPass.Alpha;
                }
                else
                {
                    this.RenderPass = RenderPass.Mask;
                }
            }
            else
            {
                this.RenderPass = RenderPass.Solid;
            }

            //mxd. Update sky render flag
            UpdateSkyRenderFlag();

            // Apply vertices
            base.SetVertices(verts);
            return(verts.Length > 0);
        }
Пример #28
0
        // This builds the geometry. Returns false when no geometry created.
        public override bool Setup()
        {
            Vector2D vl, vr;

            // Left and right vertices for this sidedef
            if (Sidedef.IsFront)
            {
                vl = new Vector2D(Sidedef.Line.Start.Position.x, Sidedef.Line.Start.Position.y);
                vr = new Vector2D(Sidedef.Line.End.Position.x, Sidedef.Line.End.Position.y);
            }
            else
            {
                vl = new Vector2D(Sidedef.Line.End.Position.x, Sidedef.Line.End.Position.y);
                vr = new Vector2D(Sidedef.Line.Start.Position.x, Sidedef.Line.Start.Position.y);
            }

            // Load sector data
            SectorData sd  = Sector.GetSectorData();
            SectorData osd = mode.GetSectorData(Sidedef.Other.Sector);

            if (!osd.Updated)
            {
                osd.Update();
            }

            //mxd
            double vlzf  = sd.Floor.plane.GetZ(vl);
            double vrzf  = sd.Floor.plane.GetZ(vr);
            double ovlzf = osd.Floor.plane.GetZ(vl);
            double ovrzf = osd.Floor.plane.GetZ(vr);

            //mxd. Side is visible when our sector's floor is lower than the other's at any vertex
            if (!(vlzf < ovlzf || vrzf < ovrzf))
            {
                base.SetVertices(null);
                return(false);
            }

            // Apply sky hack?
            UpdateSkyRenderFlag();

            //mxd. lightfog flag support
            int  lightvalue;
            bool lightabsolute;

            GetLightValue(out lightvalue, out lightabsolute);

            Vector2D tscale = new Vector2D(Sidedef.Fields.GetValue("scalex_bottom", 1.0),
                                           Sidedef.Fields.GetValue("scaley_bottom", 1.0));
            Vector2D tscaleAbs = new Vector2D(Math.Abs(tscale.x), Math.Abs(tscale.y));
            Vector2D toffset   = new Vector2D(Sidedef.Fields.GetValue("offsetx_bottom", 0.0),
                                              Sidedef.Fields.GetValue("offsety_bottom", 0.0));

            // Texture given?
            if (Sidedef.LongLowTexture != MapSet.EmptyLongName)
            {
                // Load texture
                base.Texture = General.Map.Data.GetTextureImage(Sidedef.LongLowTexture);
                if (base.Texture == null || base.Texture is UnknownImage)
                {
                    base.Texture         = General.Map.Data.UnknownTexture3D;
                    setuponloadedtexture = Sidedef.LongLowTexture;
                }
                else if (!base.Texture.IsImageLoaded)
                {
                    setuponloadedtexture = Sidedef.LongLowTexture;
                }
            }
            else
            {
                // Use missing texture
                base.Texture         = General.Map.Data.MissingTexture3D;
                setuponloadedtexture = 0;
            }

            // Get texture scaled size. Round up, because that's apparently what GZDoom does
            Vector2D tsz = new Vector2D(Math.Ceiling(base.Texture.ScaledWidth / tscale.x), Math.Ceiling(base.Texture.ScaledHeight / tscale.y));

            // Get texture offsets
            Vector2D tof = new Vector2D(Sidedef.OffsetX, Sidedef.OffsetY);

            tof = tof + toffset;

            // biwa. Also take the ForceWorldPanning MAPINFO entry into account
            if (General.Map.Config.ScaledTextureOffsets && (!base.Texture.WorldPanning && !General.Map.Data.MapInfo.ForceWorldPanning))
            {
                tof = tof / tscaleAbs;
                tof = tof * base.Texture.Scale;

                // If the texture gets replaced with a "hires" texture it adds more fuckery
                if (base.Texture is HiResImage)
                {
                    tof *= tscaleAbs;
                }

                // Round up, since that's apparently what GZDoom does. Not sure if this is the right place or if it also has to be done earlier
                tof = new Vector2D(Math.Ceiling(tof.x), Math.Ceiling(tof.y));
            }

            // Determine texture coordinates plane as they would be in normal circumstances.
            // We can then use this plane to find any texture coordinate we need.
            // The logic here is the same as in the original VisualMiddleSingle (except that
            // the values are stored in a TexturePlane)
            // NOTE: I use a small bias for the floor height, because if the difference in
            // height is 0 then the TexturePlane doesn't work!
            TexturePlane tp        = new TexturePlane();
            double       floorbias = (Sidedef.Other.Sector.FloorHeight == Sidedef.Sector.FloorHeight) ? 1.0 : 0.0;

            if (Sidedef.Line.IsFlagSet(General.Map.Config.LowerUnpeggedFlag))
            {
                if (Sidedef.Sector.CeilTexture == General.Map.Config.SkyFlatName && Sidedef.Other.Sector.CeilTexture == General.Map.Config.SkyFlatName)
                {
                    // mxd. Replicate Doom texture offset glitch when front and back sector's ceilings are sky
                    tp.tlt.y = (double)Sidedef.Other.Sector.CeilHeight - Sidedef.Other.Sector.FloorHeight;
                }
                else
                {
                    // When lower unpegged is set, the lower texture is bound to the bottom
                    tp.tlt.y = (double)Sidedef.Sector.CeilHeight - Sidedef.Other.Sector.FloorHeight;
                }
            }
            tp.trb.x = tp.tlt.x + Math.Round(Sidedef.Line.Length);             //mxd. (G)ZDoom snaps texture coordinates to integral linedef length
            tp.trb.y = tp.tlt.y + (Sidedef.Other.Sector.FloorHeight - (Sidedef.Sector.FloorHeight + floorbias));

            // Apply texture offset
            tp.tlt += tof;
            tp.trb += tof;

            // Transform pixel coordinates to texture coordinates
            tp.tlt /= tsz;
            tp.trb /= tsz;

            // Left top and right bottom of the geometry that
            tp.vlt = new Vector3D(vl.x, vl.y, Sidedef.Other.Sector.FloorHeight);
            tp.vrb = new Vector3D(vr.x, vr.y, Sidedef.Sector.FloorHeight + floorbias);

            // Make the right-top coordinates
            tp.trt = new Vector2D(tp.trb.x, tp.tlt.y);
            tp.vrt = new Vector3D(tp.vrb.x, tp.vrb.y, tp.vlt.z);

            // Create initial polygon, which is just a quad between floor and ceiling
            WallPolygon poly = new WallPolygon();

            poly.Add(new Vector3D(vl.x, vl.y, vlzf));
            poly.Add(new Vector3D(vl.x, vl.y, sd.Ceiling.plane.GetZ(vl)));
            poly.Add(new Vector3D(vr.x, vr.y, sd.Ceiling.plane.GetZ(vr)));
            poly.Add(new Vector3D(vr.x, vr.y, vrzf));

            // Determine initial color
            int lightlevel = lightabsolute ? lightvalue : sd.Ceiling.brightnessbelow + lightvalue;

            //mxd. This calculates light with doom-style wall shading
            PixelColor wallbrightness = PixelColor.FromInt(mode.CalculateBrightness(lightlevel, Sidedef));
            PixelColor wallcolor      = PixelColor.Modulate(sd.Ceiling.colorbelow, wallbrightness);

            fogfactor  = CalculateFogFactor(lightlevel);
            poly.color = wallcolor.WithAlpha(255).ToInt();

            // Cut off the part above the other floor
            CropPoly(ref poly, osd.Floor.plane, false);

            //INFO: Makes sence only when ceiling plane is lower than floor plane. Also ZDoom clips ceiling instead here.
            if (ovlzf > osd.Ceiling.plane.GetZ(vl) || ovrzf > osd.Ceiling.plane.GetZ(vr))
            {
                CropPoly(ref poly, osd.Ceiling.plane, true);
            }

            // Cut out pieces that overlap 3D floors in this sector
            List <WallPolygon> polygons = new List <WallPolygon> {
                poly
            };

            ClipExtraFloors(polygons, sd.ExtraFloors, false);             //mxd

            if (polygons.Count > 0)
            {
                // Keep top and bottom planes for intersection testing
                Vector2D linecenter = Sidedef.Line.GetCenterPoint();                 //mxd. Our sector's ceiling can be lower than the other sector's floor!
                top    = (osd.Floor.plane.GetZ(linecenter) < sd.Ceiling.plane.GetZ(linecenter) ? osd.Floor.plane : sd.Ceiling.plane);
                bottom = sd.Floor.plane;

                // Process the polygon and create vertices
                List <WorldVertex> verts = CreatePolygonVertices(polygons, tp, sd, lightvalue, lightabsolute);
                if (verts.Count > 2)
                {
                    base.SetVertices(verts);
                    return(true);
                }
            }

            base.SetVertices(null);             //mxd
            return(false);
        }
Пример #29
0
        //mxd
        public bool Setup(SectorLevel level, Effect3DFloor extrafloor, bool innerside)
        {
            Sector   s = level.sector;
            Vector2D texscale;

            this.innerside = innerside;             //mxd

            base.Setup(level, extrafloor);

            // Fetch ZDoom fields
            float    rotate = Angle2D.DegToRad(s.Fields.GetValue("rotationceiling", 0.0f));
            Vector2D offset = new Vector2D(s.Fields.GetValue("xpanningceiling", 0.0f),
                                           s.Fields.GetValue("ypanningceiling", 0.0f));
            Vector2D scale = new Vector2D(s.Fields.GetValue("xscaleceiling", 1.0f),
                                          s.Fields.GetValue("yscaleceiling", 1.0f));

            //Load ceiling texture
            if (s.LongCeilTexture != MapSet.EmptyLongName)
            {
                base.Texture = General.Map.Data.GetFlatImage(s.LongCeilTexture);
                if (base.Texture == null || base.Texture is UnknownImage)
                {
                    base.Texture         = General.Map.Data.UnknownTexture3D;
                    setuponloadedtexture = s.LongCeilTexture;
                }
                else if (!base.Texture.IsImageLoaded)
                {
                    setuponloadedtexture = s.LongCeilTexture;
                }
            }
            else
            {
                // Use missing texture
                base.Texture         = General.Map.Data.MissingTexture3D;
                setuponloadedtexture = 0;
            }

            // Determine texture scale
            if (base.Texture.IsImageLoaded)
            {
                texscale = new Vector2D(1.0f / base.Texture.ScaledWidth, 1.0f / base.Texture.ScaledHeight);
            }
            else
            {
                texscale = new Vector2D(1.0f / 64.0f, 1.0f / 64.0f);
            }

            // Determine brightness
            byte alpha = (byte)General.Clamp(level.alpha, 0, 255);
            int  color = PixelColor.FromInt(level.color).WithAlpha(alpha).ToInt();
            int  targetbrightness;

            if (extrafloor != null && !extrafloor.VavoomType && !level.disablelighting)
            {
                //mxd. Top extrafloor level should calculate fogdensity from the brightness of the level above it
                if (!innerside)
                {
                    targetbrightness = 0;
                    SectorData sd = mode.GetSectorData(this.Sector.Sector);
                    for (int i = 0; i < sd.LightLevels.Count - 1; i++)
                    {
                        if (sd.LightLevels[i] == level)
                        {
                            targetbrightness = sd.LightLevels[i + 1].brightnessbelow;
                            break;
                        }
                    }
                }
                //mxd. Inner extrafloor ceilings must be colored using control sector's color and brightness
                else
                {
                    targetbrightness = level.brightnessbelow;
                    SectorData sd = mode.GetSectorData(this.Sector.Sector);
                    for (int i = 0; i < sd.LightLevels.Count; i++)
                    {
                        if (sd.LightLevels[i] == level)
                        {
                            if (i > 0)
                            {
                                color = PixelColor.FromInt(sd.LightLevels[i - 1].color).WithAlpha(alpha).ToInt();
                            }
                            break;
                        }
                    }
                }
            }
            else
            {
                targetbrightness = level.brightnessbelow;
            }

            //mxd. Determine fog density
            fogfactor = CalculateFogFactor(targetbrightness);

            // Make vertices
            ReadOnlyCollection <Vector2D> triverts = Sector.Sector.Triangles.Vertices;

            WorldVertex[] verts = new WorldVertex[triverts.Count];
            for (int i = 0; i < triverts.Count; i++)
            {
                // Color shading
                verts[i].c = color;                 //mxd

                // Vertex coordinates
                verts[i].x = triverts[i].x;
                verts[i].y = triverts[i].y;
                verts[i].z = level.plane.GetZ(triverts[i]);

                // Texture coordinates
                Vector2D pos = triverts[i];
                pos        = pos.GetRotated(rotate);
                pos.y      = -pos.y;
                pos        = (pos + offset) * scale * texscale;
                verts[i].u = pos.x;
                verts[i].v = pos.y;
            }

            // The sector triangulation created clockwise triangles that
            // are right up for the floor. For the ceiling we must flip
            // the triangles upside down.
            if (extrafloor == null || extrafloor.VavoomType || innerside)
            {
                SwapTriangleVertices(verts);
            }

            // Determine render pass
            if (extrafloor != null)
            {
                if (extrafloor.Sloped3dFloor)                //mxd
                {
                    this.RenderPass = RenderPass.Mask;
                }
                else if (extrafloor.RenderAdditive)                //mxd
                {
                    this.RenderPass = RenderPass.Additive;
                }
                else if (level.alpha < 255)
                {
                    this.RenderPass = RenderPass.Alpha;
                }
                else
                {
                    this.RenderPass = RenderPass.Mask;
                }
            }
            else
            {
                this.RenderPass = RenderPass.Solid;
            }

            //mxd. Update sky render flag
            bool isrenderedassky = renderassky;

            renderassky = (level.sector.CeilTexture == General.Map.Config.SkyFlatName);
            if (isrenderedassky != renderassky && Sector.Sides != null)
            {
                // Upper sidedef geometry may need updating...
                foreach (Sidedef side in level.sector.Sidedefs)
                {
                    VisualSidedefParts parts = Sector.GetSidedefParts(side);

                    // Upper side can exist in either our, or the neightbouring sector, right?
                    if (parts.upper != null && parts.upper.Triangles > 0)
                    {
                        parts.upper.UpdateSkyRenderFlag();
                    }
                    else if (side.Other != null && side.Other.Sector != null && side.Other.Sector.CeilTexture == General.Map.Config.SkyFlatName)
                    {
                        // Update upper side of the neightbouring sector
                        BaseVisualSector other = (BaseVisualSector)mode.GetVisualSector(side.Other.Sector);
                        if (other != null && other.Sides != null)
                        {
                            parts = other.GetSidedefParts(side.Other);
                            if (parts.upper != null && parts.upper.Triangles > 0)
                            {
                                parts.upper.UpdateSkyRenderFlag();
                            }
                        }
                    }
                }
            }

            // Apply vertices
            base.SetVertices(verts);
            return(verts.Length > 0);
        }
        // This creates vertices from a wall polygon and applies lighting
        protected List <WorldVertex> CreatePolygonVertices(List <WallPolygon> poly, TexturePlane tp, SectorData sd, int lightvalue, bool lightabsolute)
        {
            List <WallPolygon> polygons = new List <WallPolygon>(poly);
            List <WorldVertex> verts    = new List <WorldVertex>();

            // Go for all levels to build geometry
            for (int i = sd.LightLevels.Count - 1; i >= 0; i--)
            {
                SectorLevel l = sd.LightLevels[i];
                if ((l != sd.Floor) && (l != sd.Ceiling) && (l.type != SectorLevelType.Floor))
                {
                    // Go for all polygons
                    int num = polygons.Count;
                    for (int pi = 0; pi < num; pi++)
                    {
                        // Split by plane
                        WallPolygon p  = polygons[pi];
                        WallPolygon np = SplitPoly(ref p, l.plane, false);
                        if (np.Count > 0)
                        {
                            // Determine color
                            int        lightlevel     = lightabsolute ? lightvalue : l.brightnessbelow + lightvalue;
                            PixelColor wallbrightness = PixelColor.FromInt(mode.CalculateBrightness(lightlevel));
                            PixelColor wallcolor      = PixelColor.Modulate(l.colorbelow, wallbrightness);
                            np.color = wallcolor.WithAlpha(255).ToInt();

                            if (p.Count == 0)
                            {
                                polygons[pi] = np;
                            }
                            else
                            {
                                polygons[pi] = p;
                                polygons.Add(np);
                            }
                        }
                        else
                        {
                            polygons[pi] = p;
                        }
                    }
                }
            }

            // Go for all polygons to make geometry
            foreach (WallPolygon p in polygons)
            {
                // Find texture coordinates for each vertex in the polygon
                List <Vector2D> texc = new List <Vector2D>(p.Count);
                foreach (Vector3D v in p)
                {
                    texc.Add(tp.GetTextureCoordsAt(v));
                }

                // Now we create triangles from the polygon.
                // The polygon is convex and clockwise, so this is a piece of cake.
                if (p.Count >= 3)
                {
                    for (int k = 1; k < (p.Count - 1); k++)
                    {
                        verts.Add(new WorldVertex(p[0], p.color, texc[0]));
                        verts.Add(new WorldVertex(p[k], p.color, texc[k]));
                        verts.Add(new WorldVertex(p[k + 1], p.color, texc[k + 1]));
                    }
                }
            }

            return(verts);
        }