// Selected type changes
        private void thingtype_OnTypeChanged(ThingTypeInfo value)
        {
            thinginfo = value;

            // Update arguments
            action_ValueChanges(this, EventArgs.Empty);

            //mxd. Update things
            if (preventchanges ||
                (!string.IsNullOrEmpty(thingtype.TypeStringValue) &&
                 thingtype.GetResult(0) < General.Map.FormatInterface.MinThingType ||
                 thingtype.GetResult(0) > General.Map.FormatInterface.MaxThingType))
            {
                return;
            }

            MakeUndo();             //mxd

            foreach (Thing t in things)
            {
                //Set type
                t.Type = thingtype.GetResult(t.Type);

                // Update settings
                t.UpdateConfiguration();
            }

            UpdateFlagNames();             //mxd

            General.Map.IsChanged = true;
            if (OnValuesChanged != null)
            {
                OnValuesChanged(this, EventArgs.Empty);
            }
        }
		// This runs the check
		public override void Run() 
		{
			int progress = 0;
			int stepprogress = 0;

			// Go for all things
			foreach(Thing t in General.Map.Map.Things) 
			{
				ThingTypeInfo info = General.Map.Data.GetThingInfoEx(t.Type);
				if(info != null && info.IsObsolete)
				{
					SubmitResult(new ResultObsoleteThing(t, info.ObsoleteMessage));
				}

				// Handle thread interruption
				try { Thread.Sleep(0); } catch(ThreadInterruptedException) { return; }

				// We are making progress!
				if((++progress / PROGRESS_STEP) > stepprogress) 
				{
					stepprogress = (progress / PROGRESS_STEP);
					AddProgress(1);
				}
			}	
		}
        // Checks if two things overlap
        private static bool ThingsOverlap(Thing t1, Thing t2)
        {
            Vector3D      p1     = t1.Position;
            Vector3D      p2     = t2.Position;
            ThingTypeInfo t1info = General.Map.Data.GetThingInfo(t1.Type);
            ThingTypeInfo t2info = General.Map.Data.GetThingInfo(t2.Type);

            // simple bounding box collision detection
            if (p1.x + t1.Size - ALLOWED_STUCK_DISTANCE < p2.x - t2.Size + ALLOWED_STUCK_DISTANCE ||
                p1.x - t1.Size + ALLOWED_STUCK_DISTANCE > p2.x + t2.Size - ALLOWED_STUCK_DISTANCE ||
                p1.y - t1.Size + ALLOWED_STUCK_DISTANCE > p2.y + t2.Size - ALLOWED_STUCK_DISTANCE ||
                p1.y + t1.Size - ALLOWED_STUCK_DISTANCE < p2.y - t2.Size + ALLOWED_STUCK_DISTANCE)
            {
                return(false);
            }

            // if either thing blocks full height there's no need to check the z-axis
            if (t1info.Blocking == ThingTypeInfo.THING_BLOCKING_FULL || t2info.Blocking == ThingTypeInfo.THING_BLOCKING_FULL)
            {
                return(true);
            }

            // check z-axis
            if (p1.z > p2.z + t2info.Height || p1.z + t1info.Height < p2.z)
            {
                return(false);
            }

            return(true);
        }
        public override void Browse(IWin32Window parent)
        {
            int tid = 0;

            // Find the thing with this class name
            foreach (ThingTypeInfo t in General.Map.Data.ThingTypes)
            {
                if ((t.Actor != null) && (string.Compare(t.Actor.ClassName, value, true) == 0))
                {
                    tid = t.Index;
                    break;
                }
            }

            //tid = ThingBrowserForm.BrowseThing(parent, tid);
            ThingBrowserForm f = new ThingBrowserForm(tid);

            if (f.ShowDialog(Form.ActiveForm) == DialogResult.OK)
            {
                // Find the class name for this thing
                ThingTypeInfo t = General.Map.Data.GetThingInfo(f.SelectedType);
                if (t.Actor != null)
                {
                    this.value = t.Actor.ClassName;
                }
                else
                {
                    this.value = "";
                }
            }

            f.Dispose();
        }
        protected override EnumList CreateEnumList()
        {
            // Collect polyobjects
            HashSet <int> ponums = new HashSet <int>();
            EnumList      polist = new EnumList();

            foreach (Thing t in General.Map.Map.Things)
            {
                ThingTypeInfo info = General.Map.Data.GetThingInfoEx(t.Type);
                if (info == null || info.ClassName.ToLowerInvariant() != "$polyanchor")
                {
                    continue;
                }
                ponums.Add(t.AngleDoom);
            }

            // Now sort them in descending order
            List <int> ponumslist = new List <int>(ponums);

            ponumslist.Sort((a, b) => - 1 * a.CompareTo(b));

            // Create enum items
            foreach (int ponum in ponums)
            {
                polist.Add(new EnumItem(ponum.ToString(), ponum.ToString()));
            }

            return(polist);
        }
Exemple #6
0
        private static float GetAlignedThingZ(BaseVisualMode mode, Thing t, float targtthingheight)
        {
            ThingTypeInfo info = General.Map.Data.GetThingInfoEx(t.Type);

            if (info != null)
            {
                if (info.AbsoluteZ && info.Hangs)
                {
                    return(t.Position.z);                                             // Not sure what to do here...
                }
                if (info.AbsoluteZ)
                {
                    // Transform to floor-aligned position
                    SectorData nsd = mode.GetSectorData(t.Sector);
                    return(t.Position.z - nsd.Floor.plane.GetZ(t.Position) + t.Height);
                }

                if (info.Hangs)
                {
                    // Transform to floor-aligned position. Align top of target thing to the bottom of the hanging thing
                    SectorData nsd = mode.GetSectorData(t.Sector);
                    return((nsd.Ceiling.plane.GetZ(t.Position) - nsd.Floor.plane.GetZ(t.Position)) - t.Position.z - t.Height - targtthingheight);
                }
            }

            return(t.Position.z + t.Height);
        }
        public override void Browse(IWin32Window parent)
        {
            int tid = 0;

            // Find the thing with this class name
            foreach (ThingTypeInfo t in General.Map.Data.ThingTypes)
            {
                if ((string.Compare(t.ClassName, value, true) == 0))                //mxd
                {
                    tid = t.Index;
                    break;
                }
            }

            ThingBrowserForm f = new ThingBrowserForm(tid);

            if (f.ShowDialog(Form.ActiveForm) == DialogResult.OK)
            {
                // Find the class name for this thing
                ThingTypeInfo t = General.Map.Data.GetThingInfo(f.SelectedType);
                this.value = !string.IsNullOrEmpty(t.ClassName) ? t.ClassName : "";                 //mxd
            }

            f.Dispose();
        }
Exemple #8
0
        // Selected type changes
        private void thingtype_OnTypeChanged(ThingTypeInfo value)
        {
            thinginfo = value;

            // Update preview image
            if (thinginfo != null)
            {
                if (thinginfo.Sprite.ToLowerInvariant().StartsWith(DataManager.INTERNAL_PREFIX) &&
                    (thinginfo.Sprite.Length > DataManager.INTERNAL_PREFIX.Length))
                {
                    General.DisplayZoomedImage(spritetex, General.Map.Data.GetSpriteImage(thinginfo.Sprite).GetBitmap());
                }
                else if (thinginfo.Sprite.Length > 0)
                {
                    General.DisplayZoomedImage(spritetex, General.Map.Data.GetSpriteImage(thinginfo.Sprite).GetPreview());
                }
                else
                {
                    spritetex.BackgroundImage = null;
                }
            }
            else
            {
                spritetex.BackgroundImage = null;
            }

            // Update arguments
            action_ValueChanges(this, EventArgs.Empty);
        }
Exemple #9
0
        // This is called to perform a search (and replace)
        // Returns a list of items to show in the results list
        // replacewith is null when not replacing
        public override FindReplaceObject[] Find(string value, bool withinselection, string replacewith, bool keepselection)
        {
            List <FindReplaceObject> objs = new List <FindReplaceObject>();

            // Interpret the replacement
            int replacetype = 0;

            if (replacewith != null)
            {
                // If it cannot be interpreted, set replacewith to null (not replacing at all)
                if (!int.TryParse(replacewith, out replacetype))
                {
                    replacewith = null;
                }
                if (replacetype < 0)
                {
                    replacewith = null;
                }
                if (replacetype > Int16.MaxValue)
                {
                    replacewith = null;
                }
                if (replacewith == null)
                {
                    MessageBox.Show("Invalid replace value for this search type!", "Find and Replace", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return(objs.ToArray());
                }
            }

            // Interpret the number given
            int findtype = 0;

            if (int.TryParse(value, out findtype))
            {
                // Where to search?
                ICollection <Thing> list = withinselection ? General.Map.Map.GetSelectedThings(true) : General.Map.Map.Things;

                // Go for all things
                foreach (Thing t in list)
                {
                    // Match?
                    if (t.Type == findtype)
                    {
                        // Replace
                        if (replacewith != null)
                        {
                            t.Type = replacetype;
                            t.UpdateConfiguration();
                        }

                        // Add to list
                        ThingTypeInfo ti = General.Map.Data.GetThingInfo(t.Type);
                        objs.Add(new FindReplaceObject(t, "Thing " + t.Index + " (" + ti.Title + ")"));
                    }
                }
            }

            return(objs.ToArray());
        }
Exemple #10
0
        //mxd. This checks if the thing has model override and whether pitch/roll values should be used
        internal void UpdateCache()
        {
            if (General.Map.Data == null)
            {
                return;
            }

            // Check if the thing has model override
            if (General.Map.Data.ModeldefEntries.ContainsKey(type))
            {
                ModelData md = General.Map.Data.ModeldefEntries[type];
                if ((md.LoadState == ModelLoadState.None && General.Map.Data.ProcessModel(type)) || md.LoadState != ModelLoadState.None)
                {
                    rendermode = (General.Map.Data.ModeldefEntries[type].IsVoxel ? ThingRenderMode.VOXEL : ThingRenderMode.MODEL);
                }
            }
            else // reset rendermode if we SUDDENLY became a sprite out of a model. otherwise it crashes violently.
            {
                ThingTypeInfo ti = General.Map.Data.GetThingInfo(Type);
                rendermode = (ti != null) ? ti.RenderMode : ThingRenderMode.NORMAL;
            }

            // Update radian versions of pitch and roll
            switch (rendermode)
            {
            case ThingRenderMode.MODEL:
                float     pmult = General.Map.Config.BuggyModelDefPitch ? 1 : -1;
                ModelData md    = General.Map.Data.ModeldefEntries[type];
                rollrad  = (md.UseActorRoll ? Angle2D.DegToRad(roll) : 0);
                pitchrad = ((md.InheritActorPitch || md.UseActorPitch) ? Angle2D.DegToRad(pmult * (md.InheritActorPitch ? -pitch : pitch)) : 0);
                break;

            case ThingRenderMode.FLATSPRITE:
                rollrad  = Angle2D.DegToRad(roll);
                pitchrad = Angle2D.DegToRad(pitch);
                break;

            case ThingRenderMode.WALLSPRITE:
                rollrad  = Angle2D.DegToRad(roll);
                pitchrad = 0;
                break;

            case ThingRenderMode.NORMAL:
                rollrad  = (rollsprite ? Angle2D.DegToRad(roll) : 0);
                pitchrad = 0;
                break;

            case ThingRenderMode.VOXEL:
                rollrad  = 0;
                pitchrad = 0;
                break;

            default: throw new NotImplementedException("Unknown ThingRenderMode");
            }
        }
Exemple #11
0
        //constructor
        public NodeInfo(Thing t)
        {
            type          = NodeInfoType.THING;
            index         = t.Index;
            action        = t.Action;
            tag           = t.Tag;
            polyobjnumber = ((t.Type > 9299 && t.Type < 9304) ? t.AngleDoom : int.MinValue);
            ThingTypeInfo tti = General.Map.Data.GetThingInfoEx(t.Type);

            defaultname = (tti != null ? tti.Title : "Thing");
        }
Exemple #12
0
        // This renders the associated things with the indication color
        public static void RenderAssociations(IRenderer2D renderer, Association asso, List <Line3D> eventlines)
        {
            // Tag must be above zero
            if (General.GetByIndex(asso.Tags, 0) < 1)
            {
                return;
            }

            // Things?
            switch (asso.Type)
            {
            case UniversalType.ThingTag:
                foreach (Thing t in General.Map.Map.Things)
                {
                    if (!asso.Tags.Contains(t.Tag))
                    {
                        continue;
                    }

                    //Do not draw the association if the user is hovering over a child link
                    ThingTypeInfo ti = General.Map.Data.GetThingInfoEx(t.Type);
                    if (ti != null && ti.ThingLink < 0)
                    {
                        continue;
                    }

                    renderer.RenderThing(t, General.Colors.Indication, General.Settings.ActiveThingsAlpha);
                    if (General.Settings.GZShowEventLines)
                    {
                        eventlines.Add(new Line3D(asso.Center, t.Position));                                                               //mxd
                    }
                }
                break;

            case UniversalType.SectorTag:
                foreach (Sector s in General.Map.Map.Sectors)
                {
                    if (!asso.Tags.Overlaps(s.Tags))
                    {
                        continue;
                    }
                    int          highlightedColor = General.Colors.Highlight.WithAlpha(128).ToInt();
                    FlatVertex[] verts            = new FlatVertex[s.FlatVertices.Length];
                    s.FlatVertices.CopyTo(verts, 0);
                    for (int i = 0; i < verts.Length; i++)
                    {
                        verts[i].c = highlightedColor;
                    }
                    renderer.RenderGeometry(verts, null, true);
                }
                break;
            }
        }
Exemple #13
0
        // This updates the settings from configuration
        public void UpdateConfiguration()
        {
            // Lookup settings
            ThingTypeInfo ti = General.Map.Data.GetThingInfo(type);

            // Apply size
            dynamiclighttype = GZGeneral.GetGZLightTypeByClass(ti.Actor);
            if (dynamiclighttype == null)
            {
                dynamiclighttype = ti.DynamicLightType;
            }
            //General.ErrorLogger.Add(ErrorType.Warning, string.Format("thing dynamiclighttype is {0}; class is {1}", dynamiclighttype, ti.Actor.ClassName));
            size        = ti.Radius;
            rendersize  = ti.RenderRadius;
            height      = ti.Height;        //mxd
            fixedsize   = ti.FixedSize;
            spritescale = ti.SpriteScale;   //mxd

            //mxd. Apply radius and height overrides?
            for (int i = 0; i < ti.Args.Length; i++)
            {
                if (ti.Args[i] == null)
                {
                    continue;
                }
                if (ti.Args[i].Type == (int)UniversalType.ThingRadius && args[i] > 0)
                {
                    size = args[i];
                }
                else if (ti.Args[i].Type == (int)UniversalType.ThingHeight && args[i] > 0)
                {
                    height = args[i];
                }
            }

            // Color valid?
            if ((ti.Color >= 0) && (ti.Color < ColorCollection.NUM_THING_COLORS))
            {
                // Apply color
                color = General.Colors.Colors[ti.Color + ColorCollection.THING_COLORS_OFFSET];
            }
            else
            {
                // Unknown thing color
                color = General.Colors.Colors[ColorCollection.THING_COLORS_OFFSET];
            }

            directional = ti.Arrow;      //mxd
            rendermode  = ti.RenderMode; //mxd
            rollsprite  = ti.RollSprite; //mxd
            UpdateCache();               //mxd
        }
        /// <summary>
        /// Checks if there's an association between the element and a Thing
        /// </summary>
        /// <param name="thing">Thing to check the association against</param>
        /// <returns>true if the Thing and the element are associated, false if not</returns>
        private bool IsAssociatedToThing(Thing thing)
        {
            // Get the thing type info
            ThingTypeInfo ti = General.Map.Data.GetThingInfoEx(thing.Type);

            // Known action on this thing?
            if ((thing.Action > 0) && General.Map.Config.LinedefActions.ContainsKey(thing.Action))
            {
                //Do not draw the association if this is a child link.
                //  This prevents a reverse link to a thing via an argument, when it should be a direct tag-to-tag link instead.
                if (ti != null && directlinktype < 0 && directlinktype != -thing.Type)
                {
                    return(false);
                }

                LinedefActionInfo action = General.Map.Config.LinedefActions[thing.Action];
                if (((action.Args[0].Type == (int)type) && (tags.Contains(thing.Args[0]))) ||
                    ((action.Args[1].Type == (int)type) && (tags.Contains(thing.Args[1]))) ||
                    ((action.Args[2].Type == (int)type) && (tags.Contains(thing.Args[2]))) ||
                    ((action.Args[3].Type == (int)type) && (tags.Contains(thing.Args[3]))) ||
                    ((action.Args[4].Type == (int)type) && (tags.Contains(thing.Args[4]))))
                {
                    return(true);
                }

                //If there is a link setup on this thing, and it matches the association, then draw a direct link to any matching tag
                if (ti != null && directlinktype == thing.Type && tags.Contains(thing.Tag))
                {
                    return(true);
                }
            }
            //mxd. Thing action on this thing?
            else if (thing.Action == 0)
            {
                // Gets the association, unless it is a child link.
                // This prevents a reverse link to a thing via an argument, when it should be a direct tag-to-tag link instead.
                if (ti != null && directlinktype >= 0 && Math.Abs(directlinktype) != thing.Type)
                {
                    if (((ti.Args[0].Type == (int)type) && (tags.Contains(thing.Args[0]))) ||
                        ((ti.Args[1].Type == (int)type) && (tags.Contains(thing.Args[1]))) ||
                        ((ti.Args[2].Type == (int)type) && (tags.Contains(thing.Args[2]))) ||
                        ((ti.Args[3].Type == (int)type) && (tags.Contains(thing.Args[3]))) ||
                        ((ti.Args[4].Type == (int)type) && (tags.Contains(thing.Args[4]))))
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
Exemple #15
0
        // This renders the associated things with the indication color
        public static void RenderReverseAssociations(IRenderer2D renderer, Association asso, List <Line3D> eventlines)
        {
            // Tag must be above zero
            if (General.GetByIndex(asso.Tags, 0) < 1)
            {
                return;
            }

            // Things
            foreach (Thing t in General.Map.Map.Things)
            {
                // Known action on this thing?
                if ((t.Action > 0) && General.Map.Config.LinedefActions.ContainsKey(t.Action))
                {
                    LinedefActionInfo action = General.Map.Config.LinedefActions[t.Action];
                    if (((action.Args[0].Type == (int)asso.Type) && (asso.Tags.Contains(t.Args[0]))) ||
                        ((action.Args[1].Type == (int)asso.Type) && (asso.Tags.Contains(t.Args[1]))) ||
                        ((action.Args[2].Type == (int)asso.Type) && (asso.Tags.Contains(t.Args[2]))) ||
                        ((action.Args[3].Type == (int)asso.Type) && (asso.Tags.Contains(t.Args[3]))) ||
                        ((action.Args[4].Type == (int)asso.Type) && (asso.Tags.Contains(t.Args[4]))))
                    {
                        renderer.RenderThing(t, General.Colors.Indication, General.Settings.ActiveThingsAlpha);
                        if (General.Settings.GZShowEventLines)
                        {
                            eventlines.Add(new Line3D(t.Position, asso.Center));                                                           //mxd
                        }
                    }
                }
                //mxd. Thing action on this thing?
                else if (t.Action == 0)
                {
                    ThingTypeInfo ti = General.Map.Data.GetThingInfoEx(t.Type);
                    if (ti != null)
                    {
                        if (((ti.Args[0].Type == (int)asso.Type) && (asso.Tags.Contains(t.Args[0]))) ||
                            ((ti.Args[1].Type == (int)asso.Type) && (asso.Tags.Contains(t.Args[1]))) ||
                            ((ti.Args[2].Type == (int)asso.Type) && (asso.Tags.Contains(t.Args[2]))) ||
                            ((ti.Args[3].Type == (int)asso.Type) && (asso.Tags.Contains(t.Args[3]))) ||
                            ((ti.Args[4].Type == (int)asso.Type) && (asso.Tags.Contains(t.Args[4]))))
                        {
                            renderer.RenderThing(t, General.Colors.Indication, General.Settings.ActiveThingsAlpha);
                            if (General.Settings.GZShowEventLines)
                            {
                                eventlines.Add(new Line3D(t.Position, asso.Center));
                            }
                        }
                    }
                }
            }
        }
Exemple #16
0
        protected override EnumList CreateEnumList()
        {
            // Collect tags
            List <int> tags    = new List <int>();
            EnumList   taglist = new EnumList();

            if (General.Map.Map != null)
            {
                foreach (Thing t in General.Map.Map.Things)
                {
                    if (t.Tag == 0 || tags.Contains(t.Tag))
                    {
                        continue;
                    }

                    // Check target class?
                    if (arginfo.TargetClasses.Count > 0)
                    {
                        ThingTypeInfo info = General.Map.Data.GetThingInfoEx(t.Type);
                        if (info != null && !arginfo.TargetClasses.Contains(info.ClassName))
                        {
                            continue;
                        }
                    }

                    tags.Add(t.Tag);
                }

                // Now sort them in descending order
                tags.Sort((a, b) => - 1 * a.CompareTo(b));

                // Create enum items
                foreach (int tag in tags)
                {
                    if (General.Map.Options.TagLabels.ContainsKey(tag))                    // Tag labels
                    {
                        taglist.Add(new EnumItem(tag.ToString(), General.Map.Options.TagLabels[tag]));
                    }
                    else
                    {
                        taglist.Add(new EnumItem(tag.ToString(), tag.ToString()));
                    }
                }
            }

            return(taglist);
        }
Exemple #17
0
        // This updates the settings from configuration
        public void UpdateConfiguration()
        {
            // Lookup settings
            ThingTypeInfo ti = General.Map.Data.GetThingInfo(type);

            // Apply size
            dynamiclighttype = (Array.IndexOf(GZBuilder.GZGeneral.GZ_LIGHTS, type) != -1) ? type : ti.DynamicLightType;
            size             = ti.Radius;
            height           = ti.Height;      //mxd
            fixedsize        = ti.FixedSize;
            spritescale      = ti.SpriteScale; //mxd

            //mxd. Apply radius and height overrides?
            for (int i = 0; i < ti.Args.Length; i++)
            {
                if (ti.Args[i] == null)
                {
                    continue;
                }
                if (ti.Args[i].Type == (int)UniversalType.ThingRadius && args[i] > 0)
                {
                    size = args[i];
                }
                else if (ti.Args[i].Type == (int)UniversalType.ThingHeight && args[i] > 0)
                {
                    height = args[i];
                }
            }

            // Color valid?
            if ((ti.Color >= 0) && (ti.Color < ColorCollection.NUM_THING_COLORS))
            {
                // Apply color
                color = General.Colors.Colors[ti.Color + ColorCollection.THING_COLORS_OFFSET];
            }
            else
            {
                // Unknown thing color
                color = General.Colors.Colors[ColorCollection.THING_COLORS_OFFSET];
            }

            directional = ti.Arrow;      //mxd
            rendermode  = ti.RenderMode; //mxd
            rollsprite  = ti.RollSprite; //mxd
            UpdateCache();               //mxd
        }
        //set sliders count and labels based on given thing, set lightProps start values
        //this is called only once
        private void SetupSliders(Thing referenceThing)
        {
            ThingTypeInfo typeInfo = General.Map.Data.GetThingInfoEx(referenceThing.DynamicLightType.LightNum);
            int           firstArg = 3;

            if (referenceThing.DynamicLightType.LightVavoom)
            {
                firstArg = 0;
            }

            //first slider is always used
            colorPickerSlider1.Label           = typeInfo.Args[firstArg].Title + ":";
            colorPickerSlider1.OnValueChanged += OnSliderValueChanged;

            //either both of them or none are used
            if (Array.IndexOf(LIGHT_USES_ANGLE_VALUE, referenceThing.DynamicLightType.LightNum) != -1)
            {
                showAllControls                    = true;
                colorPickerSlider2.Label           = typeInfo.Args[4].Title + ":";
                colorPickerSlider2.OnValueChanged += OnSliderValueChanged;

                colorPickerSlider3.Label           = "Interval:";
                colorPickerSlider3.OnValueChanged += OnSliderValueChanged;
                colorPickerSlider3.UseSlider(true);
            }
            else
            {
                colorPickerSlider2.Visible = false;
                colorPickerSlider3.Visible = false;
            }

            //set window height
            int newHeight;

            if (showAllControls)
            {
                newHeight = colorPickerSlider3.Location.Y + colorPickerSlider3.Height + 8;
            }
            else
            {
                newHeight = colorPickerSlider1.Location.Y + colorPickerSlider1.Height + 8;
            }

            this.ClientSize = new Size(this.ClientSize.Width, newHeight);
        }
Exemple #19
0
        // This forces to rebuild the whole thing
        public void Rebuild()
        {
            // Find thing information
            info = General.Map.Data.GetThingInfo(Thing.Type);

            // Find sprite texture
            if (info.Sprite.Length > 0)
            {
                sprite = General.Map.Data.GetSpriteImage(info.Sprite);
                if (sprite != null)
                {
                    sprite.AddReference();
                }
            }

            // Setup visual thing
            Setup();
        }
        // This is called to perform a search (and replace)
        // Returns a list of items to show in the results list
        // replacewith is null when not replacing
        public override FindReplaceObject[] Find(string value, bool withinselection, bool replace, string replacewith, bool keepselection)
        {
            List <FindReplaceObject> objs = new List <FindReplaceObject>();

            // Interpret the number given
            int index;

            if (int.TryParse(value, out index))
            {
                Thing t = General.Map.Map.GetThingByIndex(index);
                if (t != null)
                {
                    ThingTypeInfo ti = General.Map.Data.GetThingInfo(t.Type);
                    objs.Add(new FindReplaceObject(t, "Thing " + index + " (" + ti.Title + ")"));
                }
            }

            return(objs.ToArray());
        }
Exemple #21
0
        private void Setup(ICollection <Thing> selection)
        {
            this.selection = selection;

            //get thing types
            Dictionary <int, int>    thingcounts = new Dictionary <int, int>();
            Dictionary <int, string> thingtitles = new Dictionary <int, string>();

            foreach (Thing t in selection)
            {
                if (!thingcounts.ContainsKey(t.Type))
                {
                    thingcounts.Add(t.Type, 1);
                    ThingTypeInfo ti = General.Map.Data.GetThingInfo(t.Type);
                    thingtitles.Add(t.Type, ti.Title);
                }
                else
                {
                    thingcounts[t.Type]++;
                }
            }

            //add data
            foreach (KeyValuePair <int, int> group in thingcounts)
            {
                DataGridViewRow row = new DataGridViewRow();

                row.Cells.Add(new DataGridViewTextBoxCell {
                    Value = group.Key
                });                                                                               //type
                row.Cells.Add(new DataGridViewTextBoxCell {
                    Value = thingtitles[group.Key]
                });                                                                                            //title
                row.Cells.Add(new DataGridViewTextBoxCell {
                    Value = group.Value
                });                                                                                 //count

                dataGridView.Rows.Add(row);
            }

            dataGridView.Sort(ThingType, ListSortDirection.Ascending);
        }
Exemple #22
0
        // Thing type selection changed
        private void typelist_AfterSelect(object sender, TreeViewEventArgs e)
        {
            if (doupdatetextbox)
            {
                // Anything selected?
                if (typelist.SelectedNode != null)
                {
                    TreeNode n = typelist.SelectedNode;

                    // Node is a child node?
                    if ((n.Nodes.Count == 0) && (n.Tag != null) && (n.Tag is ThingTypeInfo))
                    {
                        ThingTypeInfo ti = (n.Tag as ThingTypeInfo);

                        // Show info
                        typeid.Text = ti.Index.ToString();
                    }
                }
            }
        }
Exemple #23
0
        // Constructor
        public BaseVisualThing(BaseVisualMode mode, Thing t) : base(t)
        {
            this.mode = mode;

            // Find thing information
            info = General.Map.Data.GetThingInfo(Thing.Type);

            // Find sprite texture
            if (info.Sprite.Length > 0)
            {
                sprite = General.Map.Data.GetSpriteImage(info.Sprite);
                if (sprite != null)
                {
                    sprite.AddReference();
                }
            }

            // We have no destructor
            GC.SuppressFinalize(this);
        }
Exemple #24
0
        // This is called to perform a search (and replace)
        // Returns a list of items to show in the results list
        // replacewith is null when not replacing
        public override FindReplaceObject[] Find(string value, bool withinselection, string replacewith, bool keepselection)
        {
            List <FindReplaceObject> objs = new List <FindReplaceObject>();

            // Where to search?
            ICollection <Thing> list = withinselection ? General.Map.Map.GetSelectedThings(true) : General.Map.Map.Things;

            // Go for all things
            foreach (Thing t in list)
            {
                bool match = true;

                // Parse the value string...
                foreach (string s in value.Split(','))
                {
                    string str = s.Trim();

                    // ... and check if the flags don't match
                    if (General.Map.Config.ThingFlags.ContainsKey(str) && !t.IsFlagSet(str))
                    {
                        match = false;
                        break;
                    }
                }

                // Match?
                if (match)
                {
                    // Add to list
                    ThingTypeInfo ti = General.Map.Data.GetThingInfo(t.Type);
                    objs.Add(new FindReplaceObject(t, "Thing " + t.Index + " (" + ti.Title + ")"));
                }
            }

            return(objs.ToArray());
        }
Exemple #25
0
        // This renders the associated things with the indication color
        public static void RenderReverseAssociations(IRenderer2D renderer, Association asso, List <Line3D> eventlines)
        {
            // Tag must be above zero
            if (General.GetByIndex(asso.Tags, 0) < 1)
            {
                return;
            }

            // Things
            foreach (Thing t in General.Map.Map.Things)
            {
                // Get the thing type info
                ThingTypeInfo ti = General.Map.Data.GetThingInfoEx(t.Type);

                // Known action on this thing?
                if ((t.Action > 0) && General.Map.Config.LinedefActions.ContainsKey(t.Action))
                {
                    //Do not draw the association if this is a child link.
                    //  This prevents a reverse link to a thing via an argument, when it should be a direct tag-to-tag link instead.
                    if (ti != null && asso.DirectLinkType < 0 && asso.DirectLinkType != -t.Type)
                    {
                        continue;
                    }

                    LinedefActionInfo action = General.Map.Config.LinedefActions[t.Action];
                    if (((action.Args[0].Type == (int)asso.Type) && (asso.Tags.Contains(t.Args[0]))) ||
                        ((action.Args[1].Type == (int)asso.Type) && (asso.Tags.Contains(t.Args[1]))) ||
                        ((action.Args[2].Type == (int)asso.Type) && (asso.Tags.Contains(t.Args[2]))) ||
                        ((action.Args[3].Type == (int)asso.Type) && (asso.Tags.Contains(t.Args[3]))) ||
                        ((action.Args[4].Type == (int)asso.Type) && (asso.Tags.Contains(t.Args[4]))))
                    {
                        renderer.RenderThing(t, General.Colors.Indication, General.Settings.ActiveThingsAlpha);
                        if (General.Settings.GZShowEventLines)
                        {
                            eventlines.Add(new Line3D(t.Position, asso.Center));                                                           //mxd
                        }
                    }

                    //If there is a link setup on this thing, and it matches the association, then draw a direct link to any matching tag
                    if (ti != null && asso.DirectLinkType == t.Type && asso.Tags.Contains(t.Tag))
                    {
                        renderer.RenderThing(t, General.Colors.Indication, General.Settings.ActiveThingsAlpha);
                        if (General.Settings.GZShowEventLines)
                        {
                            eventlines.Add(new Line3D(t.Position, asso.Center));
                        }
                    }
                }
                //mxd. Thing action on this thing?
                else if (t.Action == 0)
                {
                    //Draw the association, unless it is a child link.
                    //  This prevents a reverse link to a thing via an argument, when it should be a direct tag-to-tag link instead.
                    if (ti != null && asso.DirectLinkType >= 0 && Math.Abs(asso.DirectLinkType) != t.Type)
                    {
                        if (((ti.Args[0].Type == (int)asso.Type) && (asso.Tags.Contains(t.Args[0]))) ||
                            ((ti.Args[1].Type == (int)asso.Type) && (asso.Tags.Contains(t.Args[1]))) ||
                            ((ti.Args[2].Type == (int)asso.Type) && (asso.Tags.Contains(t.Args[2]))) ||
                            ((ti.Args[3].Type == (int)asso.Type) && (asso.Tags.Contains(t.Args[3]))) ||
                            ((ti.Args[4].Type == (int)asso.Type) && (asso.Tags.Contains(t.Args[4]))))
                        {
                            renderer.RenderThing(t, General.Colors.Indication, General.Settings.ActiveThingsAlpha);
                            if (General.Settings.GZShowEventLines)
                            {
                                eventlines.Add(new Line3D(t.Position, asso.Center));
                            }
                        }
                    }
                }
            }
        }
        // Apply clicked
        private void apply_Click(object sender, EventArgs e)
        {
            //mxd. Make Undo
            MakeUndo();

            List <string> defaultflags = new List <string>();

            // Verify the tag
            if (General.Map.FormatInterface.HasThingTag)  //mxd
            {
                tagSelector.ValidateTag();                //mxd
                if (((tagSelector.GetTag(0) < General.Map.FormatInterface.MinTag) || (tagSelector.GetTag(0) > General.Map.FormatInterface.MaxTag)))
                {
                    General.ShowWarningMessage("Thing tag must be between " + General.Map.FormatInterface.MinTag + " and " + General.Map.FormatInterface.MaxTag + ".", MessageBoxButtons.OK);
                    return;
                }
            }

            // Verify the type
            if (!string.IsNullOrEmpty(thingtype.TypeStringValue) && ((thingtype.GetResult(0) < General.Map.FormatInterface.MinThingType) || (thingtype.GetResult(0) > General.Map.FormatInterface.MaxThingType)))
            {
                General.ShowWarningMessage("Thing type must be between " + General.Map.FormatInterface.MinThingType + " and " + General.Map.FormatInterface.MaxThingType + ".", MessageBoxButtons.OK);
                return;
            }

            // Verify the action
            if (General.Map.FormatInterface.HasThingAction && ((action.Value < General.Map.FormatInterface.MinAction) || (action.Value > General.Map.FormatInterface.MaxAction)))
            {
                General.ShowWarningMessage("Thing action must be between " + General.Map.FormatInterface.MinAction + " and " + General.Map.FormatInterface.MaxAction + ".", MessageBoxButtons.OK);
                return;
            }

            // Go for all the things
            int offset = 0;             //mxd

            foreach (Thing t in things)
            {
                // Coordination
                //mxd. Randomize rotations?
                if (cbrandomangle.Checked)
                {
                    int newangle = General.Random(0, 359);
                    if (General.Map.Config.DoomThingRotationAngles)
                    {
                        newangle = newangle / 45 * 45;
                    }
                    t.Rotate(newangle);
                }
                if (cbrandompitch.Checked)
                {
                    t.SetPitch(General.Random(0, 359));
                }
                if (cbrandomroll.Checked)
                {
                    t.SetRoll(General.Random(0, 359));
                }

                //mxd. Check position
                double px = General.Clamp(t.Position.x, General.Map.Config.LeftBoundary, General.Map.Config.RightBoundary);
                double py = General.Clamp(t.Position.y, General.Map.Config.BottomBoundary, General.Map.Config.TopBoundary);
                if (t.Position.x != px || t.Position.y != py)
                {
                    t.Move(new Vector2D(px, py));
                }

                // Action/tags
                t.Tag = General.Clamp(tagSelector.GetSmartTag(t.Tag, offset), General.Map.FormatInterface.MinTag, General.Map.FormatInterface.MaxTag);                 //mxd
                if (!action.Empty)
                {
                    t.Action = action.Value;
                }

                //mxd. Apply args
                argscontrol.Apply(t, offset);

                //mxd. Custom fields
                fieldslist.Apply(t.Fields);
                if (!string.IsNullOrEmpty(conversationID.Text))
                {
                    UniFields.SetInteger(t.Fields, "conversation", conversationID.GetResult(t.Fields.GetValue("conversation", 0)), 0);
                }
                if (!string.IsNullOrEmpty(floatbobphase.Text))
                {
                    UniFields.SetInteger(t.Fields, "floatbobphase", General.Clamp(floatbobphase.GetResult(t.Fields.GetValue("floatbobphase", -1)), -1, 63), -1);
                }
                if (!string.IsNullOrEmpty(gravity.Text))
                {
                    UniFields.SetFloat(t.Fields, "gravity", gravity.GetResultFloat(t.Fields.GetValue("gravity", 1.0)), 1.0);
                }
                if (!string.IsNullOrEmpty(health.Text))
                {
                    UniFields.SetInteger(t.Fields, "health", health.GetResult(t.Fields.GetValue("health", 1)), 1);
                }
                if (!string.IsNullOrEmpty(score.Text))
                {
                    UniFields.SetInteger(t.Fields, "score", score.GetResult(t.Fields.GetValue("score", 0)), 0);
                }

                //mxd. User vars. Should be called after fieldslist.Apply()
                ThingTypeInfo ti = General.Map.Data.GetThingInfoEx(t.Type);
                if (ti != null && ti.Actor != null && ti.Actor.UserVars.Count > 0)
                {
                    fieldslist.ApplyUserVars(ti.Actor.UserVars, t.Fields);
                }

                color.ApplyTo(t.Fields, t.Fields.GetValue("fillcolor", 0));

                //mxd. Comments
                commenteditor.Apply(t.Fields);

                // Update settings
                t.UpdateConfiguration();

                //mxd. Increase offset...
                offset++;
            }

            // Set as defaults
            foreach (CheckBox c in flags.Checkboxes)
            {
                if (c.CheckState == CheckState.Checked)
                {
                    defaultflags.Add(c.Tag.ToString());
                }
            }
            General.Settings.DefaultThingType  = thingtype.GetResult(General.Settings.DefaultThingType);
            General.Settings.DefaultThingAngle = Angle2D.DegToRad((float)angle.GetResult((int)Angle2D.RadToDeg(General.Settings.DefaultThingAngle) - 90) + 90);
            General.Settings.SetDefaultThingFlags(defaultflags);

            // Done
            General.Map.IsChanged = true;
            if (OnValuesChanged != null)
            {
                OnValuesChanged(this, EventArgs.Empty);                                     //mxd
            }
            this.DialogResult = DialogResult.OK;
            this.Close();
        }
        // This sets up the form to edit the given things
        public void Setup(ICollection <Thing> things)
        {
            preventchanges = true;
            undocreated    = false;
            argscontrol.Reset();

            // Keep this list
            this.things = things;
            if (things.Count > 1)
            {
                this.Text = "Edit Things (" + things.Count + ")";
            }
            hint.Visible                = things.Count > 1; //mxd
            hintlabel.Visible           = things.Count > 1; //mxd
            thingtype.UseMultiSelection = things.Count > 1; //mxd

            ////////////////////////////////////////////////////////////////////////
            // Set all options to the first thing properties
            ////////////////////////////////////////////////////////////////////////

            Thing ft = General.GetByIndex(things, 0);

            // Set type
            thingtype.SelectType(ft.Type);

            // Flags
            foreach (CheckBox c in flags.Checkboxes)
            {
                if (ft.Flags.ContainsKey(c.Tag.ToString()))
                {
                    c.Checked = ft.Flags[c.Tag.ToString()];
                }
            }

            // Coordination
            angle.Text  = ft.AngleDoom.ToString();
            zlabel.Text = useabsoluteheight ? "Z:" : "Height:";       //mxd
            cbAbsoluteHeight.Checked = useabsoluteheight;             //mxd

            //mxd
            ft.DetermineSector();
            float floorheight = (ft.Sector != null ? Sector.GetFloorPlane(ft.Sector).GetZ(ft.Position) : 0);

            posX.Text       = ((int)ft.Position.x).ToString();
            posY.Text       = ((int)ft.Position.y).ToString();
            posZ.Text       = (useabsoluteheight ? ((int)Math.Round(ft.Position.z + floorheight)).ToString() : ((int)ft.Position.z).ToString());
            posX.ButtonStep = General.Map.Grid.GridSize;
            posY.ButtonStep = General.Map.Grid.GridSize;
            posZ.ButtonStep = General.Map.Grid.GridSize;

            //mxd
            thinginfo = General.Map.Data.GetThingInfoEx(ft.Type);

            // Action/tags
            action.Value = ft.Action;
            if (General.Map.FormatInterface.HasThingTag)            //mxd
            {
                tagSelector.Setup(UniversalType.ThingTag);
                tagSelector.SetTag(ft.Tag);
            }

            //mxd. Args
            argscontrol.SetValue(ft, true);

            ////////////////////////////////////////////////////////////////////////
            // Now go for all lines and change the options when a setting is different
            ////////////////////////////////////////////////////////////////////////

            thingprops = new List <ThingProperties>();

            // Go for all things
            foreach (Thing t in things)
            {
                //mxd. Update sector info
                t.DetermineSector();

                // Type does not match?
                ThingTypeInfo info = thingtype.GetSelectedInfo();                 //mxd

                if (info != null && info.Index != t.Type)
                {
                    thingtype.ClearSelectedType();
                    thinginfo = null;                     //mxd
                }

                // Flags
                foreach (CheckBox c in flags.Checkboxes)
                {
                    if (c.CheckState == CheckState.Indeterminate)
                    {
                        continue;                                                              //mxd
                    }
                    if (t.IsFlagSet(c.Tag.ToString()) != c.Checked)
                    {
                        c.ThreeState = true;
                        c.CheckState = CheckState.Indeterminate;
                    }
                }

                // Coordination
                if (t.AngleDoom.ToString() != angle.Text)
                {
                    angle.Text = "";
                }

                //mxd. Position
                if (((int)t.Position.x).ToString() != posX.Text)
                {
                    posX.Text = "";
                }
                if (((int)t.Position.y).ToString() != posY.Text)
                {
                    posY.Text = "";
                }
                if (useabsoluteheight && t.Sector != null)
                {
                    if (((int)Math.Round(Sector.GetFloorPlane(t.Sector).GetZ(t.Position) + t.Position.z)).ToString() != posZ.Text)
                    {
                        posZ.Text = "";
                    }
                }
                else if (((int)t.Position.z).ToString() != posZ.Text)
                {
                    posZ.Text = "";
                }

                // Action/tags
                if (t.Action != action.Value)
                {
                    action.Empty = true;
                }
                if (General.Map.FormatInterface.HasThingTag && t.Tag != ft.Tag)
                {
                    tagSelector.ClearTag();                                                                            //mxd
                }
                //mxd. Arguments
                argscontrol.SetValue(t, false);

                //mxd. Store initial properties
                thingprops.Add(new ThingProperties(t));
            }

            preventchanges = false;

            //mxd. Trigger updates manually...
            preventmapchange = true;
            angle_WhenTextChanged(angle, EventArgs.Empty);
            flags_OnValueChanged(flags, EventArgs.Empty);
            preventmapchange = false;

            argscontrol.UpdateScriptControls();         //mxd
            actionhelp.UpdateAction(action.GetValue()); //mxd
            UpdateFlagNames();                          //mxd
        }
Exemple #28
0
        //mxd
        protected static void DeleteThings(ICollection <Thing> things)
        {
            if (things.Count == 0)
            {
                return;
            }

            General.Map.Map.BeginAddRemove();             //mxd

            // Dispose selected things
            foreach (Thing t in things)
            {
                //mxd. Do some path reconnecting shenanigans...
                ThingTypeInfo info        = General.Map.Data.GetThingInfo(t.Type);
                string        targetclass = string.Empty;
                int           targetarg   = -1;

                // Thing type can be changed in MAPINFO DoomEdNums block...
                switch (info.ClassName.ToLowerInvariant())
                {
                case "interpolationpoint":
                    if (t.Tag != 0 && t.Args[3] != 0)
                    {
                        targetclass = "interpolationpoint";
                        targetarg   = 3;
                    }
                    break;

                case "patrolpoint":
                    if (t.Tag != 0 && t.Args[0] != 0)
                    {
                        targetclass = "patrolpoint";
                        targetarg   = 0;
                    }
                    break;
                }

                // Try to reconnect path...
                if (!string.IsNullOrEmpty(targetclass) && targetarg > -1)
                {
                    General.Map.Map.EndAddRemove();                     // We'll need to unlock the things array...

                    foreach (Thing other in General.Map.Map.Things)
                    {
                        if (other.Index == t.Index)
                        {
                            continue;
                        }
                        info = General.Map.Data.GetThingInfo(other.Type);
                        if (info.ClassName.ToLowerInvariant() == targetclass && other.Args[targetarg] == t.Tag)
                        {
                            other.Move(other.Position);                             //hacky way to call BeforePropsChange()...
                            other.Args[targetarg] = t.Args[targetarg];
                            break;
                        }
                    }

                    General.Map.Map.BeginAddRemove();                     // We'll need to lock it again...
                }

                // Get rid of the thing
                t.Dispose();
            }

            General.Map.Map.EndAddRemove();             //mxd
        }
        /// <summary>
        /// Gets a dictionary of sector tags, linedef tags, and thing tags, grouped by their type, that the map element is referencing
        /// </summary>
        /// <returns>Dictionary of sector tags, linedef tags, and thing tags that the map element is referencing</returns>
        private Dictionary <int, HashSet <int> > GetTagsByType()
        {
            LinedefActionInfo action = null;

            int[] actionargs = new int[5];
            Dictionary <int, HashSet <int> > actiontags = new Dictionary <int, HashSet <int> >();

            // Get the action and its arguments from a linedef or a thing, if they have them
            if (element is Linedef)
            {
                Linedef ld = element as Linedef;

                if (ld.Action > 0 && General.Map.Config.LinedefActions.ContainsKey(ld.Action))
                {
                    action = General.Map.Config.LinedefActions[ld.Action];
                }

                actionargs = ld.Args;
            }
            else if (element is Thing)
            {
                Thing t = element as Thing;

                if (t.Action > 0 && General.Map.Config.LinedefActions.ContainsKey(t.Action))
                {
                    action = General.Map.Config.LinedefActions[t.Action];
                }

                actionargs = t.Args;
            }
            else             // element is a Sector
            {
                return(actiontags);
            }

            if (action != null)
            {
                // Collect what map element the action arguments are referencing. Ignore the argument if it's 0, so that they
                // are not associated to everything untagged
                for (int i = 0; i < Linedef.NUM_ARGS; i++)
                {
                    if ((action.Args[i].Type == (int)UniversalType.SectorTag ||
                         action.Args[i].Type == (int)UniversalType.LinedefTag ||
                         action.Args[i].Type == (int)UniversalType.ThingTag) &&
                        actionargs[i] > 0)
                    {
                        if (!actiontags.ContainsKey(action.Args[i].Type))
                        {
                            actiontags[action.Args[i].Type] = new HashSet <int>();
                        }

                        actiontags[action.Args[i].Type].Add(actionargs[i]);
                    }
                }
            }
            else if (element is Thing && directlinktype >= 0 && Math.Abs(directlinktype) != ((Thing)element).Type)
            {
                // The direct link shenanigans if the thing doesn't have an action, but still reference something through
                // the action parameters
                Thing         t  = element as Thing;
                ThingTypeInfo ti = General.Map.Data.GetThingInfoEx(t.Type);

                if (ti != null && directlinktype >= 0 && Math.Abs(directlinktype) != t.Type)
                {
                    for (int i = 0; i < Linedef.NUM_ARGS; i++)
                    {
                        if ((ti.Args[i].Type == (int)UniversalType.SectorTag ||
                             ti.Args[i].Type == (int)UniversalType.LinedefTag ||
                             ti.Args[i].Type == (int)UniversalType.ThingTag))
                        {
                            if (!actiontags.ContainsKey(ti.Args[i].Type))
                            {
                                actiontags[ti.Args[i].Type] = new HashSet <int>();
                            }

                            actiontags[ti.Args[i].Type].Add(actionargs[i]);
                        }
                    }
                }
            }

            return(actiontags);
        }
        /// <summary>
        /// Sets the association to a map element. Only works with an instance of Thing, Sector, or Linedef.
        /// Also gets the forward and reverse associations
        /// </summary>
        /// <param name="element">An instance of Thing, Sector, or Linedef</param>
        public void Set(SelectableElement element)
        {
            this.element = element;
            things       = new List <Thing>();
            sectors      = new List <Sector>();
            linedefs     = new List <Linedef>();
            eventlines   = new Dictionary <string, List <Line3D> >();

            if (element is Sector)
            {
                Sector s = element as Sector;
                center = (s.Labels.Count > 0 ? s.Labels[0].position : new Vector2D(s.BBox.X + s.BBox.Width / 2, s.BBox.Y + s.BBox.Height / 2));

                type = UniversalType.SectorTag;
                tags = new HashSet <int>(s.Tags);
            }
            else if (element is Linedef)
            {
                Linedef ld = element as Linedef;
                center = ld.GetCenterPoint();

                type = UniversalType.LinedefTag;
                tags = new HashSet <int>(ld.Tags);
            }
            else if (element is Thing)
            {
                Thing t = element as Thing;
                center = t.Position;

                ThingTypeInfo ti = General.Map.Data.GetThingInfoEx(t.Type);

                if (ti != null)
                {
                    directlinktype = ti.ThingLink;
                }
                else
                {
                    directlinktype = 0;
                }

                type = UniversalType.ThingTag;
                tags = new HashSet <int>(new int[] { t.Tag });
            }

            // Remove the tag 0, because nothing sensible will come from it
            tags.Remove(0);

            // Get forward and reverse associations
            GetAssociations();

            // Cache width of label text and generate the labels
            textwidths = new Dictionary <string, Vector2D>(eventlines.Count);
            textlabels = new Dictionary <string, List <TextLabel> >(eventlines.Count);

            foreach (KeyValuePair <string, List <Line3D> > kvp in eventlines)
            {
                SizeF size = General.Interface.MeasureString(kvp.Key, font);
                textwidths[kvp.Key] = new Vector2D(size.Width, size.Height);

                // Create one label for each line. We might not need them all, but better
                // to have them all at the beginning than to generate them later
                textlabels[kvp.Key] = new List <TextLabel>(kvp.Value.Count);

                for (int i = 0; i < kvp.Value.Count; i++)
                {
                    // We don't need to set the position here, since it'll be done on the fly later
                    TextLabel l = new TextLabel();
                    l.AlignX          = TextAlignmentX.Center;
                    l.AlignY          = TextAlignmentY.Middle;
                    l.TransformCoords = true;
                    l.Text            = kvp.Key;

                    textlabels[kvp.Key].Add(l);
                }

                textwidths[kvp.Key] = new Vector2D(textlabels[kvp.Key][0].TextSize.Width, textlabels[kvp.Key][0].TextSize.Height);
            }

            SetEventLineColors();
        }