/// <summary>Delete the current function being edited.</summary> public void Delete() { if (editFunction != null) { string oldFunctionFile = functionDir + "/" + editFunction.Id + ".math"; if (System.IO.File.Exists(oldFunctionFile)) { System.IO.File.Delete(oldFunctionFile); } if (selectedFunction != null && selectedFunction.Id == editFunction.Id) { selectedFunction = null; } if (RunFunction != null && RunFunction.Id == editFunction.Id) { RunFunction = null; } kalc.Functions.Remove(editFunction.Id); } editFunction = null; editWindowEnabled = false; editFunctionContent = ""; editFunctionName = "unnamed"; }
public Solver(JITFunction func, int maxiter, int maxfev, double xtol, double ftol) { this.func = func; this.maxiter = maxiter; this.maxfev = maxfev; this.xtol = xtol; this.ftol = ftol; }
public Solver(JITFunction func) { this.func = func; maxiter = 0; maxfev = 0; xtol = 1E-8; ftol = 1E-8; }
public static JITFunction FromFile(string filename, Kerbulator kalc) { StreamReader file = File.OpenText(filename); string contents = file.ReadToEnd() + "\n"; file.Close(); JITFunction f = new JITFunction(Path.GetFileNameWithoutExtension(filename), contents, kalc); return(f); }
public static string FormatResult(JITFunction f, List <Object> result) { string str = ""; for (int i = 0; i < result.Count - 1; i++) { str += f.Outs[i] + " = " + FormatVar(result[i]) + ", "; } str += f.Outs[result.Count - 1] + " = " + FormatVar(result[result.Count - 1]); return(str); }
public List <Object> Run(JITFunction f) { if (f.InError) { throw new Exception(f.ErrorString); } List <Object> r = f.Execute(new List <Object>()); if (f.InError) { throw new Exception(f.ErrorString); } return(r); }
/// <summary>Obtain some info of a function.</summary> /// <param name="f">The function to obtain the info of</param> public string FunctionDescription(JITFunction f) { if (f.InError) { return("ERROR: " + f.ErrorString); } string desc = ""; if (f.Ins.Count == 0) { desc += "Inputs:\nnone\n"; } else { desc += "Inputs:\n"; for (int i = 0; i < f.Ins.Count; i++) { desc += f.Ins[i]; if (i < f.InDescriptions.Count && f.InDescriptions[i] != "") { desc += ": " + f.InDescriptions[i]; } desc += "\n"; } } if (f.Outs.Count == 0) { desc += "\nOutputs:\nnone\n"; } else { desc += "\nOutputs:\n"; for (int i = 0; i < f.Outs.Count; i++) { desc += f.Outs[i]; if (i < f.OutDescriptions.Count && f.OutDescriptions[i] != "") { desc += ": " + f.OutDescriptions[i]; } desc += "\n"; } } return(desc); }
public string Run(string functionId) { if (!functions.ContainsKey(functionId)) { throw new Exception("Function not found: " + functionId); } JITFunction f = functions[functionId]; if (f.InError) { throw new Exception(f.ErrorString); } List <Object> r = functions[functionId].Execute(new List <Object>()); if (f.InError) { throw new Exception(f.ErrorString); } return(FormatResult(f, r)); }
/// <summary>Scan for available functions and update funtion references if needed.</summary> public void Scan() { try { JITFunction.Scan(functionDir, kalc); error = null; } catch (Exception e) { error = "Cannot access function dir (" + functionDir + "): " + e.Message; functions = new Dictionary <string, JITFunction>(); throw e; } if (selectedFunction != null) { if (functions.ContainsKey(selectedFunction.Id)) { selectedFunction = functions[selectedFunction.Id]; functionDescription = FunctionDescription(selectedFunction); } else { selectedFunction = null; functionDescription = ""; } functionDescriptionHeight = GUI.skin.GetStyle("label").CalcHeight(new GUIContent(functionDescription), 225); } if (editFunction != null) { if (functions.ContainsKey(editFunction.Id)) { editFunction = functions[editFunction.Id]; } else { editFunction = null; editWindowEnabled = false; } } if (runFunction != null) { if (functions.ContainsKey(runFunction.Id)) { runFunction = functions[runFunction.Id]; } else { runFunction = null; } functionOutput = ""; } List <int> envsToRemove = new List <int>(); foreach (KeyValuePair <int, ExecutionEnvironment> pair in envs) { if (functions.ContainsKey(pair.Value.func.Id)) { pair.Value.func = functions[pair.Value.func.Id]; } else { envsToRemove.Add(pair.Key); } } foreach (int id in envsToRemove) { envs.Remove(id); } }
/// <summary>Save the current function being edited.</summary> public void Save() { if (!IsValidName(editFunctionName)) { editFunctionStyle = invalidFunctionName; return; } else { editFunctionStyle = validFunctionName; } int id; if (editFunction != null && editFunction.Id != editFunctionName) { // Changing function name, remove old function string oldFunctionFile = functionDir + "/" + editFunction.Id + ".math"; if (System.IO.File.Exists(oldFunctionFile)) { try { System.IO.File.Delete(oldFunctionFile); error = null; } catch (Exception e) { error = "Cannot save function: " + e.Message; return; } } kalc.Functions.Remove(editFunction.Id); if (selectedFunction != null && selectedFunction.Id == editFunction.Id) { selectedFunction = null; } if (RunFunction != null && RunFunction.Id == editFunction.Id) { RunFunction = null; } id = WindowIdOfRepeatingFunction(editFunction.Id); if (id != -1) { envs.Remove(id); } } // Save new function try { functionFile = functionDir + "/" + editFunctionName + ".math"; System.IO.File.WriteAllText(functionFile, editFunctionContent); error = null; } catch (Exception e) { error = "Cannot save function: " + e.Message; return; } // Compile new function JITFunction f = JITFunction.FromFile(functionFile, kalc); f.Compile(); if (RunFunction != null && RunFunction.Id == f.Id) { RunFunction = f; } id = WindowIdOfRepeatingFunction(f.Id); if (id != -1) { envs[id].func = f; } if (!kalc.Functions.ContainsKey(editFunctionName)) { kalc.Functions.Add(editFunctionName, f); } else { kalc.Functions[editFunctionName] = f; } editFunction = f; }
/// <summary>Draws the edit window that allows basic text editing.</summary> /// <param name="id">An unique number indentifying the window</param> public void DrawEditWindow(int id) { // Close button editWindowEnabled = !GUI.Toggle(new Rect(options.editWindowPos.width - 25, 0, 20, 20), !editWindowEnabled, ""); GUILayout.BeginHorizontal(); if (GUILayout.Button(deleteIcon, defaultButton, GUILayout.Width(25), GUILayout.Height(24))) { Delete(); } editFunctionName = GUILayout.TextField(editFunctionName, editFunctionStyle, GUILayout.Height(24)); if (GUILayout.Button(saveIcon, defaultButton, GUILayout.Width(24), GUILayout.Height(24))) { Save(); if (editFunction == null) { editFunction = kalc.Functions[editFunctionName]; } } if (GUILayout.Button(runIcon, defaultButton, GUILayout.Width(24), GUILayout.Height(24))) { // Save it Save(); // Load the function to be run RunFunction = editFunction; runWindowEnabled = true; // Run it Run(); functionOutput = FormatOutput(env); } GUILayout.EndHorizontal(); if (functionNameError != null) { GUILayout.Label("Cannot save function:" + functionNameError, invalidFunctionName); } editorScrollPos = GUILayout.BeginScrollView(editorScrollPos, false, true, GUILayout.Height(options.editWindowPos.height - 140)); //, GUILayout.Width(460)); editFunctionContent = GUILayout.TextArea(editFunctionContent, GUILayout.ExpandWidth(true)); TextEditor editor = (TextEditor)GUIUtility.GetStateObject(typeof(TextEditor), GUIUtility.keyboardControl); GUILayout.EndScrollView(); GUILayout.BeginHorizontal(); foreach (string s in greekLetters) { if (GUILayout.Button(s, keyboard, GUILayout.Width(15))) { editFunctionContent = editFunctionContent.Insert(editor.cursorIndex, s); editor.cursorIndex++; editor.selectIndex++; //editor.UpdateScrollOffsetIfNeeded(); } } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); foreach (string s in greekUCLetters) { if (GUILayout.Button(s, keyboard, GUILayout.Width(15))) { editFunctionContent = editFunctionContent.Insert(editor.cursorIndex, s); editor.cursorIndex++; editor.selectIndex++; //editor.UpdateScrollOffsetIfNeeded(); } } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); foreach (string s in symbols) { if (GUILayout.Button(s, keyboard, GUILayout.Width(15))) { editFunctionContent = editFunctionContent.Insert(editor.cursorIndex, s); editor.cursorIndex++; editor.selectIndex++; //editor.UpdateScrollOffsetIfNeeded(); } } GUILayout.EndHorizontal(); options.editWindowPos = ResizeWindow(id, options.editWindowPos, minEditWindowSize); GUI.DragWindow(titleBarRect); if (Event.current.type == EventType.Repaint) { tooltip = GUI.tooltip; } }
public Kerbulator(string functionDir) { operators = new Dictionary <string, Operator>(); operators.Add("=", new Operator("=", 1, Arity.BINARY)); // Assignment operators.Add("-", new Operator("-", 4, Arity.BOTH)); // Substraction or negation operators.Add("+", new Operator("+", 4, Arity.BINARY)); // Addition operators.Add("/", new Operator("/", 5, Arity.BINARY)); // Division operators.Add("÷", new Operator("÷", 5, Arity.BINARY)); // Division operators.Add("√", new Operator("√", 5, Arity.BOTH)); // Square Root or ^(1/n) operators.Add("%", new Operator("%", 5, Arity.BINARY)); // Modulo operators.Add("*", new Operator("*", 5, Arity.BINARY)); // Multiplication operators.Add("·", new Operator("·", 5, Arity.BINARY)); // Multiplication operators.Add("×", new Operator("×", 5, Arity.BINARY)); // Multiplication operators.Add("^", new Operator("^", 6, Arity.BINARY)); // Multiplication operators.Add("|", new Operator("|", 6, Arity.UNARY)); // Absolute operators.Add("⌊", new Operator("⌊", 6, Arity.UNARY)); // Floor operators.Add("⌈", new Operator("⌈", 6, Arity.UNARY)); // Ceiling operators.Add("<", new Operator("<", 3, Arity.BINARY)); // Less than operators.Add(">", new Operator(">", 3, Arity.BINARY)); // Greater than operators.Add("<=", new Operator("<=", 3, Arity.BINARY)); // Less than or equal operators.Add("≤", new Operator("≤", 3, Arity.BINARY)); // Less than or equal operators.Add(">=", new Operator(">=", 3, Arity.BINARY)); // Greater than or equal operators.Add("≥", new Operator("≥", 3, Arity.BINARY)); // Greater than or equal operators.Add("==", new Operator("==", 3, Arity.BINARY)); // Equals operators.Add("!=", new Operator("!=", 3, Arity.BINARY)); // Not equals operators.Add("≠", new Operator("≠", 3, Arity.BINARY)); // Not equals operators.Add("!", new Operator("!", 6, Arity.UNARY)); // Boolean not operators.Add("¬", new Operator("¬", 6, Arity.UNARY)); // Boolean not operators.Add("and", new Operator("and", 2, Arity.BINARY)); // AND operators.Add("∧", new Operator("∧", 2, Arity.BINARY)); // AND operators.Add("or", new Operator("or", 2, Arity.BINARY)); // OR operators.Add("∨", new Operator("∨", 2, Arity.BINARY)); // OR operators.Add("buildin-function", new Operator("buildin-function", 5, Arity.BINARY)); // Execute buildin function as unary operator operators.Add("user-function", new Operator("user-function", 5, Arity.BINARY)); // Execute user function as unary operator buildInFunctions = new Dictionary <string, BuildInFunction>(); buildInFunctions.Add("abs", new BuildInFunction("abs", 1)); buildInFunctions.Add("acos", new BuildInFunction("acos", 1)); buildInFunctions.Add("acos_rad", new BuildInFunction("acos_rad", 1)); buildInFunctions.Add("asin", new BuildInFunction("asin", 1)); buildInFunctions.Add("asin_rad", new BuildInFunction("asin_rad", 1)); buildInFunctions.Add("atan", new BuildInFunction("atan", 1)); buildInFunctions.Add("atan_rad", new BuildInFunction("atan_rad", 1)); buildInFunctions.Add("atan2", new BuildInFunction("atan2", 2)); buildInFunctions.Add("atan2_rad", new BuildInFunction("atan2_rad", 2)); buildInFunctions.Add("ceil", new BuildInFunction("ceil", 1)); buildInFunctions.Add("cos", new BuildInFunction("cos", 1)); buildInFunctions.Add("cos_rad", new BuildInFunction("cos_rad", 1)); buildInFunctions.Add("cosh", new BuildInFunction("cosh", 1)); buildInFunctions.Add("cosh_rad", new BuildInFunction("cosh_rad", 1)); buildInFunctions.Add("exp", new BuildInFunction("exp", 1)); buildInFunctions.Add("floor", new BuildInFunction("floor", 1)); buildInFunctions.Add("ln", new BuildInFunction("ln", 1)); buildInFunctions.Add("log", new BuildInFunction("log", 1)); buildInFunctions.Add("log10", new BuildInFunction("log10", 1)); buildInFunctions.Add("max", new BuildInFunction("max", 2)); buildInFunctions.Add("min", new BuildInFunction("min", 2)); buildInFunctions.Add("pow", new BuildInFunction("pow", 2)); buildInFunctions.Add("rand", new BuildInFunction("rand", 0)); buildInFunctions.Add("round", new BuildInFunction("round", 2)); buildInFunctions.Add("sign", new BuildInFunction("sign", 1)); buildInFunctions.Add("sin", new BuildInFunction("sin", 1)); buildInFunctions.Add("sin_rad", new BuildInFunction("sin_rad", 1)); buildInFunctions.Add("sinh", new BuildInFunction("sinh", 1)); buildInFunctions.Add("sinh_rad", new BuildInFunction("sinh_rad", 1)); buildInFunctions.Add("sqrt", new BuildInFunction("sqrt", 1)); buildInFunctions.Add("tan", new BuildInFunction("tan", 1)); buildInFunctions.Add("tan_rad", new BuildInFunction("tan_rad", 1)); buildInFunctions.Add("tanh", new BuildInFunction("tanh", 1)); buildInFunctions.Add("tanh_rad", new BuildInFunction("tanh_rad", 1)); buildInFunctions.Add("len", new BuildInFunction("len", 1)); buildInFunctions.Add("mag", new BuildInFunction("mag", 1)); buildInFunctions.Add("norm", new BuildInFunction("norm", 1)); buildInFunctions.Add("dot", new BuildInFunction("dot", 2)); buildInFunctions.Add("cross", new BuildInFunction("cross", 2)); buildInFunctions.Add("all", new BuildInFunction("all", 1)); buildInFunctions.Add("any", new BuildInFunction("any", 1)); globals = new Dictionary <string, Object>(); globals.Add("pi", Math.PI); globals.Add("π", Math.PI); globals.Add("e", Math.E); globals.Add("G", 6.67408E-11); globals.Add("Inf", double.PositiveInfinity); globals.Add("∞", double.PositiveInfinity); functions = new SortedDictionary <string, JITFunction>(); JITFunction.Scan(functionDir, this); }
public static void Scan(string dir, Kerbulator kalc) { // This function is called pretty often, so I went through some lengths to ensure that only new or updated functions are compiled. List <string> files = new List <string>(Directory.GetFiles(dir, "*.math")); List <string> compiledFunctions = new List <string>(kalc.Functions.Keys); files.Sort(); compiledFunctions.Sort(); int i = 0; int j = 0; while (i < files.Count || j < compiledFunctions.Count) { if (i >= files.Count) { // Deleted function kalc.Functions.Remove(compiledFunctions[j]); j++; } else if (j >= compiledFunctions.Count) { // Added function JITFunction f = FromFile(files[i], kalc); kalc.Functions[f.Id] = f; i++; } else if (string.Compare(Path.GetFileNameWithoutExtension(files[i]), compiledFunctions[j]) == 1) { // Deleted function kalc.Functions.Remove(compiledFunctions[j]); i++; } else if (string.Compare(Path.GetFileNameWithoutExtension(files[i]), compiledFunctions[j]) == -1) { // Added function JITFunction f = FromFile(files[i], kalc); kalc.Functions[f.Id] = f; j++; } else { // Function already exists // Reload only if file is newer DateTime dt = File.GetLastWriteTime(files[i]); if (dt > lastScan) { JITFunction f = FromFile(files[i], kalc); kalc.Functions[f.Id] = f; } i++; j++; } } foreach (JITFunction f in kalc.Functions.Values) { f.Compile(); } lastScan = DateTime.Now; }
public Kerbulator(string functionDir) { operators = new Dictionary <string, Operator>(); operators.Add("=", new Operator("=", 1, Arity.BINARY)); // Assignment operators.Add("-", new Operator("-", 1, Arity.BOTH)); // Substraction or negation operators.Add("+", new Operator("+", 1, Arity.BINARY)); // Addition operators.Add("/", new Operator("/", 2, Arity.BINARY)); // Division operators.Add("÷", new Operator("÷", 2, Arity.BINARY)); // Division operators.Add("√", new Operator("√", 2, Arity.BOTH)); // Square Root or ^(1/n) operators.Add("%", new Operator("%", 2, Arity.BINARY)); // Modulo operators.Add("*", new Operator("*", 2, Arity.BINARY)); // Multiplication operators.Add("·", new Operator("·", 2, Arity.BINARY)); // Multiplication operators.Add("×", new Operator("×", 2, Arity.BINARY)); // Multiplication operators.Add("^", new Operator("^", 3, Arity.BINARY)); // Multiplication operators.Add("|", new Operator("|", 3, Arity.UNARY)); // Absolute operators.Add("⌊", new Operator("⌊", 3, Arity.UNARY)); // Floor operators.Add("⌈", new Operator("⌈", 3, Arity.UNARY)); // Ceiling operators.Add("func", new Operator("func", 2, Arity.BINARY)); // Execute buildin function as unary operator operators.Add("buildin-function", new Operator("buildin-function", 2, Arity.BINARY)); // Execute buildin function as unary operator operators.Add("user-function", new Operator("user-function", 2, Arity.BINARY)); // Execute user function as unary operator buildInFunctions = new Dictionary <string, BuildInFunction>(); buildInFunctions.Add("abs", new BuildInFunction("abs", 1)); buildInFunctions.Add("acos", new BuildInFunction("acos", 1)); buildInFunctions.Add("acos_rad", new BuildInFunction("acos_rad", 1)); buildInFunctions.Add("asin", new BuildInFunction("asin", 1)); buildInFunctions.Add("asin_rad", new BuildInFunction("asin_rad", 1)); buildInFunctions.Add("atan", new BuildInFunction("atan", 1)); buildInFunctions.Add("atan_rad", new BuildInFunction("atan_rad", 1)); buildInFunctions.Add("ceil", new BuildInFunction("ceil", 1)); buildInFunctions.Add("cos", new BuildInFunction("cos", 1)); buildInFunctions.Add("cos_rad", new BuildInFunction("cos_rad", 1)); buildInFunctions.Add("cosh", new BuildInFunction("cosh", 1)); buildInFunctions.Add("cosh_rad", new BuildInFunction("cosh_rad", 1)); buildInFunctions.Add("exp", new BuildInFunction("exp", 1)); buildInFunctions.Add("floor", new BuildInFunction("floor", 1)); buildInFunctions.Add("ln", new BuildInFunction("ln", 1)); buildInFunctions.Add("log", new BuildInFunction("log", 1)); buildInFunctions.Add("log10", new BuildInFunction("log10", 1)); buildInFunctions.Add("max", new BuildInFunction("max", 2)); buildInFunctions.Add("min", new BuildInFunction("min", 2)); buildInFunctions.Add("pow", new BuildInFunction("pow", 2)); buildInFunctions.Add("rand", new BuildInFunction("rand", 0)); buildInFunctions.Add("round", new BuildInFunction("round", 2)); buildInFunctions.Add("sign", new BuildInFunction("sign", 1)); buildInFunctions.Add("sin", new BuildInFunction("sin", 1)); buildInFunctions.Add("sin_rad", new BuildInFunction("sin_rad", 1)); buildInFunctions.Add("sinh", new BuildInFunction("sinh", 1)); buildInFunctions.Add("sinh_rad", new BuildInFunction("sinh_rad", 1)); buildInFunctions.Add("sqrt", new BuildInFunction("sqrt", 1)); buildInFunctions.Add("tan", new BuildInFunction("tan", 1)); buildInFunctions.Add("tan_rad", new BuildInFunction("tan_rad", 1)); buildInFunctions.Add("tanh", new BuildInFunction("tanh", 1)); buildInFunctions.Add("tanh_rad", new BuildInFunction("tanh_rad", 1)); buildInFunctions.Add("len", new BuildInFunction("len", 1)); buildInFunctions.Add("mag", new BuildInFunction("mag", 1)); buildInFunctions.Add("norm", new BuildInFunction("norm", 1)); buildInFunctions.Add("dot", new BuildInFunction("dot", 2)); buildInFunctions.Add("cross", new BuildInFunction("cross", 2)); globals = new Dictionary <string, Object>(); globals.Add("pi", Math.PI); globals.Add("π", Math.PI); globals.Add("e", Math.E); globals.Add("G", 6.67384E-11); functions = new SortedDictionary <string, JITFunction>(); JITFunction.Scan(functionDir, this); }
public ExecutionEnvironment(JITFunction func, Kerbulator kalc) { this.func = func; this.kalc = kalc; inputExpressions = new List <JITExpression>(func.Ins.Count); }
private void ParseIdentifier(Stack <Expression> expr, Stack <Operator> ops) { Token t = tokens.Dequeue(); if (kalc.Functions.ContainsKey(t.val)) { // User function call JITFunction f = kalc.Functions[t.val]; if (tokens.Count > 0 && tokens.Peek().val == "(") { // Parameter list supplied, execute function now List <Expression> args = ParseArgumentList(); expr.Push(ParseUserFunction(t.val, args, t.pos)); } else if (f.Ins.Count == 0) { // Function takes no arguments, execute now expr.Push(ParseUserFunction(t.val, new List <Expression>(), t.pos)); } else { // Do function call later, when parameters are known ops.Push(kalc.Operators["user-function"]); expr.Push(Expression.Constant(t.val)); } } else if (kalc.BuildInFunctions.ContainsKey(t.val)) { BuildInFunction f = kalc.BuildInFunctions[t.val]; if (tokens.Count > 0 && tokens.Peek().val == "(") { // Parameter list supplied, execute function now List <Expression> args = ParseArgumentList(); if (args.Count != f.numArgs) { throw new Exception(t.pos + "function " + f + " takes " + f.numArgs + " arguments, but " + args.Count + " were supplied"); } expr.Push(ParseBuildInFunction(f, args, t.pos)); } else if (f.numArgs == 0) { // Function takes no arguments, execute now expr.Push(ParseBuildInFunction(f, new List <Expression>(), t.pos)); } else { // Do function call later, when parameters are known ops.Push(kalc.Operators["buildin-function"]); expr.Push(Expression.Constant(t.val)); } } else { // Variable identifier if (tokens.Count > 0 && tokens.Peek().val == "(") { // Parameter list supplied, but function doesn't exist throw new Exception(t.pos + "function " + t.val + " does not exist"); } expr.Push( Expression.Call( thisExpression, typeof(JITFunction).GetMethod("GetVar"), Expression.Constant(t.val), Expression.Constant(t.pos) ) ); } }
/// <summary>Draws the GUI</summary> public void OnGUI() { // Initiate styles if (!stylesInitiated) { keyboard = new GUIStyle(GUI.skin.GetStyle("button")); keyboard.padding = new RectOffset(0, 0, 2, 2); defaultButton = new GUIStyle(GUI.skin.GetStyle("button")); defaultButton.padding = new RectOffset(4, 4, 4, 4); tooltipStyle = new GUIStyle(GUI.skin.GetStyle("label")); Texture2D texBack = new Texture2D(1, 1, TextureFormat.ARGB32, false); texBack.SetPixel(0, 0, new Color(0.0f, 0.0f, 0.0f, 1f)); texBack.Apply(); tooltipStyle.normal.background = texBack; validFunctionName = new GUIStyle(GUI.skin.GetStyle("TextField")); editFunctionStyle = validFunctionName; invalidFunctionName = new GUIStyle(GUI.skin.GetStyle("TextField")); invalidFunctionName.normal.textColor = Color.red; invalidFunctionName.active.textColor = Color.red; invalidFunctionName.hover.textColor = Color.red; invalidFunctionName.focused.textColor = Color.red; stylesInitiated = true; } if (drawMainButton) { // Draw the main button if (GUI.Button(mainButtonPos, kerbulatorIcon, defaultButton)) { ChangeState(!mainWindowEnabled); } } if (reload) { reload = false; // Rebuild the list of functions. It could be that they were edited outside of KSP JITFunction.Scan(functionDir, kalc); // Reload the function being edited if (editFunction != null) { editFunctionContent = System.IO.File.ReadAllText(functionFile); } } // Draw the windows (if enabled) if (mainWindowEnabled) { options.mainWindowPos = GUI.Window(windowId, options.mainWindowPos, DrawMainWindow, "Kerbulator"); glue.PreventClickthrough(options.mainWindowPos, "KerbulatorMainWindow"); } else { glue.EnsureLockReleased("KerbulatorMainWindow"); } if (editWindowEnabled) { options.editWindowPos = GUI.Window(windowId + 1, options.editWindowPos, DrawEditWindow, "Function Editor"); glue.PreventClickthrough(options.editWindowPos, "KerbulatorEditWindow"); } else { glue.EnsureLockReleased("KerbulatorEditWindow"); } if (runWindowEnabled) { options.runWindowPos = GUI.Window(windowId + 2, options.runWindowPos, DrawRunWindow, "Run " + RunFunction.Id); glue.PreventClickthrough(options.runWindowPos, "KerbulatorRunWindow"); } else { glue.EnsureLockReleased("KerbulatorRunWindow"); } if (running) { foreach (KeyValuePair <int, ExecutionEnvironment> pair in envs) { pair.Value.windowPos = GUI.Window(pair.Key, pair.Value.windowPos, DrawRepeatedWindow, pair.Value.func.Id); glue.PreventClickthrough(pair.Value.windowPos, "KerbulatorEnvironment" + pair.Value.func.Id); } } DrawToolTip(); }
/// <summary>Draws the main window that displays a list of available functions</summary> /// <param name="id">An unique number indentifying the window</param> public void DrawMainWindow(int id) { // Close button at the top right corner if (drawMainButton) { ChangeState(!GUI.Toggle(new Rect(options.mainWindowPos.width - 25, 0, 20, 20), !mainWindowEnabled, "")); } if (error != null) { GUILayout.Label(error); } GUILayout.Label("Available functions:"); mainScrollPos = GUILayout.BeginScrollView(mainScrollPos, false, true, GUILayout.Height(options.mainWindowPos.height - 110)); bool runSomething = false; foreach (KeyValuePair <string, JITFunction> f in kalc.Functions) { GUILayout.BeginHorizontal(); if (GUILayout.Button(f.Key, GUILayout.Height(24))) { selectedFunction = f.Value; functionDescription = FunctionDescription(f.Value); functionDescriptionHeight = GUI.skin.GetStyle("label").CalcHeight(new GUIContent(functionDescription), 225); } if (GUILayout.Button(editIcon, defaultButton, GUILayout.Width(24), GUILayout.Height(24))) { // Load the function to be edited editFunction = f.Value; functionFile = functionDir + "/" + f.Key + ".math"; editFunctionName = f.Key; editFunctionContent = System.IO.File.ReadAllText(functionFile); editWindowEnabled = true; } if (GUILayout.Button(runIcon, defaultButton, GUILayout.Width(24), GUILayout.Height(24))) { // Load the function to be run RunFunction = f.Value; runWindowEnabled = true; // Run it, but only after this loop finishes. // Run() calls Scan(), which updates the dictionary we're currently // enumerating over, which is not allowed. runSomething = true; } GUILayout.EndHorizontal(); // When a function is selected, display some info if (selectedFunction == f.Value) { GUILayout.Label("Function info:"); GUILayout.Label(functionDescription, GUILayout.Width(225), GUILayout.Height(functionDescriptionHeight)); } } GUILayout.EndScrollView(); GUILayout.Space(20); GUILayout.BeginHorizontal(); if (GUILayout.Button("New function")) { editFunction = null; // Load template for an empty function functionFile = functionDir + "/unnamed.math"; editFunctionName = "unnamed"; editFunctionContent = ""; editWindowEnabled = true; } if (GUILayout.Button("New maneuver")) { editFunction = null; // Load template for a function controlling a maneuver node functionFile = functionDir + "/maneuver.math"; editFunctionName = "maneuver"; editFunctionContent = maneuverTemplate; editWindowEnabled = true; } GUILayout.EndHorizontal(); options.mainWindowPos = ResizeWindow(id, options.mainWindowPos, minMainWindowSize); GUI.DragWindow(titleBarRect); if (Event.current.type == EventType.Repaint) { tooltip = GUI.tooltip; } // Run button was pressed, run the function if (runSomething) { Run(); functionOutput = FormatOutput(env); GUI.FocusWindow(windowId + 2); runSomething = false; } }
/// <summary>Draws the GUI</summary> public void OnGUI() { // Initiate styles if (!stylesInitiated) { keyboard = new GUIStyle(GUI.skin.GetStyle("button")); keyboard.padding = new RectOffset(0, 0, 2, 2); defaultButton = new GUIStyle(GUI.skin.GetStyle("button")); defaultButton.padding = new RectOffset(4, 4, 4, 4); tooltipStyle = new GUIStyle(GUI.skin.GetStyle("label")); Texture2D texBack = new Texture2D(1, 1, TextureFormat.ARGB32, false); texBack.SetPixel(0, 0, new Color(0.0f, 0.0f, 0.0f, 1f)); texBack.Apply(); tooltipStyle.normal.background = texBack; stylesInitiated = true; } if (drawMainButton) { // Draw the main button if (GUI.Button(mainButtonPos, kerbulatorIcon, defaultButton)) { ChangeState(!mainWindowEnabled); } } if (reload) { reload = false; // Rebuild the list of functions. It could be that they were edited outside of KSP JITFunction.Scan(functionDir, kalc); // Reload the function being edited if (editFunction != null) { editFunctionContent = System.IO.File.ReadAllText(functionFile); } } // Draw the windows (if enabled) if (mainWindowEnabled) { mainWindowPos = GUILayout.Window(windowId, mainWindowPos, DrawMainWindow, "Kerbulator", GUILayout.ExpandHeight(false)); } if (editWindowEnabled) { editWindowPos = GUILayout.Window(windowId + 1, editWindowPos, DrawEditWindow, "Function Editor", GUILayout.ExpandHeight(false)); } if (runWindowEnabled) { runWindowPos = GUILayout.Window(windowId + 2, runWindowPos, DrawRunWindow, "Run " + RunFunction.Id, GUILayout.ExpandHeight(false)); } if (running) { foreach (KeyValuePair <int, ExecutionEnvironment> pair in envs) { pair.Value.windowPos = GUILayout.Window(pair.Key, pair.Value.windowPos, DrawRepeatedWindow, pair.Value.func.Id, GUILayout.ExpandHeight(false)); } } DrawToolTip(); }