static void AddUnique(this List <TypedMemberBase> listToAddTo, TypedMemberBase itemToAdd) { if (!listToAddTo.ContainsMatch(itemToAdd)) { listToAddTo.Add(itemToAdd); } }
private static void TryAddMember(List <TypedMemberBase> members, Dictionary <string, string> untypedMembers, List <string> membersAlreadyAdded, string memberName, Type type, string classType) { string toAdd = memberName; if (!string.IsNullOrEmpty(memberName) && toAdd.Contains("=")) { toAdd = toAdd.Substring(0, toAdd.IndexOf("=")).Trim(); } if (!string.IsNullOrEmpty(toAdd) && !membersAlreadyAdded.Contains(toAdd)) { membersAlreadyAdded.Add(toAdd); if (type == null) { untypedMembers.Add(memberName, classType); } else { TypedMemberBase typedMemberBase = TypedMemberBase.GetTypedMemberUnequatable( memberName, type); members.Add(typedMemberBase); } } }
public static InstructionSave SetPropertyValue(this NamedObjectSave instance, string propertyName, object valueToSet) { InstructionSave instruction = instance.GetInstructionFromMember(propertyName); if (instruction == null) { TypedMemberBase tmb = instance.TypedMembers.FirstOrDefault(member => member.MemberName == propertyName); if (tmb != null) { instruction = instance.AddNewGenericInstructionFor(propertyName, tmb.MemberType); } else { instruction = instance.AddNewGenericInstructionFor(propertyName, valueToSet.GetType()); } if (tmb.CustomTypeName != null) { instruction.Type = tmb.CustomTypeName; } } instruction.Value = valueToSet; return(instruction); }
private static void PerformStandardVariableAssignments(NamedObjectSave instance, TypedMemberBase typedMember, object value, DataGridItem instanceMember, Type memberType) { // If we ignore the next refresh, then AnimationChains won't update when the user // picks an AnimationChainList from a combo box: //RefreshLogic.IgnoreNextRefresh(); GlueCommands.Self.GluxCommands.SetVariableOn( instance, typedMember.MemberName, memberType, value); GlueCommands.Self.RefreshCommands.RefreshPropertyGrid(); // let's make the UI faster: // Get this on the UI thread, but use it in the async call below var currentElement = GlueState.Self.CurrentElement; TaskManager.Self.AddAsyncTask(() => { GlueCommands.Self.GluxCommands.SaveGlux(); GlueCommands.Self.GenerateCodeCommands.GenerateElementCode(currentElement); }, "Saving .glux and regenerating the code for the current element"); }
private static bool IsTypeFile(TypedMemberBase typedMember) { var memberType = typedMember.MemberType; // old (hardcoded) code: //return memberType == typeof(Microsoft.Xna.Framework.Graphics.Texture2D) || // memberType == typeof(FlatRedBall.Graphics.BitmapFont) || // memberType == typeof(FlatRedBall.Graphics.Animation.AnimationChainList) || // memberType == typeof(Scene); // But we could just check for extensions in all of the ATIs //We can have types that go to strings, and we dont' want a drop-down for all strings: if (memberType == typeof(string)) { return(false); } foreach (var ati in AvailableAssetTypes.Self.AllAssetTypes.Where(item => !string.IsNullOrEmpty(item.Extension))) { if (ati.QualifiedRuntimeTypeName.QualifiedType == memberType.FullName || ati.FriendlyName == memberType.Name) { return(true); } if (!string.IsNullOrEmpty(typedMember.CustomTypeName) && ati.QualifiedRuntimeTypeName.QualifiedType == typedMember.CustomTypeName) { return(true); } } return(false); }
public static void ReactToValueSet(NamedObjectSave instance, TypedMemberBase typedMember, object value, DataGridItem instanceMember, Type memberType) { instanceMember.IsDefault = false; TryAdjustingValue(instance, typedMember, ref value, instanceMember); PerformStandardVariableAssignments(instance, typedMember, value, instanceMember, memberType); }
private bool ShouldMemberBeSkipped(TypedMemberBase typedMemberBase) { // This variable is only available for exposing, not for setting on the NOS itself if (typedMemberBase.MemberName == "SourceFile") { return(true); } return(false); }
private static void CreateCategoriesAndVariables(NamedObjectSave instance, IElement container, List <MemberCategory> categories, AssetTypeInfo ati) { // May 13, 2017 // I'd like to get // completely rid of // TypedMembers and move // to using the custom variables. // We'll try this out: if (ati?.VariableDefinitions != null && ati.VariableDefinitions.Count > 0) { foreach (var variableDefinition in ati.VariableDefinitions) { try { var type = FlatRedBall.Glue.Parsing.TypeManager.GetTypeFromString(variableDefinition.Type); TypedMemberBase typedMember = TypedMemberBase.GetTypedMember(variableDefinition.Name, type); InstanceMember instanceMember = CreateInstanceMember(instance, container, typedMember, ati); if (instanceMember != null) { var categoryToAddTo = GetOrCreateCategoryToAddTo(categories, ati, typedMember); categoryToAddTo.Members.Add(instanceMember); } } catch { // this new code isn't working with some things like generics. Until I fix that, let's fall back: var typedMember = instance.TypedMembers.FirstOrDefault(item => item.MemberName == variableDefinition.Name); if (typedMember != null) { AddForTypedMember(instance, container, categories, ati, typedMember); } } } } else { for (int i = 0; i < instance.TypedMembers.Count; i++) { TypedMemberBase typedMember = instance.TypedMembers[i]; AddForTypedMember(instance, container, categories, ati, typedMember); } } bool shouldAddSourceNameVariable = instance.SourceType == SourceType.File && !string.IsNullOrEmpty(instance.SourceFile); if (shouldAddSourceNameVariable) { AddSourceNameVariable(instance, categories); } }
public static TypedMemberBase GetTypedMemberBase(string typeString, string memberName) { // make the typeString proper Type type = TypeManager.GetTypeFromString(typeString); // At one time this was using GetTypedMember, but I don't know why we need them // to be equatable //TypedMemberBase typedMemberBase = TypedMemberBase.GetTypedMember(memberName, type); TypedMemberBase typedMemberBase = TypedMemberBase.GetTypedMemberUnequatable(memberName, type); return(typedMemberBase); }
public void TestSetByDerivedVariables() { TypedMemberBase tmb = GetTypedMemberBase(mDerivedNosInContainer, mSetByDerivedVariable.Name); bool isCsv = NamedObjectPropertyGridDisplayer.GetIfIsCsv( mDerivedNosInContainer, tmb.MemberName); if (isCsv) { throw new Exception("String veriables are improperly being identified as CSVs"); } }
static bool ContainsMatch(this List <TypedMemberBase> listToAddTo, TypedMemberBase itemToCheck) { foreach (var item in listToAddTo) { if (DoTypedMemberBasesMatch(item, itemToCheck)) { return(true); } } return(false); }
public static List <TypedMemberBase> GetTypedMembers(this AssetTypeInfo thisAti) { List <TypedMemberBase> typedMembers = new List <TypedMemberBase>(); foreach (var item in thisAti.CachedExtraVariables) { TypedMemberBase typedMemberBase = GetTypedMemberBase(item.Type, item.Member); typedMembers.Add(typedMemberBase); } return(typedMembers); }
private static void TryAdjustingValue(NamedObjectSave instance, TypedMemberBase typedMember, ref object value, DataGridItem instanceMember) { if(typedMember.MemberType == typeof(AnimationChainList)) { if(value is string && ((string)value) == "<NONE>") { value = null; instanceMember.IsDefault = true; // Let's also set the CurrentChainName to null GlueCommands.Self.GluxCommands.SetVariableOn( instance, "CurrentChainName", typeof(string), null); } } }
private static void TryAdjustingValue(NamedObjectSave instance, TypedMemberBase typedMember, ref object value, DataGridItem instanceMember) { if (typedMember.MemberType == typeof(AnimationChainList)) { if (value is string && ((string)value) == "<NONE>") { value = null; instanceMember.IsDefault = true; // Let's also set the CurrentChainName to null GlueCommands.Self.GluxCommands.SetVariableOn( instance, "CurrentChainName", typeof(string), null); } } }
/// <summary> /// Determines if a variable should be ignored by the variable plugin. /// </summary> /// <param name="typedMember">The typed member - represents the variable which may be ignored.</param> /// <param name="instance">The NamedObjectSave owning the variable.</param> /// <param name="ati">The Asset Typ Info for the NamedObjectSave.</param> /// <returns>Whether to skip the variable.</returns> private static bool GetIfShouldBeSkipped(TypedMemberBase typedMember, NamedObjectSave instance, AssetTypeInfo ati) { ///////////////////Early Out//////////////////////// if (typedMember == null) { return(true); } //////////////////End Early Out////////////////////// var name = typedMember.MemberName; if (ati != null) { if (ati.IsPositionedObject) { if (name.EndsWith("Velocity") || name.EndsWith("Acceleration") || name.StartsWith("Relative") || name == "ParentBone" || name == "KeepTrackOfReal" || name == "Drag" ) { return(true); } } if (ati.QualifiedRuntimeTypeName.QualifiedType == "FlatRedBall.Math.Geometry.AxisAlignedRectangle") { return(name == "ScaleX" || name == "ScaleY" || name == "Top" || name == "Bottom" || name == "Left" || name == "Right"); } if (ati.QualifiedRuntimeTypeName.QualifiedType == "FlatRedBall.Graphics.Text") { return (name == "AlphaRate" || name == "RedRate" || name == "GreenRate" || name == "BlueRate" || name == "ScaleVelocity" || name == "SpacingVelocity" || name == "ScaleXVelocity" || name == "ScaleYVelocity" || // These used to be the standard way to size text, but now we just // use "TextureScale" name == "Scale" || name == "Spacing" || name == "NewLineDistance" ); } if (ati.QualifiedRuntimeTypeName.QualifiedType == "FlatRedBall.Camera") { return (name == "AspectRatio" || name == "DestinationRectangle" || name == "CameraModelCullMode"); } if (ati.QualifiedRuntimeTypeName.QualifiedType == "FlatRedBall.Math.Geometry.Polygon") { return (name == "RotationX" || name == "RotationY" || name == "Points"); } if (ati.QualifiedRuntimeTypeName.QualifiedType == "FlatRedBall.Graphics.Layer") { return (name == "LayerCameraSettings"); } if (ati.QualifiedRuntimeTypeName.QualifiedType == "FlatRedBall.Sprite") { return (name == "AlphaRate" || name == "RedRate" || name == "GreenRate" || name == "BlueRate" || name == "RelativeTop" || name == "RelativeBottom" || name == "RelativeLeft" || name == "RelativeRight" || name == "TimeCreated" || name == "TimeIntoAnimation" || name == "ScaleX" || name == "ScaleY" || name == "CurrentChainIndex" || name == "Top" || name == "Bottom" || name == "Left" || name == "Right" || name == "PixelSize" || name == "LeftTextureCoordinate" || name == "RightTextureCoordinate" || name == "BottomTextureCoordinate" || name == "TopTextureCoordinate" || name == "ScaleXVelocity" || name == "ScaleYVelocity" || name == "TextureFilter" ); } } return(false); }
private static MemberCategory GetOrCreateCategoryToAddTo(List <MemberCategory> categories, AssetTypeInfo ati, TypedMemberBase typedMember) { // By defaut make the last category get used (this is "Variables") var categoryToAddTo = categories.Last(); // If there is an AssetTypeInfo... if (ati != null) { // ... see if there is avariable definition for this variable... var foundVariableDefinition = ati.VariableDefinitions.FirstOrDefault(item => item.Name == typedMember.MemberName); if (foundVariableDefinition != null) { //... if so, see the category that it's a part of... string categoryName = foundVariableDefinition.Category; if (!string.IsNullOrEmpty(categoryName)) { //... if a category is defined, see if we have a MemberCategory that we've created for it... categoryToAddTo = categories.FirstOrDefault(item => item.Name == categoryName); if (categoryToAddTo == null) { //... if not, make one, and insert it before the last: categoryToAddTo = new MemberCategory(categoryName); categoryToAddTo.FontSize = 14; categories.Insert(categories.Count - 1, categoryToAddTo); } } } } return(categoryToAddTo); }
private static string PrepareTypeToBeWritten(TypedMemberBase member, string memberType) { if (memberType.Contains("`1")) { // This is generic string name = memberType.Substring(0, memberType.IndexOf('`')); // We want to use FullName rather than Name so we don't rely on using's in generated code //string genericContents = PrepareTypeToBeWritten(null, member.MemberType.GetGenericArguments()[0].Name); string genericContents = PrepareTypeToBeWritten(null, member.MemberType.GetGenericArguments()[0].FullName); memberType = string.Format("{0}<{1}>", name, genericContents); } else if (memberType.Contains("<")) { string name = memberType.Substring(0, memberType.IndexOf('<')); // See above //string genericContents = PrepareTypeToBeWritten(null, member.MemberType.GetGenericArguments()[0].Name); string genericContents = PrepareTypeToBeWritten(null, member.MemberType.GetGenericArguments()[0].FullName); memberType = string.Format("{0}<{1}>", name, genericContents); } else { memberType = TypeManager.ConvertToCommonType(memberType); } return memberType; }
private TypeConverter HandleGetTypeConverter(IElement container, NamedObjectSave instance, TypedMemberBase member) { if (member.CustomTypeName == "AtlasedTextureName") { return(new AtlasTextureTypeConverter()); } else { return(null); } }
private static InstanceMember CreateInstanceMember(NamedObjectSave instance, IElement container, TypedMemberBase typedMember, AssetTypeInfo ati) { bool shouldBeSkipped = GetIfShouldBeSkipped(typedMember, instance, ati); DataGridItem instanceMember = null; if (!shouldBeSkipped) { var memberType = typedMember.MemberType; VariableDefinition variableDefinition = null; if (ati != null) { variableDefinition = ati.VariableDefinitions.FirstOrDefault(item => item.Name == typedMember.MemberName); } instanceMember = new DataGridItem(); instanceMember.FirstGridLength = new System.Windows.GridLength(140); instanceMember.UnmodifiedVariableName = typedMember.MemberName; string displayName = StringFunctions.InsertSpacesInCamelCaseString(typedMember.MemberName); instanceMember.DisplayName = displayName; instanceMember.TypeConverter = PluginManager.GetTypeConverter( container, instance, typedMember); instanceMember.CustomGetTypeEvent += (throwaway) => memberType; instanceMember.IsDefault = instance.GetInstructionFromMember(typedMember.MemberName) == null; instanceMember.CustomGetEvent += (throwaway) => { var instruction = instance.GetInstructionFromMember(typedMember.MemberName); if (instruction == null) { if (variableDefinition != null) { var toReturn = variableDefinition.DefaultValue; if (memberType == typeof(bool)) { bool boolToReturn = false; bool.TryParse(variableDefinition.DefaultValue, out boolToReturn); return boolToReturn; } else { return toReturn; } } else { return null; } } else { return instruction.Value; } }; instanceMember.CustomSetEvent += (owner, value) => { instanceMember.IsDefault = false; RefreshLogic.IgnoreNextRefresh(); GlueCommands.Self.GluxCommands.SetVariableOn( instance, typedMember.MemberName, memberType, value); GlueCommands.Self.GluxCommands.SaveGlux(); GlueCommands.Self.RefreshCommands.RefreshPropertyGrid(); GlueCommands.Self.GenerateCodeCommands.GenerateCurrentElementCode(); }; instanceMember.IsDefaultSet += (owner, args) => { MakeDefault(instance, typedMember.MemberName); }; instanceMember.SetValueError += (newValue) => { if (newValue is string && string.IsNullOrEmpty(newValue as string)) { MakeDefault(instance, typedMember.MemberName); } }; } return instanceMember; }
private static void PerformStandardVariableAssignments(NamedObjectSave instance, TypedMemberBase typedMember, object value, DataGridItem instanceMember, Type memberType) { // If we ignore the next refresh, then AnimationChains won't update when the user // picks an AnimationChainList from a combo box: //RefreshLogic.IgnoreNextRefresh(); GlueCommands.Self.GluxCommands.SetVariableOn( instance, typedMember.MemberName, memberType, value); GlueCommands.Self.RefreshCommands.RefreshPropertyGrid(); // let's make the UI faster: // Get this on the UI thread, but use it in the async call below var currentElement = GlueState.Self.CurrentElement; TaskManager.Self.AddAsyncTask(() => { // don't send an entire frefresh command, we'll refresh // just the variables (prevents a full camera reset) bool sendRefreshCommands = false; GlueCommands.Self.GluxCommands.SaveGlux(sendRefreshCommands); GlueCommands.Self.GlueViewCommands.SendRefreshVariablesCommand(); if (currentElement != null) { GlueCommands.Self.GenerateCodeCommands.GenerateElementCode(currentElement); } }, "Saving .glux and regenerating the code for the current element"); }
private static InstanceMember CreateInstanceMember(NamedObjectSave instance, IElement container, TypedMemberBase typedMember, AssetTypeInfo ati) { bool shouldBeSkipped = GetIfShouldBeSkipped(typedMember, instance, ati); DataGridItem instanceMember = null; if (!shouldBeSkipped) { var typeConverter = PluginManager.GetTypeConverter( container, instance, typedMember); bool isObjectInFile = typeConverter is IObjectsInFileConverter; var memberType = typedMember.MemberType; VariableDefinition variableDefinition = null; if (ati != null) { variableDefinition = ati.VariableDefinitions.FirstOrDefault(item => item.Name == typedMember.MemberName); } if (isObjectInFile) { var fileInstanceMember = new FileInstanceMember(); instanceMember = fileInstanceMember; fileInstanceMember.View += () => { var rfs = (typeConverter as IObjectsInFileConverter).ReferencedFileSave; if (rfs != null) { var value = fileInstanceMember.Value as string; GlueCommands.Self.SelectCommands.Select( rfs, value); } }; instanceMember.PreferredDisplayer = typeof(FileReferenceComboBox); } else { instanceMember = new DataGridItem(); } instanceMember.FirstGridLength = new System.Windows.GridLength(140); instanceMember.UnmodifiedVariableName = typedMember.MemberName; string displayName = StringFunctions.InsertSpacesInCamelCaseString(typedMember.MemberName); instanceMember.DisplayName = displayName; instanceMember.TypeConverter = typeConverter; instanceMember.CustomRefreshOptions += () => { if (typeConverter != null) { instanceMember.CustomOptions.Clear(); var values = typeConverter.GetStandardValues(); foreach (var value in values) { instanceMember.CustomOptions.Add(value); } } }; instanceMember.CustomGetTypeEvent += (throwaway) => memberType; instanceMember.IsDefault = instance.GetInstructionFromMember(typedMember.MemberName) == null; instanceMember.CustomGetEvent += (throwaway) => { var instruction = instance.GetInstructionFromMember(typedMember.MemberName); if (instruction == null) { if (variableDefinition != null) { var toReturn = variableDefinition.DefaultValue; if (memberType == typeof(bool)) { bool boolToReturn = false; bool.TryParse(variableDefinition.DefaultValue, out boolToReturn); return(boolToReturn); } else { return(toReturn); } } else { return(null); } } else { return(instruction.Value); } }; instanceMember.CustomSetEvent += (owner, value) => { NamedObjectVariableChangeLogic.ReactToValueSet(instance, typedMember, value, instanceMember, memberType); }; instanceMember.IsDefaultSet += (owner, args) => { MakeDefault(instance, typedMember.MemberName); }; instanceMember.SetValueError += (newValue) => { if (newValue is string && string.IsNullOrEmpty(newValue as string)) { MakeDefault(instance, typedMember.MemberName); } }; } return(instanceMember); }
private static void AddForTypedMember(NamedObjectSave instance, IElement container, List <MemberCategory> categories, AssetTypeInfo ati, TypedMemberBase typedMember) { InstanceMember instanceMember = CreateInstanceMember(instance, container, typedMember, ati); var categoryToAddTo = GetOrCreateCategoryToAddTo(categories, ati, typedMember); if (instanceMember != null) { categoryToAddTo.Members.Add(instanceMember); } }
private TypeConverter HandleGetTypeConverter(IElement container, NamedObjectSave instance, TypedMemberBase typedMember) { Type memberType = typedMember.MemberType; string memberName = typedMember.MemberName; TypeConverter typeConverter = null; // If the NOS references a FRB type, we need to adjust the type appropriately bool wasTypeModified = false; Type oldType = memberType; bool handled = false; if (instance.SourceType == SourceType.FlatRedBallType) { Type type = TypeManager.GetTypeFromString(instance.SourceClassType); if (type == typeof(Sprite) && memberName == "CurrentChainName") { // special case handling for CurrentChainName typeConverter = new AvailableAnimationChainsStringConverter(container, instance); handled = true; } else if (typedMember.MemberType?.Name == "Sprite") { var nosTypeConverter = new AvailableNamedObjectsAndFiles(container); nosTypeConverter.NamedObjectTypeRestriction = "FlatRedBall.Sprite"; typeConverter = nosTypeConverter; handled = true; } } else if (instance.SourceType == SourceType.File) { if (instance.ClassType == "Sprite" && memberName == "CurrentChainName") { // special case handling for CurrentChainName typeConverter = new AvailableAnimationChainsStringConverter(container, instance); handled = true; } } if (!handled) { if (instance.DoesMemberNeedToBeSetByContainer(memberName)) { var availableNamedObjectsAndFiles = new AvailableNamedObjectsAndFiles(container); availableNamedObjectsAndFiles.NamedObjectTypeRestriction = typedMember.MemberType.FullName; typeConverter = availableNamedObjectsAndFiles; } else if (memberType.IsEnum) { typeConverter = new EnumConverter(memberType); } else if (memberType == typeof(Microsoft.Xna.Framework.Color)) { typeConverter = new AvailableColorTypeConverter(); memberType = typeof(string); } else if (IsTypeFile(typedMember)) { AvailableFileStringConverter availableFileStringConverter = new AvailableFileStringConverter(container); availableFileStringConverter.QualifiedRuntimeTypeName = memberType.FullName; if (!string.IsNullOrEmpty(typedMember.CustomTypeName)) { availableFileStringConverter.QualifiedRuntimeTypeName = typedMember.CustomTypeName; } availableFileStringConverter.RemovePathAndExtension = true; typeConverter = availableFileStringConverter; memberType = typeof(string); } else if (instance.SourceType == SourceType.Entity && !string.IsNullOrEmpty(instance.SourceClassType)) { EntitySave entity = ObjectFinder.Self.GetEntitySave(instance.SourceClassType); if (entity != null) { CustomVariable customVariable = entity.GetCustomVariable(memberName); if (customVariable != null) { typeConverter = customVariable.GetTypeConverter(entity); } } } } //else if (this.SourceType == SaveClasses.SourceType.FlatRedBallType && // typedMember != null && typedMember.MemberType != null) //{ //} if (wasTypeModified) { memberType = oldType; } return(typeConverter); }
private static MemberCategory GetOrCreateCategoryToAddTo(List<MemberCategory> categories, AssetTypeInfo ati, TypedMemberBase typedMember) { // By defaut make the last category get used (this is "Variables") var categoryToAddTo = categories.Last(); // If there is an AssetTypeInfo... if (ati != null) { // ... see if there is avariable definition for this variable... var foundVariableDefinition = ati.VariableDefinitions.FirstOrDefault(item => item.Name == typedMember.MemberName); if (foundVariableDefinition != null) { //... if so, see the category that it's a part of... string categoryName = foundVariableDefinition.Category; if (!string.IsNullOrEmpty(categoryName)) { //... if a category is defined, see if we have a MemberCategory that we've created for it... categoryToAddTo = categories.FirstOrDefault(item => item.Name == categoryName); if (categoryToAddTo == null) { //... if not, make one, and insert it before the last: categoryToAddTo = new MemberCategory(categoryName); categoryToAddTo.FontSize = 14; categories.Insert(categories.Count - 1, categoryToAddTo); } } } } return categoryToAddTo; }
static bool DoTypedMemberBasesMatch(TypedMemberBase item1, TypedMemberBase item2) { return(item1.MemberName == item2.MemberName && item1.MemberType == item2.MemberType); }
private static InstanceMember CreateInstanceMember(NamedObjectSave instance, IElement container, TypedMemberBase typedMember, AssetTypeInfo ati) { bool shouldBeSkipped = GetIfShouldBeSkipped(typedMember, instance, ati); DataGridItem instanceMember = null; if (!shouldBeSkipped) { var typeConverter = PluginManager.GetTypeConverter( container, instance, typedMember); bool isObjectInFile = typeConverter is IObjectsInFileConverter; var memberType = typedMember.MemberType; VariableDefinition variableDefinition = null; if (ati != null) { variableDefinition = ati.VariableDefinitions.FirstOrDefault(item => item.Name == typedMember.MemberName); } if(isObjectInFile) { var fileInstanceMember = new FileInstanceMember(); instanceMember = fileInstanceMember; fileInstanceMember.View += () => { var rfs = (typeConverter as IObjectsInFileConverter).ReferencedFileSave; if (rfs != null) { var value = fileInstanceMember.Value as string; GlueCommands.Self.SelectCommands.Select( rfs, value); } }; instanceMember.PreferredDisplayer = typeof(FileReferenceComboBox); } else { instanceMember = new DataGridItem(); } instanceMember.FirstGridLength = new System.Windows.GridLength(140); instanceMember.UnmodifiedVariableName = typedMember.MemberName; string displayName = StringFunctions.InsertSpacesInCamelCaseString(typedMember.MemberName); instanceMember.DisplayName = displayName; instanceMember.TypeConverter = typeConverter; instanceMember.CustomRefreshOptions += () => { if (typeConverter != null) { instanceMember.CustomOptions.Clear(); var values = typeConverter.GetStandardValues(); foreach (var value in values) { instanceMember.CustomOptions.Add(value); } } }; instanceMember.CustomGetTypeEvent += (throwaway) => memberType; instanceMember.IsDefault = instance.GetInstructionFromMember(typedMember.MemberName) == null; instanceMember.CustomGetEvent += (throwaway) => { var instruction = instance.GetInstructionFromMember(typedMember.MemberName); if (instruction == null) { if (variableDefinition != null) { var toReturn = variableDefinition.DefaultValue; if (memberType == typeof(bool)) { bool boolToReturn = false; bool.TryParse(variableDefinition.DefaultValue, out boolToReturn); return boolToReturn; } else { return toReturn; } } else { return null; } } else { return instruction.Value; } }; instanceMember.CustomSetEvent += (owner, value) => { NamedObjectVariableChangeLogic.ReactToValueSet(instance, typedMember, value, instanceMember, memberType); }; instanceMember.IsDefaultSet += (owner, args) => { MakeDefault(instance, typedMember.MemberName); }; instanceMember.SetValueError += (newValue) => { if (newValue is string && string.IsNullOrEmpty(newValue as string)) { MakeDefault(instance, typedMember.MemberName); } }; } return instanceMember; }
public static List <FlatRedBall.Instructions.Reflection.TypedMemberBase> GetTypedMembers(this EntitySave instance) { List <TypedMemberBase> typedMembers = new List <TypedMemberBase>(); foreach (var customVariable in instance.CustomVariables) { if (customVariable.Scope == Scope.Public || customVariable.Scope == Scope.Internal) { string type = customVariable.Type; if (!string.IsNullOrEmpty(customVariable.OverridingPropertyType)) { type = customVariable.OverridingPropertyType; } TypedMemberBase typedMemberBase = AssetTypeInfoExtensionMethods.GetTypedMemberBase( type, customVariable.Name); typedMembers.Add(typedMemberBase); } } // Add any variables that are set by container for (int i = 0; i < instance.NamedObjects.Count; i++) { NamedObjectSave nos = instance.NamedObjects[i]; if (nos.SetByContainer && !string.IsNullOrEmpty(nos.InstanceType)) { if (nos.SourceType == SourceType.Entity) { TypedMemberBase typedMemberBase = TypedMemberBase.GetTypedMember(nos.InstanceName, typeof(string)); typedMembers.Add(typedMemberBase); } else { if (!nos.IsList) { TypedMemberBase typedMemberBase = AssetTypeInfoExtensionMethods.GetTypedMemberBase( nos.InstanceType, nos.InstanceName); typedMembers.Add(typedMemberBase); } } } } if (!string.IsNullOrEmpty(instance.BaseEntity)) { EntitySave entitySave = ObjectFinder.Self.GetEntitySave( instance.BaseEntity); // This may be null if the project improperly references // an EntitySave that really doesn't exist. if (entitySave != null) { // We used to call "AddRange" but we don't want duplicates // (I don't think) so we're going to use the custom extension // method to prevent duplicates: //typedMembers.AddRange(entitySave.GetTypedMembers()); typedMembers.AddRangeUnique(entitySave.GetTypedMembers()); } } return(typedMembers); }
/// <summary> /// Determines if a variable should be ignored by the variable plugin. /// </summary> /// <param name="typedMember">The typed member - represents the variable which may be ignored.</param> /// <param name="instance">The NamedObjectSave owning the variable.</param> /// <param name="ati">The Asset Typ Info for the NamedObjectSave.</param> /// <returns>Whether to skip the variable.</returns> private static bool GetIfShouldBeSkipped(TypedMemberBase typedMember, NamedObjectSave instance, AssetTypeInfo ati) { var name = typedMember.MemberName; if (ati != null) { if (ati.IsPositionedObject) { if (name.EndsWith("Velocity") || name.EndsWith("Acceleration") || name.StartsWith("Relative") || name == "ParentBone" || name == "KeepTrackOfReal" || name == "Drag" ) { return true; } } if (ati.QualifiedRuntimeTypeName.QualifiedType == "FlatRedBall.Math.Geometry.AxisAlignedRectangle") { return name == "ScaleX" || name == "ScaleY" || name == "Top" || name == "Bottom" || name == "Left" || name == "Right"; } if (ati.QualifiedRuntimeTypeName.QualifiedType == "FlatRedBall.Graphics.Text") { return name == "AlphaRate" || name == "RedRate" || name == "GreenRate" || name == "BlueRate" || name == "ScaleVelocity" || name == "SpacingVelocity" || name == "ScaleXVelocity" || name == "ScaleYVelocity" || // These used to be the standard way to size text, but now we just // use "TextureScale" name == "Scale" || name == "Spacing" || name == "NewLineDistance" ; } if (ati.QualifiedRuntimeTypeName.QualifiedType == "FlatRedBall.Camera") { return name == "AspectRatio" || name == "DestinationRectangle" || name == "CameraModelCullMode"; } if (ati.QualifiedRuntimeTypeName.QualifiedType == "FlatRedBall.Math.Geometry.Polygon") { return name == "RotationX" || name == "RotationY" || name == "Points"; } if (ati.QualifiedRuntimeTypeName.QualifiedType == "FlatRedBall.Graphics.Layer") { return name == "LayerCameraSettings"; } if (ati.QualifiedRuntimeTypeName.QualifiedType == "FlatRedBall.Sprite") { return name == "AlphaRate" || name == "RedRate" || name == "GreenRate" || name == "BlueRate" || name == "RelativeTop" || name == "RelativeBottom" || name == "RelativeLeft" || name == "RelativeRight" || name == "TimeCreated" || name == "TimeIntoAnimation" || name == "ScaleX" || name == "ScaleY" || name == "CurrentChainIndex" || name == "Top" || name == "Bottom" || name == "Left" || name == "Right" || name == "PixelSize" || name == "LeftTextureCoordinate" || name == "RightTextureCoordinate" || name == "BottomTextureCoordinate" || name == "TopTextureCoordinate" || name == "ScaleXVelocity" || name == "ScaleYVelocity" || name == "TextureFilter" ; } } return false; }
public static TypeConverter GetTypeConverter(IElement container, NamedObjectSave instance, TypedMemberBase typedMember) { TypeConverter toReturn = null; SaveRelativeDirectory(); CallMethodOnPlugin( delegate (PluginBase plugin) { if (plugin.GetTypeConverter != null) { var foundValue = plugin.GetTypeConverter(container, instance, typedMember); if (foundValue != null) { toReturn = foundValue; } } }, "GetTypeConverter"); ResumeRelativeDirectory("GetTypeConverter"); return toReturn; }
static void AddUnique(this List<TypedMemberBase> listToAddTo, TypedMemberBase itemToAdd) { if (!listToAddTo.ContainsMatch(itemToAdd)) { listToAddTo.Add(itemToAdd); } }
private static void UpdateTypedMembers(this NamedObjectSave instance) { if (instance.SourceType == SourceType.Entity) { if (string.IsNullOrEmpty(instance.SourceClassType) || instance.SourceClassType == "<NONE>") { instance.TypedMembers.Clear(); } else { EntitySave entitySave = ObjectFinder.Self.GetEntitySave( instance.SourceClassType); if (entitySave != null) { instance.TypedMembers.Clear(); // This is null if a property that calls // UpdateProperties is called before the project // is loaded - as is the case when the GLUX is // deserialized. instance.TypedMembers.AddRange(entitySave.GetTypedMembers()); } } } else if (string.IsNullOrEmpty(instance.ClassType) || instance.ClassType.Contains("PositionedObjectList<")) { instance.TypedMembers.Clear(); } else if (instance.IsList) { // do nothing. } else { instance.TypedMembers.Clear(); // We used to only include members in the // ATI. Now we want to include every possible // variable so that they all show up in the PropertyGrid. //AssetTypeInfo ati = instance.GetAssetTypeInfo(); //if (ati == null) //{ // throw new NullReferenceException("Could not find an AssetType for the type " + // instance.SourceClassType + ". This either means that your ContenTypes CSV is corrupt, out of date, missing, or that you have not loaded a content types CSV if you are using teh GluxViewManager in a custom app."); // instance.TypedMembers.Clear(); //} //else //{ // instance.TypedMembers.Clear(); // instance.TypedMembers.AddRange(ati.GetTypedMembers()); //} List <MemberWithType> variables = ExposedVariableManager.GetExposableMembersFor(instance); foreach (var member in variables) { int errorCode = 0; try { errorCode = 0; string memberType = member.Type; errorCode = 1; memberType = TypeManager.ConvertToCommonType(memberType); errorCode = 2; Type type = TypeManager.GetTypeFromString(memberType); errorCode = 3; // Glue can't do anything with generic properties (yet) // Update: I'm adding support for it now //if (type != null && type.IsGenericType == false) TypedMemberBase typedMember = null; if (type != null) { typedMember = TypedMemberBase.GetTypedMemberUnequatable(member.Member, type); } else { typedMember = TypedMemberBase.GetTypedMemberUnequatable(member.Member, typeof(object)); typedMember.CustomTypeName = memberType; } instance.TypedMembers.Add(typedMember); } catch (Exception e) { throw new Exception("Error trying to fix member " + member + " in object " + instance + ". Error code: " + errorCode + "Additional info:\n\n\n" + e.ToString(), e); } } var ati = instance.GetAssetTypeInfo(); if (ati != null) { foreach (var member in ati.VariableDefinitions) { // Only consider this if it's not already handled: bool isAlreadyHandled = instance.TypedMembers.Any(item => item.MemberName == member.Name); if (!isAlreadyHandled) { string memberType = member.Type; memberType = TypeManager.ConvertToCommonType(memberType); Type type = TypeManager.GetTypeFromString(memberType); // Glue can't do anything with generic properties (yet) // Update: I'm adding support for it now //if (type != null && type.IsGenericType == false) TypedMemberBase typedMember = null; if (type != null) { typedMember = TypedMemberBase.GetTypedMemberUnequatable(member.Name, type); } else { typedMember = TypedMemberBase.GetTypedMemberUnequatable(member.Name, typeof(object)); typedMember.CustomTypeName = memberType; } instance.TypedMembers.Add(typedMember); } } } } }
static bool DoTypedMemberBasesMatch(TypedMemberBase item1, TypedMemberBase item2) { return item1.MemberName == item2.MemberName && item1.MemberType == item2.MemberType; }
private bool ShouldMemberBeSkipped(TypedMemberBase typedMemberBase) { // This variable is only available for exposing, not for setting on the NOS itself if (typedMemberBase.MemberName == "SourceFile") { return true; } return false; }
static bool ContainsMatch(this List<TypedMemberBase> listToAddTo, TypedMemberBase itemToCheck) { foreach (var item in listToAddTo) { if (DoTypedMemberBasesMatch(item, itemToCheck)) { return true; } } return false; }
private static void AddForTypedMember(NamedObjectSave instance, IElement container, List <MemberCategory> categories, AssetTypeInfo ati, TypedMemberBase typedMember) { var variableDefinition = ati?.VariableDefinitions.FirstOrDefault(item => item.Name == typedMember.MemberName); InstanceMember instanceMember = CreateInstanceMember(instance, container, typedMember, ati, variableDefinition); var categoryToAddTo = GetOrCreateCategoryToAddTo(categories, ati, typedMember); if (instanceMember != null) { categoryToAddTo.Members.Add(instanceMember); } }
private static bool IsTypeFile(TypedMemberBase typedMember) { var memberType = typedMember.MemberType; // old (hardcoded) code: //return memberType == typeof(Microsoft.Xna.Framework.Graphics.Texture2D) || // memberType == typeof(FlatRedBall.Graphics.BitmapFont) || // memberType == typeof(FlatRedBall.Graphics.Animation.AnimationChainList) || // memberType == typeof(Scene); // But we could just check for extensions in all of the ATIs //We can have types that go to strings, and we dont' want a drop-down for all strings: if (memberType == typeof(string)) { return false; } foreach (var ati in AvailableAssetTypes.Self.AllAssetTypes.Where(item => !string.IsNullOrEmpty(item.Extension))) { if (ati.QualifiedRuntimeTypeName.QualifiedType == memberType.FullName || ati.FriendlyName == memberType.Name) { return true; } if(!string.IsNullOrEmpty(typedMember.CustomTypeName) && ati.QualifiedRuntimeTypeName.QualifiedType == typedMember.CustomTypeName) { return true; } } return false; }
private static InstanceMember CreateInstanceMember(NamedObjectSave instance, IElement container, TypedMemberBase typedMember, AssetTypeInfo ati, VariableDefinition variableDefinition) { bool shouldBeSkipped = GetIfShouldBeSkipped(typedMember, instance, ati); DataGridItem instanceMember = null; if (!shouldBeSkipped) { var typeConverter = PluginManager.GetTypeConverter( container, instance, typedMember); bool isObjectInFile = typeConverter is IObjectsInFileConverter; var memberType = typedMember.MemberType; if (isObjectInFile) { var fileInstanceMember = new FileInstanceMember(); instanceMember = fileInstanceMember; fileInstanceMember.View += () => { var rfs = (typeConverter as IObjectsInFileConverter).ReferencedFileSave; if (rfs != null) { var value = fileInstanceMember.Value as string; GlueCommands.Self.SelectCommands.Select( rfs, value); } }; instanceMember.PreferredDisplayer = typeof(FileReferenceComboBox); } else { instanceMember = new DataGridItem(); } if (variableDefinition?.Name == "RotationZ" && variableDefinition.Type == "float") { instanceMember.PreferredDisplayer = typeof(AngleSelectorDisplay); instanceMember.PropertiesToSetOnDisplayer[nameof(AngleSelectorDisplay.TypeToPushToInstance)] = AngleType.Radians; } instanceMember.FirstGridLength = new System.Windows.GridLength(140); instanceMember.UnmodifiedVariableName = typedMember.MemberName; string displayName = StringFunctions.InsertSpacesInCamelCaseString(typedMember.MemberName); instanceMember.DisplayName = displayName; instanceMember.TypeConverter = typeConverter; instanceMember.CustomRefreshOptions += () => { if (typeConverter != null) { instanceMember.CustomOptions.Clear(); var values = typeConverter.GetStandardValues(); foreach (var value in values) { instanceMember.CustomOptions.Add(value); } } }; instanceMember.CustomGetTypeEvent += (throwaway) => memberType; instanceMember.IsDefault = instance.GetInstructionFromMember(typedMember.MemberName) == null; instanceMember.CustomGetEvent += (throwaway) => { var instruction = instance.GetInstructionFromMember(typedMember.MemberName); if (instruction == null) { if (variableDefinition != null) { var toReturn = variableDefinition.DefaultValue; if (memberType == typeof(bool)) { bool boolToReturn = false; bool.TryParse(variableDefinition.DefaultValue, out boolToReturn); return(boolToReturn); } else { return(toReturn); } } else { return(null); } } else { return(instruction.Value); } }; instanceMember.CustomSetEvent += (owner, value) => { NamedObjectVariableChangeLogic.ReactToValueSet(instance, typedMember, value, instanceMember, memberType); }; instanceMember.IsDefaultSet += (owner, args) => { MakeDefault(instance, typedMember.MemberName); }; instanceMember.SetValueError += (newValue) => { if (newValue is string && string.IsNullOrEmpty(newValue as string)) { MakeDefault(instance, typedMember.MemberName); } }; instanceMember.ContextMenuEvents.Add("Tunnel Variable", (not, used) => { string variableToTunnel = null; if (variableDefinition != null) { variableToTunnel = variableDefinition?.Name; } else if (typedMember != null) { variableToTunnel = typedMember.MemberName; } GlueCommands.Self.DialogCommands.ShowAddNewVariableDialog( FlatRedBall.Glue.Controls.CustomVariableType.Tunneled, instance.InstanceName, variableToTunnel); }); } return(instanceMember); }
private TypeConverter HandleGetTypeConverter(IElement container, NamedObjectSave instance, TypedMemberBase typedMember) { Type memberType = typedMember.MemberType; string memberName = typedMember.MemberName; TypeConverter typeConverter = null; // If the NOS references a FRB type, we need to adjust the type appropriately bool wasTypeModified = false; Type oldType = memberType; bool handled = false; if (instance.SourceType == SourceType.FlatRedBallType) { Type type = TypeManager.GetTypeFromString(instance.SourceClassType); if (type == typeof(Sprite) && memberName == "CurrentChainName") { // special case handling for CurrentChainName typeConverter = new AvailableAnimationChainsStringConverter(container, instance); handled = true; } // Victor Chelaru // October 26, 2015: // I don't think we need this anymore - we should just let the CSVs do their job // defining variables and not rely on reflection. That way plugins will be able to // handle everything without relying on reflection //if (!handled && type != null) //{ // FieldInfo fieldInfo = type.GetField(memberName); // if (fieldInfo != null) // { // memberType = fieldInfo.FieldType; // wasTypeModified = true; // } // if (wasTypeModified == false) // { // PropertyInfo propertyInfo = type.GetProperty(memberName); // if (propertyInfo != null) // { // memberType = propertyInfo.PropertyType; // wasTypeModified = true; // } // } //} } else if (instance.SourceType == SourceType.File) { if (instance.ClassType == "Sprite" && memberName == "CurrentChainName") { // special case handling for CurrentChainName typeConverter = new AvailableAnimationChainsStringConverter(container, instance); handled = true; } } if (!handled) { if (instance.DoesMemberNeedToBeSetByContainer(memberName)) { typeConverter = new AvailableNamedObjectsAndFiles(container); } else if (memberType.IsEnum) { typeConverter = new EnumConverter(memberType); } else if (memberType == typeof(Microsoft.Xna.Framework.Color)) { typeConverter = new AvailableColorTypeConverter(); memberType = typeof(string); } else if (IsTypeFile(typedMember)) { AvailableFileStringConverter availableFileStringConverter = new AvailableFileStringConverter(container); availableFileStringConverter.QualifiedRuntimeTypeName = memberType.FullName; if(!string.IsNullOrEmpty( typedMember.CustomTypeName )) { availableFileStringConverter.QualifiedRuntimeTypeName = typedMember.CustomTypeName; } availableFileStringConverter.RemovePathAndExtension = true; typeConverter = availableFileStringConverter; memberType = typeof(string); } else if (instance.SourceType == SourceType.Entity && !string.IsNullOrEmpty(instance.SourceClassType)) { EntitySave entity = ObjectFinder.Self.GetEntitySave(instance.SourceClassType); if (entity != null) { CustomVariable customVariable = entity.GetCustomVariable(memberName); if (customVariable != null) { typeConverter = customVariable.GetTypeConverter(entity); } } } } //else if (this.SourceType == SaveClasses.SourceType.FlatRedBallType && // typedMember != null && typedMember.MemberType != null) //{ //} if (wasTypeModified) { memberType = oldType; } return typeConverter; }
private TypeConverter HandleGetTypeConverter(IElement container, NamedObjectSave instance, TypedMemberBase typedMember) { Type memberType = typedMember.MemberType; string memberName = typedMember.MemberName; TypeConverter typeConverter = null; // If the NOS references a FRB type, we need to adjust the type appropriately bool wasTypeModified = false; Type oldType = memberType; bool handled = false; if (instance.SourceType == SourceType.FlatRedBallType) { Type type = TypeManager.GetTypeFromString(instance.SourceClassType); if (type == typeof(Sprite) && memberName == "CurrentChainName") { // special case handling for CurrentChainName typeConverter = new AvailableAnimationChainsStringConverter(container, instance); handled = true; } // Victor Chelaru // October 26, 2015: // I don't think we need this anymore - we should just let the CSVs do their job // defining variables and not rely on reflection. That way plugins will be able to // handle everything without relying on reflection //if (!handled && type != null) //{ // FieldInfo fieldInfo = type.GetField(memberName); // if (fieldInfo != null) // { // memberType = fieldInfo.FieldType; // wasTypeModified = true; // } // if (wasTypeModified == false) // { // PropertyInfo propertyInfo = type.GetProperty(memberName); // if (propertyInfo != null) // { // memberType = propertyInfo.PropertyType; // wasTypeModified = true; // } // } //} } else if (instance.SourceType == SourceType.File) { if (instance.ClassType == "Sprite" && memberName == "CurrentChainName") { // special case handling for CurrentChainName typeConverter = new AvailableAnimationChainsStringConverter(container, instance); handled = true; } } if (!handled) { if (instance.DoesMemberNeedToBeSetByContainer(memberName)) { var availableNamedObjectsAndFiles = new AvailableNamedObjectsAndFiles(container); availableNamedObjectsAndFiles.NamedObjectTypeRestriction = typedMember.MemberType.FullName; typeConverter = availableNamedObjectsAndFiles; } else if (memberType.IsEnum) { typeConverter = new EnumConverter(memberType); } else if (memberType == typeof(Microsoft.Xna.Framework.Color)) { typeConverter = new AvailableColorTypeConverter(); memberType = typeof(string); } else if (IsTypeFile(typedMember)) { AvailableFileStringConverter availableFileStringConverter = new AvailableFileStringConverter(container); availableFileStringConverter.QualifiedRuntimeTypeName = memberType.FullName; if (!string.IsNullOrEmpty(typedMember.CustomTypeName)) { availableFileStringConverter.QualifiedRuntimeTypeName = typedMember.CustomTypeName; } availableFileStringConverter.RemovePathAndExtension = true; typeConverter = availableFileStringConverter; memberType = typeof(string); } else if (instance.SourceType == SourceType.Entity && !string.IsNullOrEmpty(instance.SourceClassType)) { EntitySave entity = ObjectFinder.Self.GetEntitySave(instance.SourceClassType); if (entity != null) { CustomVariable customVariable = entity.GetCustomVariable(memberName); if (customVariable != null) { typeConverter = customVariable.GetTypeConverter(entity); } } } } //else if (this.SourceType == SaveClasses.SourceType.FlatRedBallType && // typedMember != null && typedMember.MemberType != null) //{ //} if (wasTypeModified) { memberType = oldType; } return(typeConverter); }
private TypeConverter HandleGetTypeConverter(IElement container, NamedObjectSave instance, TypedMemberBase member) { if(member.CustomTypeName == "AtlasedTextureName") { return new AtlasTextureTypeConverter(); } else { return null; } }