public override ICodeBlock GenerateAdditionalMethods(ICodeBlock codeBlock, IElement element) { EntitySave entitySave = element as EntitySave; if (entitySave == null || (!entitySave.ImplementsIClickable && !entitySave.ImplementsIWindow)) { return codeBlock; } if (entitySave.ImplementsIWindow) { bool inheritsFromIWindow = entitySave.GetInheritsFromIWindow(); // Add all the code that never changes if this is the base IWindow (doesn't have a parent IWindow) if (!inheritsFromIWindow) { GenerateEnabledVariable(codeBlock, element); } } IWindowCodeGenerator.WriteCodeForHasCursorOver( entitySave, codeBlock, entitySave.GetInheritsFromIWindowOrIClickable()); var isVirtual = string.IsNullOrEmpty(entitySave.BaseEntity) || entitySave.GetInheritsFromIWindowOrIClickable() == false; codeBlock .Function("WasClickedThisFrame", "FlatRedBall.Gui.Cursor cursor", Public: true, Virtual: isVirtual, Override: !isVirtual, Type: "bool") .Line("return cursor.PrimaryClick && HasCursorOver(cursor);") .End(); return codeBlock; }
public override ICodeBlock GenerateInitialize(ICodeBlock codeBlock, SaveClasses.IElement element) { // Before August 23, 2010 Custom Variables used to be set // here in Initialize before the AddToManagers method. This // is problematic because: // 1. We probably want these // variables reset whenever // this object is recycled. // 2. If we set the position of // the Entity before its children // have been attached, then the attachment // will not work as expected. Therefore, I've // decided to move custom variable code to AddToManagers. // UPDATE: Actually, we do want variables set here so that they // are available in Custom Initialize. // UPDATE2: This was moved to its own method so that inheritance works. // UPDATE3: It turns out there's 2 types of variables. // 1. Variables that are not set by derived. These variables should get set // in the base class or else they'll never get set for derived objects. // 2. Variables that are set by derived. These variables should get set in the // "SetCustomVariables" method so that they get overridden by derived objects. // This means that we're going to set variables that are not set by derived here, and the // rest will get set in SetCustomVariables. // UPDATE4: This has all moved to PostInitialize, which is called // bottom-up. This means there is no more split on variables. // UPDATE5: This has been moved out of BaseElementTreeNode int CustomVariableCodeGenerator. return codeBlock; }
public override void GenerateInitializeEnd(ICodeBlock codeBlock) { codeBlock.Line("#if DEBUG && WINDOWS"); codeBlock.Line("InitializeFileWatch();"); codeBlock.Line("#endif"); }
public CodeBlockFinally(ICodeBlock pParent) : base(pParent) { PreCodeLines.Add(new CodeLine("finally")); PreCodeLines.Add(new CodeLine("{")); PostCodeLines.Add(new CodeLine("}")); }
public override ICodeBlock GenerateFields(ICodeBlock codeBlock, IElement element) { foreach (EventResponseSave ers in element.Events) { bool isTunneling = ers.GetIsTunneling(); bool isExposing = ers.GetIsExposing(); bool shouldCreateMember = isExposing || isTunneling; if (!shouldCreateMember) { shouldCreateMember = !string.IsNullOrEmpty(ers.DelegateType); } if (shouldCreateMember) { string delegateType = ers.GetEffectiveDelegateType(element); codeBlock.Line("public event " + delegateType + " " + ers.EventName + ";"); } } return codeBlock; }
public static void GenerateTimedEmit(ICodeBlock codeBlock, NamedObjectSave nos) { if (!nos.IsDisabled && nos.AddToManagers && !nos.DefinedByBase && nos.IsEmitter()) { codeBlock.Line(nos.InstanceName + ".TimedEmit();"); } }
public CodeBlockCatch(ICodeBlock pParent, string pCondition) : base(pParent) { PreCodeLines.Add(new CodeLine("catch(" + (string.IsNullOrEmpty(pCondition) ? "" : pCondition) + ")")); PreCodeLines.Add(new CodeLine("{")); PostCodeLines.Add(new CodeLine("}")); }
private static void TryGenerateRemoveShapeCollectionFromManagers(ICodeBlock codeBlock, IElement element) { if (element.IsICollidable()) { codeBlock.Line("mGeneratedCollision.RemoveFromManagers(clearThis: false);"); } }
public static void GenerateStart(IElement saveObject, ICodeBlock codeBlock, string appendName) { if (ObjectFinder.Self.GlueProject.PerformanceSettingsSave.RecordInitializeSegments) { StartMeasurement(saveObject, codeBlock, appendName, true); } }
public override ICodeBlock GenerateAddToManagers(ICodeBlock codeBlock, IElement element) { if (ShouldGenerate) { foreach (var layer in GetObjectsForGumLayers(element)) { var rfs = GetScreenRfsIn(element); if (rfs != null) { codeBlock.Line(layer.InstanceName + "Gum = RenderingLibrary.SystemManagers.Default.Renderer.AddLayer();"); codeBlock.Line(rfs.GetInstanceName() + ".AddGumLayerToFrbLayer(" + layer.InstanceName + "Gum, " + layer.InstanceName + ");"); } } // todo: Need to register the layer here foreach (var item in element.AllNamedObjects.Where(item => GumPluginCodeGenerator.IsGue(item) && !string.IsNullOrEmpty(item.LayerOn) && NamedObjectSaveCodeGenerator.GetFieldCodeGenerationType(item) == CodeGenerationType.Full)) { codeBlock.Line(item.FieldName + ".MoveToLayer(" + item.LayerOn + "Gum);"); } } return base.GenerateAddToManagers(codeBlock, element); }
public CodeBlockEnum(ICodeBlock pParent, string pPre, string pName) : base(pParent) { PreCodeLines.Add(new CodeLine(StringHelper.SpaceStrings(pPre, "enum", pName))); PreCodeLines.Add(new CodeLine("{")); PostCodeLines.Add(new CodeLine("}")); }
public override ICodeBlock GenerateInitialize(ICodeBlock codeBlock, SaveClasses.IElement element) { // Do the named object saves // We're going to do all "Entire File" NOS's first so that they aren't null before for (int i = 0; i < element.NamedObjects.Count; i++) { NamedObjectSave nos = element.NamedObjects[i]; if (nos.IsEntireFile) { WriteCodeForNamedObjectInitialize(nos, element, codeBlock, null); } } // Now do non-entire files: for (int i = 0; i < element.NamedObjects.Count; i++) { NamedObjectSave nos = element.NamedObjects[i]; if (!nos.IsEntireFile) { WriteCodeForNamedObjectInitialize(nos, element, codeBlock, null); } } return codeBlock; }
public override ICodeBlock GenerateFields(ICodeBlock codeBlock, SaveClasses.IElement element) { var currentBlock = codeBlock; if (element.HasStates) { List<StateSave> statesForThisCategory = GetSharedVariableStates(element); const string enumName = "VariableState"; currentBlock = AppendEnum(currentBlock, statesForThisCategory, enumName, element); GenerateCurrentStateProperty(element, codeBlock, "VariableState", statesForThisCategory); //Build State Categories var stateCategories = GetAllStateCategoryNames(element, false); foreach (var stateCategory in stateCategories) { var states = GetAllStatesForCategory(element, stateCategory); AppendEnum(currentBlock, states, stateCategory, element); GenerateCurrentStateProperty(element, codeBlock, stateCategory, states); } } return codeBlock; }
private ICodeBlock GenerateInterpolateToStateAdvanced(ICodeBlock codeBlock, string enumName) { codeBlock = codeBlock.Function("public void", "InterpolateToState", enumName + " fromState, " + enumName + " toState, double secondsToTake, FlatRedBall.Glue.StateInterpolation.InterpolationType interpolationType, FlatRedBall.Glue.StateInterpolation.Easing easing"); string variableName; if (enumName == "VariableState") { variableName = "CurrentState"; } else { variableName = "Current" + enumName + "State"; } codeBlock = codeBlock.If("secondsToTake <= 0"); codeBlock.Line(variableName + " = toState;"); codeBlock = codeBlock.End().Else(); // Immediately set the state to the from state: codeBlock.Line(variableName + " = fromState;"); codeBlock.Line("mFrom" + enumName + "Tween = fromState;"); codeBlock.Line("mTo" + enumName + "Tween = toState;"); codeBlock.Line( TweenerNameFor(enumName) + ".Start(0, 1, (float)secondsToTake, FlatRedBall.Glue.StateInterpolation.Tweener.GetInterpolationFunction(interpolationType, easing));"); codeBlock = codeBlock.End();// else codeBlock = codeBlock.End(); return codeBlock; }
public CodeBlockSet(ICodeBlock pParent, string pPre) : base(pParent) { PreCodeLines.Add(new CodeLine(StringHelper.SpaceStrings(pPre,"set"))); PreCodeLines.Add(new CodeLine("{")); PostCodeLines.Add(new CodeLine("}")); }
private void GenerateHandleFileChanged(ICodeBlock codeBlock) { var method = codeBlock.Function("private static void", "HandleFileChanged", "object sender, System.IO.FileSystemEventArgs e"); { var tryBlock = method.Try(); tryBlock.Line("System.Threading.Thread.Sleep(500);"); tryBlock.Line("var fullFileName = e.FullPath;"); tryBlock.Line("var relativeFileName = FlatRedBall.IO.FileManager.MakeRelative(FlatRedBall.IO.FileManager.Standardize(fullFileName));"); foreach(var rfs in GlueState.Self.CurrentGlueProject.GlobalFiles) { bool shouldGenerate = rfs.LoadedAtRuntime && rfs.IsDatabaseForLocalizing == false; if(shouldGenerate) { var fileName = ProjectBase.AccessContentDirectory + rfs.Name.ToLower().Replace("\\", "/"); var instanceName = rfs.GetInstanceName(); var ifStatement = tryBlock.If($"relativeFileName == \"{fileName}\""); { ifStatement.Line($"Reload({instanceName});"); } } } var catchBlock = tryBlock.End().Line("catch{}"); } }
private void GenerateInitializeLevel(ICodeBlock codeBlock, IElement element) { #region /////////////////////////////////Early out//////////////////////////////// bool shouldGenerate = GetIfShouldGenerate(element); if (!shouldGenerate) { return; } ///////////////////////////////End early out///////////////////////////// #endregion codeBlock.Line("FlatRedBall.TileGraphics.LayeredTileMap CurrentTileMap;"); var function = codeBlock.Function("void", "InitializeLevel", "string levelName"); GenerateInitializeLevelObjects(function); GenerateInitializeCamera(function); GenerateAddCollisionAndEntities(function); GenerateInitializeAnimations(function); }
public override ICodeBlock GenerateFields(ICodeBlock codeBlock, SaveClasses.IElement element) { #region Get the ContentManager variable to use string contentManagerName = "ContentManagerName"; if (element is ScreenSave) { contentManagerName = (element as ScreenSave).ContentManagerForCodeGeneration; } #endregion if (element is EntitySave) { codeBlock.Line("static object mLockObject = new object();"); codeBlock.Line("static System.Collections.Generic.List<string> mRegisteredUnloads = new System.Collections.Generic.List<string>();"); #region Keep track of whether we've already registered an unload method and if StaticContent has been loaded codeBlock.Line("static System.Collections.Generic.List<string> LoadedContentManagers = new System.Collections.Generic.List<string>();"); #endregion } for (int i = 0; i < element.ReferencedFiles.Count; i++) { AppendFieldOrPropertyForReferencedFile(codeBlock, element.ReferencedFiles[i], element.Name, element, contentManagerName); //stringBuilder.AppendLine(GetFieldForReferencedFile(mSaveObject.ReferencedFiles[i])); } return codeBlock; }
public ClassCodeElement Build () { classCodeElement = new ClassCodeElement (targetClassName); classCodeElement.Summary.Add ("Convenience class to access Animator states and parameters."); classCodeElement.Summary.Add ("Edits will be lost when this class is regenerated. "); classCodeElement.Summary.Add ("Hint: Editing might be useful after renaming animator items in complex projects:"); classCodeElement.Summary.Add (" - Right click on an obsolete member and select Refactor/Rename. "); classCodeElement.Summary.Add (" - Change it to the new name. "); classCodeElement.Summary.Add (" - Delete this member to avoid comile error CS0102 ... already contains a definition ...''. "); string versionString = "" + DateTime.Now; classCodeElement.AddAttribute (new GeneratedClassAttributeCodeElement (versionString)); if (!string.IsNullOrEmpty (config.DefaultNamespace)) { classCodeElement.NameSpace = new NameSpaceCodeElement (config.DefaultNamespace); } ProcessInternalFields (); if (config.GenerateMonoBehaviourComponent) { classCodeElement.SetBaseClass (config.MonoBehaviourComponentBaseClass); AwakeMethod = PrepareAwakeMethod (); } else { AwakeMethod = PrepareConstructors (); } EventManagerInitialiser = PrepareEventManagerInitialiserMethod (); ProcessAnimatorStates (); ProcessAnimatorParameters (); ProcessStateEventHandling (); return classCodeElement; }
public override ICodeBlock GenerateFields(ICodeBlock codeBlock, SaveClasses.IElement element) { codeBlock.Line("#if DEBUG"); codeBlock.Line("static bool HasBeenLoadedWithGlobalContentManager = false;"); codeBlock.Line("#endif"); return codeBlock; }
public static void GenerateTimedEmit(ICodeBlock codeBlock, ReferencedFileSave rfs, IElement element) { if (rfs.LoadedAtRuntime && !rfs.LoadedOnlyWhenReferenced && (element is ScreenSave || rfs.IsSharedStatic == false) && !string.IsNullOrEmpty(rfs.Name) && FileManager.GetExtension(rfs.Name) == "emix") { codeBlock.Line(rfs.GetInstanceName() + ".TimedEmit();"); } }
public static Exception Expect(Type exception, Type cause, ICodeBlock block, string customMessage) { Exception e = GetThrowable(block); AssertThrowable(exception, e, customMessage); AssertThrowable(cause, e.InnerException, customMessage); return e; }
public static void GenerateAdditionalMethodsPluginCode(PluginManager pluginManager, ICodeBlock codeBlock, IElement element) { foreach (ComponentPluginPair cpp in GetPluginsIn(pluginManager)) { GenerateWithException(cpp.Generator.GenerateAdditionalMethods, codeBlock, element, cpp.Plugin, pluginManager); } }
private void AssertEventThrows(string eventName, ICodeBlock codeBlock, IProcedure4 listenerSetter) { IEventRegistry eventRegistry = EventRegistryFactory.ForObjectContainer(Db()); listenerSetter.Apply(eventRegistry); Assert.Expect(typeof(EventException), typeof(NotImplementedException), codeBlock, eventName); }
public override ICodeBlock GenerateAdditionalMethods(ICodeBlock codeBlock, IElement element) { GeneratePreloadLevel(codeBlock, element); GenerateInitializeLevel(codeBlock, element); return codeBlock; }
public CodeBlockBase(ICodeBlock parent) { TabCharacter = CodeBuilderDefaults.TabCharacter; TabCount = CodeBuilderDefaults.TabCount; Parent = parent; if(Parent != null) Parent.BodyCodeLines.Add(this); }
public override ICodeBlock GenerateActivity(ICodeBlock codeBlock, IElement element) { if(IsLoadingScreen(element)) { codeBlock.Line("AsyncActivity();"); } return codeBlock; }
private static void GenerateInitializeLevelObjects(ICodeBlock function) { // Load the file and store it off: function.Line("CurrentTileMap = GetFile(levelName) as FlatRedBall.TileGraphics.LayeredTileMap;"); // Add it to managers function.Line("CurrentTileMap.AddToManagers();"); }
public override ICodeBlock GenerateFields(ICodeBlock codeBlock, IElement element) { if (IsLoadingScreen(element)) { codeBlock.Line("double mSavedTargetElapedTime;"); } return codeBlock; }
// 20141117 public AddScenarioCmdletBaseDataObject() { // 20141211 // BeforeTest = new ScriptBlock[] {}; // AfterTest = new ScriptBlock[] {}; BeforeTest = new ICodeBlock[] {}; AfterTest = new ICodeBlock[] {}; }
public LocatedInstruction Disassemble(ICodeBlock codeBlock, int address) { var romOffset = codeBlock.ConvertMappedAddressToRomOffset(address); var input = codeBlock.Rom[romOffset]; var decoded = OpcodeTables.Decode(input); var result = new LocatedInstruction { AddressingMode = decoded.AddressingMode, Opcode = decoded.Opcode, Address = address }; switch (result.Length) { case 2: result.Operand = GetOperand(codeBlock, romOffset); break; case 3: result.Operand = GetFullOperand(codeBlock, romOffset); break; } return(result); }
private void GenerateMoveObjectsToGumLayers(ICodeBlock codeBlock, IElement element) { if (ShouldGenerate) { bool wasAnythingMovedToALayer = false; // todo: Need to register the layer here foreach (var item in element.AllNamedObjects.Where(item => GumPluginCodeGenerator.IsGue(item) && !string.IsNullOrEmpty(item.LayerOn) && NamedObjectSaveCodeGenerator.GetFieldCodeGenerationType(item) == CodeGenerationType.Full)) { string frbLayerName = item.LayerOn; string gumLayerName = $"{item.LayerOn}Gum"; if (item.LayerOn == AvailableLayersTypeConverter.UnderEverythingLayerName) { frbLayerName = AvailableLayersTypeConverter.UnderEverythingLayerCode; gumLayerName = UnderEverythingLayerGumName; } if (item.LayerOn == AvailableLayersTypeConverter.TopLayerName) { frbLayerName = AvailableLayersTypeConverter.TopLayerName; gumLayerName = TopLayerGumName; } codeBlock.Line($"{item.FieldName}.MoveToFrbLayer({frbLayerName}, {gumLayerName});"); wasAnythingMovedToALayer = true; } if (wasAnythingMovedToALayer && element is FlatRedBall.Glue.SaveClasses.ScreenSave) { codeBlock.Line("FlatRedBall.Gui.GuiManager.SortZAndLayerBased();"); } } }
public override ICodeBlock GenerateInitialize(ICodeBlock codeBlock, IElement element) { /////////////////Early Out////////////////////// if (GetIfIsTopDown(element) == false) { return(codeBlock); } //////////////End Early Out////////////////////// // The platformer plugin sets events here, but we don't need to // here on the top-down (yet) since there are no events // Update 1 - actually we should prob assign the default movement // here if there is one... codeBlock.Line("InitializeInput();"); var ifBlock = codeBlock.If("TopDownValues?.Count > 0"); { ifBlock.Line("mCurrentMovement = TopDownValues.Values.FirstOrDefault();"); } codeBlock.Line("PossibleDirections = PossibleDirections.FourWay;"); return(codeBlock); }
private static string GenerateEmptyCustomScreenNetworkCode(ScreenSave screen) { ICodeBlock topBlock = new CodeBlockBaseNoIndent(null); string screenNamespace = CodeGeneratorCommonLogic.GetElementNamespace(screen); ICodeBlock codeBlock = topBlock.Namespace(screenNamespace); codeBlock = codeBlock.Class("public partial", screen.GetStrippedName()); codeBlock.Function("void", "CustomRequestCreateNetworkEntity", "ref RedGrin.INetworkEntity entity, object entityData") .Line(); codeBlock.Line(); codeBlock.Function("void", "CustomRequestDestroyNetworkEntity", "RedGrin.INetworkEntity entity") .Line(); return(topBlock.ToString()); }
private static void GenerateResetMethodNew(bool generateDisplayCode, ICodeBlock classContents) { var resetMethod = classContents.Function( "internal static void", "ResetCamera", "Camera cameraToReset = null"); { if (generateDisplayCode) { resetMethod.If("cameraToReset == null") .Line("cameraToReset = FlatRedBall.Camera.Main;"); resetMethod.Line($"cameraToReset.Orthogonal = Data.Is2D;"); var ifStatement = resetMethod.If("Data.Is2D") .Line($"cameraToReset.OrthogonalHeight = Data.ResolutionHeight;") .Line($"cameraToReset.OrthogonalWidth = Data.ResolutionWidth;") .Line($"cameraToReset.FixAspectRatioYConstant();") .End().Else() .Line("cameraToReset.UsePixelCoordinates3D(0);"); ifStatement = resetMethod.If("Data.AspectRatio != null") .Line( $"SetAspectRatioTo(Data.AspectRatio.Value, Data.DominantInternalCoordinates, Data.ResolutionWidth, Data.ResolutionHeight);"); } } }
public async Task <EvaluateResult> EvaluateAsync() { if (_position >= _blocks.Count) { State = BlockState.Done; return(EvaluateResult.None()); } State = BlockState.InProgress; ICodeBlock currentBlock = _blocks[_position]; EvaluateResult result = await currentBlock.EvaluateAsync(); if (result.Type == ResultType.Break) { State = BlockState.Done; } else if (currentBlock.State == BlockState.Done) { _position++; } return(result); }
public override ICodeBlock GenerateAddToManagers(ICodeBlock codeBlock, IElement element) { if (ShouldGenerate) { // Creates Gum layers for every FRB layer, so that objects can be moved between layers at runtime, and so code gen // can use these for objects that are placed on layers in Glue. foreach (var layer in GetObjectsForGumLayers(element)) { var rfs = GetScreenRfsIn(element); var idbName = rfs?.GetInstanceName(); var rfsAssetTpe = rfs?.GetAssetTypeInfo(); var isIdb = rfsAssetTpe == AssetTypeInfoManager.Self.ScreenIdbAti; if (string.IsNullOrEmpty(idbName) && element is FlatRedBall.Glue.SaveClasses.ScreenSave) { idbName = "gumIdb"; } else if (rfs != null && isIdb == false) { idbName = "FlatRedBall.Gum.GumIdb.Self"; } if (idbName != null) { codeBlock.Line(layer.InstanceName + "Gum = RenderingLibrary.SystemManagers.Default.Renderer.AddLayer();"); codeBlock.Line(layer.InstanceName + "Gum.Name = \"" + layer.InstanceName + "Gum\";"); codeBlock.Line(idbName + ".AddGumLayerToFrbLayer(" + layer.InstanceName + "Gum, " + layer.InstanceName + ");"); } } } return(base.GenerateAddToManagers(codeBlock, element)); }
private void GenerateAnimationEnumerables(ElementSave elementSave, ICodeBlock currentBlock) { currentBlock.Line("#region State Animations"); StateCodeGeneratorContext context = new StateCodeGeneratorContext(); context.Element = elementSave; ElementAnimationsSave animations = GetAnimationsFor(elementSave); if (animations != null) { foreach (var animation in animations.Animations) { GenerateGetEnumerableFor(context, currentBlock, animation, AbsoluteOrRelative.Absolute); GenerateGetEnumerableFor(context, currentBlock, animation, AbsoluteOrRelative.Relative); GenerateAnimationMember(context, currentBlock, animation, AbsoluteOrRelative.Absolute); GenerateAnimationMember(context, currentBlock, animation, AbsoluteOrRelative.Relative); } } currentBlock.Line("#endregion"); }
public override ICodeBlock GenerateAdditionalMethods(ICodeBlock codeBlock, IElement element) { bool isGlueScreen = element is FlatRedBall.Glue.SaveClasses.ScreenSave; var gumScreenRfs = GetGumScreenRfs(element); if (isGlueScreen && gumScreenRfs != null) { var method = codeBlock.Function("private void", "RefreshLayoutInternal", "object sender, EventArgs e"); var ati = gumScreenRfs.GetAssetTypeInfo(); if (ati.RuntimeTypeName == "GumIdb") { method.Line($"{gumScreenRfs.GetInstanceName()}.Element.UpdateLayout();"); } else { method.Line($"{gumScreenRfs.GetInstanceName()}.UpdateLayout();"); } } return(codeBlock); }
private static void CreateInstructionForSubAnimation(ICodeBlock currentBlock, AnimationReferenceSave animationReferenceSave, AbsoluteOrRelative absoluteOrRelative, AnimationSave parentAnimation) { currentBlock = currentBlock.Block(); //var instruction = new FlatRedBall.Instructions.DelegateInstruction(() => //FlatRedBall.Instructions.InstructionManager.Instructions.AddRange(ClickableBushInstance.GrowAnimation)); //instruction.TimeToExecute = FlatRedBall.TimeManager.CurrentTime + asdf; //yield return instruction; string animationName = animationReferenceSave.PropertyNameInCode(); //animationReferenceSave. FlatRedBall.IO.FileManager.RemovePath(animationReferenceSave.Name) + "Animation"; if (absoluteOrRelative == AbsoluteOrRelative.Relative) { animationName += "Relative"; } currentBlock.Line($"var instruction = new FlatRedBall.Instructions.DelegateInstruction(()=>{animationName}.Play({parentAnimation.PropertyNameInCode()}));"); currentBlock.Line("instruction.TimeToExecute = FlatRedBall.TimeManager.CurrentTime + " + ToFloatString(animationReferenceSave.Time) + ";"); currentBlock.Line("yield return instruction;"); currentBlock = currentBlock.End(); }
public void CodeGenerationStart(IElement element) { var stateChainCollection = GlueCommands.TreeNodeCommands.GetProperty <StateChainCollection>(element, PropertyName); if (stateChainCollection == null) { return; } var elementNameWithoutPath = FileManager.RemovePath(element.Name); var document = new CodeDocument(); ICodeBlock codeBlock = document; if (stateChainCollection.StateChains.Count <= 0) { return; } codeBlock = codeBlock .Line("using FlatRedBall.Instructions;") .Namespace(GlueCommands.GenerateCodeCommands.GetNamespaceForElement(element)) .Class("public partial ", element.ClassName, ""); //Create Enum codeBlock = codeBlock .Enum("public", "StateChains") .Line("None = 0,"); for (int i = 0; i < stateChainCollection.StateChains.Count; i++) { if (i == stateChainCollection.StateChains.Count - 1) { codeBlock.Line(stateChainCollection.StateChains[i].Name); } else { codeBlock.Line(stateChainCollection.StateChains[i].Name + ","); } } codeBlock = codeBlock.End(); //Private members codeBlock ._() .Line("private StateChains _currentStateChain = StateChains.None;") .Line("private int _index;") .Line("private Instruction _instruction;") ._(); //CurrentStateChain Property codeBlock = codeBlock .Property("public StateChains", "CurrentStateChain") .Get() .Line("return _currentStateChain;") .End() .Set() .Line("StopStateChain();") ._() .Line("_currentStateChain = value;") .Line("_index = 0;") ._() .Switch("_currentStateChain"); foreach (var stateChain in stateChainCollection.StateChains) { codeBlock .Case("StateChains." + stateChain.Name) .Line("StartNextState" + stateChain.Name + "();"); } codeBlock = codeBlock .End() .End() .End(); codeBlock._(); //ManageStateChains codeBlock = codeBlock .Function("public void", "ManageStateChains", "") .If("CurrentStateChain == StateChains.None") .Line("return;") .End() ._() .Switch("CurrentStateChain"); foreach (var stateChain in stateChainCollection.StateChains) { var index = 0; codeBlock = codeBlock .Case("StateChains." + stateChain.Name); foreach (var stateChainState in stateChain.StateChainStates.Where(stateChainState => !string.IsNullOrEmpty(stateChainState.State))) { if (index == 0) { codeBlock .If("_index == 0 && CurrentState == VariableState." + stateChainState.State) .Line("_index++;") .Line("StartNextState" + stateChain.Name + "();"); } else { codeBlock .ElseIf("_index == " + index + " && CurrentState == VariableState." + stateChainState.State) .Line("_index++;") .Line("StartNextState" + stateChain.Name + "();"); } index++; } codeBlock = codeBlock .End(); } codeBlock = codeBlock .End() .End(); codeBlock._(); //StopStateChain codeBlock = codeBlock .Function("public void", "StopStateChain", "") .If("CurrentStateChain == StateChains.None") .Line("return;") .End() ._() .Switch("CurrentStateChain"); foreach (var stateChain in stateChainCollection.StateChains) { var index = 0; codeBlock = codeBlock .Case("StateChains." + stateChain.Name); foreach (var stateChainState in stateChain.StateChainStates) { if (index == 0) { codeBlock .If("_index == 0") .Line("Instructions.Remove(_instruction);") .Line("StopStateInterpolation(VariableState." + stateChainState.State + ");") .End(); } else { codeBlock .ElseIf("_index == " + index) .Line("Instructions.Remove(_instruction);") .Line("StopStateInterpolation(VariableState." + stateChainState.State + ");") .End(); } index++; } codeBlock = codeBlock .End(); } codeBlock = codeBlock .End() .Line("_instruction = null;") .End(); codeBlock._(); //StartNextState***** foreach (var stateChain in stateChainCollection.StateChains) { codeBlock = codeBlock .Function("private void", "StartNextState" + stateChain.Name, "") .If("_index < 0") .Line("_index = 0;") .End() ._() .If("_index >= " + stateChain.StateChainStates.Count) .Line("_index = 0;") .End() ._() .Switch("_index"); var index = 0; foreach (var stateChainState in stateChain.StateChainStates) { codeBlock .Case(index.ToString()) .Line("_instruction = InterpolateToState(VariableState." + stateChainState.State + ", " + stateChainState.Time / 1000 + ");"); index++; } codeBlock = codeBlock .End() .End() ._(); } GlueCommands.ProjectCommands.CreateAndAddPartialFile(element, "StateChains", document.ToString()); }
private static ICodeBlock GenerateInterpolateBetweenMethod(IElement element, ICodeBlock codeBlock, string enumType, List <StateSave> states) { var curBlock = codeBlock; // Right now we // create the InterpolateBetween // method if there are any states // in the argument List. We may want // to only create the InterpolateBetween // method only if there are variables that // can be interpolated between - do we want // to do this? Not creating the method will // clean up the Entity/Screen's interface, but // the programmer should not have to remove calls // to this method if the designer decides to modify // variables or states. Also, always creating the method // means that Entities/Screens can be stubbed out and coded // against before the states are filled. // Update September 18, 2012 by Victor Chelaru // We used to only generate this method if there was more than // one state in the entity, but instead we want to generate it if // there are any for two reasons - so that code doesn't break and so // plugins (like the advanced state interpolator) can simply check for // the presence of state categories and not worry about the complexity of // looking for more than one state. //if (states.Count > 1) if (states.Count > 0) { var elementNameWithoutPath = FileManager.RemovePath(element.Name); curBlock = curBlock .Function("public void", "InterpolateBetween", enumType + " firstState, " + enumType + " secondState, float interpolationValue"); GenerateDebugCheckForInterpolationValueNaN(curBlock); // Create the bools StateSave firstState = states[0]; Dictionary <InstructionSave, InterpolationCharacteristic> interpolationCharacteristics = new Dictionary <InstructionSave, InterpolationCharacteristic>(); // states only include instructions for things they set. Otherwise they'll be null CreateStartingValueVariables(element, states, curBlock, interpolationCharacteristics); curBlock = curBlock.Switch("firstState"); curBlock = SetInterpolateBetweenValuesForStates(element, enumType, states, curBlock, interpolationCharacteristics, FirstValue); curBlock = curBlock.End(); curBlock = curBlock.Switch("secondState"); curBlock = SetInterpolateBetweenValuesForStates(element, enumType, states, curBlock, interpolationCharacteristics, SecondValue); curBlock = curBlock.End(); curBlock = AssignValuesUsingStartingValues(element, curBlock, interpolationCharacteristics); curBlock = curBlock.If("interpolationValue < 1"); // mCurrentCircleVisibilityState = (int)firstState; // string fieldToAssign; if (enumType == "VariableState") { fieldToAssign = "mCurrentState"; } else { fieldToAssign = "mCurrent" + enumType + "State"; } curBlock.Line(fieldToAssign + " = (int)firstState;"); curBlock = curBlock.End().Else(); curBlock.Line(fieldToAssign + " = (int)secondState;"); curBlock = curBlock.End(); } return(curBlock); }
private static void GenerateInterpolateForIndividualStateNoSource(ref ICodeBlock codeBlock, IElement element, ref ICodeBlock otherBlock, InstructionSave instruction, CustomVariable customVariable, string valueAsString, string timeCastString) { string velocityMember = FlatRedBall.Instructions.InstructionManager.GetVelocityForState(instruction.Member); // If the velocityMember exists, we need to make sure it's actually exposable if (!ExposedVariableManager.GetExposableMembersFor(element, false).Any(item => item.Member == velocityMember)) { velocityMember = null; } if (velocityMember == null && customVariable.HasAccompanyingVelocityProperty) { velocityMember = customVariable.Name + "Velocity"; } if (!string.IsNullOrEmpty(velocityMember)) { string relativeVelocity = InstructionManager.GetRelativeForAbsolute(velocityMember); string leftHandPlusEquals = null; if (!string.IsNullOrEmpty(relativeVelocity)) { codeBlock = codeBlock .If("this.Parent != null"); otherBlock = otherBlock .If("this.Parent != null"); string instructionMemberRelative = InstructionManager.GetRelativeForAbsolute(instruction.Member); leftHandPlusEquals = relativeVelocity + " = "; codeBlock.Line(leftHandPlusEquals + "(" + valueAsString + " - " + instructionMemberRelative + ") / " + timeCastString + "secondsToTake;"); otherBlock.Line(leftHandPlusEquals + " 0;"); codeBlock = codeBlock .End() .Else(); otherBlock = otherBlock .End() .Else(); } leftHandPlusEquals = velocityMember + " = "; codeBlock.Line(leftHandPlusEquals + "(" + valueAsString + " - " + instruction.Member + ") / " + timeCastString + "secondsToTake;"); otherBlock.Line(leftHandPlusEquals + " 0;"); if (!string.IsNullOrEmpty(relativeVelocity)) { codeBlock = codeBlock.End(); otherBlock = otherBlock.End(); } } }
private void CreateInstructionForInterpolationAbsolute(StateCodeGeneratorContext context, ICodeBlock currentBlock, string animationType, AnimatedStateSave previousState, AnimatedStateSave currentState, string animationName) { if (previousState == null) { string variableStateName = null; variableStateName = "CurrentVariableState"; if (currentState.StateName.Contains("/")) { var split = currentState.StateName.Split('/'); animationType = split[0]; } if (animationType != "VariableState") { variableStateName = "Current" + animationType + "State"; } // todo: Change this on categories //System.Action action = () => this.CurrentState = fromState; string enumValue = currentState.StateName; if (enumValue.Contains("/")) { enumValue = enumValue.Split('/')[1]; } currentBlock.Line("var toReturn = new FlatRedBall.Instructions.DelegateInstruction( ()=> this." + variableStateName + " = " + animationType + "." + enumValue + ");"); currentBlock.Line("toReturn.TimeToExecute = FlatRedBall.TimeManager.CurrentTime;"); currentBlock.Line("toReturn.Target = target;"); } else { var previousCategory = context.Element.Categories.FirstOrDefault(item => item.States.Any(stateCandiate => stateCandiate.Name == previousState.StateName)); var currentCategory = context.Element.Categories.FirstOrDefault(item => item.States.Any(stateCandiate => stateCandiate.Name == currentState.StateName)); // Now that we interpolateTo a single state, we don't // need to pass in the StateSave object: //bool differentCategories = previousCategory != currentCategory; // November 3, 2015 // Gum uses a "cumulative // state" system, so that each // keyframe in an animation will // tween with variables both before // and after. // The code as of the time of the writing // of this comment does InterpolateBetween // two states, which does not consider the state // of the object and only tweens variables common // to the two states. This makes the runtime behave // different than Glue, and it also makes the runtime // behave in confusing ways as authors don't often think // about the individual variables that may be set in a state. // We can solve this by instead doing Interpolate to between the // current state of the instance and the state that we are interpolating // to. Going to accomplish this by getting rid of the "from" state: //string fromState = null; string toState = null; string enumValue = currentState.StateName; if (currentState.StateName.Contains("/")) { currentCategory = context.Element.Categories.FirstOrDefault(item => item.Name == currentState.StateName.Split('/')[0]); enumValue = currentState.StateName.Split('/')[1]; } //if (differentCategories) //{ //fromState = "this.ElementSave.AllStates.FirstOrDefault(item => item.Name == \"" + previousState.StateName + "\")"; //toState = "this.ElementSave.AllStates.FirstOrDefault(item => item.Name == \"" + currentState.StateName + "\")"; //} //else //{ //fromState = animationType + "." + previousState.StateName; if (currentCategory == null) { toState = "VariableState." + enumValue; } else { toState = currentCategory.Name + "." + enumValue; } //} string previousStateTime = ToFloatString(previousState.Time); string interpolationTime = ToFloatString(currentState.Time - previousState.Time); string easing = "FlatRedBall.Glue.StateInterpolation.Easing." + previousState.Easing; string interpolationType = "FlatRedBall.Glue.StateInterpolation.InterpolationType." + previousState.InterpolationType; var line = "var toReturn = new FlatRedBall.Instructions.DelegateInstruction( () => this.InterpolateTo(" + string.Format("{0}, {1}, {2}, {3}, {4}));", toState, interpolationTime, interpolationType, easing, animationName); currentBlock.Line(line); currentBlock.Line("toReturn.Target = target;"); currentBlock.Line("toReturn.TimeToExecute = FlatRedBall.TimeManager.CurrentTime + " + previousStateTime + ";"); } currentBlock.Line("yield return toReturn;"); //System.Action action = () => this.InterpolateTo(fromState, toState, timeToTake, interpolationType, easing); }
private void GenerateAnimationMember(StateCodeGeneratorContext context, ICodeBlock currentBlock, AnimationSave animation, AbsoluteOrRelative absoluteOrRelative) { string propertyName = animation.PropertyNameInCode(); if (absoluteOrRelative == AbsoluteOrRelative.Relative) { propertyName += "Relative"; } string referencedInstructionProperty = propertyName + "Instructions"; // Force the property to be upper-case, since the field is lower-case: // We want to generate something like: //private FlatRedBall.Gum.Animation.GumAnimation uncategorizedAnimation; //public FlatRedBall.Gum.Animation.GumAnimation UncategorizedAnimation //{ // get // { // if (uncategorizedAnimation == null) // { // uncategorizedAnimation = new FlatRedBall.Gum.Animation.GumAnimation(1, () => UncategorizedAnimationInstructions); // uncategorizedAnimation.AddEvent("Event1", 3.0f); // } // return uncategorizedAnimation; // } //} var firstCharacterLower = propertyName.Substring(0, 1).ToLowerInvariant(); var fieldName = firstCharacterLower + propertyName.Substring(1); currentBlock.Line($"private FlatRedBall.Gum.Animation.GumAnimation {fieldName};"); currentBlock = currentBlock.Property("public FlatRedBall.Gum.Animation.GumAnimation", propertyName).Get(); float length = GetAnimationLength(context.Element, animation); string lengthAsString = ToFloatString(length); var ifBlock = currentBlock.If($"{fieldName} == null"); { ifBlock.Line( $"{fieldName} = new FlatRedBall.Gum.Animation.GumAnimation({lengthAsString}, {referencedInstructionProperty});"); foreach (var namedEvent in animation.Events) { string timeAsString = ToFloatString(namedEvent.Time); ifBlock.Line( $"{fieldName}.AddEvent(\"{namedEvent.Name}\", {timeAsString});"); } foreach (var subAnimation in animation.Animations) { if (string.IsNullOrEmpty(subAnimation.SourceObject) == false) { var isMissingInstance = context.Element.GetInstance(subAnimation.SourceObject) == null; if (isMissingInstance) { ifBlock.Line($"//Missing object {subAnimation.SourceObject}"); } else { ifBlock.Line($"{fieldName}.SubAnimations.Add({subAnimation.PropertyNameInCode()});"); } } } } currentBlock.Line($"return {fieldName};"); }
public static void GenerateEventGeneratedFile(IElement element) { //string fileName = EventManager.GetEventFileNameForElement(element); //string fullCustomFileName = ProjectManager.ProjectBase.Directory + fileName; ////////////////// Early Out ////////////////////// ///////////////// End Early Out//////////////////// string projectDirectory = ProjectManager.ProjectBase.Directory; string fullGeneratedFileName = projectDirectory + EventManager.GetGeneratedEventFileNameForElement(element); ////////////////EARLY OUT/////////////// if (element.Events.Count == 0) { // The file may exist. If it does, we want to make sure it's empty: if (File.Exists(fullGeneratedFileName)) { FileWatchManager.IgnoreNextChangeOnFile(fullGeneratedFileName); FileManager.SaveText("", fullGeneratedFileName); } return; } ///////////////END EARLY OUT/////////// if (!File.Exists(fullGeneratedFileName)) { CodeWriter.AddEventGeneratedCodeFileForElement(element); } else { // Make sure the file is part of the project GlueCommands.Self.ProjectCommands.UpdateFileMembershipInProject(ProjectManager.ProjectBase, fullGeneratedFileName, false, false); } ICodeBlock codeBlock = GenerateEventGeneratedCodeFile(element); // Let's try this a few times: int numberOfFailures = 0; bool succeeded = false; FileWatchManager.IgnoreNextChangeOnFile(fullGeneratedFileName); while (numberOfFailures < 3) { try { FileManager.SaveText(codeBlock.ToString(), fullGeneratedFileName); succeeded = true; break; } catch { numberOfFailures++; System.Threading.Thread.Sleep(30); } } if (!succeeded) { GlueGui.ShowMessageBox("Could not save " + fullGeneratedFileName); } }
public static Exception Expect(Type exception, Type cause, ICodeBlock block) { return(Expect(exception, cause, block, null)); }
private void GenerateGetEnumerableFor(StateCodeGeneratorContext context, ICodeBlock currentBlock, AnimationSave animation, AbsoluteOrRelative absoluteOrRelative) { string animationType = "VariableState"; string animationName = animation.PropertyNameInCode(); if (absoluteOrRelative == AbsoluteOrRelative.Relative) { animationName += "Relative"; } string propertyName = animationName + "Instructions"; // Instructions used to be public - the user would grab them and add them to the InstructionManager, // but now everything is encased in an Animation object which handles stopping itself and provides a simple // Play method. const string signature = "private System.Collections.Generic.IEnumerable<FlatRedBall.Instructions.Instruction>"; if (animation.States.Count == 0 && animation.Animations.Count == 0) { currentBlock = currentBlock.Function(signature, propertyName, "object target"); currentBlock.Line("yield break;"); } else if (absoluteOrRelative == AbsoluteOrRelative.Relative && animation.States.Count < 2 && animation.Animations.Count == 0) { currentBlock = currentBlock.Function(signature, propertyName, "object target"); currentBlock.Line("yield break;"); } else { if (animation.States.Count != 0) { var firstState = context.Element.AllStates.FirstOrDefault(item => item.Name == animation.States.First().StateName); var category = context.Element.Categories.FirstOrDefault(item => item.States.Contains(firstState)); if (category != null) { animationType = category.Name; } } currentBlock = currentBlock.Function(signature, propertyName, "object target"); GenerateOrderedStateAndSubAnimationCode(context, currentBlock, animation, animationType, absoluteOrRelative); if (animation.Loops) { currentBlock = currentBlock.Block(); currentBlock.Line("var toReturn = new FlatRedBall.Instructions.DelegateInstruction( " + "() => FlatRedBall.Instructions.InstructionManager.Instructions.AddRange(this." + propertyName + "(target)));"); string executionTime = "0.0f"; if (animation.States.Count != 0) { executionTime = ToFloatString(animation.States.Last().Time); } currentBlock.Line("toReturn.TimeToExecute = FlatRedBall.TimeManager.CurrentTime + " + executionTime + ";"); currentBlock.Line("toReturn.Target = target;"); currentBlock.Line("yield return toReturn;"); currentBlock = currentBlock.End(); } } }
private void GenerateOrderedStateAndSubAnimationCode(StateCodeGeneratorContext context, ICodeBlock currentBlock, AnimationSave animation, string animationType, AbsoluteOrRelative absoluteOrRelative) { List <AnimatedStateSave> remainingStates = new List <AnimatedStateSave>(); remainingStates.AddRange(animation.States); List <AnimationReferenceSave> remainingSubAnimations = new List <AnimationReferenceSave>(); remainingSubAnimations.AddRange(animation.Animations); double nextStateTime; double nextAnimationTime; AnimatedStateSave previousState = null; AnimatedStateSave currentState = null; while (remainingStates.Count > 0 || remainingSubAnimations.Count > 0) { if (remainingStates.Count > 0) { nextStateTime = remainingStates[0].Time; } else { nextStateTime = double.PositiveInfinity; } if (remainingSubAnimations.Count > 0) { nextAnimationTime = remainingSubAnimations[0].Time; } else { nextAnimationTime = double.PositiveInfinity; } if (nextAnimationTime < nextStateTime) { CreateInstructionForSubAnimation(currentBlock, remainingSubAnimations[0], absoluteOrRelative, animation, context); remainingSubAnimations.RemoveAt(0); } else { currentState = remainingStates[0]; CreateInstructionForInterpolation(context, currentBlock, animationType, previousState, currentState, absoluteOrRelative, animation.PropertyNameInCode()); previousState = currentState; remainingStates.RemoveAt(0); } } }
private void GenerateGetCurrentValuesOnStateForCategory(ICodeBlock currentBlock, ElementSave container, string categoryName, List <Gum.DataTypes.Variables.StateSave> states, bool addValues = false) { string methodName = "GetCurrentValuesOnState"; if (addValues) { methodName = "AddToCurrentValuesWithState"; } currentBlock = currentBlock.Function("private Gum.DataTypes.Variables.StateSave", methodName, categoryName + " state"); currentBlock.Line("Gum.DataTypes.Variables.StateSave newState = new Gum.DataTypes.Variables.StateSave();"); var switchBlock = currentBlock.Switch("state"); { foreach (var state in states) { var caseBlock = switchBlock.Case(categoryName + "." + state.MemberNameInCode()); { var instanceNames = container.Instances.Select(item => item.Name).ToList(); var orderedVariables = state.Variables .Where(item => GetIfShouldGenerateStateVariable(item, container)) .OrderBy(variable => instanceNames.IndexOf(variable.SourceObject)); foreach (var variable in orderedVariables) { string memberNameInCode = variable.MemberNameInCode(container, VariableNamesToReplaceForStates); caseBlock.Line("newState.Variables.Add(new Gum.DataTypes.Variables.VariableSave()"); var instantiatorBlock = caseBlock.Block(); { instantiatorBlock.Line("SetsValue = true,"); // Don't use memberNameInCode - states from the XML files will not, and we want this // to behave the same so merging (used in interpolation) works properly //instantiatorBlock.Line("Name = \"" + memberNameInCode + "\","); instantiatorBlock.Line("Name = \"" + variable.Name + "\","); instantiatorBlock.Line($"Type = \"{variable.Type}\","); string valueString = "Value = " + memberNameInCode + ""; if (addValues && IsVariableNumeric(variable)) { string variableValue = variable.Value.ToString(); bool isEntireAssignment; GueDerivingClassCodeGenerator.Self.AdjustVariableValueIfNecessary(variable, container, ref variableValue, out isEntireAssignment); if (isEntireAssignment) { valueString = variableValue; } else { valueString += " + " + variableValue; } } instantiatorBlock.Line(valueString); } caseBlock.Line(");"); } } } } currentBlock.Line("return newState;"); }
private static ICodeBlock GenerateInterpolateForIndividualState(IElement element, ICodeBlock codeBlock, ICodeBlock otherBlock, StateSave stateSave, string enumType) { codeBlock = codeBlock.Case(enumType + "." + stateSave.Name); otherBlock = otherBlock.Case(enumType + "." + stateSave.Name); foreach (InstructionSave instruction in stateSave.InstructionSaves) { CustomVariable customVariable = null; customVariable = element.GetCustomVariable(instruction.Member); string valueAsString = CodeParser.ParseObjectValue(instruction.Value); if (customVariable != null && !string.IsNullOrEmpty(valueAsString)) { NamedObjectSave sourceNamedObjectSave = element.GetNamedObjectRecursively(customVariable.SourceObject); if (sourceNamedObjectSave == null || sourceNamedObjectSave.IsDisabled == false) { if (sourceNamedObjectSave != null) { NamedObjectSaveCodeGenerator.AddIfConditionalSymbolIfNecesssary(codeBlock, sourceNamedObjectSave); NamedObjectSaveCodeGenerator.AddIfConditionalSymbolIfNecesssary(otherBlock, sourceNamedObjectSave); } string timeCastString = ""; if (instruction.Value is float) { timeCastString = "(float)"; } if (string.IsNullOrEmpty(customVariable.SourceObject)) { GenerateInterpolateForIndividualStateNoSource(ref codeBlock, element, ref otherBlock, instruction, customVariable, valueAsString, timeCastString); } else { GenerateInterpolateForIndividualStateWithSource(ref codeBlock, element, ref otherBlock, customVariable, valueAsString, sourceNamedObjectSave, timeCastString); } if (sourceNamedObjectSave != null) { NamedObjectSaveCodeGenerator.AddEndIfIfNecessary(codeBlock, sourceNamedObjectSave); NamedObjectSaveCodeGenerator.AddEndIfIfNecessary(otherBlock, sourceNamedObjectSave); } } } } return(codeBlock); }
private void GeneratePropertyForCurrentState(ICodeBlock currentBlock, string propertyType, string propertyName, List <Gum.DataTypes.Variables.StateSave> states, ElementSave container, bool isNullable) { string propertyPrefix; if (isNullable) { propertyPrefix = $"public {propertyType}?"; } else { propertyPrefix = $"public {propertyType}"; } var property = currentBlock.Property(propertyPrefix, propertyName); property.Get().Line("return m" + propertyName + ";"); var setter = property.Set(); { if (isNullable) { setter = setter.If("value != null"); } setter.Line("m" + propertyName + " = value;"); var switchBlock = setter.Switch("m" + propertyName); foreach (var state in states) { var caseBlock = switchBlock.Case(propertyType + "." + state.MemberNameInCode()); { // Parent variables need to be assigned in the order of the objects in the component so that they're attached in the right order. // If they're attached in the wrong order, then stacking won't work properly: var instanceNames = container.Instances.Select(item => item.Name).ToList(); var orderedVariables = state.Variables.OrderBy(variable => instanceNames.IndexOf(variable.SourceObject)).ToList(); foreach (var variable in orderedVariables) { var shouldGenerate = false; try { shouldGenerate = GetIfShouldGenerateStateVariable(variable, container); } catch (Exception e) { GlueCommands.Self.PrintError(e.ToString()); } // where block doesn't debug well for some reason, so I unrolled it... if (shouldGenerate) { // Note that this could return values like "1,2" instead of "1.2" depending // on the current language, so the AdjustVariableValueIfNecessary needs to account for that. string variableValue = variable.Value.ToString(); bool isEntireAssignment; GueDerivingClassCodeGenerator.Self.AdjustVariableValueIfNecessary(variable, container, ref variableValue, out isEntireAssignment); if (isEntireAssignment) { caseBlock.Line(variableValue); } else { string memberNameInCode = variable.MemberNameInCode(container, VariableNamesToReplaceForStates); caseBlock.Line(memberNameInCode + " = " + variableValue + ";"); } } } } } } }
private static void CreateStartingValueVariables(IElement element, List <StateSave> states, ICodeBlock curBlock, Dictionary <InstructionSave, InterpolationCharacteristic> interpolationCharacteristics) { foreach (StateSave state in states) { foreach (InstructionSave instructionSave in state.InstructionSaves) { string member = instructionSave.Member; if (!ContainsKey(interpolationCharacteristics, member)) { CustomVariable customVariable = element.GetCustomVariable(member); NamedObjectSave nos = null; if (customVariable != null) { nos = element.GetNamedObjectRecursively(customVariable.SourceObject); } if (nos == null || nos.IsDisabled == false) { InterpolationCharacteristic interpolationCharacteristic = CustomVariableHelper.GetInterpolationCharacteristic(customVariable, element); interpolationCharacteristics.Add(instructionSave, interpolationCharacteristic); if (interpolationCharacteristic != InterpolationCharacteristic.CantInterpolate) { curBlock.Line("bool set" + instructionSave.Member + " = true;"); string defaultStartingValue = ""; try { if (customVariable.GetIsVariableState()) { IElement stateContainingEntity = null; if (nos != null) { stateContainingEntity = ObjectFinder.Self.GetIElement(nos.SourceClassType); } else if (string.IsNullOrEmpty(customVariable.SourceObject)) { stateContainingEntity = element; } if (stateContainingEntity != null) { string stateType = "VariableState"; if (customVariable != null && customVariable.Type.ToLower() != "string") { stateType = customVariable.Type; } defaultStartingValue = StateCodeGenerator.FullyQualifiedDefaultStateValue(stateContainingEntity, stateType); } } else { defaultStartingValue = TypeManager.GetDefaultForType(instructionSave.Type); } } catch { throw new Exception("Could not get a default value for " + instructionSave.Member + " of type " + instructionSave.Type); } string type = CustomVariableCodeGenerator.GetMemberTypeFor(customVariable, element); curBlock.Line(type + " " + member + FirstValue + "= " + defaultStartingValue + ";"); curBlock.Line(type + " " + member + SecondValue + "= " + defaultStartingValue + ";"); } } } } } }
private static ICodeBlock SetInterpolateBetweenValuesForStates(IElement element, string enumType, List <StateSave> states, ICodeBlock curBlock, Dictionary <InstructionSave, InterpolationCharacteristic> mInterpolationCharacteristics, string firstOrSecondValue) { foreach (StateSave state in states) { curBlock = curBlock.Case(enumType + "." + state.Name); foreach (InstructionSave instructionSave in state.InstructionSaves) { var customVariable = element.GetCustomVariable(instructionSave.Member); NamedObjectSave sourceNamedObjectSave = null; if (customVariable != null) { sourceNamedObjectSave = element.GetNamedObjectRecursively(customVariable.SourceObject); } if (sourceNamedObjectSave != null) { NamedObjectSaveCodeGenerator.AddIfConditionalSymbolIfNecesssary(curBlock, sourceNamedObjectSave); } if (GetValue(mInterpolationCharacteristics, instructionSave.Member) != InterpolationCharacteristic.CantInterpolate) { if (instructionSave.Value == null) { curBlock.Line("set" + instructionSave.Member + " = false;"); } else { string valueToWrite = GetRightSideAssignmentValueAsString(element, instructionSave); curBlock.Line(instructionSave.Member + firstOrSecondValue + " = " + valueToWrite + ";"); } } else // This value can't be interpolated, but if the user has set a value of 0 or 1, then it should be set { ICodeBlock ifBlock; // value will come from the first state unless the interpolationValue is 1. // This makes the code behave the same as InterpolateTo which uses instructions. if (firstOrSecondValue == FirstValue) { ifBlock = curBlock.If("interpolationValue < 1"); } else { ifBlock = curBlock.If("interpolationValue >= 1"); } string valueToWrite = GetRightSideAssignmentValueAsString(element, instructionSave); ifBlock.Line("this." + instructionSave.Member + " = " + valueToWrite + ";"); } if (sourceNamedObjectSave != null) { NamedObjectSaveCodeGenerator.AddEndIfIfNecessary(curBlock, sourceNamedObjectSave); } } curBlock = curBlock.End(); } return(curBlock); }
private static void GenerateRequestCreateEntity(ICodeBlock codeBlock) { var requestCreateMethod = codeBlock.Function( "public RedGrin.INetworkEntity", "RequestCreateEntity", "long ownerId, object entityData"); requestCreateMethod.Line("RedGrin.INetworkEntity entity = null;"); bool needsElseIf = false; var netEntities = GlueState.Self.CurrentGlueProject.Entities .Where(item => NetworkEntityViewModel.IsNetworked(item)); foreach (var entitySave in netEntities) { ICodeBlock ifBlock; var fullNetStateType = CodeGeneratorCommonLogic.GetNetStateFullName(entitySave); var fullEntityType = CodeGeneratorCommonLogic.GetElementFullName(entitySave); string ifcontents = $"entityData is {fullNetStateType}"; if (needsElseIf == false) { ifBlock = requestCreateMethod.If(ifcontents); } else { ifBlock = requestCreateMethod.ElseIf(ifcontents); } var hasFactory = entitySave.CreatedByOtherEntities; if (hasFactory) { var factoryName = $"{GlueState.Self.ProjectNamespace}.Factories.{entitySave.GetStrippedName()}Factory"; ifBlock.Line($"entity = {factoryName}.CreateNew();"); } else { ifBlock.Line($"entity = new {fullEntityType}();"); } // Even though the NetworkManager assigns the owner ID, we're going to do it here // to before calling UpdateFromState, so that any custom code that gets triggered from // UpdateFromState are guaranteed to have the right ID: ifBlock.Line("entity.OwnerId = ownerId;"); ifBlock.Line("entity.UpdateFromState(entityData, 0);"); needsElseIf = true; } // At first I thought to have the CustomRequestCreateNetworkEntity // inside the if/else if so that the created entity could be modified // but it's possible the user may want to have their own totally custom // network entities and network entity states, in which case they will need // to instantiate the object fully in custom code. Therefore, we'll call the // method no matter what, even if the entity is null requestCreateMethod.Line("CustomRequestCreateNetworkEntity(ref entity, entityData);"); requestCreateMethod.Line("return entity;"); }
private void CreateInstructionForInterpolation(StateCodeGeneratorContext context, ICodeBlock currentBlock, string animationType, AnimatedStateSave previousState, AnimatedStateSave currentState, AbsoluteOrRelative absoluteOrRelative, string animationName) { currentBlock = currentBlock.Block(); if (absoluteOrRelative == AbsoluteOrRelative.Absolute) { CreateInstructionForInterpolationAbsolute(context, currentBlock, animationType, previousState, currentState, animationName); } else { CreateInstructionForInterpolationRelative(context, currentBlock, previousState, currentState); } currentBlock = currentBlock.End(); }
private void CreateInstructionForInterpolationRelative(StateCodeGeneratorContext context, ICodeBlock currentBlock, AnimatedStateSave previousState, AnimatedStateSave currentState) { if (previousState != null) { currentBlock.Line("var toReturn = new FlatRedBall.Instructions.DelegateInstruction(() =>"); { currentBlock = currentBlock.Block(); // Is the start clone necessary? currentBlock.Line("var relativeStart = ElementSave.AllStates.FirstOrDefault(item => item.Name == \"" + previousState.StateName + "\").Clone();"); currentBlock.Line("var relativeEnd = ElementSave.AllStates.FirstOrDefault(item => item.Name == \"" + currentState.StateName + "\").Clone();"); currentBlock.Line("Gum.DataTypes.Variables.StateSaveExtensionMethods.SubtractFromThis(relativeEnd, relativeStart);"); currentBlock.Line("var difference = relativeEnd;"); string categoryName = "VariableState"; var category = context.Element.Categories.FirstOrDefault(item => item.States.Any(stateCandidate => stateCandidate.Name == currentState.StateName)); string enumValue = currentState.StateName; if (currentState.StateName.Contains('/')) { var split = currentState.StateName.Split('/'); category = context.Element.Categories.FirstOrDefault(item => item.Name == split[0]); enumValue = split[1]; } if (category != null) { categoryName = category.Name; } currentBlock.Line("Gum.DataTypes.Variables.StateSave first = GetCurrentValuesOnState(" + categoryName + "." + enumValue + ");"); currentBlock.Line("Gum.DataTypes.Variables.StateSave second = first.Clone();"); currentBlock.Line("Gum.DataTypes.Variables.StateSaveExtensionMethods.AddIntoThis(second, difference);"); string interpolationTime = ToFloatString(currentState.Time - previousState.Time); string easing = "FlatRedBall.Glue.StateInterpolation.Easing." + previousState.Easing; string interpolationType = "FlatRedBall.Glue.StateInterpolation.InterpolationType." + previousState.InterpolationType; currentBlock.Line( string.Format("FlatRedBall.Glue.StateInterpolation.Tweener tweener = new FlatRedBall.Glue.StateInterpolation.Tweener(from: 0, to: 1, duration: {0}, type: {1}, easing: {2});", interpolationTime, interpolationType, easing)); currentBlock.Line("tweener.Owner = this;"); currentBlock.Line("tweener.PositionChanged = newPosition => this.InterpolateBetween(first, second, newPosition);"); currentBlock.Line("tweener.Start();"); currentBlock.Line("StateInterpolationPlugin.TweenerManager.Self.Add(tweener);"); currentBlock = currentBlock.End(); } currentBlock.Line(");"); string previousStateTime = ToFloatString(previousState.Time); currentBlock.Line("toReturn.TimeToExecute = FlatRedBall.TimeManager.CurrentTime + " + previousStateTime + ";"); currentBlock.Line("toReturn.Target = target;"); currentBlock.Line("yield return toReturn;"); } }
private static void GenerateInitializeForEvent(ICodeBlock codeBlock, IElement element, EventResponseSave ers) { bool wasEventAdded = false; //We always want this to happen, even if it's // emtpy //if (!string.IsNullOrEmpty(ers.Contents)) //{ NamedObjectSave sourceNos = null; bool shouldCloseIfStatementForNos = false; if (!string.IsNullOrEmpty(ers.SourceVariable)) { // This is tied to a variable, so the name comes from the variable event rather than the // event name itself string eventName = ers.BeforeOrAfter.ToString() + ers.SourceVariable + "Set"; codeBlock.Line("this." + eventName + " += On" + ers.EventName + ";"); wasEventAdded = true; } else if (string.IsNullOrEmpty(ers.SourceObject) || ers.SourceObject == "<NONE>") { string leftSide = null; EventSave eventSave = ers.GetEventSave(); if (eventSave == null || string.IsNullOrEmpty(eventSave.ExternalEvent)) { leftSide = "this." + ers.EventName; } else { leftSide = eventSave.ExternalEvent; } codeBlock.Line(leftSide + " += On" + ers.EventName + ";"); wasEventAdded = true; } else if (!string.IsNullOrEmpty(ers.SourceObjectEvent)) { // Only append this if the source NOS is fully-defined. If not, we don't want to generate compile errors. sourceNos = element.GetNamedObject(ers.SourceObject); if (sourceNos != null && sourceNos.IsFullyDefined) { NamedObjectSaveCodeGenerator.AddIfConditionalSymbolIfNecesssary(codeBlock, sourceNos); string leftSide = null; leftSide = ers.SourceObject + "." + ers.SourceObjectEvent; codeBlock.Line(leftSide + " += On" + ers.EventName + ";"); wasEventAdded = true; shouldCloseIfStatementForNos = true; } } if (!string.IsNullOrEmpty(ers.SourceObject) && !string.IsNullOrEmpty(ers.SourceObjectEvent) && wasEventAdded) { codeBlock.Line(ers.SourceObject + "." + ers.SourceObjectEvent + " += On" + ers.EventName + "Tunnel;"); if (shouldCloseIfStatementForNos) { NamedObjectSaveCodeGenerator.AddEndIfIfNecessary(codeBlock, sourceNos); } } }
private static void GenerateInterpolateForIndividualStateWithSource(ref ICodeBlock codeBlock, IElement element, ref ICodeBlock otherBlock, CustomVariable customVariable, string valueAsString, NamedObjectSave sourceNamedObjectSave, string timeCastString) { if (customVariable.GetIsVariableState()) { GenerateInterpolateForIndividualStateWithSourceStateVariable(codeBlock, customVariable, element, valueAsString.Replace("\"", "")); } else { string velocityMember = FlatRedBall.Instructions.InstructionManager.GetVelocityForState(customVariable.SourceObjectProperty); bool generatedVelocity = false; if (velocityMember == null && customVariable.HasAccompanyingVelocityProperty) { velocityMember = customVariable.Name + "Velocity"; generatedVelocity = true; } bool velocityComesFromTunnel = false; if (velocityMember == null && // Only want to go 1 deep. The reason is if the tunneled variable has a // velocity value, we can use that. However, if it's tunneled multiple times // into a variable that ultimately has a velocity variable we may not be able to // get to it, so we shouldn't just assume we can add "Velocity" to the variable name. customVariable.HasAccompanyingVelocityConsideringTunneling(element, 1)) { velocityMember = customVariable.SourceObjectProperty + "Velocity"; generatedVelocity = true; velocityComesFromTunnel = true; } if (!string.IsNullOrEmpty(velocityMember)) { string sourceDot = customVariable.SourceObject + "."; IEnumerable <string> exposableVariables = FlatRedBall.Glue.Reflection.ExposedVariableManager.GetExposableMembersFor(sourceNamedObjectSave).Select(item => item.Member); // We will generate this if the variable is contained in exposable variables, // if the user explicitly said to generate a velocity variable, or if // this is a FRB type. The reason we check if it's a FRB Type is because FRB // types have velocity variables which may not be exposable. We don't want Glue // to mess with temporary values like Velocity, so they are removed from the exposab // variable list: bool shouldGenerate = exposableVariables.Contains(velocityMember) || generatedVelocity || sourceNamedObjectSave.SourceType == SourceType.FlatRedBallType; if (shouldGenerate) { string relativeVelocity = InstructionManager.GetRelativeForAbsolute(velocityMember); string leftHandPlusEquals = null; if (!string.IsNullOrEmpty(relativeVelocity)) { codeBlock = codeBlock .If(customVariable.SourceObject + ".Parent != null"); otherBlock = otherBlock .If(customVariable.SourceObject + ".Parent != null"); string sourceObjectPropertyRelative = InstructionManager.GetRelativeForAbsolute(customVariable.SourceObjectProperty); leftHandPlusEquals = sourceDot + relativeVelocity + " = "; codeBlock.Line(leftHandPlusEquals + "(" + valueAsString + " - " + sourceDot + sourceObjectPropertyRelative + ") / " + timeCastString + "secondsToTake;"); otherBlock.Line(leftHandPlusEquals + " 0;"); codeBlock = codeBlock .End() .Else(); otherBlock = otherBlock .End() .Else(); } // If we're using a custom velocity value, we don't want to // use the sourceDot. We just want to use the velocity value if (generatedVelocity && !velocityComesFromTunnel) { leftHandPlusEquals = velocityMember + " = "; } else { leftHandPlusEquals = sourceDot + velocityMember + " = "; } codeBlock.Line(leftHandPlusEquals + "(" + valueAsString + " - " + sourceDot + customVariable.SourceObjectProperty + ") / " + timeCastString + "secondsToTake;"); otherBlock.Line(leftHandPlusEquals + " 0;"); if (!string.IsNullOrEmpty(relativeVelocity)) { codeBlock = codeBlock.End(); otherBlock = otherBlock.End(); } } } } }