public static void SetDefaultValueAccordingToType(this CustomVariable customVariable, string typeAsString) { Type type = TypeManager.GetTypeFromString(typeAsString); if (type == typeof(string)) { customVariable.DefaultValue = ""; } else if (type == null && customVariable.Type == "VariableState") { customVariable.DefaultValue = ""; } // We used to check just Texture2D, but we want to check all file types since we're expanding that //else if (type == typeof(Microsoft.Xna.Framework.Graphics.Texture2D)) else if (customVariable.GetIsFile()) { customVariable.DefaultValue = ""; } else if (type == typeof(Microsoft.Xna.Framework.Color)) { customVariable.DefaultValue = ""; } else if (type == typeof(byte)) { customVariable.DefaultValue = (byte)0; } else if (type == typeof(short)) { customVariable.DefaultValue = (short)0; } else if (type == typeof(int)) { customVariable.DefaultValue = (int)0; } else if (type == typeof(long)) { customVariable.DefaultValue = (long)0; } else if (type == typeof(char)) { customVariable.DefaultValue = ' '; } else if (type == typeof(float)) { customVariable.DefaultValue = 0.0f; } else if (type == typeof(double)) { customVariable.DefaultValue = 0.0; } else { // This will be things like types defined in CSV values customVariable.DefaultValue = ""; } customVariable.FixEnumerationTypes(); }
private void SetVariablesForNamedObject(object newlyCreatedElementRuntime, NamedObjectSave n) { if (newlyCreatedElementRuntime != null) { ElementRuntime containedElementRuntime = GetContainedElementRuntime(n); Type typeOfNewObject = newlyCreatedElementRuntime.GetType(); // As of June 24, 2012 // States are set before // CustomVariables: if (!string.IsNullOrEmpty(n.CurrentState)) { containedElementRuntime.SetState(n.CurrentState, false); } // If it's null, this means it's a default value so don't set anything foreach (CustomVariableInNamedObject cvino in n.InstructionSaves.Where(cvino=>cvino.Value != null)) { // If there isn't a TypedMember for the variable, that means Glue won't generate code for it, so we shouln't be applying it. if (!IsVariableExposed(cvino, n)) { continue; } try { // We used to execute // the Instructions right // on the element runtime itself // but I think it's best if we use // the CustomVariable code so that we // get all the benefit of CustomVariables // like loading of files, and calling events. //cvino.ToInstruction(newlyCreatedElementRuntime).Execute(); // Update May 25, 2012 // We used to get the ElementRuntime // for the NamedObjectSave and have it // set the CustomVariable - however this // doesn't work because it tries to access // files within its own scope, instead of files // that belong to "this". //CustomVariable customVariable = new CustomVariable(); //customVariable.Type = cvino.Type; ////customVariable.SourceObject = n.InstanceName; ////customVariable.SourceObjectProperty = cvino.Member; //customVariable.DefaultValue = cvino.Value; //customVariable.Name = cvino.Member; //containedElementRuntime.SetCustomVariable(customVariable, customVariable.DefaultValue, false); CustomVariable customVariable = new CustomVariable(); customVariable.Type = cvino.Type; customVariable.SourceObject = n.InstanceName; customVariable.SourceObjectProperty = cvino.Member; customVariable.DefaultValue = cvino.Value; customVariable.Name = cvino.Member; if (cvino.Value is string && customVariable.GetIsFile()) { // We want to load the file at this level and pass the result down: ReferencedFileSave rfs = GetReferencedFileFromName(cvino.Value); object fileRuntime = null; if (rfs == null) { fileRuntime = null; } else { fileRuntime = LoadReferencedFileSave(rfs, true, this.AssociatedIElement); } customVariable.DefaultValue = fileRuntime; } if (customVariable.DefaultValue is float && customVariable.SourceObjectProperty == "Z" && newlyCreatedElementRuntime is PositionedObject && ((PositionedObject)newlyCreatedElementRuntime).Parent == Camera.Main) { float value = (float)customVariable.DefaultValue - 40; customVariable.DefaultValue = value; } SetCustomVariable(customVariable, mAssociatedIElement, customVariable.DefaultValue, false); } catch(Exception e) { int m = 3; m++; // for now, do nothing } } } }
private PositionedObject SetFieldOrPropertyCustomVariable(CustomVariable cv, object valueToSetTo, bool attachAndUnattach, IElement container, ElementRuntime sourceElement, object objectToSetOn, PositionedObject parent, PropertyInfo property, FieldInfo field) { if (objectToSetOn != sourceElement && sourceElement.mAssociatedNamedObjectSave.SourceType == SourceType.FlatRedBallType && objectToSetOn is PositionedObject && attachAndUnattach) { parent = sourceElement; } // Not sure if this is the best place to put this, but let's replace "\\n" with "\n" if (valueToSetTo is string && ((string)valueToSetTo).Contains("\\n")) { valueToSetTo = ((string)valueToSetTo).Replace("\\n", "\n"); } VariableSetArgs vse = new VariableSetArgs(); vse.Value = valueToSetTo; vse.VariableName = cv.Name; if (BeforeVariableApply != null) { BeforeVariableApply(this, vse); } if (property != null) { //try //{ if (cv.GetIsFile()) { object fileRuntime = null; if (valueToSetTo is string) { ReferencedFileSave rfs = GetReferencedFileFromName(valueToSetTo); if (rfs == null) { fileRuntime = null; } else { fileRuntime = LoadReferencedFileSave(rfs, true, container); } } else { fileRuntime = valueToSetTo; } property.SetValue(objectToSetOn, fileRuntime, null); } else { object convertedValue = valueToSetTo; if (property.PropertyType == typeof(Microsoft.Xna.Framework.Color) && valueToSetTo is string) { convertedValue = PropertyValuePair.ConvertStringToType((string)valueToSetTo, property.PropertyType); } if(property.PropertyType == typeof(IList<FlatRedBall.Math.Geometry.Point>)) { // We may be storing vectors, so if so we need to convert if (valueToSetTo != null && valueToSetTo is List<Vector2>) { List<FlatRedBall.Math.Geometry.Point> converted = new List<FlatRedBall.Math.Geometry.Point>(); foreach(var item in valueToSetTo as List<Vector2>) { converted.Add(new Math.Geometry.Point(item.X, item.Y)); } convertedValue = converted; } } bool shouldSet = true; if (convertedValue is string && (string.IsNullOrEmpty((string)convertedValue)) && ( property.PropertyType == typeof(float) || property.PropertyType == typeof(bool) || property.PropertyType == typeof(long) || property.PropertyType == typeof(double) || property.PropertyType == typeof(int))) { shouldSet = false; } if (shouldSet) { // It's possible that GlueView // can set a bad value like float.NaN // on an X which ultimately makes the engine // crash hard! If an exception occurs on a property // set, then we need to catch it and undo the set, then // throw an exception so that whoever set it can deal with // the problem. object oldValue = null; if(property.CanRead) { oldValue = property.GetValue(objectToSetOn, null); } try { bool wasCustomSet = false; if (objectToSetOn is PositionedObject) { } else { } property.SetValue(objectToSetOn, convertedValue, null); } catch (Exception e) { if (property.CanRead) { // We failed, so let's set the value back (if we can) try { property.SetValue(objectToSetOn, oldValue, null); } catch { // do nothing } } //throw new Exception("Error setting " + property.Name + " on " + objectToSetOn + ":\n" + e.ToString()); } } } //} //catch //{ // // do nothing for now //} } else if (field != null) { field.SetValue(objectToSetOn, valueToSetTo); } if (objectToSetOn is PositionedObject) { ((PositionedObject)objectToSetOn).ForceUpdateDependencies(); } // If we changed the position of this, we want to make sure to update any // children before we continue to eliminate errors from repositioning foreach (PositionedObject childObject in this.Children) { childObject.ForceUpdateDependenciesDeep(); } foreach (ElementRuntime er in this.ContainedElements) { er.ForceUpdateDependenciesDeep(); } if (AfterVariableApply != null) { AfterVariableApply(this, vse); } return parent; }
public static bool GetShouldCustomVariableBeConvertedToType(MemberChangeArgs args, CustomVariable variable) { var runtimeType = variable.GetRuntimeType(); return runtimeType != null && args.Value is string && !variable.GetIsFile() && variable.Type != "Color"; }
/// <summary> /// This method populates the mCustomVariables list with default valued variables. These can later get set in SetCustomVariable, but they need to exist so that /// plugins like the script parser know whether something is a custom variable or not. /// </summary> /// <param name="cv">The variable to evaluate and add if it is a custom variable.</param> private void CreateCustomVariableContainer(CustomVariable cv) { bool isCustomVariable = true; if(!string.IsNullOrEmpty(cv.SourceObject)) { isCustomVariable = false; } if (isCustomVariable) { Type positionedObjectType = typeof(PositionedObject); PropertyInfo property = positionedObjectType.GetProperty(cv.Name); FieldInfo field = positionedObjectType.GetField(cv.Name); if (property != null || field != null) { isCustomVariable = false; } } if (isCustomVariable) { EntitySave baseEntitySave = ObjectFinder.Self.GetEntitySave(this.AssociatedIElement.BaseElement); if (baseEntitySave != null && baseEntitySave.GetCustomVariable(cv.Name) != null) { isCustomVariable = false; } } if (isCustomVariable) { object defaultValue = null; if (cv.GetIsFile()) { defaultValue = null; } else if (cv.GetIsCsv()) { defaultValue = null; } else if (cv.GetIsVariableState()) { defaultValue = null; } else { try { defaultValue = TypeManager.GetDefaultForTypeAsType(cv.Type); } catch { throw new Exception("Could not get the default value for variable " + cv); } } mCustomVariables.Add(new PropertyValuePair(cv.Name, defaultValue)); } }
private object CastAndTranslateValueToSet(CustomVariable cv, object valueToSetTo) { if (cv.Type == "Color") { if (valueToSetTo == null || string.IsNullOrEmpty(valueToSetTo as string)) { } Type colorType = typeof(Color); PropertyInfo propertyInfo = colorType.GetProperty((string)valueToSetTo, BindingFlags.Public | BindingFlags.Static); Color colorToSet = (Color)(propertyInfo.GetValue(null, null)); return colorToSet; } else if (cv.Type == "string" && valueToSetTo is string) { if (cv.GetIsFile()) { // do noting } else if (cv != null && cv.GetIsAnimationChain()) { // do nothing } else if (LocalizationManager.HasDatabase) { valueToSetTo = LocalizationManager.Translate((string)valueToSetTo); } //else if (namedObject.SourceType == SourceType.File) //{ // if (instructionSave.Member != "CurrentChain") // { // value = "LocalizationManager.Translate(" + value + ")"; // } //} //else if (namedObject.SourceType == SourceType.Entity) //{ // EntitySave entitySave = ObjectFinder.GetEntitySave(namedObject.SourceClassType); // if (entitySave != null) // { // CustomVariable variableInEntity = entitySave.GetCustomVariable(instructionSave.Member); // if (variableInEntity == null || variableInEntity.IsAnimationChain == false) // { // value = "LocalizationManager.Translate(" + value + ")"; // } // } //} return valueToSetTo; } else { return valueToSetTo; } }
public static TypeConverter GetTypeConverter(this CustomVariable customVariable, IElement containingElement, StateSave stateSave, FlatRedBall.Glue.Plugins.ExportedInterfaces.IGlueState glueState) { TypeConverter typeConverter = null; if (customVariable.GetIsVariableState()) { typeConverter = new AvailableStates( FacadeContainer.Self.GlueState.CurrentNamedObjectSave, FacadeContainer.Self.GlueState.CurrentElement, FacadeContainer.Self.GlueState.CurrentCustomVariable, FacadeContainer.Self.GlueState.CurrentStateSave ); } else { Type runtimeType = customVariable.GetRuntimeType(); if (runtimeType != null) { if (runtimeType.IsEnum) { typeConverter = new EnumConverter(runtimeType); } else if (runtimeType == typeof(Color)) { return(new AvailableColorTypeConverter()); } else if ((runtimeType == typeof(string) || runtimeType == typeof(AnimationChainList)) && customVariable.SourceObjectProperty == "CurrentChainName") { typeConverter = new AvailableAnimationChainsStringConverter(customVariable, stateSave); } else if (customVariable.GetIsFile()) { AvailableFileStringConverter converter = new AvailableFileStringConverter(containingElement); converter.QualifiedRuntimeTypeName = runtimeType.FullName; converter.ShowNewFileOption = false; converter.RemovePathAndExtension = true; typeConverter = converter; } } else if (customVariable.GetIsCsv()) { if (FacadeContainer.Self.ProjectValues == null) { throw new NullReferenceException("The ProjectValues property in FAcadeContainer.Self.ProjectValues must be set before trying to get the CSV type converter for the variable " + customVariable.ToString()); } ReferencedFileSave rfs = ObjectFinder.Self.GetAllReferencedFiles().FirstOrDefault(item => item.IsCsvOrTreatedAsCsv && item.GetTypeForCsvFile() == customVariable.Type); AvailableSpreadsheetValueTypeConverter converter = null; if (rfs != null) { converter = new AvailableSpreadsheetValueTypeConverter( FacadeContainer.Self.ProjectValues.ContentDirectory + rfs.Name, containingElement); } else { converter = new AvailableSpreadsheetValueTypeConverter( FacadeContainer.Self.ProjectValues.ContentDirectory + customVariable.Type, containingElement); } converter.ShouldAppendFileName = true; typeConverter = converter; } else if (customVariable.GetIsFile()) { // If we got here, that means that the // CustomVariable is a file, but it doesn't // have a System.Type, so it only knows its runtime // type; AvailableFileStringConverter converter = new AvailableFileStringConverter(containingElement); converter.UnqualifiedRuntimeTypeName = customVariable.Type; converter.ShowNewFileOption = false; converter.RemovePathAndExtension = true; typeConverter = converter; } } return(typeConverter); }
public static ICodeBlock AppendAssignmentForCustomVariableInElement(ICodeBlock codeBlock, CustomVariable customVariable, IElement saveObject) { bool hasBase = !string.IsNullOrEmpty(((INamedObjectContainer)saveObject).BaseObject); // Victor Chelaru // December 17, 2014 // We used to not go into // this if statement if SetByDerived // was true, but actually since variables // are set bottom-up, there's really no reason // to set it only on the derived, because the base // will always get assigned first, then the derived // can override it. //if (!customVariable.SetByDerived && if (customVariable.DefaultValue != null && // if it's null the user doesn't want to change what is set in the file or in the source object !customVariable.IsShared && // no need to handle statics here because they're always defined in class scope !IsVariableTunnelingToDisabledObject(customVariable, saveObject) ) { string variableToAssign = ""; CustomVariable variableConsideringDefinedByBase = customVariable.GetDefiningCustomVariable(); IElement containerOfState = null; // This can be null // if the user takes // an Element that inherits // from another and has variables // from it, then changes the Element // to no longer inherit. if (variableConsideringDefinedByBase != null) { containerOfState = BaseElementTreeNode.GetElementIfCustomVariableIsVariableState(variableConsideringDefinedByBase, saveObject); if (containerOfState == null) { variableToAssign = CodeParser.ParseObjectValue(customVariable.DefaultValue); NamedObjectSave namedObject = saveObject.GetNamedObject(customVariable.SourceObject); if (customVariable.GetIsFile()) { variableToAssign = variableToAssign.Replace("\"", "").Replace("-", "_"); if (variableToAssign == "<NONE>") { variableToAssign = "null"; } } else if (customVariable != null && customVariable.GetIsCsv()) { if (ShouldAssignToCsv(customVariable, variableToAssign)) { variableToAssign = GetAssignmentToCsvItem(customVariable, saveObject, variableToAssign); } else { variableToAssign = null; } } else if (customVariable.Type == "Color") { variableToAssign = "Color." + variableToAssign.Replace("\"", ""); } else if (customVariable.Type != "string" && variableToAssign == "\"\"") { variableToAssign = null; } else { //Not sure why this wasn't localizing variables but it caused a problem with //variables that tunnel in to a Text's DisplayText not being localized //finish here // Special Case: // We don't want to // set Visible on NOS's // which are added/removed // when Visible is set on them: // Update March 7, 2014 // We do want to set it because if we don't, // then the checks inside the Visible property // don't properly detect that they've been changed. // Therefore, we're going to set it on the underlying // object bool shouldSetUnderlyingValue = namedObject != null && namedObject.RemoveFromManagersWhenInvisible && customVariable.SourceObjectProperty == "Visible"; if (shouldSetUnderlyingValue) { // Don't change the variable to assign } else { variableToAssign = CodeWriter.MakeLocalizedIfNecessary(namedObject, customVariable.SourceObjectProperty, customVariable.DefaultValue, variableToAssign, null); variableToAssign = variableToAssign.Replace("+", "."); } } } else { string valueAsString = (string)customVariable.DefaultValue; if (!string.IsNullOrEmpty(valueAsString)) { variableToAssign = StateCodeGenerator.FullyQualifyStateValue(containerOfState, (string)customVariable.DefaultValue, customVariable.Type); } } if (!string.IsNullOrEmpty(variableToAssign)) { string relativeVersionOfProperty = InstructionManager.GetRelativeForAbsolute(customVariable.Name); if (!string.IsNullOrEmpty(relativeVersionOfProperty)) { codeBlock = codeBlock.If("Parent == null"); } NamedObjectSave namedObject = saveObject.GetNamedObject(customVariable.SourceObject); bool shouldSetUnderlyingValue = namedObject != null && namedObject.RemoveFromManagersWhenInvisible && customVariable.SourceObjectProperty == "Visible"; if (namedObject != null) { NamedObjectSaveCodeGenerator.AddIfConditionalSymbolIfNecesssary(codeBlock, namedObject); } if (shouldSetUnderlyingValue) { codeBlock.Line(StringHelper.SpaceStrings(namedObject.InstanceName + "." + customVariable.SourceObjectProperty + " = ", variableToAssign + ";")); } else { codeBlock.Line(StringHelper.SpaceStrings(customVariable.Name, "=", variableToAssign + ";")); } if (!string.IsNullOrEmpty(relativeVersionOfProperty)) { if (customVariable.Name == "Z") { codeBlock = codeBlock.End().ElseIf("Parent is FlatRedBall.Camera"); codeBlock.Line(relativeVersionOfProperty + " = " + variableToAssign + " - 40.0f;"); } codeBlock = codeBlock.End().Else(); codeBlock.Line(relativeVersionOfProperty + " = " + variableToAssign + ";"); codeBlock = codeBlock.End(); } if (namedObject != null) { NamedObjectSaveCodeGenerator.AddEndIfIfNecessary(codeBlock, namedObject); } } } } return codeBlock; }
private static void CreateNewVariableMember(ICodeBlock codeBlock, CustomVariable customVariable, bool isExposing, IElement element) { string variableAssignment = ""; if (customVariable.DefaultValue != null) { if (!IsTypeFromCsv(customVariable)) { variableAssignment = CodeParser.ParseObjectValue(customVariable.DefaultValue); // If this is a file, we don't want to assign it here if (customVariable.GetIsFile()) { variableAssignment = null; } if (customVariable.Type == "Color") { variableAssignment = "Color." + variableAssignment.Replace("\"", ""); } else if (customVariable.Type != "string" && variableAssignment == "\"\"") { variableAssignment = null; } if (variableAssignment != null) { variableAssignment = " = " + variableAssignment; } } else if(!string.IsNullOrEmpty(customVariable.DefaultValue as string) && (string)customVariable.DefaultValue != "<NULL>") { // If the variable IsShared (ie static) then we // don't want to assign the value because the CSV // may not yet be loaded. This may create behavior // the user doesn't expect, but the alternative is either // to load the file before the user wants to (which maybe we // will end up doing) or to get a crash // Update June 2, 2013 // If the customVariable // is not "IsShared" (it's // not static), we don't want // to assign the value where we // create the variable as a field // because this means the value will // attempt to assign before LoadStaticContent. // This can cause a crash, and has in the GlueTestProject. // Update June 2, 2013 // Used to set it to null // if it's static, but we should // allow statics to set their values // if they come from global content files. if ( ReferencesCsvFromGlobalContent(customVariable) && ShouldAssignToCsv(customVariable, customVariable.DefaultValue as string)) { variableAssignment = " = " + GetAssignmentToCsvItem(customVariable, element, (string)customVariable.DefaultValue); } else { variableAssignment = null; } } } string formatString = null; bool needsToBeProperty = (customVariable.SetByDerived && !customVariable.IsShared) || customVariable.CreatesProperty || customVariable.CreatesEvent || IsVariableWholeNumberWithVelocity(customVariable); needsToBeProperty = needsToBeProperty & !customVariable.GetIsVariableState(); EventCodeGenerator.TryGenerateEventsForVariable(codeBlock, customVariable, element); string memberType = GetMemberTypeFor(customVariable, element); if (needsToBeProperty) { // If the variable // creates an event // then it needs to have // custom code (it can't be // an automatic property). bool isWholeNumberWithVelocity = IsVariableWholeNumberWithVelocity(customVariable); if (customVariable.CreatesEvent || isWholeNumberWithVelocity || customVariable.DefaultValue != null ) { string variableToAssignInProperty = "base." + customVariable.Name; // create a field for this, unless it's defined by base - then the base creates a field for it if (!isExposing && !customVariable.DefinedByBase) { variableToAssignInProperty = "m" + customVariable.Name; // First we make the field that will get set here: codeBlock.Line(StringHelper.Modifiers(Public: false, Static: customVariable.IsShared, Type: memberType, Name: variableToAssignInProperty) + variableAssignment + ";"); } string propertyHeader = null; if (isExposing) { propertyHeader = "public new " + memberType + " " + customVariable.Name; } else if (customVariable.DefinedByBase) { propertyHeader = "public override " + memberType + " " + customVariable.Name; } else if (customVariable.SetByDerived) { propertyHeader = "public virtual " + memberType + " " + customVariable.Name; } else { propertyHeader = "public " + memberType + " " + customVariable.Name; } ICodeBlock set = codeBlock.Property(propertyHeader, Static:customVariable.IsShared) .Set(); if (EventCodeGenerator.ShouldGenerateEventsForVariable(customVariable, element)) { EventCodeGenerator.GenerateEventRaisingCode(set, BeforeOrAfter.Before, customVariable.Name, element); } set.Line(variableToAssignInProperty + " = value;"); if (IsVariableWholeNumberWithVelocity(customVariable)) { set.Line(customVariable.Name + "ModifiedByVelocity = value;"); } if (EventCodeGenerator.ShouldGenerateEventsForVariable(customVariable, element)) { EventCodeGenerator.GenerateEventRaisingCode(set, BeforeOrAfter.After, customVariable.Name, element); } ICodeBlock get = set.End().Get(); codeBlock = get.Line("return " + variableToAssignInProperty + ";") .End().End(); // end the getter, end the property } else { // Static vars can't be virtual bool isVirtual = !customVariable.IsShared; codeBlock.AutoProperty(customVariable.Name, Public: true, Virtual: isVirtual, Static: customVariable.IsShared, Type: memberType); } } else { if (!customVariable.GetIsVariableState()) { codeBlock.Line(StringHelper.Modifiers(Public: true, Static: customVariable.IsShared, Type: memberType, Name: customVariable.Name) + variableAssignment + ";"); } else { if (IsVariableTunnelingToDisabledObject(customVariable, element)) { // If it's a varaible // that is exposing a // state variable for a // disabled object, we still // want to generate something: codeBlock.Line(StringHelper.Modifiers(Public: true, Static: customVariable.IsShared, Type: memberType, Name: customVariable.Name) // No assignment for now. Do we eventually want this? The reason // this even exists is to satisfy a variable that may be needed by other // code which would point to a disabled object. //+ variableAssignment + ";"); } } } }