private bool GetIfShouldGenerateProperty(Gum.DataTypes.Variables.VariableSave variable, ElementSave standardElementSave) { string variableName = variable.GetRootName(); if (mVariableNamesToSkipForProperties.Contains(variableName)) { return(false); } // Core Gum objets don't have states, so if it's a state then don't create a property for it - it'll be handled // by the code that handles states if (variable.IsState(standardElementSave)) { return(false); } return(true); }
private bool GetIfShouldGenerateStateVariable(Gum.DataTypes.Variables.VariableSave variable, ElementSave container) { bool toReturn = true; string variableName = variable.GetRootName(); if (variable.Value == null || !variable.SetsValue) { toReturn = false; } // states can't set states on this if (variable.IsState(container) && string.IsNullOrEmpty(variable.SourceObject)) { toReturn = false; } if (toReturn && mVariableNamesToSkipForStates.Contains(variableName)) { toReturn = false; } bool hasSourceObject = !string.IsNullOrEmpty(variable.SourceObject); if (toReturn && hasSourceObject) { InstanceSave instanceSave = container.GetInstance(variable.SourceObject); if (instanceSave == null) { toReturn = false; } else { var baseElement = Gum.Managers.ObjectFinder.Self.GetElementSave(instanceSave.BaseType); if (baseElement == null) { toReturn = false; } if (toReturn) { // Gum (just like Glue) keeps variables that aren't needed around. This allows users to rename things and not lose // important information accidentally. But because of that we have to make sure that the variable we're working with is // valid for the type of object we're dealing with. var defaultState = baseElement.DefaultState; // October 26, 2018 // Bernardo reported // a crash caused by the // RecursiveVariableFinder // being given a state without // a ParentContainer. This is a // sign that the element hasn't // been initialized yet. Elements // should be initialized, but if they're // not, we could just catch it here and initialize // it on the spot. Not sure if I like this solution // or not. It allows code to behave a little unpredictably, // but at the same time, we could simply solve the problem by // initializing here, so I'm going to do that: if (defaultState.ParentContainer == null) { baseElement.Initialize(null); } RecursiveVariableFinder rvf = new RecursiveVariableFinder(defaultState); var foundVariable = rvf.GetVariable(variable.GetRootName()); if (foundVariable == null) { // This doesn't exist anywhere in the inheritance chain, so we don't want to generate it: toReturn = false; } } } } if (toReturn && !hasSourceObject) { // If a variable is part of a component, it better be defined in the base type or else we won't generate it. // For example, consider a component that used to inherit from Text. It will have variables for fonts. If that // component switches to inheriting from Sprite, those variables will still exist in the XML for that component, // but we shouldn't generate any state variables for those variables. So we'll go to the base type and see if those // variables exist bool isComponent = container is ComponentSave; var rootStandardElementSave = Gum.Managers.ObjectFinder.Self.GetRootStandardElementSave(container); // If the Container is a Screen, then rootComponent will be null, so we don't need to do anything if (rootStandardElementSave == null) { toReturn = false; } else { IEnumerable <VariableSave> variablesToCheck; // This code used to get the default state from the rootStandardElementSave, // but the standard element save can have variables missing from the Gum XML, // but it should still support them based on the definition in the StandardElementsManager, // especially if new variables have been added in the future. Therefore, use the StandardElementsManager // rather than the DefaultState: //var rootStandardElementVariables = rootStandardElementSave.DefaultState.Variables; var rootStandardElementVariables = StandardElementsManager.Self .DefaultStates[rootStandardElementSave.Name].Variables; if (isComponent) { var component = Gum.Managers.ObjectFinder.Self.GetStandardElement("Component"); variablesToCheck = rootStandardElementVariables.Concat(component.DefaultState.Variables).ToList(); } else { variablesToCheck = rootStandardElementVariables.ToList(); } bool wasMatchFound = variablesToCheck.Any(item => item.Name == variable.GetRootName()); toReturn = wasMatchFound; } } return(toReturn); }
private InterpolationCharacteristic GetInterpolationCharacteristic(VariableSave variableSave, ElementSave container) { string variableType = null; if (variableSave != null) { variableType = variableSave.Type; } if (variableSave != null && variableSave.IsState(container)) { ElementSave categoryContainer; StateSaveCategory stateSaveCategory; if (variableSave.IsState(container, out categoryContainer, out stateSaveCategory, recursive: false)) { return InterpolationCharacteristic.CanInterpolate; } else { // it's an exposed variable which cant be interpolated currently return InterpolationCharacteristic.CantInterpolate; } } if (variableSave == null || variableType == null || variableType == "string" || variableType == "bool" || variableType == "Color" || variableSave.IsFile ) { return InterpolationCharacteristic.CantInterpolate; } if (variableType == "float" || variableType == "int" || variableType == "double" || variableType == "byte") { return InterpolationCharacteristic.CanInterpolate; } return InterpolationCharacteristic.CantInterpolate; }
private void AddAssignmentForInterpolationForVariable(ICodeBlock curBlock, VariableSave variable, ElementSave container) { string memberNameInCode = variable.MemberNameInCode(container, mVariableNamesToReplaceForStates); ElementSave categoryContainer; StateSaveCategory stateSaveCategory; if (variable.IsState(container, out categoryContainer, out stateSaveCategory, recursive:false) && !string.IsNullOrEmpty(variable.SourceObject)) { string line = string.Format( "{0}.InterpolateBetween({1}FirstValue, {1}SecondValue, interpolationValue);", SaveObjectExtensionMethods.InstanceNameInCode( variable.SourceObject), memberNameInCode.Replace(".", "")); curBlock.Line(line); } else { switch (variable.Type) { case "int": curBlock.Line(string.Format("{0} = FlatRedBall.Math.MathFunctions.RoundToInt({1}FirstValue* (1 - interpolationValue) + {1}SecondValue * interpolationValue);", memberNameInCode, memberNameInCode.Replace(".", ""))); break; case "float": case "double": curBlock.Line(string.Format("{0} = {1}FirstValue * (1 - interpolationValue) + {1}SecondValue * interpolationValue;", memberNameInCode, memberNameInCode.Replace(".", ""))); break; } } }
/// <summary> /// Adjusts a variable value to be code which can execute properly. For example, converts a file string to a load call. /// </summary> /// <param name="variableSave">The variable</param> /// <param name="container">The container of the variable</param> /// <param name="variableValue">The variable value to modify</param> /// <param name="isEntireAssignment">Whether the modified value is an entire assignment - meaning no assignment is necessary. This is used for file loading.</param> public void AdjustVariableValueIfNecessary(Gum.DataTypes.Variables.VariableSave variableSave, ElementSave container, ref string variableValue, out bool isEntireAssignment) { isEntireAssignment = false; ElementSave categoryContainer; Gum.DataTypes.Variables.StateSaveCategory stateSaveCategory; string variableType = variableSave.Type; if (variableSave.IsState(container, out categoryContainer, out stateSaveCategory)) { string categoryName = "Category"; if (stateSaveCategory != null) { categoryName = stateSaveCategory.Name; } else { categoryName = "VariableState"; } variableValue = GetQualifiedRuntimeTypeFor(categoryContainer) + "." + categoryName + "." + variableSave.Value; } else if (variableSave.IsEnumeration()) { AdjustEnumerationVariableValue(variableSave, container, ref variableValue, ref variableType); } else if (variableSave.GetRootName() == "Parent") { if (container is ComponentSave) { variableValue = $"this.ContainedElements.FirstOrDefault(item =>item.Name == \"{variableValue}\") ?? this"; } else { variableValue = $"this.ContainedElements.FirstOrDefault(item =>item.Name == \"{variableValue}\")"; } } else if (variableSave.IsFile) { isEntireAssignment = true; string fileName = "\"" + variableValue.Replace("\\", "\\\\") + "\""; variableValue = "SetProperty(\"" + variableSave.Name + "\", " + fileName + ");"; ////RenderingLibrary.Content.LoaderManager.Self.Load("fileName", managers); //variableValue = "RenderingLibrary.Content.LoaderManager.Self.Load(\"" + variableValue.Replace("\\", "\\\\") + "\", RenderingLibrary.SystemManagers.Default)"; } else if (variableSave.Type == "string") { variableValue = variableValue.Replace("\\", "\\\\"); variableValue = variableValue.Replace("\"", "\\\""); // do this after replacing the backslashes up above variableValue = variableValue.Replace("\n", "\\n"); variableValue = "\"" + variableValue + "\""; } else if (variableSave.Type == "float") { //variableValue = variableValue + "f"; // convert this using the current language: var value = Convert.ToSingle(variableValue, System.Globalization.CultureInfo.CurrentCulture); variableValue = value.ToString(System.Globalization.CultureInfo.InvariantCulture) + "f"; } else if (variableSave.Type == "bool") { variableValue = variableValue.ToLower(); } }
private bool GetIfShouldGenerateStateVariable(Gum.DataTypes.Variables.VariableSave variable, ElementSave container) { bool toReturn = true; string variableName = variable.GetRootName(); if (variable.Value == null || !variable.SetsValue) { toReturn = false; } // states can't set states on this if (variable.IsState(container) && string.IsNullOrEmpty(variable.SourceObject)) { toReturn = false; } if (toReturn && mVariableNamesToSkipForStates.Contains(variableName)) { toReturn = false; } bool hasSourceObject = !string.IsNullOrEmpty(variable.SourceObject); if (toReturn && hasSourceObject) { InstanceSave instanceSave = container.GetInstance(variable.SourceObject); if (instanceSave == null) { toReturn = false; } else { var baseElement = Gum.Managers.ObjectFinder.Self.GetElementSave(instanceSave.BaseType); if (baseElement == null) { toReturn = false; } if (toReturn) { // Gum (just like Glue) keeps variables that aren't needed around. This allows users to rename things and not lose // important information accidentally. But because of that we have to make sure that the variable we're working with is // valid for the type of object we're dealing with. var defaultState = baseElement.DefaultState; RecursiveVariableFinder rvf = new RecursiveVariableFinder(defaultState); var foundVariable = rvf.GetVariable(variable.GetRootName()); if (foundVariable == null) { // This doesn't exist anywhere in the inheritance chain, so we don't want to generate it: toReturn = false; } } } } if (toReturn && !hasSourceObject) { // If a variable is part of a component, it better be defined in the base type or else we won't generate it. // For example, consider a component that used to inherit from Text. It will have variables for fonts. If that // component switches to inheriting from Sprite, those variables will still exist in the XML for that component, // but we shouldn't generate any state variables for those variables. So we'll go to the base type and see if those // variables exist bool isComponent = container is ComponentSave; var rootComponent = Gum.Managers.ObjectFinder.Self.GetRootStandardElementSave(container); // If the Container is a Screen, then rootComponent will be null, so we don't need to do anything if (rootComponent == null) { toReturn = false; } else { IEnumerable <VariableSave> variablesToCheck; if (isComponent) { var component = Gum.Managers.ObjectFinder.Self.GetStandardElement("Component"); variablesToCheck = rootComponent.DefaultState.Variables.Concat(component.DefaultState.Variables); } else { var defaultState = rootComponent.DefaultState; variablesToCheck = defaultState.Variables; } bool wasMatchFound = variablesToCheck.Any(item => item.Name == variable.GetRootName()); toReturn = wasMatchFound; } } return(toReturn); }