public static void SetVariableToDefault(NamedObjectSave currentNamedObject, string variableToSet) { // July 13, 2014 // This used to simply set the value to null, but why don't we remove it if it exists? // This way if an error is introduced by some plugin that sets the type to something invalid // the user can still remove it through this option and recover the type later. //currentNamedObject.SetPropertyValue(variableToSet, null); currentNamedObject.InstructionSaves.RemoveAll(item => item.Member == variableToSet); if (currentNamedObject.GetCustomVariable(variableToSet) != null) { // See if this variable is tunneled into in this element. // If so, set that value too. CustomVariableInNamedObject cvino = currentNamedObject.GetCustomVariable(variableToSet); object value = cvino.Value; foreach (CustomVariable customVariable in EditorLogic.CurrentElement.CustomVariables) { if (customVariable.SourceObject == currentNamedObject.InstanceName && customVariable.SourceObjectProperty == variableToSet) { customVariable.DefaultValue = value; break; } } GlueCommands.Self.RefreshCommands.RefreshPropertyGrid(); } }
private static void AddSpriteValues(NamedObjectSave newNos, bool is2D) { // whatToAdd = new AxisAlignedRectangle(); CustomVariableInNamedObject scaleX = GetOrCreateInstruction(newNos, "ScaleX"); scaleX.Type = "Single"; CustomVariableInNamedObject scaleY = GetOrCreateInstruction(newNos, "ScaleY"); scaleY.Type = "Single"; if (is2D) { scaleX.Value = 16.0f; scaleY.Value = 16.0f; CustomVariableInNamedObject pixelSize = GetOrCreateInstruction(newNos, "PixelSize"); pixelSize.Type = "Single"; } else { scaleX.Value = 1.0f; scaleY.Value = 1.0f; } }
private void RefreshToNamedObject(NamedObjectSave namedObjectSave) { bool shouldShow = namedObjectSave != null; if (shouldShow) { shouldShow = namedObjectSave.SourceClassType == "Polygon" || namedObjectSave.SourceClassType == "FlatRedBall.Math.Geometry.Polygon"; } if (shouldShow) { var instructions = namedObjectSave.GetInstructionFromMember("Points"); if (instructions == null) { instructions = new CustomVariableInNamedObject(); instructions.Member = "Points"; instructions.Value = new List <Vector2>(); namedObjectSave.InstructionSaves.Add(instructions); } mPointEditWindow.Data = instructions.Value as List <Vector2>; ShowTab(); } else { HideTab(); } }
protected virtual void AddVariableToNos(NamedObjectSave toReturn, string memberName, object currentValue) { CustomVariableInNamedObject cvino = new CustomVariableInNamedObject(); cvino.Member = memberName; cvino.Value = currentValue; toReturn.InstructionSaves.Add(cvino); }
private static void AddCircleValues(NamedObjectSave newNos, bool is2D) { CustomVariableInNamedObject cvino = GetOrCreateInstruction(newNos, "Radius"); cvino.Type = "Single"; if (is2D) { cvino.Value = 16.0f; } else { cvino.Value = 1.0f; } }
private static CustomVariableInNamedObject GetOrCreateInstruction(NamedObjectSave nos, string variableName) { foreach (var instruction in nos.InstructionSaves) { if (instruction.Member == variableName) { return(instruction); } } CustomVariableInNamedObject cvino = new CustomVariableInNamedObject(); nos.InstructionSaves.Add(cvino); return(cvino); }
private static void AddTextValues(NamedObjectSave newNos, bool is2D) { CustomVariableInNamedObject scale = GetOrCreateInstruction(newNos, "Scale"); CustomVariableInNamedObject spacing = GetOrCreateInstruction(newNos, "Spacing"); CustomVariableInNamedObject newLineDistance = GetOrCreateInstruction(newNos, "NewLineDistance"); CustomVariableInNamedObject displayText = GetOrCreateInstruction(newNos, "DisplayText"); scale.Value = 8; scale.Type = "Single"; spacing.Value = 8; spacing.Type = "Single"; newLineDistance.Value = 12; newLineDistance.Type = "Single"; displayText.Value = newNos.InstanceName; displayText.Type = "string"; }
private bool ShouldApplyVariableOnRuntime(CustomVariableInNamedObject cvino, NamedObjectSave n) { bool shouldApply = // December 16, 2012 Victor Chelaru // I think that even if the NOS isn't // a Entity, the TypedMembers should still // have all properties shouldn't they? It looks // like they do according to my tests... //n.SourceType != SourceType.Entity || n.TypedMembers.FirstOrDefault(member => member.MemberName == cvino.Member) != null; if (!shouldApply) { // Check for special cases - variables whihch can't be exposed, but which should still be aplied: if (cvino.Member == "Points" && n.SourceType == SourceType.FlatRedBallType && n.ClassType == "Polygon") { shouldApply = true; } } return(shouldApply); }
private static EntitySave CreateEntityAndObjects(AddEntityWindow window, string entityName, string directory) { var gluxCommands = GlueCommands.Self.GluxCommands; var newElement = gluxCommands.EntityCommands.AddEntity( directory + entityName, is2D: true); GlueState.Self.CurrentElement = newElement; if (window.SpriteChecked) { AddObjectViewModel addObjectViewModel = new AddObjectViewModel(); addObjectViewModel.ObjectName = "SpriteInstance"; addObjectViewModel.SourceClassType = "Sprite"; addObjectViewModel.SourceType = SourceType.FlatRedBallType; gluxCommands.AddNewNamedObjectToSelectedElement(addObjectViewModel); GlueState.Self.CurrentElement = newElement; } if (window.TextChecked) { AddObjectViewModel addObjectViewModel = new AddObjectViewModel(); addObjectViewModel.ObjectName = "TextInstance"; addObjectViewModel.SourceClassType = "Text"; addObjectViewModel.SourceType = SourceType.FlatRedBallType; gluxCommands.AddNewNamedObjectToSelectedElement(addObjectViewModel); GlueState.Self.CurrentElement = newElement; } if (window.CircleChecked) { AddObjectViewModel addObjectViewModel = new AddObjectViewModel(); addObjectViewModel.ObjectName = "CircleInstance"; addObjectViewModel.SourceClassType = "Circle"; addObjectViewModel.SourceType = SourceType.FlatRedBallType; gluxCommands.AddNewNamedObjectToSelectedElement(addObjectViewModel); GlueState.Self.CurrentElement = newElement; } if (window.AxisAlignedRectangleChecked) { AddObjectViewModel addObjectViewModel = new AddObjectViewModel(); addObjectViewModel.ObjectName = "AxisAlignedRectangleInstance"; addObjectViewModel.SourceClassType = "AxisAlignedRectangle"; addObjectViewModel.SourceType = SourceType.FlatRedBallType; gluxCommands.AddNewNamedObjectToSelectedElement(addObjectViewModel); GlueState.Self.CurrentElement = newElement; } // There are a few important things to note about this function: // 1. Whenever gluxCommands.AddNewNamedObjectToSelectedElement is called, Glue performs a full // refresh and save. The reason for this is that gluxCommands.AddNewNamedObjectToSelectedElement // is the standard way to add a new named object to an element, and it may be called by other parts // of the code (and plugins) that expect the add to be a complete set of logic (add, refresh, save, etc). // This is less efficient than adding all of them and saving only once, but that would require a second add // method, which would add complexity. For now, we deal with the slower calls because it's not really noticeable. // 2. Some actions, like adding Points to a polygon, are done after the polygon is created and added, and that requires // an additional save. Therefore, we do one last save/refresh at the end of this method in certain situations. // Again, this is less efficient than if we performed just a single call, but a single call would be more complicated. // because we'd have to suppress all the other calls. bool needsRefreshAndSave = false; if (window.PolygonChecked) { AddObjectViewModel addObjectViewModel = new AddObjectViewModel(); addObjectViewModel.ObjectName = "PolygonInstance"; addObjectViewModel.SourceClassType = "Polygon"; addObjectViewModel.SourceType = SourceType.FlatRedBallType; var nos = gluxCommands.AddNewNamedObjectToSelectedElement(addObjectViewModel); CustomVariableInNamedObject instructions = null; instructions = nos.GetCustomVariable("Points"); if (instructions == null) { instructions = new CustomVariableInNamedObject(); instructions.Member = "Points"; nos.InstructionSaves.Add(instructions); } var points = new List <Vector2>(); points.Add(new Vector2(-16, 16)); points.Add(new Vector2(16, 16)); points.Add(new Vector2(16, -16)); points.Add(new Vector2(-16, -16)); points.Add(new Vector2(-16, 16)); instructions.Value = points; needsRefreshAndSave = true; GlueState.Self.CurrentElement = newElement; } if (window.IVisibleChecked) { newElement.ImplementsIVisible = true; needsRefreshAndSave = true; } if (window.IClickableChecked) { newElement.ImplementsIClickable = true; needsRefreshAndSave = true; } if (window.IWindowChecked) { newElement.ImplementsIWindow = true; needsRefreshAndSave = true; } if (window.ICollidableChecked) { newElement.ImplementsICollidable = true; needsRefreshAndSave = true; } if (needsRefreshAndSave) { MainGlueWindow.Self.PropertyGrid.Refresh(); ElementViewWindow.GenerateSelectedElementCode(); GluxCommands.Self.SaveGlux(); } return(newElement); }
public void ReactToCustomVariableChangedValue(string changedMember, CustomVariable customVariable, object oldValue) { #region Name if (changedMember == "Name") { ReactToChangedCustomVariableName((string)oldValue, customVariable); } #endregion #region SetByDerived if (changedMember == "SetByDerived") { bool didErrorOccur = false; if (customVariable.SetByDerived && customVariable.IsShared) { MessageBox.Show("Variables that are IsShared cannot be SetByDerived"); didErrorOccur = true; } if (didErrorOccur) { customVariable.SetByDerived = (bool)oldValue; } else { ProjectManager.UpdateAllDerivedElementFromBaseValues(false, true); } } #endregion #region IsShared else if (changedMember == "IsShared") { HandleIsSharedVariableSet(customVariable, oldValue); } #endregion #region SouceObjectProperty else if (changedMember == "SourceObjectProperty") { // See if there is already a NOS that uses this SourceObject/SourceObjectProperty combo IElement currentElement = EditorLogic.CurrentElement; CustomVariable currentVariable = customVariable; if (!string.IsNullOrEmpty(currentVariable.SourceObject) && !string.IsNullOrEmpty(currentVariable.SourceObjectProperty)) { foreach (CustomVariable variableInLoop in currentElement.CustomVariables) { if (variableInLoop != currentVariable && !string.IsNullOrEmpty(variableInLoop.SourceObject) && currentVariable.SourceObject == variableInLoop.SourceObject && !string.IsNullOrEmpty(variableInLoop.SourceObjectProperty) && currentVariable.SourceObjectProperty == variableInLoop.SourceObjectProperty) { MessageBox.Show("There is already a variable that is modifying " + currentVariable.SourceObjectProperty + " on " + currentVariable.SourceObject); currentVariable.SourceObjectProperty = (string)oldValue; } } } } #endregion #region DefaultValue else if (changedMember == "DefaultValue") { customVariable.FixEnumerationTypes(); var currentElement = GlueState.Self.CurrentElement; if (!string.IsNullOrEmpty(customVariable.SourceObject)) { // See if the source NamedObjectSave has // this variable exposed, and if so, set that // variable too so the two mirror each other... // or make it null if this is a recasted variable. NamedObjectSave nos = currentElement.GetNamedObjectRecursively(customVariable.SourceObject); if (nos != null) { CustomVariableInNamedObject cvino = nos.GetCustomVariable(customVariable.SourceObjectProperty); // If the cvino is null, that means that the NOS doesn't have this exposed, so we don't // need to do anything. if (cvino != null) { if (string.IsNullOrEmpty(customVariable.OverridingPropertyType)) { cvino.Value = customVariable.DefaultValue; } else { cvino.Value = null; } } } } Plugins.PluginManager.ReactToElementVariableChange(currentElement, customVariable); } #endregion #region HasAccompanyingVelocityProperty else if (changedMember == "HasAccompanyingVelocityProperty") { ReactToChangedHasAccompanyingVelocityProperty(customVariable); } #endregion #region OverridingPropertyType else if (changedMember == "OverridingPropertyType") { if (customVariable.OverridingPropertyType != null) { customVariable.SetDefaultValueAccordingToType(customVariable.OverridingPropertyType); } GlueCommands.Self.RefreshCommands.RefreshPropertyGrid(); } #endregion #region Type else if (changedMember == "Type") { customVariable.SetDefaultValueAccordingToType(customVariable.Type); } #endregion }
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); }
private void UpdateIElementVariable(ElementRuntime elementRuntime, string variableToUpdate) { IElement currentIElement = elementRuntime.AssociatedIElement; if (currentIElement != null) { bool exists = currentIElement.GetCustomVariable(variableToUpdate) != null; if (!exists) { CustomVariable variable = new CustomVariable(); variable.Type = "float"; variable.Name = variableToUpdate; currentIElement.CustomVariables.Add(variable); variable.DefaultValue = 0.0f; //Update the Save so you can see the newly added variables elementRuntime.AssociatedNamedObjectSave.UpdateCustomProperties(); } } bool isFlatRedBallType = elementRuntime.AssociatedNamedObjectSave.SourceType == SourceType.FlatRedBallType; bool wasFound = false; //Update the saves to the new position object objectToGetValueFrom = elementRuntime; if (elementRuntime.DirectObjectReference != null) { objectToGetValueFrom = elementRuntime.DirectObjectReference; } try { foreach (InstructionSave instruction in elementRuntime.AssociatedNamedObjectSave.InstructionSaves) { if (instruction.Member == variableToUpdate) { Type objectType = objectToGetValueFrom.GetType(); instruction.Value = (float)LateBinder.GetInstance(objectType).GetValue(objectToGetValueFrom, variableToUpdate); wasFound = true; break; } } } catch (Exception e) { int m = 3; } if (!wasFound) { CustomVariableInNamedObject newVariable = new CustomVariableInNamedObject(); newVariable.Member = variableToUpdate; Type objectType = objectToGetValueFrom.GetType(); newVariable.Value = (float)LateBinder.GetInstance(objectType).GetValue(objectToGetValueFrom, variableToUpdate); newVariable.Type = "float";// assume this for now, change later if necessary elementRuntime.AssociatedNamedObjectSave.InstructionSaves.Add(newVariable); wasFound = true; } }
public void ReactToCustomVariableChangedValue(string changedMember, CustomVariable customVariable, object oldValue) { #region Name if (changedMember == nameof(CustomVariable.Name)) { ReactToChangedCustomVariableName((string)oldValue, customVariable); } #endregion #region SetByDerived if (changedMember == nameof(CustomVariable.SetByDerived)) { bool didErrorOccur = false; if (customVariable.SetByDerived && customVariable.IsShared) { MessageBox.Show("Variables that are IsShared cannot be SetByDerived"); didErrorOccur = true; } if (didErrorOccur) { customVariable.SetByDerived = (bool)oldValue; } else { ProjectManager.UpdateAllDerivedElementFromBaseValues(true); } } #endregion #region IsShared else if (changedMember == nameof(CustomVariable.IsShared)) { HandleIsSharedVariableSet(customVariable, oldValue); } #endregion #region Scope else if (changedMember == nameof(CustomVariable.Scope)) { HandleScopeSet(customVariable, oldValue); } #endregion #region SouceObjectProperty else if (changedMember == nameof(CustomVariable.SourceObjectProperty)) { // See if there is already a NOS that uses this SourceObject/SourceObjectProperty combo IElement currentElement = EditorLogic.CurrentElement; CustomVariable currentVariable = customVariable; if (!string.IsNullOrEmpty(currentVariable.SourceObject) && !string.IsNullOrEmpty(currentVariable.SourceObjectProperty)) { foreach (CustomVariable variableInLoop in currentElement.CustomVariables) { if (variableInLoop != currentVariable && !string.IsNullOrEmpty(variableInLoop.SourceObject) && currentVariable.SourceObject == variableInLoop.SourceObject && !string.IsNullOrEmpty(variableInLoop.SourceObjectProperty) && currentVariable.SourceObjectProperty == variableInLoop.SourceObjectProperty) { MessageBox.Show("There is already a variable that is modifying " + currentVariable.SourceObjectProperty + " on " + currentVariable.SourceObject); currentVariable.SourceObjectProperty = (string)oldValue; } } } } #endregion #region DefaultValue else if (changedMember == nameof(CustomVariable.DefaultValue)) { customVariable.FixEnumerationTypes(); var currentElement = GlueState.Self.CurrentElement; if (!string.IsNullOrEmpty(customVariable.SourceObject)) { // See if the source NamedObjectSave has // this variable exposed, and if so, set that // variable too so the two mirror each other... // or make it null if this is a recasted variable. NamedObjectSave nos = currentElement.GetNamedObjectRecursively(customVariable.SourceObject); if (nos != null) { CustomVariableInNamedObject cvino = nos.GetCustomVariable(customVariable.SourceObjectProperty); // If the cvino is null, that means that the NOS doesn't have this exposed, so we don't // need to do anything. if (cvino != null) { if (string.IsNullOrEmpty(customVariable.OverridingPropertyType)) { cvino.Value = customVariable.DefaultValue; } else { cvino.Value = null; } } } } Plugins.PluginManager.ReactToElementVariableChange(currentElement, customVariable); } #endregion #region HasAccompanyingVelocityProperty else if (changedMember == nameof(CustomVariable.HasAccompanyingVelocityProperty)) { ReactToChangedHasAccompanyingVelocityProperty(customVariable); } #endregion #region OverridingPropertyType else if (changedMember == nameof(CustomVariable.OverridingPropertyType)) { if (customVariable.OverridingPropertyType != null) { customVariable.SetDefaultValueAccordingToType(customVariable.OverridingPropertyType); } GlueCommands.Self.RefreshCommands.RefreshPropertyGrid(); } #endregion #region Type else if (changedMember == nameof(CustomVariable.Type)) { var currentValue = customVariable.DefaultValue; var oldType = (string)oldValue; bool wasAbleToConvert = false; if (currentValue != null) { if (oldType == "int") { var valueAsInt = (int)currentValue; switch (customVariable.Type) { case "float": customVariable.DefaultValue = (float)valueAsInt; wasAbleToConvert = true; break; case "double": customVariable.DefaultValue = (double)valueAsInt; wasAbleToConvert = true; break; case "string": customVariable.DefaultValue = valueAsInt.ToString(); wasAbleToConvert = true; break; } } else if (oldType == "float") { var valueAsFloat = (float)currentValue; switch (customVariable.Type) { case "int": customVariable.DefaultValue = (int)valueAsFloat; wasAbleToConvert = true; break; case "double": customVariable.DefaultValue = (double)valueAsFloat; wasAbleToConvert = true; break; case "string": customVariable.DefaultValue = valueAsFloat.ToString(); wasAbleToConvert = true; break; } } else if (oldType == "double") { var valueAsDouble = (double)currentValue; switch (customVariable.Type) { case "int": customVariable.DefaultValue = (int)valueAsDouble; wasAbleToConvert = true; break; case "float": customVariable.DefaultValue = (float)valueAsDouble; wasAbleToConvert = true; break; case "string": customVariable.DefaultValue = valueAsDouble.ToString(); wasAbleToConvert = true; break; } } else if (oldType == "string") { var valueAsString = (string)currentValue; switch (customVariable.Type) { case "int": { if (int.TryParse(valueAsString, out int result)) { customVariable.DefaultValue = result; } } break; case "float": { if (float.TryParse(valueAsString, out float result)) { customVariable.DefaultValue = result; } } break; case "double": { if (double.TryParse(valueAsString, out double result)) { customVariable.DefaultValue = result; } } break; } } } if (wasAbleToConvert == false) { customVariable.SetDefaultValueAccordingToType(customVariable.Type); } // If the type changed, the Property Grid needs to be re-made so that the new // grid will have the right type for the DefaultValue cell: PropertyGridHelper.UpdateDisplayedPropertyGridProperties(); } #endregion }