debug console init
							parent
							
								
									213358a2ba
								
							
						
					
					
						commit
						ad29c9cd29
					
				|  | @ -0,0 +1,29 @@ | |||
| namespace SupaLidlGame.Debug; | ||||
| 
 | ||||
| internal sealed class CharIterator : Iterator<char> | ||||
| { | ||||
|     public CharIterator(string str) : base(str.ToCharArray()) | ||||
|     { | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     public CharIterator(char[] chars) : base(chars) | ||||
|     { | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     public override char MoveNext() | ||||
|     { | ||||
|         char c = base.MoveNext(); | ||||
|         if (c == '\n') | ||||
|         { | ||||
|             Line++; | ||||
|             Column = 0; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             Column++; | ||||
|         } | ||||
|         return c; | ||||
|     } | ||||
| } | ||||
|  | @ -2,21 +2,97 @@ using Godot; | |||
| 
 | ||||
| namespace SupaLidlGame.Debug; | ||||
| 
 | ||||
| public partial class DebugConsole : Node | ||||
| public sealed partial class DebugConsole : Control | ||||
| { | ||||
|     public void SetProp( | ||||
|         Utils.World world, | ||||
|         string entityName, | ||||
|         string property, | ||||
|         string value) | ||||
|     private Node _context; | ||||
|     public Node Context | ||||
|     { | ||||
|         var ent = world.CurrentMap.Entities.GetNodeOrNull(entityName); | ||||
|         if (ent is not null) | ||||
|         get => _context; | ||||
|         private set | ||||
|         { | ||||
|             ent.Set(property, value); | ||||
|             if (value is not null) | ||||
|             { | ||||
|                 _context = value; | ||||
|                 if (_entry is not null) | ||||
|                 { | ||||
|                     _entry.PlaceholderText = "Enter Godot expression from " + | ||||
|                         _context.GetPath(); | ||||
|                     GetParent<Window>().Title = "Supa Developer Console: " + | ||||
|                         _context.GetPath(); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private Entry _entry; | ||||
| 
 | ||||
|     private RichTextLabel _output; | ||||
| 
 | ||||
|     private Node ctx => Context; | ||||
| 
 | ||||
|     public override void _Ready() | ||||
|     { | ||||
|         _entry = GetNode<Entry>("%Entry"); | ||||
|         _output = GetNode<RichTextLabel>("%Output"); | ||||
|         Context = Utils.World.Instance; | ||||
| 
 | ||||
|         _entry.ConsoleInput += (string input) => | ||||
|         { | ||||
|             try | ||||
|             { | ||||
|                 Execute(input); | ||||
|             } | ||||
|             catch (InterpreterException ex) | ||||
|             { | ||||
|                 _output.Text += ex.Message + '\n'; | ||||
|             } | ||||
|         }; | ||||
|     } | ||||
| 
 | ||||
|     enum PathType | ||||
|     { | ||||
|         Node, | ||||
|         Property | ||||
|     }; | ||||
| 
 | ||||
|     public Variant From(NodePath path) | ||||
|     { | ||||
|         CharIterator iterator = new(path); | ||||
|         Variant variant = Context ?? this; | ||||
|         foreach (var subpath in NodePathParser.ParseNodePath(iterator)) | ||||
|         { | ||||
|             if (variant.VariantType == Variant.Type.Object) | ||||
|             { | ||||
|                 if (variant.AsGodotObject() is Node n) | ||||
|                 { | ||||
|                     if (subpath.Type == NodePathTokenType.Node) | ||||
|                     { | ||||
|                         if (subpath.Path != "") | ||||
|                         { | ||||
|                             variant = n.GetNode(subpath.Path); | ||||
|                         } | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         variant = n.GetIndexed(subpath.Path); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         return variant; | ||||
|     } | ||||
| 
 | ||||
|     public void SetProp(NodePath path, Variant value) | ||||
|     { | ||||
|         var node = GetNode(path.GetAsPropertyPath()); | ||||
|         //var ent = CurrentMap.Entities.GetNodeOrNull(entityName); | ||||
|         //if (ent is not null) | ||||
|         //{ | ||||
|         //    ent.Set(property, value); | ||||
|         //} | ||||
|     } | ||||
| 
 | ||||
|     public string CallMethod( | ||||
|         Utils.World world, | ||||
|         string entityName, | ||||
|  | @ -31,4 +107,54 @@ public partial class DebugConsole : Node | |||
|         } | ||||
|         return ""; | ||||
|     } | ||||
| 
 | ||||
|     public void Print(string text) | ||||
|     { | ||||
|         GD.Print(text); | ||||
|     } | ||||
| 
 | ||||
|     public void Execute(string str) | ||||
|     { | ||||
|         str = Sanitizer.Sanitize(str); | ||||
|         string inputMirror = $"[b]{Context.GetPath()}:[/b] {str}"; | ||||
|         _output.Text += inputMirror + "\n"; | ||||
|         var context = Context; | ||||
| 
 | ||||
|         Godot.Expression exp = new(); | ||||
| 
 | ||||
|         string[] reserved = { "from", "set_context", "context" }; | ||||
|         Godot.Collections.Array reservedMap = new(); | ||||
|         reservedMap.Add(new Callable(this, MethodName.From)); | ||||
|         reservedMap.Add(new Callable(this, MethodName.SetContext)); | ||||
|         reservedMap.Add(Context); | ||||
| 
 | ||||
|         var err = exp.Parse(str, reserved); | ||||
|         if (err != Error.Ok) | ||||
|         { | ||||
|             throw new InterpreterException( | ||||
|                 "Error occurred while parsing Godot.Expression: \n" + | ||||
|                 exp.GetErrorText(), | ||||
|                 0, 0); | ||||
|         } | ||||
| 
 | ||||
|         Variant result = exp.Execute(reservedMap, context); | ||||
|         if (exp.HasExecuteFailed()) | ||||
|         { | ||||
|             throw new InterpreterException( | ||||
|                 "Error occurred while evaluating Godot.Expression: \n" + | ||||
|                 exp.GetErrorText(), | ||||
|                 0, 0); | ||||
|         } | ||||
| 
 | ||||
|         // send result to output | ||||
|         if (result.VariantType != Variant.Type.Nil) | ||||
|         { | ||||
|             _output.Text += result + "\n"; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public void SetContext(Node node) | ||||
|     { | ||||
|         Context = node; | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -0,0 +1,30 @@ | |||
| using Godot; | ||||
| 
 | ||||
| namespace SupaLidlGame.Debug; | ||||
| 
 | ||||
| public partial class Entry : LineEdit | ||||
| { | ||||
|     [Signal] | ||||
|     public delegate void ConsoleInputEventHandler(string input); | ||||
| 
 | ||||
|     public override void _Ready() | ||||
|     { | ||||
|         GuiInput += OnGuiInput; | ||||
|     } | ||||
| 
 | ||||
|     public void OnGuiInput(InputEvent @event) | ||||
|     { | ||||
|         if (@event is InputEventKey key) | ||||
|         { | ||||
|             if (key.KeyLabel == Key.Enter && !key.Pressed) | ||||
|             { | ||||
|                 EmitSignal(SignalName.ConsoleInput, Text); | ||||
| 
 | ||||
|                 if (!key.CtrlPressed) | ||||
|                 { | ||||
|                     Text = ""; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,46 @@ | |||
| using System.Collections.Generic; | ||||
| 
 | ||||
| namespace SupaLidlGame.Debug; | ||||
| 
 | ||||
| public class Iterator<T> where T : struct | ||||
| { | ||||
|     public int Line { get; protected set; } = 1; | ||||
| 
 | ||||
|     public int Column { get; protected set; } = 0; | ||||
| 
 | ||||
|     public int Index { get; protected set; } = -1; | ||||
| 
 | ||||
|     protected List<T> _elements; | ||||
| 
 | ||||
|     public Iterator(T[] elements) | ||||
|     { | ||||
|         _elements = new List<T>(elements); | ||||
|     } | ||||
| 
 | ||||
|     public Iterator(List<T> elements) | ||||
|     { | ||||
|         _elements = new List<T>(elements); | ||||
|     } | ||||
| 
 | ||||
|     public T GetNext(int offset = 0) | ||||
|     { | ||||
|         if (Index + offset + 1 < _elements.Count) | ||||
|         { | ||||
|             return _elements[Index + offset + 1]; | ||||
|         } | ||||
| 
 | ||||
|         return default; | ||||
|     } | ||||
| 
 | ||||
|     public virtual T MoveNext() | ||||
|     { | ||||
|         T next = GetNext(); | ||||
|         Index++; | ||||
|         return next; | ||||
|     } | ||||
| 
 | ||||
|     public virtual void MoveBack() | ||||
|     { | ||||
|         Index--; | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,65 @@ | |||
| using Godot; | ||||
| using System.Collections.Generic; | ||||
| 
 | ||||
| namespace SupaLidlGame.Debug; | ||||
| 
 | ||||
| internal static class NodePathParser | ||||
| { | ||||
|     internal static IEnumerable<NodePathToken> ParseNodePath(CharIterator iterator) | ||||
|     { | ||||
|         // Some/Node/Path:And:Property/More/Paths | ||||
|         // -> | ||||
|         // Some/Node/Path (Node) | ||||
|         // :And:Property  (Property) | ||||
|         // More/Paths     (Node) | ||||
| 
 | ||||
|         NodePathTokenType curType = NodePathTokenType.Node; | ||||
|         string path = ""; | ||||
|         while (iterator.GetNext() != '\0') | ||||
|         { | ||||
|             char curChar = iterator.MoveNext(); | ||||
| 
 | ||||
|             if (curChar == ':') | ||||
|             { | ||||
|                 // if we have been parsing a nodepath, yield a nodepath | ||||
|                 if (curType == NodePathTokenType.Node) | ||||
|                 { | ||||
|                     if (path.Length > 0) | ||||
|                     { | ||||
|                         yield return new NodePathToken(path, curType); | ||||
|                         path = ""; | ||||
|                         curType = NodePathTokenType.Property; | ||||
|                     } | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     path += curChar; | ||||
|                 } | ||||
|             } | ||||
|             else if (curChar == '/') | ||||
|             { | ||||
|                 // if we have been parsing property, yield a property | ||||
|                 if (curType == NodePathTokenType.Property) | ||||
|                 { | ||||
|                     yield return new NodePathToken(path, curType); | ||||
|                     path = ""; | ||||
|                     curType = NodePathTokenType.Node; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     path += curChar; | ||||
|                 } | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 path += curChar; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         // reached the end | ||||
|         if (path.Length > 0) | ||||
|         { | ||||
|             yield return new NodePathToken(path, curType); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,20 @@ | |||
| using Godot; | ||||
| 
 | ||||
| public enum NodePathTokenType | ||||
| { | ||||
|     Node, | ||||
|     Property | ||||
| } | ||||
| 
 | ||||
| public struct NodePathToken | ||||
| { | ||||
|     public NodePath Path { get; set; } | ||||
| 
 | ||||
|     public NodePathTokenType Type { get; set; } | ||||
| 
 | ||||
|     public NodePathToken(NodePath path, NodePathTokenType type) | ||||
|     { | ||||
|         Path = path; | ||||
|         Type = type; | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,136 @@ | |||
| using Godot; | ||||
| using System.Text.RegularExpressions; | ||||
| 
 | ||||
| namespace SupaLidlGame.Debug; | ||||
| 
 | ||||
| public static class Sanitizer | ||||
| { | ||||
|     private static Regex _nonAlphanum = new("[^a-zA-Z0-9_]"); | ||||
| 
 | ||||
|     private static Regex _nonNodeName = new("[^a-zA-Z0-9_\\-\\/]"); | ||||
| 
 | ||||
|     private static string ScanString(CharIterator iterator) | ||||
|     { | ||||
|         string ret = ""; | ||||
| 
 | ||||
|         while (iterator.GetNext() != '\0') | ||||
|         { | ||||
|             char c = iterator.MoveNext(); | ||||
| 
 | ||||
|             if (c == '"') | ||||
|             { | ||||
|                 return ret; | ||||
|             } | ||||
|             else if (c == '\\') | ||||
|             { | ||||
|                 char escape = iterator.MoveNext(); | ||||
| 
 | ||||
|                 switch (escape) | ||||
|                 { | ||||
|                     case 'n': | ||||
|                         ret += '\n'; | ||||
|                         break; | ||||
|                     case 't': | ||||
|                         ret += '\t'; | ||||
|                         break; | ||||
|                     case '\0': | ||||
|                         throw new InterpreterException("Unexpected EOL", | ||||
|                             iterator.Line, iterator.Column); default: | ||||
|                         ret += escape; | ||||
|                         break; | ||||
|                 } | ||||
|             } | ||||
|              | ||||
|             ret += c; | ||||
|         } | ||||
|         throw new InterpreterException("Unexpected EOL, expected '\"'", | ||||
|             iterator.Line, iterator.Column); | ||||
|     } | ||||
| 
 | ||||
|     private static string ScanNodePath(CharIterator iterator) | ||||
|     { | ||||
|         string ret = ""; | ||||
|         while (iterator.GetNext() != '\0') | ||||
|         { | ||||
|             char c = iterator.MoveNext(); | ||||
| 
 | ||||
|             if (c == '"') | ||||
|             { | ||||
|                 return ScanString(iterator); | ||||
|             } | ||||
|             else if (_nonNodeName.IsMatch(c.ToString())) | ||||
|             { | ||||
|                 iterator.MoveBack(); | ||||
|                 return ret; | ||||
|             } | ||||
| 
 | ||||
|             ret += c; | ||||
|         } | ||||
|         return ret; | ||||
|     } | ||||
| 
 | ||||
|     private static string ScanUntilOrEOL(CharIterator iterator, char delim) | ||||
|     { | ||||
|         string ret = ""; | ||||
|         while (iterator.GetNext() != '\0') | ||||
|         { | ||||
|             char c = iterator.GetNext(); | ||||
|             if (c == delim) | ||||
|             { | ||||
|                 return ret; | ||||
|             } | ||||
|             ret += c; | ||||
|         } | ||||
|         return ret; | ||||
|     } | ||||
| 
 | ||||
|     private static string ScanGlobalCommand(CharIterator iterator) | ||||
|     { | ||||
|         string ret = ""; | ||||
|         while (iterator.GetNext() != '\0') | ||||
|         { | ||||
|             char c = iterator.MoveNext(); | ||||
|             if (_nonAlphanum.IsMatch(c.ToString())) | ||||
|             { | ||||
|                 iterator.MoveBack(); | ||||
|                 return ret; | ||||
|             } | ||||
|             ret += c; | ||||
|         } | ||||
|         return ret; | ||||
|     } | ||||
| 
 | ||||
|     public static string Sanitize(string input) | ||||
|     { | ||||
|         CharIterator iterator = new(input); | ||||
|         string ret = ""; | ||||
| 
 | ||||
|         while (iterator.GetNext() != '\0') | ||||
|         { | ||||
|             char c = iterator.MoveNext(); | ||||
| 
 | ||||
|             if (c == '$') | ||||
|             { | ||||
|                 string nodePath = ScanNodePath(iterator); | ||||
|                 ret += $"from.call(\"{nodePath}\")"; | ||||
|             } | ||||
|             else if (c == '"') | ||||
|             { | ||||
|                 string str = ScanString(iterator); | ||||
|                 ret += $"\"{str}\""; | ||||
|             } | ||||
|             else if (c == '\\') | ||||
|             { | ||||
|                 // \global -> global.call | ||||
|                 string command = ScanGlobalCommand(iterator); | ||||
|                 ret += $"{command}.call"; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 ret += c; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         return ret; | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,49 @@ | |||
| namespace SupaLidlGame.Debug; | ||||
| 
 | ||||
| public enum TokenType | ||||
| { | ||||
|     None, | ||||
|     Identifier, | ||||
|     String, | ||||
|     GodotExpression, | ||||
|     Command, | ||||
|     End | ||||
| }; | ||||
| 
 | ||||
| public struct Token | ||||
| { | ||||
|     public TokenType Type { get; set; } | ||||
| 
 | ||||
|     public string Value { get; set; } | ||||
| 
 | ||||
|     public int Line { get; set; } | ||||
| 
 | ||||
|     public int Column { get; set; } | ||||
| 
 | ||||
|     public Token(TokenType type, string value, int line, int col) | ||||
|     { | ||||
|         Type = type; | ||||
|         Value = value; | ||||
|         Line = line; | ||||
|         Column = col; | ||||
|     } | ||||
| 
 | ||||
|     public bool CompareTypeValue(Token token) | ||||
|     { | ||||
|         return Type == token.Type && Value == token.Value; | ||||
|     } | ||||
| 
 | ||||
|     public override bool Equals(object obj) | ||||
|     { | ||||
|         return base.Equals(obj); | ||||
|     } | ||||
| 
 | ||||
|     public override int GetHashCode() | ||||
|     { | ||||
|         return base.GetHashCode(); | ||||
|     } | ||||
| 
 | ||||
|     public static bool operator ==(Token left, Token right) => left.Equals(right); | ||||
| 
 | ||||
|     public static bool operator !=(Token left, Token right) => !left.Equals(right); | ||||
| } | ||||
|  | @ -0,0 +1,185 @@ | |||
| using System.Collections.Generic; | ||||
| 
 | ||||
| namespace SupaLidlGame.Debug; | ||||
| 
 | ||||
| internal sealed class Tokenizer | ||||
| { | ||||
|     private static readonly HashSet<char> WHITESPACE = new HashSet<char> { ' ', '\n' }; | ||||
| 
 | ||||
|     private static string ScanString(CharIterator iterator) | ||||
|     { | ||||
|         string ret = ""; | ||||
|         while (iterator.GetNext() != '\0') | ||||
|         { | ||||
|             char c = iterator.MoveNext(); | ||||
| 
 | ||||
|             if (c == '"') | ||||
|             { | ||||
|                 return ret; | ||||
|             } | ||||
|             else if (c == '\\') | ||||
|             { | ||||
|                 char escape = iterator.MoveNext(); | ||||
| 
 | ||||
|                 switch (escape) | ||||
|                 { | ||||
|                     case 'n': | ||||
|                         ret += '\n'; | ||||
|                         break; | ||||
|                     case 't': | ||||
|                         ret += '\t'; | ||||
|                         break; | ||||
|                     case '\0': | ||||
|                         throw new InterpreterException("Unexpected EOL", | ||||
|                             iterator.Line, iterator.Column); | ||||
|                     default: | ||||
|                         ret += escape; | ||||
|                         break; | ||||
|                 } | ||||
|             } | ||||
|              | ||||
|             ret += c; | ||||
|         } | ||||
|         throw new InterpreterException("Unexpected EOL, expected '\"'", | ||||
|             iterator.Line, iterator.Column); | ||||
|     } | ||||
| 
 | ||||
|     private static string ScanNodePath(CharIterator iterator) | ||||
|     { | ||||
|         string ret = ""; | ||||
|         while (iterator.GetNext() != '\0') | ||||
|         { | ||||
|             char c = iterator.GetNext(); | ||||
| 
 | ||||
|             if (c == '"') | ||||
|             { | ||||
|                 ret += ScanString(iterator); | ||||
|             } | ||||
|             else if (WHITESPACE.Contains(c)) | ||||
|             { | ||||
|                 return ret; | ||||
|             } | ||||
| 
 | ||||
|             ret += c; | ||||
|         } | ||||
|         return ret; | ||||
|     } | ||||
| 
 | ||||
|     /* | ||||
|     private static string ScanUntil(CharIterator iterator) | ||||
|     { | ||||
| 
 | ||||
|     } | ||||
|     */ | ||||
| 
 | ||||
|     private static string ScanExpression(CharIterator iterator) | ||||
|     { | ||||
|         int level = 0; | ||||
|         string exp = ""; | ||||
|         while (iterator.GetNext() != '\0') | ||||
|         { | ||||
|             char c = iterator.GetNext(); | ||||
| 
 | ||||
|             if (c == '(') | ||||
|             { | ||||
|                 level++; | ||||
|             } | ||||
|             else if (c == ')') | ||||
|             { | ||||
|                 level--; | ||||
|             } | ||||
| 
 | ||||
|             if (level < 0) | ||||
|             { | ||||
|                 return exp; | ||||
|             } | ||||
| 
 | ||||
|             exp += c; | ||||
|         } | ||||
|         return exp; | ||||
|     } | ||||
| 
 | ||||
|     private static string ScanUntilOrEOL(CharIterator iterator, char delim) | ||||
|     { | ||||
|         string ret = ""; | ||||
|         while (iterator.GetNext() != '\0') | ||||
|         { | ||||
|             char c = iterator.GetNext(); | ||||
|             if (c == delim) | ||||
|             { | ||||
|                 return ret; | ||||
|             } | ||||
|             ret += c; | ||||
|         } | ||||
|         return ret; | ||||
|     } | ||||
| 
 | ||||
|     public static IEnumerable<Token> Tokenize(CharIterator iterator) | ||||
|     { | ||||
|         System.Diagnostics.Debug.Print("hi"); | ||||
|         while (iterator.GetNext() != '\0') | ||||
|         { | ||||
|             char curChar = iterator.MoveNext(); | ||||
|             System.Diagnostics.Debug.Print(curChar.ToString()); | ||||
| 
 | ||||
|             int line = iterator.Line; | ||||
|             int col = iterator.Column; | ||||
| 
 | ||||
|             if (WHITESPACE.Contains(curChar)) | ||||
|             { | ||||
|                 continue; | ||||
|             } | ||||
|             else if (curChar == '\\') | ||||
|             { | ||||
|                 string command = ScanUntilOrEOL(iterator, ' '); | ||||
|                 if (command == "") | ||||
|                 { | ||||
|                     throw new InterpreterException( | ||||
|                         "Expected a command name", | ||||
|                         iterator.Line, | ||||
|                         iterator.Column); | ||||
|                 } | ||||
|                 yield return new Token(TokenType.Command, | ||||
|                     command, | ||||
|                     line, | ||||
|                     col); | ||||
|             } | ||||
|             else if (curChar == '(') | ||||
|             { | ||||
|                 string exp = ScanExpression(iterator); | ||||
|                 yield return new Token(TokenType.GodotExpression, | ||||
|                     exp, | ||||
|                     line, | ||||
|                     col); | ||||
|             } | ||||
|             else if (curChar == '"') | ||||
|             { | ||||
|                 yield return new Token(TokenType.String, | ||||
|                     ScanString(iterator), | ||||
|                     line, | ||||
|                     col); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 // parse this as expression | ||||
|                 string exp = ScanUntilOrEOL(iterator, ' '); | ||||
|                 yield return new Token(TokenType.GodotExpression, | ||||
|                     exp, | ||||
|                     line, | ||||
|                     col); | ||||
|             } | ||||
|             /* | ||||
|             else if (curChar == '$') | ||||
|             { | ||||
|                 yield return new Token(TokenType.NodePath, | ||||
|                     ScanNodePath(iterator), | ||||
|                     line, | ||||
|                     col); | ||||
|             } | ||||
|             */ | ||||
|         } | ||||
|         yield return new Token(TokenType.End, "", | ||||
|             iterator.Line, iterator.Column); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | @ -0,0 +1,13 @@ | |||
| namespace SupaLidlGame; | ||||
| 
 | ||||
| public class InterpreterException : System.Exception | ||||
| { | ||||
|     public int Line { get; set; } | ||||
|     public int Column { get; set; } | ||||
| 
 | ||||
|     public InterpreterException(string msg, int line, int column) : base(msg) | ||||
|     { | ||||
|         Line = line; | ||||
|         Column = column; | ||||
|     } | ||||
| } | ||||
|  | @ -4,28 +4,6 @@ namespace SupaLidlGame.Extensions; | |||
| 
 | ||||
| public static class NodeExtensions | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Iterates through each ancestor until it finds an ancestor of type | ||||
|     /// <c>T</c> | ||||
|     /// </summary> | ||||
|     [System.Obsolete] | ||||
|     public static T GetAncestorDeprecated<T>(this Node node) where T : Node | ||||
|     { | ||||
|         Node parent; | ||||
| 
 | ||||
|         while ((parent = node.GetParent()) != null) | ||||
|         { | ||||
|             if (parent is T t) | ||||
|             { | ||||
|                 return t; | ||||
|             } | ||||
| 
 | ||||
|             node = parent; | ||||
|         } | ||||
| 
 | ||||
|         return null; | ||||
|     } | ||||
| 
 | ||||
|     /// <summary> | ||||
|     /// A version <c>GetNode</c> that returns null rather than cause an | ||||
|     /// exception if the node is not found or is not the same type. | ||||
|  |  | |||
|  | @ -29,6 +29,7 @@ stretch = true | |||
| stretch_shrink = 3 | ||||
| 
 | ||||
| [node name="UIViewport" type="SubViewport" parent="SubViewportContainer"] | ||||
| disable_3d = true | ||||
| transparent_bg = true | ||||
| handle_input_locally = false | ||||
| size = Vector2i(640, 360) | ||||
|  |  | |||
|  | @ -1,4 +1,7 @@ | |||
| [gd_scene format=3 uid="uid://be8bc4eivsg4s"] | ||||
| [gd_scene load_steps=3 format=3 uid="uid://be8bc4eivsg4s"] | ||||
| 
 | ||||
| [ext_resource type="Script" path="res://Debug/DebugConsole.cs" id="1_3fw5a"] | ||||
| [ext_resource type="Script" path="res://Debug/Entry.cs" id="2_kdlsh"] | ||||
| 
 | ||||
| [node name="DebugUI" type="Control"] | ||||
| layout_mode = 3 | ||||
|  | @ -8,11 +11,47 @@ anchor_bottom = 1.0 | |||
| grow_horizontal = 2 | ||||
| grow_vertical = 2 | ||||
| 
 | ||||
| [node name="VBoxContainer" type="VBoxContainer" parent="."] | ||||
| layout_mode = 1 | ||||
| anchors_preset = 12 | ||||
| anchor_top = 1.0 | ||||
| [node name="Window" type="Window" parent="."] | ||||
| disable_3d = true | ||||
| gui_embed_subwindows = true | ||||
| title = "Supa Developer Console" | ||||
| position = Vector2i(32, 32) | ||||
| size = Vector2i(1280, 720) | ||||
| always_on_top = true | ||||
| 
 | ||||
| [node name="DebugConsole" type="Control" parent="Window"] | ||||
| layout_mode = 3 | ||||
| anchors_preset = 15 | ||||
| anchor_right = 1.0 | ||||
| anchor_bottom = 1.0 | ||||
| grow_horizontal = 2 | ||||
| grow_vertical = 0 | ||||
| grow_vertical = 2 | ||||
| script = ExtResource("1_3fw5a") | ||||
| 
 | ||||
| [node name="VBoxContainer" type="VBoxContainer" parent="Window/DebugConsole"] | ||||
| layout_mode = 1 | ||||
| anchors_preset = 15 | ||||
| anchor_right = 1.0 | ||||
| anchor_bottom = 1.0 | ||||
| grow_horizontal = 2 | ||||
| grow_vertical = 2 | ||||
| 
 | ||||
| [node name="Output" type="RichTextLabel" parent="Window/DebugConsole/VBoxContainer"] | ||||
| unique_name_in_owner = true | ||||
| layout_mode = 2 | ||||
| size_flags_vertical = 3 | ||||
| theme_override_font_sizes/normal_font_size = 24 | ||||
| theme_override_font_sizes/bold_font_size = 24 | ||||
| bbcode_enabled = true | ||||
| text = "[b]/root/World:[/b] \\echo :CurrentPlayer:Health | ||||
| 100 | ||||
| " | ||||
| scroll_following = true | ||||
| 
 | ||||
| [node name="Entry" type="LineEdit" parent="Window/DebugConsole/VBoxContainer"] | ||||
| unique_name_in_owner = true | ||||
| layout_mode = 2 | ||||
| theme_override_font_sizes/font_size = 24 | ||||
| placeholder_text = "Enter a GDScript expression or \\command..." | ||||
| draw_control_chars = true | ||||
| script = ExtResource("2_kdlsh") | ||||
|  |  | |||
|  | @ -23,8 +23,8 @@ EventBus="*res://Events/EventBus.cs" | |||
| BaseUI="*res://UI/Base.tscn" | ||||
| World="*res://Scenes/Level.tscn" | ||||
| AudioManager="*res://Audio/AudioManager.cs" | ||||
| DebugConsole="*res://Debug/DebugConsole.cs" | ||||
| Panku="*res://addons/panku_console/console.tscn" | ||||
| DebugUi="*res://UI/Debug/DebugUI.tscn" | ||||
| 
 | ||||
| [dialogue_manager] | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue