public C2Addon ReadEdittimeJs(string source) { c2addon = new C2Addon(); var parser = new JavaScriptParser(source); var program = parser.ParseProgram(); var json = program.ToJsonString(); dynamic ast = JObject.Parse(json); return(TraverseJavascriptTree(ast)); }
public static string GenerateBehaviorJs(C2Addon addon) { // var id = addon.Properties["id"]; var name = addon.Properties["name"]; var author = addon.Properties["author"]; var onlyOne = addon.Properties["flags"].Contains("bf_onlyone").ToString().ToLower(); var propList = string.Join(",\n ", addon.PluginProperties.Select(GeneratePluginProperty)); var template = $@"""use strict""; {{ const BEHAVIOR_ID = ""{id}""; const BEHAVIOR_VERSION = ""1.0.0.0""; const BEHAVIOR_CATEGORY = ""other""; const BEHAVIOR_CLASS = SDK.Behaviors.{id} = class {name}Behavior extends SDK.IBehaviorBase {{ constructor() {{ super(BEHAVIOR_ID); SDK.Lang.PushContext(""behaviors."" + BEHAVIOR_ID.toLowerCase()); this._info.SetName(lang("".name"")); this._info.SetDescription(lang("".description"")); this._info.SetVersion(BEHAVIOR_VERSION); this._info.SetCategory(BEHAVIOR_CATEGORY); this._info.SetAuthor(""{author}""); this._info.SetHelpUrl(lang("".help-url"")); this._info.SetIsOnlyOneAllowed({onlyOne}); this._info.SetSupportedRuntimes([""c3""]); SDK.Lang.PushContext("".properties""); this._info.SetProperties([ {propList} ]); SDK.Lang.PopContext(); //.properties SDK.Lang.PopContext(); }} }}; PLUGIN_CLASS.Register(PLUGIN_ID, PLUGIN_CLASS); }}"; return(template); }
public C2Addon Parse(string json) { var c2addon = new C2Addon(); dynamic data = JObject.Parse(json); //settings var settings = data["settings"]; foreach (JProperty prop in settings) { //handle array if (prop.Name == "flags") { var sb = new StringBuilder(); foreach (var val in prop.Value) { sb.Append($" {val} "); } c2addon.Properties.Add(prop.Name, sb.ToString()); continue; } c2addon.Properties.Add(prop.Name, prop.Value.ToString()); } //properties var props = data["properties"]; foreach (var p in props) { var property = new C2Property(); property.Type = p["flags"].ToString(); property.Name = p["key"].ToString(); property.Value = p["initial_str"]?.ToString() ?? string.Empty; property.Description = p["description"].ToString(); var flags = p["params"]; var fList = new List <string>(); foreach (var flag in flags) { fList.Add(flag); } property.Params = string.Join("|", fList); property.Readonly = p["read_only"] != null ? p["read_only"].ToString().ToLower() : "false"; } //actions var actions = data["actions"]; c2addon.Actions = new List <C2Ace>(); foreach (JObject act in actions) { var ace = new C2Ace { Id = act["id"].ToString(), ListName = act["list_name"].ToString(), Category = act["category"].ToString(), DisplayString = act["display_string"].ToString(), Description = act["description"].ToString(), ScriptName = act["script_name"].ToString() }; //get flags var sb = new StringBuilder(); foreach (var val in act["flags"]) { sb.Append($" {val} "); } ace.Flags = sb.ToString(); //params foreach (var param in act["params"]) { var aceParam = new C2AceParam { Text = param["name"]?.ToString(), Description = param["description"]?.ToString(), DefaultValue = param["initial"]?.ToString(), Script = param["caller"]?.ToString() }; if (param["caller"]?.ToString() == "AddComboParam") { aceParam.ComboItems = new List <string>(); foreach (var val in param["options"]) { aceParam.ComboItems.Add(val["text"].ToString()); } } ace.Params.Add(aceParam); c2addon.Actions.Add(ace); } } //conditions var conditions = data["conditions"]; c2addon.Conditions = new List <C2Ace>(); foreach (JObject cnd in conditions) { var ace = new C2Ace { Id = cnd["id"].ToString(), ListName = cnd["list_name"].ToString(), Category = cnd["category"].ToString(), DisplayString = cnd["display_string"].ToString(), Description = cnd["description"].ToString(), ScriptName = cnd["script_name"].ToString() }; //get flags var sb = new StringBuilder(); foreach (var val in cnd["flags"]) { sb.Append($" {val} "); } ace.Flags = sb.ToString(); //params foreach (var param in cnd["params"]) { var aceParam = new C2AceParam { Text = param["name"]?.ToString(), Description = param["description"]?.ToString(), DefaultValue = param["initial"]?.ToString(), Script = param["caller"]?.ToString() }; if (param["caller"]?.ToString() == "AddComboParam") { aceParam.ComboItems = new List <string>(); foreach (var val in param["options"]) { aceParam.ComboItems.Add(val["text"].ToString()); } } ace.Params.Add(aceParam); } c2addon.Conditions.Add(ace); } //expressions var expressions = data["expressions"]; c2addon.Expressions = new List <C2Ace>(); foreach (JObject exp in expressions) { var ace = new C2Ace { Id = exp["id"].ToString(), ListName = exp["list_name"].ToString(), Category = exp["category"].ToString(), Description = exp["description"].ToString(), ScriptName = exp["expression_name"].ToString(), }; //get flags var sb = new StringBuilder(); foreach (var val in exp["flags"]) { sb.Append($" {val} "); } ace.Flags = sb.ToString(); //params foreach (var param in exp["params"]) { var aceParam = new C2AceParam { Text = param["name"]?.ToString(), Description = param["description"]?.ToString(), DefaultValue = param["initial"]?.ToString(), Script = param["caller"]?.ToString() }; if (param["caller"]?.ToString() == "AddComboParam") { aceParam.ComboItems = new List <string>(); foreach (var val in param["options"]) { aceParam.ComboItems.Add(val["text"].ToString()); } } ace.Params.Add(aceParam); } c2addon.Expressions.Add(ace); } return(c2addon); }
public async Task <C3Addon> Import2Addon(string path) { WindowManager.ShowLoadingOverlay(true); try { C2Addon c2addon = null; C3Addon c3addon = null; await Task.Run(() => { var tmpPath = OptionsManager.CurrentOptions.DataPath + "\\tmp_c2"; if (Directory.Exists(tmpPath)) { Directory.Delete(tmpPath, true); } //unzip c3addon to temp location ZipFile.ExtractToDirectory(path, tmpPath); var edittimefile = Directory.GetFiles(tmpPath, "edittime.js", SearchOption.AllDirectories).FirstOrDefault(); var runtimefile = Directory.GetFiles(tmpPath, "runtime.js", SearchOption.AllDirectories).FirstOrDefault(); var effectXml = Directory.GetFiles(tmpPath, "*.xml", SearchOption.AllDirectories).FirstOrDefault(x => !x.Contains("info.xml")); var effectCode = Directory.GetFiles(tmpPath, "*.fx", SearchOption.AllDirectories).FirstOrDefault(); LogManager.AddImportLogMessage($"edittime.js => {edittimefile}"); if (edittimefile != null) { var source = File.ReadAllText(edittimefile); //try to parse file using https://github.com/WebCreationClub/construct-addon-parser try { if (!OptionsManager.CurrentOptions.UseC2ParserService) { throw new Exception("C2 parsing service is no enabled"); } c2addon = C2ParsingService.Insatnce.Execute(source); } //if online parse fails fallback to walkign ast tree catch (Exception ex) { LogManager.AddErrorLog(ex); LogManager.AddImportLogMessage( $"C2 Pasring Service Failed => {ex.Message} \nFalling back to Walking Edittime.js AST"); c2addon = C2AddonParser.Insatnce.ReadEdittimeJs(source); } LogManager.AddImportLogMessage( $"C2 Parsed Model => \n\n\n {JsonConvert.SerializeObject(c2addon, Formatting.Indented)}"); c3addon = C2AddonConverter.Insatnce.ConvertToC3(c2addon); //todo generate properties/category var runtime = !string.IsNullOrWhiteSpace(runtimefile) ? File.ReadAllText(runtimefile) : string.Empty; c3addon.C2RunTime = runtime; } else { //check for effect LogManager.AddImportLogMessage($"effect xml => {effectXml}"); if (!string.IsNullOrWhiteSpace(effectXml) && !string.IsNullOrWhiteSpace(effectCode)) { try { var xml = File.ReadAllText(effectXml); var code = File.ReadAllText(effectCode); c3addon = C2EffectConverter.Insatnce.ConvertEffect(xml, code); } catch (Exception ex) { LogManager.AddErrorLog(ex); throw; } } } }); if (c3addon != null) { return(c3addon); } LogManager.AddImportLogMessage($"ERROR => edittime.js not found => null"); throw new Exception("edittime.js not found"); } catch (Exception ex) { LogManager.AddErrorLog(ex); LogManager.AddImportLogMessage($"ERROR => \n{ex.Message}"); LogManager.AddImportLogMessage($"STACKTRACE => \n{ex.StackTrace}"); return(null); } finally { var logData = string.Join(Environment.NewLine, LogManager.ImportLog); File.WriteAllText(Path.Combine(OptionsManager.CurrentOptions.DataPath, "import.log"), logData); LogManager.ImportLog.Clear(); WindowManager.ShowLoadingOverlay(false); } }
public static string GeneratePluginJs(C2Addon addon) { var id = addon.Properties["id"]; var name = addon.Properties["name"]; var author = addon.Properties["author"]; var singleglobal = addon.Properties["flags"].Contains("pf_singleglobal").ToString().ToLower(); var pluginType = addon.Properties["type"]; var hasImage = addon.Properties["flags"].Contains("pf_texture").ToString().ToLower(); var isTiled = addon.Properties["flags"].Contains("pf_tiling").ToString().ToLower(); var acePos = addon.Properties["flags"].Contains("pf_position_aces") ? "\n this._info.AddCommonPositionACEs();" : string.Empty; var aceSize = addon.Properties["flags"].Contains("pf_size_aces") ? "\n this._info.AddCommonSizeACEs();" : string.Empty; var aceApp = addon.Properties["flags"].Contains("pf_appearance_aces") ? "\n this._info.AddCommonAppearanceACEs();" : string.Empty; var aceZor = addon.Properties["flags"].Contains("pf_zorder_aces") ? "\n this._info.AddCommonZOrderACEs();" : string.Empty; var aceAngle = addon.Properties["flags"].Contains("pf_angle_aces") ? "\n this._info.AddCommonAngleACEs();" : string.Empty; var effectAllowed = addon.Properties["flags"].Contains("pf_effects").ToString().ToLower(); var predraw = addon.Properties["flags"].Contains("pf_predraw").ToString().ToLower(); var nosize = (!addon.Properties["flags"].Contains("pf_nosize")).ToString().ToLower(); var propList = string.Join(",\n ", addon.PluginProperties.Select(GeneratePluginProperty)); var rotate = addon.Properties.ContainsKey("rotatable") ? addon.Properties["rotatable"].ToLower() : "false"; var template = $@"""use strict""; {{ const PLUGIN_ID = ""{id}""; const PLUGIN_VERSION = ""1.0.0.0""; const PLUGIN_CATEGORY = ""other""; const PLUGIN_CLASS = SDK.Plugins.{id} = class {name}Plugin extends SDK.IPluginBase {{ constructor() {{ super(PLUGIN_ID); SDK.Lang.PushContext(""plugins."" + PLUGIN_ID.toLowerCase()); this._info.SetName(lang("".name"")); this._info.SetDescription(lang("".description"")); this._info.SetVersion(PLUGIN_VERSION); this._info.SetCategory(PLUGIN_CATEGORY); this._info.SetAuthor(""{author}""); this._info.SetHelpUrl(lang("".help-url"")); this._info.SetIsSingleGlobal({singleglobal}); this._info.SetPluginType(""{pluginType}""); this._info.SetIsResizable({nosize}); // allow to be resized this._info.SetIsRotatable({rotate}); // allow to be rotated this._info.SetHasImage({hasImage}); this._info.SetSupportsEffects({effectAllowed}); // allow effects this._info.SetMustPreDraw({predraw}); this._info.SetIsTiled({isTiled});{acePos}{aceAngle}{aceApp}{aceSize}{aceZor} this._info.SetSupportedRuntimes([""c3""]); SDK.Lang.PushContext("".properties""); this._info.SetProperties([ {propList} ]); SDK.Lang.PopContext(); //.properties SDK.Lang.PopContext(); }} }}; PLUGIN_CLASS.Register(PLUGIN_ID, PLUGIN_CLASS); }}"; return(template); }
public C3Addon ConvertToC3(C2Addon c2addon) { if (c2addon == null) { throw new NullReferenceException("C2ADDON file is null"); } if (c2addon.Type == "Effect") { throw new Exception("C2 Effect Currently not supported for import"); //todo: need to develop this } //add fall back for not being able to parse type if (c2addon.Type == null) { c2addon.Properties.TryGetValue("type", out var type); switch (type) { case "plugin": c2addon.Type = "Plugin"; break; case "behavior": c2addon.Type = "Behavior"; break; case "effect": throw new Exception("C2 Effect Currently not supported for import"); default: c2addon.Type = "Plugin"; break; } } var c3addon = new C3Addon { Name = c2addon.Properties["name"], Class = c2addon.Properties["name"], Author = c2addon.Properties["author"], AddonId = c2addon.Properties["id"], Description = c2addon.Properties["description"], AddonCategory = c2addon.Properties["category"], Effect = new Effect(), IconXml = ResourceReader.Insatnce.GetResourceText("c3IDE.Templates.Files.icon.svg"), CreateDate = DateTime.Now, LastModified = DateTime.Now, MajorVersion = 1, MinorVersion = 0, RevisionVersion = 0, BuildVersion = 0 }; //add version PluginType pluginType = PluginType.SingleGlobalPlugin; switch (c2addon.Type) { case "Plugin": { if (c2addon.Properties["type"] == "object") { pluginType = PluginType.SingleGlobalPlugin; break; } pluginType = PluginType.DrawingPlugin; break; } case "Behavior": pluginType = PluginType.Behavior; break; case "Effect": pluginType = PluginType.Effect; break; } c3addon.Type = pluginType; //get templates based on type c3addon.Template = TemplateFactory.Insatnce.CreateTemplate(c3addon.Type); //compile other files AddonManager.CompileTemplates(c3addon); //add actions c3addon.Actions = new Dictionary <string, Models.Action>(); foreach (var c2Action in c2addon.Actions) { C2AcesToAction(c3addon, c2Action); } //conditions c3addon.Conditions = new Dictionary <string, Models.Condition>(); foreach (var c2Condition in c2addon.Conditions) { C2AcesToCondition(c3addon, c2Condition); } //expression c3addon.Expressions = new Dictionary <string, Models.Expression>(); foreach (var c2Expression in c2addon.Expressions) { C2AceToExpression(c3addon, c2Expression); } //third party files if (c2addon.Properties.ContainsKey("dependency")) { //todo: handle third party files } //handle plugin properties //update edit time plugin switch (c3addon.Type) { case PluginType.SingleGlobalPlugin: case PluginType.DrawingPlugin: c3addon.PluginEditTime = C2TemplateHelper.GeneratePluginJs(c2addon); break; case PluginType.Behavior: c3addon.PluginEditTime = C2TemplateHelper.GenerateBehaviorJs(c2addon); break; case PluginType.Effect: throw new NotImplementedException("effects are not implement yet"); default: throw new ArgumentOutOfRangeException(); } //use c2addon to generate text for properties return(c3addon); }