private VarNames BuildVariableNames(FsmModel model) { Dictionary <Type, string> interfaceArgs = new Dictionary <Type, string>(); Dictionary <Type, string> interfaceContextCall = new Dictionary <Type, string>(); // TODO: conflict resolution between same name interfaces in different namespaces foreach (var iface in model.context.requiredInterfaces) { if (iface.Name[0] == 'I') { interfaceArgs[iface] = iface.Name.Substring(1, 1).ToLower() + iface.Name.Substring(2, iface.Name.Length - 2); interfaceContextCall[iface] = iface.Name.Substring(1, 1).ToUpper() + iface.Name.Substring(2, iface.Name.Length - 2); } else { interfaceArgs[iface] = iface.Name.Substring(0, 1).ToLower() + iface.Name.Substring(1, iface.Name.Length - 1); interfaceContextCall[iface] = iface.Name.Substring(0, 1).ToUpper() + iface.Name.Substring(1, iface.Name.Length - 1); } } Dictionary <MethodInfo, string> methodCalls = new Dictionary <MethodInfo, string>(); foreach (var state in model.states) { foreach (var m in state.onEnter) { methodCalls[m._delegate.method] = MakeMethodInvoke(m._delegate.method); } foreach (var m in state.onExit) { methodCalls[m._delegate.method] = MakeMethodInvoke(m._delegate.method); } foreach (var m in state.internalActions) { methodCalls[m._delegate.method] = MakeMethodInvoke(m._delegate.method); } } Dictionary <string, string> stateEnum = new Dictionary <string, string>(); foreach (var state in model.states) { stateEnum[state.name] = state.name.Trim().Replace(" ", ""); } Dictionary <string, string> eventEnum = new Dictionary <string, string>(); foreach (var evt in model.events) { eventEnum[evt.name] = evt.name.Trim().Replace(" ", ""); } return(new VarNames { interfaceArgs = interfaceArgs, interfaceContextCall = interfaceContextCall, stateNameToEnum = stateEnum, eventNameToEnum = eventEnum, methodInvoke = methodCalls, }); }
private string GetIgnoreEvents(FsmModel model, VarNames varNames) { // Build state switch var sb = new System.Text.StringBuilder(); int count = 0; foreach (var state in model.states) { if (state.ignoreEvents.Count == 0) { continue; } count++; sb.Append(ignoreEventsStateCaseTemplate .Replace("{{name}}", varNames.stateNameToEnum[state.name]) .Replace("{{ignoreevents}}", GetStateIgnoreEvents(model, state, varNames)) .Replace("{{defaultbreak}}", "")); } if (count == 0) { return(PostIndent(ignoreEventsNoneTemplate, options.padding)); } return(PostIndent(ignoreEventsTemplate .Replace("{{states}}", sb.ToString()), options.padding)); }
private string GetImplementInterfaces(FsmModel model, VarNames varNames) { // This is gross, should add a list of interfaces and make it cleaner var sb = new System.Text.StringBuilder(); bool addedPrefix = false; if (options.enableIntrospectionSupport) { addedPrefix = true; sb.Append(",\n"); PreIndent(sb, options.padding); sb.Append("UnityFSMCodeGenerator.IFsmIntrospectionSupport"); } if (options.enableDebugSupport) { if (!addedPrefix) { sb.Append(",\n"); } if (options.enableIntrospectionSupport) { sb.Append(",\n"); } PreIndent(sb, options.padding); sb.Append("UnityFSMCodeGenerator.IFsmDebugSupport"); } return(sb.ToString()); }
private string GetIntrospectionSupport(FsmModel model, VarNames varNames) { if (!options.enableIntrospectionSupport) { return(""); } var sb = new System.Text.StringBuilder(); var sb2 = new System.Text.StringBuilder(); // Make two dictionary initializer entries for introspection lookup // { "Hung Up", "HungUp" }, // { "Hung Up", (object)State.HungUp}, // for (int i = 0; i < model.states.Count; i++) { var state = model.states[i]; // { "Hung Up", "HungUp" }, PreIndent(sb, options.padding); sb.Append("{ State."); sb.Append(varNames.stateNameToEnum[state.name]); sb.Append(", \""); sb.Append(state.name); sb.Append("\" },\n"); // { "Hung Up", (object)State.HungUp}, PreIndent(sb2, options.padding); sb2.Append("{ \""); sb2.Append(state.name); sb2.Append("\", "); sb2.Append("State."); sb2.Append(varNames.stateNameToEnum[state.name]); sb2.Append(" },\n"); } var stateLookups = sb.ToString(); var stringToEnumState = sb2.ToString(); // Make list initializer of state names sb = new System.Text.StringBuilder(); for (int i = 0; i < model.states.Count; i++) { var state = model.states[i]; PreIndent(sb, options.padding); sb.Append("\""); sb.Append(state.name); sb.Append("\",\n"); } return(PostIndent(introspectionSupportTemplate .Replace("{{statelookups}}", stateLookups) .Replace("{{stateenumlookup}}", stringToEnumState) .Replace("{{statelist}}", sb.ToString()), options.padding)); }
private string GetStartState(FsmModel model, VarNames varNames) { foreach (var state in model.states) { if (state.isStart) { return("public const State START_STATE = State." + varNames.stateNameToEnum[state.name]); } } return(""); }
private string GetDebugSupport(FsmModel model, VarNames varNames) { if (!options.enableDebugSupport) { return(""); } return(PostIndent(debugSupportTemplate, //.Replace("{{statelookups}}", stateLookups) options.padding)); }
private string GetDefaultContextInterfaces(FsmModel model, VarNames varNames) { var sb = new System.Text.StringBuilder(); foreach (var kvp in varNames.interfaceArgs) { sb.Append("public "); sb.Append(kvp.Key.FullName); sb.Append(" "); sb.Append(varNames.interfaceContextCall[kvp.Key]); sb.Append(" { get; set; }\n"); } return(PostIndent(sb.ToString(), options.padding * 2, false)); }
private string GetDispatchOnExit(FsmModel model, VarNames varNames) { // Build state switch var sb = new System.Text.StringBuilder(); foreach (var state in model.states) { sb.Append(dispatchStateCaseTemplate .Replace("{{name}}", varNames.stateNameToEnum[state.name]) .Replace("{{methodcalls}}", GetDispatchMethodCalls(model, state, varNames, state.onExit))); } return(PostIndent(dispatchOnExitTemplate .Replace("{{states}}", sb.ToString()), options.padding)); }
private string GetStateIgnoreEvents(FsmModel model, FsmStateModel state, VarNames varNames) { var sb = new System.Text.StringBuilder(); int count = 0; foreach (var ignore in state.ignoreEvents) { count++; sb.Append(PostIndent(ignoreEventTrue .Replace("{{event}}", varNames.eventNameToEnum[ignore.name]), options.padding * 2, false)); } return(sb.ToString()); }
private string GetStates(FsmModel model) { var sb = new System.Text.StringBuilder(); for (int i = 0; i < model.states.Count; i++) { var state = model.states[i]; PreIndent(sb, options.padding * 2); sb.Append(state.name.Trim().Replace(" ", "")); sb.Append(","); if (i + 1 != model.states.Count) { sb.Append("\n"); } } return(sb.ToString()); }
private string GetStateInternalActions(FsmModel model, FsmStateModel state, VarNames varNames) { var sb = new System.Text.StringBuilder(); int count = 0; foreach (var action in state.internalActions) { count++; sb.Append(PostIndent(internalActionsEventTemplate .Replace("{{event}}", varNames.eventNameToEnum[action.evt.name]) .Replace("{{methodcall}}", MakeMethodCall(action._delegate, varNames)), options.padding * 2, false)); } return(sb.ToString()); }
private string GetSingleInternalSendEvent(FsmModel model, VarNames varNames) { // Build state switch var sb = new System.Text.StringBuilder(); foreach (var state in model.states) { bool needDefaultBreak = false; sb.Append(sendInternalEventStateCaseTemplate .Replace("{{name}}", varNames.stateNameToEnum[state.name]) .Replace("{{transitions}}", GetTransitions(model, state, varNames, out needDefaultBreak)) .Replace("{{defaultbreak}}", needDefaultBreak ? PostIndent(defaultBreakEventHandlerTemplate, options.padding * 2, false) : "")); } return(PostIndent(sendInternalEventBaseTemplate .Replace("{{states}}", sb.ToString()), options.padding)); }
private string GetTransitions(FsmModel model, FsmStateModel state, VarNames varNames, out bool needDefaultBreak) { var sb = new System.Text.StringBuilder(); int count = 0; foreach (var transition in state.transitions) { count++; sb.Append(PostIndent(stateTransitionTemplate .Replace("{{event}}", varNames.eventNameToEnum[transition.evt.name]) .Replace("{{tostate}}", varNames.stateNameToEnum[transition.to.name]), options.padding * 2, false)); } needDefaultBreak = count != model.events.Count; return(sb.ToString()); }
public static string CreateDescription(FsmModel model) { var sb = new System.Text.StringBuilder(); sb.Append("\n"); sb.Append("-----------------------\n"); sb.Append("Required Interfaces \n"); sb.Append("-----------------------\n\n"); foreach (var _interface in model.context.requiredInterfaces) { sb.Append(_interface.FullName); sb.Append("\n"); } sb.Append("\n"); sb.Append("--------\n"); sb.Append("Events \n"); sb.Append("--------\n\n"); foreach (var evt in model.events) { sb.Append(evt.name); sb.Append("\n"); } sb.Append("\n"); sb.Append("--------\n"); sb.Append("States \n"); sb.Append("--------\n\n"); foreach (var state in model.states) { ToDebugStringAppendState(sb, state, 0); sb.Append("\n"); } return(sb.ToString()); }
private string GetNewDefaultContext(FsmModel model, VarNames varNames) { var sb = new System.Text.StringBuilder(); int count = 0; foreach (var kvp in varNames.interfaceArgs) { PreIndent(sb, options.padding); sb.Append(kvp.Key.FullName); sb.Append(" "); sb.Append(kvp.Value); if (count != varNames.interfaceArgs.Count - 1) { sb.Append(",\n"); } else { sb.Append(","); } count++; } var _params = sb.ToString(); sb = new System.Text.StringBuilder(); foreach (var kvp in varNames.interfaceArgs) { sb.Append(varNames.interfaceContextCall[kvp.Key]); sb.Append(" = "); sb.Append(kvp.Value); sb.Append(", "); } var args = sb.ToString(); return(PostIndent(newDefaultContextTemplate .Replace("{{params}}", _params) .Replace("{{args}}", args), options.padding)); }
private string GetIContext(FsmModel model, VarNames varNames) { var sb = new System.Text.StringBuilder(); for (int i = 0; i < model.context.requiredInterfaces.Count; i++) { var iface = model.context.requiredInterfaces[i]; PreIndent(sb, options.padding * 2); sb.Append(iface.FullName); sb.Append(" "); sb.Append(varNames.interfaceContextCall[iface]); sb.Append(" { get; }"); if (i + 1 != model.context.requiredInterfaces.Count) { sb.Append("\n"); } } return(sb.ToString()); }
private string GetHandleInternalActions(FsmModel model, VarNames varNames) { bool haveActions = false; foreach (var state in model.states) { if (state.internalActions.Count > 0) { haveActions = true; break; } } if (!haveActions) { return(PostIndent(noInternalActionsTemplate, options.padding)); } // Build state switch var sb = new System.Text.StringBuilder(); foreach (var state in model.states) { if (state.internalActions.Count == 0) { continue; } sb.Append(internalActionsStateCaseTemplate .Replace("{{name}}", varNames.stateNameToEnum[state.name]) .Replace("{{internalactions}}", GetStateInternalActions(model, state, varNames)) .Replace("{{defaultbreak}}", "")); } return(PostIndent(internalActionsTemplate .Replace("{{states}}", sb.ToString()), options.padding)); }
private string GetDispatchMethodCalls(FsmModel model, FsmStateModel state, VarNames varNames, List <FsmOnEnterExitModel> calls) { var sb = new System.Text.StringBuilder(); if (calls.Count > 0) { sb.Append("\n"); } for (int i = 0; i < calls.Count; i++) { var call = calls[i]; PreIndent(sb, options.padding * 2); sb.Append("context."); sb.Append(varNames.interfaceContextCall[call._delegate._interface]); sb.Append("."); sb.Append(varNames.methodInvoke[call._delegate.method]); sb.Append(";"); if (i != calls.Count - 1) { sb.Append("\n"); } } return(sb.ToString()); }
public Output Generate(FsmModel model, string className) { var output = new Output(); var sb = new System.Text.StringBuilder(); sb.Append(header); if (options.commentedOut) { sb.Append("/*\n"); } var indentLevel = 0; // Add namespace if (!string.IsNullOrEmpty(options._namespace)) { sb.Append(namespaceTemplate.Replace("{{ns}}", options._namespace)); indentLevel = options.padding; } // Build variable names var varNames = BuildVariableNames(model); // Build class. // This is very inefficient with string.Replace, but I did not want to introduce // a dependency on an external templating library. sb.Append(PostIndent( clsStartTemplate .Replace("{{description}}", model.description != null ? "// " + model.description.Replace("\n", "") : "") .Replace("{{cls}}", className) .Replace("{{implementinterfaces}}", GetImplementInterfaces(model, varNames)) .Replace("{{genprefab}}", model.fromPrefab != null ? model.fromPrefab.Replace("\"", "") : "") .Replace("{{genguid}}", model.prefabGuid != null ? model.prefabGuid.Replace("\"", "") : "") .Replace("{{startstate}}", GetStartState(model, varNames)) .Replace("{{newdefaultcontext}}", GetNewDefaultContext(model, varNames)) .Replace("{{defaultcontextinterfaces}}", GetDefaultContextInterfaces(model, varNames)) .Replace("{{states}}", GetStates(model)) .Replace("{{events}}", GetEvents(model)) .Replace("{{icontext}}", GetIContext(model, varNames)) .Replace("{{singleinternalsendEvent}}", GetSingleInternalSendEvent(model, varNames)) .Replace("{{handleinternalactions}}", GetHandleInternalActions(model, varNames)) .Replace("{{checkignoreevents}}", GetIgnoreEvents(model, varNames)) .Replace("{{dispatchonenter}}", GetDispatchOnEnter(model, varNames)) .Replace("{{dispatchonexit}}", GetDispatchOnExit(model, varNames)) .Replace("{{introspectionsupport}}", GetIntrospectionSupport(model, varNames)) .Replace("{{debugsupport}}", GetDebugSupport(model, varNames)), indentLevel)); // Close namespace if (!string.IsNullOrEmpty(options._namespace)) { sb.Append("}\n"); } if (options.commentedOut) { sb.Append("*/\n"); } output.code = sb.ToString(); return(output); }