예제 #1
0
        private static bool MoveObjectOnObjectsRoot(TreeNode treeNodeMoving, TreeNode targetNode, NamedObjectSave movingNos, bool succeeded)
        {
            // Dropped it on the "Objects" tree node

            // Let's see if it's the Objects that contains node or another one

            IElement parentOfMovingNos = movingNos.GetContainer();
            IElement elementMovingInto = ((BaseElementTreeNode)targetNode.Parent).SaveObject;

            if (parentOfMovingNos == elementMovingInto)
            {
                if (treeNodeMoving.Parent.IsNamedObjectNode())
                {
                    succeeded = true;

                    // removing from a list
                    NamedObjectSave container = treeNodeMoving.Parent.Tag as NamedObjectSave;

                    IElement elementToAddTo = movingNos.GetContainer();
                    container.ContainedObjects.Remove(movingNos);
                    AddExistingNamedObjectToElement(
                        GlueState.Self.CurrentElement, movingNos);
                    EditorLogic.CurrentElementTreeNode.UpdateReferencedTreeNodes();

                    IElement elementToRegenerate = targetNode.Parent.Tag as IElement;
                }
            }
            else
            {
                succeeded = DragDropNosIntoElement(movingNos, elementMovingInto);
            }
            return(succeeded);
        }
예제 #2
0
        public static string GetSecondGenericType(NamedObjectSave collisionRelationship, out bool isList)
        {
            var secondName = collisionRelationship.Properties.GetValue <string>(nameof(CollisionRelationshipViewModel.SecondCollisionName));

            var container = collisionRelationship.GetContainer();

            string secondType = null;

            isList = false;

            if (container != null)
            {
                var secondObject = container.GetNamedObject(secondName);

                isList = secondObject?.IsList == true;

                if (secondObject != null)
                {
                    if (secondObject.IsList)
                    {
                        secondType = secondObject.SourceClassGenericType?.Replace("\\", ".");
                    }
                    else
                    {
                        secondType = NamedObjectSaveCodeGenerator.GetQualifiedTypeName(secondObject);
                    }
                }
            }

            return(secondType);
        }
예제 #3
0
        public TreeNode NamedObjectTreeNode(NamedObjectSave namedObjectSave)
        {
            IElement container = namedObjectSave.GetContainer();

            if (container is ScreenSave)
            {
                ScreenTreeNode screenTreeNode = GlueState.Self.Find.ScreenTreeNode((ScreenSave)container);
                return(screenTreeNode.GetTreeNodeFor(namedObjectSave));
            }
            else if (container is EntitySave)
            {
                EntityTreeNode entityTreeNode = GlueState.Self.Find.EntityTreeNode((EntitySave)container);
                return(entityTreeNode.GetTreeNodeFor(namedObjectSave));
            }
            else
            {
                return(null);
            }
        }
예제 #4
0
        public static void RemoveNamedObject(NamedObjectSave namedObjectToRemove, bool performSave, bool updateUi, List <string> additionalFilesToRemove)
        {
            StringBuilder removalInformation = new StringBuilder();

            // The additionalFilesToRemove is included for consistency with other methods.  It may be used later

            // There are the following things that need to happen:
            // 1.  Remove the NamedObject from the Glue project (GLUX)
            // 2.  Remove any variables that use this NamedObject as their source
            // 3.  Remove the named object from the GUI
            // 4.  Update the variables for any NamedObjects that use this element containing this NamedObject
            // 5.  Find any Elements that contain NamedObjects that are DefinedByBase - if so, see if we should remove those or make them not DefinedByBase
            // 6.  Remove any events that tunnel into this.

            IElement element = namedObjectToRemove.GetContainer();

            if (element != null)
            {
                if (!namedObjectToRemove.RemoveSelfFromNamedObjectList(element.NamedObjects))
                {
                    throw new ArgumentException();
                }

                #region Remove all CustomVariables that reference the removed NamedObject
                for (int i = element.CustomVariables.Count - 1; i > -1; i--)
                {
                    CustomVariable variable = element.CustomVariables[i];

                    if (variable.SourceObject == namedObjectToRemove.InstanceName)
                    {
                        removalInformation.AppendLine("Removed variable " + variable.ToString());

                        element.CustomVariables.RemoveAt(i);
                    }
                }
                #endregion

                // Remove any events that use this
                for (int i = element.Events.Count - 1; i > -1; i--)
                {
                    EventResponseSave ers = element.Events[i];
                    if (ers.SourceObject == namedObjectToRemove.InstanceName)
                    {
                        removalInformation.AppendLine("Removed event " + ers.ToString());
                        element.Events.RemoveAt(i);
                    }
                }

                // Remove any objects that use this as a layer
                for (int i = 0; i < element.NamedObjects.Count; i++)
                {
                    if (element.NamedObjects[i].LayerOn == namedObjectToRemove.InstanceName)
                    {
                        removalInformation.AppendLine("Removed the following object from the deleted Layer: " + element.NamedObjects[i].ToString());
                        element.NamedObjects[i].LayerOn = null;
                    }
                }



                element.RefreshStatesToCustomVariables();

                #region Ask the user what to do with all NamedObjects that are DefinedByBase

                List <IElement> derivedElements = new List <IElement>();
                if (element is EntitySave)
                {
                    derivedElements.AddRange(ObjectFinder.Self.GetAllEntitiesThatInheritFrom(element as EntitySave));
                }
                else
                {
                    derivedElements.AddRange(ObjectFinder.Self.GetAllScreensThatInheritFrom(element as ScreenSave));
                }

                foreach (IElement derivedElement in derivedElements)
                {
                    // At this point, namedObjectToRemove is already removed from the current Element, so this will only
                    // return NamedObjects that exist in the derived.
                    NamedObjectSave derivedNamedObject = derivedElement.GetNamedObjectRecursively(namedObjectToRemove.InstanceName);

                    if (derivedNamedObject != null && derivedNamedObject != namedObjectToRemove && derivedNamedObject.DefinedByBase)
                    {
                        MultiButtonMessageBox mbmb = new MultiButtonMessageBox();
                        mbmb.MessageText = "What would you like to do with the object " + derivedNamedObject.ToString();
                        mbmb.AddButton("Keep it", DialogResult.OK);
                        mbmb.AddButton("Delete it", DialogResult.Cancel);

                        DialogResult result = mbmb.ShowDialog(MainGlueWindow.Self);

                        if (result == DialogResult.OK)
                        {
                            // Keep it
                            derivedNamedObject.DefinedByBase = false;
                            BaseElementTreeNode treeNode = GlueState.Self.Find.ElementTreeNode(derivedElement);

                            if (updateUi)
                            {
                                treeNode.UpdateReferencedTreeNodes();
                            }
                            CodeWriter.GenerateCode(derivedElement);
                        }
                        else
                        {
                            // Delete it
                            RemoveNamedObject(derivedNamedObject, performSave, updateUi, additionalFilesToRemove);
                        }
                    }
                }
                #endregion


                var elementTreeNode = GlueState.Self.Find.ElementTreeNode(element);

                if (updateUi)
                {
                    elementTreeNode.UpdateReferencedTreeNodes();
                }
                CodeWriter.GenerateCode(element);
                if (element is EntitySave)
                {
                    List <NamedObjectSave> entityNamedObjects = ObjectFinder.Self.GetAllNamedObjectsThatUseEntity(element.Name);

                    foreach (NamedObjectSave nos in entityNamedObjects)
                    {
                        nos.UpdateCustomProperties();
                    }
                }
            }

            if (performSave)
            {
                GluxCommands.Self.SaveGlux();
            }
        }
예제 #5
0
        public void GetTextureCoordinates(NamedObjectSave nos, out float leftTextureCoordinate, out float rightTextureCoordinate, out float topTextureCoordinate, out float bottomTextureCoordinate, out string fullFileName)
        {
            var textureVar = nos.InstructionSaves.FirstOrDefault(item => item.Member == "Texture");
            var leftTextureCoordinateVar   = nos.InstructionSaves.FirstOrDefault(item => item.Member == "LeftTexturePixel");
            var rightTextureCoordinateVar  = nos.InstructionSaves.FirstOrDefault(item => item.Member == "RightTexturePixel");
            var topTextureCoordinateVar    = nos.InstructionSaves.FirstOrDefault(item => item.Member == "TopTexturePixel");
            var bottomTextureCoordinateVar = nos.InstructionSaves.FirstOrDefault(item => item.Member == "BottomTexturePixel");


            leftTextureCoordinate   = 0;
            rightTextureCoordinate  = 1;
            topTextureCoordinate    = 0;
            bottomTextureCoordinate = 1;

            fullFileName = null;

            if (textureVar != null && textureVar.Value != null)
            {
                var fileVariableName = textureVar.Value as string;

                var container = nos.GetContainer();

                var rfs = container.ReferencedFiles.FirstOrDefault((item) =>
                {
                    return(FileManager.RemovePath(FileManager.RemoveExtension(item.Name)) == fileVariableName);
                });

                if (rfs == null)
                {
                    var allBaseElements = container.BaseElements();
                    foreach (var baseElement in allBaseElements)
                    {
                        rfs = baseElement.ReferencedFiles.FirstOrDefault((item) =>
                        {
                            return(FileManager.RemovePath(FileManager.RemoveExtension(item.Name)) == fileVariableName);
                        });

                        if (rfs != null)
                        {
                            break;
                        }
                    }
                }



                if (rfs != null)
                {
                    fullFileName = FlatRedBall.Glue.ProjectManager.MakeAbsolute(rfs.Name, true);
                }
            }

            if (leftTextureCoordinateVar != null && leftTextureCoordinateVar.Value != null)
            {
                leftTextureCoordinate = (float)leftTextureCoordinateVar.Value;
            }

            if (rightTextureCoordinateVar != null && rightTextureCoordinateVar.Value != null)
            {
                rightTextureCoordinate = (float)rightTextureCoordinateVar.Value;
            }

            if (topTextureCoordinateVar != null && topTextureCoordinateVar.Value != null)
            {
                topTextureCoordinate = (float)topTextureCoordinateVar.Value;
            }

            if (bottomTextureCoordinateVar != null && bottomTextureCoordinateVar.Value != null)
            {
                bottomTextureCoordinate = (float)bottomTextureCoordinateVar.Value;
            }

            bool needsFile = rightTextureCoordinateVar == null || bottomTextureCoordinateVar == null;

            if (needsFile)
            {
                if (System.IO.File.Exists(fullFileName))
                {
                    var size = Glue.IO.ImageHeader.GetDimensions(fullFileName);
                    if (rightTextureCoordinateVar == null)
                    {
                        rightTextureCoordinate = size.Width;
                    }
                    if (bottomTextureCoordinateVar == null)
                    {
                        bottomTextureCoordinate = size.Height;
                    }
                }
            }
        }
예제 #6
0
        public static void ElementDoubleClicked()
        {
            TreeNode selectedNode = SelectedNode;

            if (selectedNode != null)
            {
                string text = selectedNode.Text;



                #region Double-clicked a file
                string extension       = FileManager.GetExtension(text);
                string sourceExtension = null;

                if (EditorLogic.CurrentReferencedFile != null && !string.IsNullOrEmpty(EditorLogic.CurrentReferencedFile.SourceFile))
                {
                    sourceExtension = FileManager.GetExtension(EditorLogic.CurrentReferencedFile.SourceFile);
                }
                if (EditorLogic.CurrentReferencedFile != null && !string.IsNullOrEmpty(extension))
                {
                    string application = "";

                    ReferencedFileSave currentReferencedFileSave = EditorLogic.CurrentReferencedFile;
                    string             fileName;

                    if (currentReferencedFileSave != null && currentReferencedFileSave.OpensWith != "<DEFAULT>")
                    {
                        application = currentReferencedFileSave.OpensWith;
                    }
                    else
                    {
                        if (!string.IsNullOrEmpty(sourceExtension))
                        {
                            application = EditorData.FileAssociationSettings.GetApplicationForExtension(sourceExtension);
                        }
                        else
                        {
                            application = EditorData.FileAssociationSettings.GetApplicationForExtension(extension);
                        }
                    }

                    if (currentReferencedFileSave != null)
                    {
                        if (!string.IsNullOrEmpty(currentReferencedFileSave.SourceFile))
                        {
                            fileName = "\"" + ProjectManager.MakeAbsolute(ProjectManager.ContentDirectoryRelative + currentReferencedFileSave.SourceFile, true) + "\"";
                        }
                        else
                        {
                            fileName = "\"" + ProjectManager.MakeAbsolute(ProjectManager.ContentDirectoryRelative + currentReferencedFileSave.Name) + "\"";
                        }
                    }
                    else
                    {
                        fileName = "\"" + ProjectManager.MakeAbsolute(text) + "\"";
                    }

                    if (string.IsNullOrEmpty(application) || application == "<DEFAULT>")
                    {
                        try
                        {
                            ProcessManager.OpenProcess(fileName, null);
                        }
                        catch (Exception ex)
                        {
                            System.Windows.Forms.MessageBox.Show("Error opening " + fileName + "\nTry navigating to this file and opening it through explorer");
                        }
                    }
                    else
                    {
                        bool applicationFound = true;
                        try
                        {
                            application = FileManager.Standardize(application);
                        }
                        catch
                        {
                            applicationFound = false;
                        }

                        if (!System.IO.File.Exists(application) || applicationFound == false)
                        {
                            string error = "Could not find the application\n\n" + application;

                            System.Windows.Forms.MessageBox.Show(error);
                        }
                        else
                        {
                            ProcessManager.OpenProcess(application, fileName);
                        }
                    }
                }

                #endregion

                #region Double-clicked a named object

                else if (selectedNode.IsNamedObjectNode())
                {
                    NamedObjectSave nos = selectedNode.Tag as NamedObjectSave;

                    if (nos.SourceType == SourceType.Entity)
                    {
                        TreeNode entityNode = GlueState.Self.Find.EntityTreeNode(nos.SourceClassType);

                        SelectedNode = entityNode;
                    }
                    else if (nos.SourceType == SourceType.FlatRedBallType && nos.IsGenericType)
                    {
                        // Is this an entity?
                        EntitySave genericEntityType = ObjectFinder.Self.GetEntitySave(nos.SourceClassGenericType);

                        if (genericEntityType != null)
                        {
                            SelectedNode = GlueState.Self.Find.EntityTreeNode(genericEntityType);
                        }
                    }
                    else if (nos.SourceType == SourceType.File && !string.IsNullOrEmpty(nos.SourceFile))
                    {
                        ReferencedFileSave rfs      = nos.GetContainer().GetReferencedFileSave(nos.SourceFile);
                        TreeNode           treeNode = GlueState.Self.Find.ReferencedFileSaveTreeNode(rfs);

                        SelectedNode = treeNode;
                    }
                }

                #endregion

                #region Double-clicked a CustomVariable
                else if (selectedNode.IsCustomVariable())
                {
                    CustomVariable customVariable = EditorLogic.CurrentCustomVariable;

                    if (!string.IsNullOrEmpty(customVariable.SourceObject))
                    {
                        NamedObjectSave namedObjectSave = EditorLogic.CurrentElement.GetNamedObjectRecursively(customVariable.SourceObject);

                        if (namedObjectSave != null)
                        {
                            SelectedNode = GlueState.Self.Find.NamedObjectTreeNode(namedObjectSave);
                        }
                    }
                }

                #endregion

                #region Double-click an Event

                else if (selectedNode.IsEventResponseTreeNode())
                {
                    EventResponseSave ers = EditorLogic.CurrentEventResponseSave;

                    if (!string.IsNullOrEmpty(ers.SourceObject))
                    {
                        NamedObjectSave namedObjectSave = EditorLogic.CurrentElement.GetNamedObjectRecursively(ers.SourceObject);

                        if (namedObjectSave != null)
                        {
                            SelectedNode = GlueState.Self.Find.NamedObjectTreeNode(namedObjectSave);
                        }
                    }
                }


                #endregion

                #region Double-click an Enity/Screen

                else if (selectedNode.IsElementNode())
                {
                    IElement element = selectedNode.Tag as IElement;

                    string baseObject = element.BaseElement;

                    if (!string.IsNullOrEmpty(baseObject))
                    {
                        IElement baseElement = ObjectFinder.Self.GetIElement(baseObject);

                        SelectedNode = GlueState.Self.Find.ElementTreeNode(baseElement);
                    }
                }

                #endregion

                #region Code

                else if (selectedNode.IsCodeNode())
                {
                    var fileName = selectedNode.Text;

                    var absolute = GlueState.Self.CurrentGlueProjectDirectory + fileName;

                    if (System.IO.File.Exists(absolute))
                    {
                        System.Diagnostics.Process.Start(absolute);
                    }
                }

                #endregion
            }
        }
예제 #7
0
        private void ReactToTextureAddressMode(NamedObjectSave namedObjectSave, object oldValue)
        {
            bool isSprite = namedObjectSave.SourceType == SourceType.FlatRedBallType && namedObjectSave.SourceClassType == "Sprite";

            if (isSprite)
            {
                var addressModeVariable = namedObjectSave.GetCustomVariable("TextureAddressMode");

                if (addressModeVariable != null && addressModeVariable.Value != null &&
                    ((TextureAddressMode)(addressModeVariable.Value) == TextureAddressMode.Wrap || (TextureAddressMode)(addressModeVariable.Value) == TextureAddressMode.Mirror))
                {
                    // How big is the texture?
                    var textureVariable = namedObjectSave.GetCustomVariable("Texture");

                    if (textureVariable != null && textureVariable.Value != null)
                    {
                        string value = textureVariable.Value as string;

                        var rfs = namedObjectSave.GetContainer().GetReferencedFileSaveByInstanceName(value);

                        if (rfs != null)
                        {
                            var width = ImageHeader.GetDimensions(
                                ProjectManager.MakeAbsolute(rfs.Name)).Width;
                            var height = ImageHeader.GetDimensions(
                                ProjectManager.MakeAbsolute(rfs.Name)).Height;

                            string whatIsWrong = null;

                            if (FlatRedBall.Math.MathFunctions.IsPowerOfTwo(width) == false)
                            {
                                whatIsWrong = "This Sprite's texture (" + textureVariable.Value + ") has a width of " +
                                              width + " but it should be a power of two to use " + addressModeVariable.Value + " TextureAddressMode";
                            }


                            if (FlatRedBall.Math.MathFunctions.IsPowerOfTwo(height) == false)
                            {
                                whatIsWrong = "This Sprite's texture (" + textureVariable.Value + ") has a height of " +
                                              height + " but it should be a power of two to use " + addressModeVariable.Value + " TextureAddressMode";
                            }

                            if (!string.IsNullOrEmpty(whatIsWrong))
                            {
                                whatIsWrong += "\nWhat would you like to do?";

                                MultiButtonMessageBox mbmb = new MultiButtonMessageBox();
                                mbmb.MessageText = whatIsWrong;
                                mbmb.AddButton("Undo the change", DialogResult.Cancel);
                                mbmb.AddButton("Keep the change (May cause runtime crashes)", DialogResult.Yes);

                                var result = mbmb.ShowDialog();

                                if (result == DialogResult.Cancel)
                                {
                                    addressModeVariable.Value = oldValue;
                                }
                            }
                        }
                    }
                }
            }
        }
예제 #8
0
        public void ReactToNamedObjectChangedValue(string changedMember, string parent, object oldValue)
        {
            string combinedMember;

            if (string.IsNullOrEmpty(parent))
            {
                combinedMember = changedMember;
            }
            else
            {
                combinedMember = parent + "." + changedMember;
            }

            NamedObjectSave namedObjectSave = EditorLogic.CurrentNamedObject;
            IElement        element         = EditorLogic.CurrentElement;

            if (PropertiesToMethods.ContainsKey(changedMember))
            {
                PropertiesToMethods[changedMember](namedObjectSave, oldValue);
            }

            #region SourceType changed
            else if (changedMember == "SourceType")
            {
                bool didErrorOccur = false;

                if (didErrorOccur)
                {
                    namedObjectSave.SourceType = (SourceType)oldValue;
                }
                else
                {
                    if (namedObjectSave.SourceType == SourceType.Entity)
                    {
                        namedObjectSave.AddToManagers = true;
                    }
                    else if (namedObjectSave.SourceType == SourceType.File &&
                             namedObjectSave.GetContainerType() == ContainerType.Screen)
                    {
                        namedObjectSave.AddToManagers = false;
                    }
                }
            }
            #endregion

            #region SourceClassType changed

            else if (changedMember == "SourceClassType")
            {
                ReactToChangedSourceClassType(namedObjectSave, oldValue);
            }

            #endregion

            #region SourceFile changed
            else if (changedMember == "SourceFile")
            {
                if (namedObjectSave.SourceFile != (string)oldValue)
                {
                    // See if the current SourceName is valid or not
                    List <string> availableSourceNames =
                        AvailableNameablesStringConverter.GetAvailableNamedObjectSourceNames(namedObjectSave);


                    bool isSourceNameValid = availableSourceNames.Contains(namedObjectSave.SourceName);

                    if (!isSourceNameValid)
                    {
                        namedObjectSave.SourceName = "<NONE>";
                    }
                }
            }

            #endregion

            #region SourceName

            else if (changedMember == "SourceName")
            {
                // This needs to happen before we update custom properties
                ReactToChangedNosSourceName(namedObjectSave, oldValue as string);


                namedObjectSave.UpdateCustomProperties();
            }

            #endregion

            #region InstanceName changed

            else if (changedMember == "InstanceName")
            {
                ReactToNamedObjectChangedInstanceName(namedObjectSave, oldValue);
            }

            #endregion

            #region SetByDerived Changed

            else if (changedMember == "SetByDerived")
            {
                if (namedObjectSave.SourceType == SourceType.Entity &&
                    !string.IsNullOrEmpty(namedObjectSave.SourceClassType))
                {
                    if (ProjectManager.VerifyReferenceGraph(ObjectFinder.Self.GetEntitySave(namedObjectSave.SourceClassType)) == ProjectManager.CheckResult.Failed)
                    {
                        namedObjectSave.SetByDerived = !namedObjectSave.SetByDerived;
                    }
                }


                if (namedObjectSave.SetByDerived && namedObjectSave.ExposedInDerived)
                {
                    // The user has just set SetByDerived to true, but ExposedInDerived means that
                    // the derived expects that the base instantiates.  We need to tell the user that
                    // both values can't be true at the same time, and that ExposedInDerived will be set
                    // to false.
                    MessageBox.Show("You have set SetByDerived to true, but ExposedInDerived is also true.  Both cannot be true at the same time " +
                                    "so Glue will set ExposedInDerived to false.");
                    namedObjectSave.ExposedInDerived = false;
                }


                if (namedObjectSave.SourceType == SourceType.FlatRedBallType &&
                    namedObjectSave.IsList &&
                    namedObjectSave.SetByDerived == true &&
                    namedObjectSave.ContainedObjects.Count != 0)
                {
                    MessageBox.Show("This list is not empty, so it can't be set to \"Set By Derived\".  You must first empty the list", "Invalid Setting");

                    namedObjectSave.SetByDerived = false;
                }
                else
                {
                    ProjectManager.UpdateAllDerivedElementFromBaseValues(false, true);
                }
            }

            #endregion

            #region ExposedInDerived Changed

            else if (changedMember == "ExposedInDerived")
            {
                if (namedObjectSave.SetByDerived && namedObjectSave.ExposedInDerived)
                {
                    // See comment in ExposedByDerived block on why this occurs
                    MessageBox.Show("You have set ExposedInDerived to true, but SetByDerived is also true.  Both cannot be true at the same time " +
                                    "so Glue will set SetByDerived to false.");
                    namedObjectSave.SetByDerived = false;
                }


                SetExposedByDerivedRecursively(namedObjectSave, oldValue);

                ProjectManager.UpdateAllDerivedElementFromBaseValues(false, true);
            }


            #endregion

            #region SourceClassGenericType

            else if (changedMember == "SourceClassGenericType")
            {
                ReactToSourceClassGenericType(namedObjectSave, oldValue);
            }

            #endregion

            #region IsDisabled

            else if (changedMember == "IsDisabled")
            {
                GlueState.Self.Find.ElementTreeNode(EditorLogic.CurrentElement).UpdateReferencedTreeNodes();
            }

            #endregion

            #region SetByContainer Changed
            else if (changedMember == "SetByContainer")
            {
                if (namedObjectSave.SourceType == SourceType.Entity &&
                    !string.IsNullOrEmpty(namedObjectSave.SourceClassType))
                {
                    if (ProjectManager.VerifyReferenceGraph(ObjectFinder.Self.GetEntitySave(namedObjectSave.SourceClassType)) == ProjectManager.CheckResult.Failed)
                    {
                        namedObjectSave.SetByContainer = !namedObjectSave.SetByContainer;
                    }
                }

                List <IElement> derivedElements = ObjectFinder.Self.GetAllElementsThatInheritFrom(
                    EditorLogic.CurrentElement.Name);

                foreach (IElement derived in derivedElements)
                {
                    foreach (NamedObjectSave nos in derived.NamedObjects)
                    {
                        if (nos.InstanceName == namedObjectSave.InstanceName)
                        {
                            nos.SetByContainer = namedObjectSave.SetByContainer;
                        }
                    }
                }

                if (EditorLogic.CurrentEntitySave != null)
                {
                    List <NamedObjectSave> entityNamedObjects = ObjectFinder.Self.GetAllNamedObjectsThatUseEntity(EditorLogic.CurrentEntitySave.Name);

                    foreach (NamedObjectSave nos in entityNamedObjects)
                    {
                        nos.UpdateCustomProperties();
                    }
                }
            }

            #endregion

            #region AddToManagers Changed

            else if (changedMember == "AddToManagers")
            {
                if (namedObjectSave.AddToManagers &&
                    namedObjectSave.GetContainerType() == ContainerType.Screen && namedObjectSave.SourceType == SourceType.File)
                {
                    ScreenSave screenSave = namedObjectSave.GetContainer() as ScreenSave;

                    ReferencedFileSave rfs = screenSave.GetReferencedFileSave(namedObjectSave.SourceFile);

                    if (rfs != null && !rfs.IsSharedStatic)
                    {
                        System.Windows.Forms.MessageBox.Show("This object comes from a file.  Files which are part of Screens " +
                                                             "are automatically added to the engine managers.  " +
                                                             "Adding this object would result in double-membership in the engine which may cause unexpected results.  " +
                                                             "\n\nGlue will now set this value back to false.");
                        namedObjectSave.AddToManagers = false;
                    }
                }
            }

            #endregion


            #region LayerOn

            else if (changedMember == "LayerOn")
            {
                if (namedObjectSave.IsList)
                {
                    DialogResult result = DialogResult.No;
                    if (string.IsNullOrEmpty(namedObjectSave.LayerOn))
                    {
                        result = MessageBox.Show("Do you want to remove every object in the List " + namedObjectSave.InstanceName +
                                                 " from its Layer?",
                                                 "Remove all from Layer?",
                                                 MessageBoxButtons.YesNo);
                    }
                    else
                    {
                        result = MessageBox.Show("Do you want to add every object contained in the List " + namedObjectSave.InstanceName +
                                                 " to the Layer " + namedObjectSave.LayerOn + "?",
                                                 "Add all to Layer?",
                                                 MessageBoxButtons.YesNo);
                    }

                    if (result == DialogResult.Yes)
                    {
                        namedObjectSave.SetLayerRecursively(namedObjectSave.LayerOn);
                    }
                }
            }

            #endregion

            #region IsContainer

            else if (changedMember == "IsContainer")
            {
                HandleChangedIsContainer(namedObjectSave, element);
            }

            #endregion


            #region AttachToCamera

            else if (changedMember == "AttachToCamera")
            {
                if (namedObjectSave.IsList)
                {
                    DialogResult result = DialogResult.No;

                    if (namedObjectSave.AttachToCamera)
                    {
                        result = MessageBox.Show("Do you want to attach every object contained in the list " + namedObjectSave.InstanceName +
                                                 " to the Camera?", "Attach all to Camera?",
                                                 MessageBoxButtons.YesNo);
                    }
                    else
                    {
                        result = MessageBox.Show("Do you want to detach every object contained in the list " + namedObjectSave.InstanceName +
                                                 " from the Camera?", "Detach all from the Camera?",
                                                 MessageBoxButtons.YesNo);
                    }

                    if (result == DialogResult.Yes)
                    {
                        namedObjectSave.SetAttachToCameraRecursively(namedObjectSave.AttachToCamera);
                    }
                }
            }


            #endregion

            #region DestinationRectangle.Y (for Layers)
            else if (parent == "DestinationRectangle" && changedMember == "Y")
            {
                // If the Y is odd, we should warn the user that it should be even
                // or else text will draw incorrectly
                if (namedObjectSave.DestinationRectangle.HasValue && namedObjectSave.DestinationRectangle.Value.Y % 2 == 1)
                {
                    MessageBox.Show("Setting an odd value to the DestinationRectangle's Y may cause text to render improperly.  An " +
                                    "even value is recommended");
                }
            }

            #endregion

            #region RemoveFromManagersWhenInvisible

            else if (changedMember == "RemoveFromManagersWhenInvisible")
            {
                // is this an Entity instance?
                if (namedObjectSave.SourceType == SourceType.Entity && namedObjectSave.RemoveFromManagersWhenInvisible)
                {
                    var entitySave = ObjectFinder.Self.GetEntitySave(namedObjectSave.SourceClassType);

                    if (entitySave != null)
                    {
                        // Is this CreatedByOtherEntities?
                        if (!entitySave.CreatedByOtherEntities)
                        {
                            MessageBox.Show("The Entity " + entitySave + " should have its CreatedByOtherEntities set to true to enable " +
                                            "visibility-based removal to work properly");
                        }
                    }
                }
            }
            #endregion


            else if (namedObjectSave?.GetCustomVariable(changedMember) != null)
            {
                // See if this variable is tunneled into in this element.
                // If so, set that value too.
                CustomVariableInNamedObject cvino = namedObjectSave.GetCustomVariable(changedMember);
                object value = cvino.Value;

                foreach (CustomVariable customVariable in EditorLogic.CurrentElement.CustomVariables)
                {
                    if (customVariable.SourceObject == namedObjectSave.InstanceName &&
                        customVariable.SourceObjectProperty == changedMember)
                    {
                        // The custom variable may have a different type:
                        if (!string.IsNullOrEmpty(customVariable.OverridingPropertyType))
                        {
                            // it does, so convert
                            Type overridingType = TypeManager.GetTypeFromString(customVariable.OverridingPropertyType);

                            customVariable.DefaultValue = System.Convert.ChangeType(value, overridingType);
                        }
                        else
                        {
                            customVariable.DefaultValue = value;
                        }
                        break;
                    }
                }
            }

            // If we changed BitmapFont and if the NOS is marked as PixelPerfect
            // and if it's a Text object, then we should set the Scale, Spacing, and
            // NewLineDistance according to the set BitmapFont
            // We don't do an else because there could be a CustomVariable by the name
            // of BitmapFont as well, and we dont' want to eliminate that.
            if (changedMember == "Font" && namedObjectSave.SourceType == SourceType.FlatRedBallType &&
                namedObjectSave.SourceClassType == "Text" && namedObjectSave.IsPixelPerfect)
            {
                ReactToFontSet(namedObjectSave, oldValue);
            }

            PropertyGridHelper.UpdateNamedObjectDisplay();

            PluginManager.ReactToNamedObjectChangedValue(changedMember, oldValue);
        }