diff --git a/DungeonShooting_Godot/editor/prefabs/CodePanel.tscn b/DungeonShooting_Godot/editor/prefabs/CodePanel.tscn new file mode 100644 index 0000000..4966385 --- /dev/null +++ b/DungeonShooting_Godot/editor/prefabs/CodePanel.tscn @@ -0,0 +1,47 @@ +[gd_scene load_steps=5 format=2] + +[ext_resource path="res://editor/src/CodeTextEditor.cs" type="Script" id=1] +[ext_resource path="res://editor/ide_cn_font_6.tres" type="DynamicFont" id=2] +[ext_resource path="res://editor/src/CodePanel.cs" type="Script" id=3] +[ext_resource path="res://editor/src/TextEditPainter.cs" type="Script" id=4] + +[node name="CodePanel" type="Control"] +anchor_right = 1.0 +anchor_bottom = 1.0 +script = ExtResource( 3 ) + +[node name="ScalePanel" type="Control" parent="."] +anchor_right = 1.0 +anchor_bottom = 1.0 +margin_right = 720.0 +margin_bottom = 405.0 +rect_scale = Vector2( 0.4, 0.4 ) + +[node name="TextEdit" type="TextEdit" parent="ScalePanel"] +anchor_right = 1.0 +anchor_bottom = 1.0 +custom_colors/member_variable_color = Color( 0.862745, 0.862745, 0.862745, 1 ) +custom_colors/function_color = Color( 0.862745, 0.862745, 0.666667, 1 ) +custom_colors/safe_line_number_color = Color( 1, 0.164706, 0.141176, 1 ) +custom_colors/background_color = Color( 0.117647, 0.117647, 0.117647, 1 ) +custom_colors/number_color = Color( 0.709804, 0.807843, 0.658824, 1 ) +custom_colors/current_line_color = Color( 0.0588235, 0.0588235, 0.0588235, 1 ) +custom_constants/line_spacing = 0 +custom_fonts/font = ExtResource( 2 ) +highlight_current_line = true +syntax_highlighting = true +show_line_numbers = true +draw_tabs = true +bookmark_gutter = true +fold_gutter = true +context_menu_enabled = false +minimap_draw = true +caret_blink = true +caret_blink_speed = 0.4 +script = ExtResource( 1 ) + +[node name="TextEditPainter" type="Node2D" parent="ScalePanel/TextEdit"] +script = ExtResource( 4 ) + +[connection signal="resized" from="ScalePanel" to="." method="_on_ScalePanel_resized"] +[connection signal="text_changed" from="ScalePanel/TextEdit" to="ScalePanel/TextEdit" method="_on_TextEdit_text_changed"] diff --git a/DungeonShooting_Godot/editor/prefabs/IdePanel.tscn b/DungeonShooting_Godot/editor/prefabs/IdePanel.tscn deleted file mode 100644 index de1493b..0000000 --- a/DungeonShooting_Godot/editor/prefabs/IdePanel.tscn +++ /dev/null @@ -1,42 +0,0 @@ -[gd_scene load_steps=4 format=2] - -[ext_resource path="res://editor/src/IdeTextEditor.cs" type="Script" id=1] -[ext_resource path="res://editor/ide_cn_font_6.tres" type="DynamicFont" id=2] -[ext_resource path="res://editor/src/IdePanel.cs" type="Script" id=3] - -[node name="IdePanel" type="Control"] -anchor_right = 1.0 -anchor_bottom = 1.0 -script = ExtResource( 3 ) - -[node name="ScalePanel" type="Control" parent="."] -anchor_right = 1.0 -anchor_bottom = 1.0 -margin_right = 720.0 -margin_bottom = 405.0 -rect_scale = Vector2( 0.4, 0.4 ) - -[node name="TextEdit" type="TextEdit" parent="ScalePanel"] -anchor_right = 1.0 -anchor_bottom = 1.0 -custom_colors/member_variable_color = Color( 0.862745, 0.862745, 0.862745, 1 ) -custom_colors/function_color = Color( 0.862745, 0.862745, 0.666667, 1 ) -custom_colors/background_color = Color( 0.117647, 0.117647, 0.117647, 1 ) -custom_colors/number_color = Color( 0.709804, 0.807843, 0.658824, 1 ) -custom_colors/current_line_color = Color( 0.0588235, 0.0588235, 0.0588235, 1 ) -custom_constants/line_spacing = 0 -custom_fonts/font = ExtResource( 2 ) -highlight_current_line = true -syntax_highlighting = true -show_line_numbers = true -draw_tabs = true -bookmark_gutter = true -fold_gutter = true -context_menu_enabled = false -minimap_draw = true -caret_blink = true -caret_blink_speed = 0.4 -script = ExtResource( 1 ) - -[connection signal="resized" from="ScalePanel" to="." method="_on_ScalePanel_resized"] -[connection signal="text_changed" from="ScalePanel/TextEdit" to="ScalePanel/TextEdit" method="_on_TextEdit_text_changed"] diff --git a/DungeonShooting_Godot/editor/src/CodePanel.cs b/DungeonShooting_Godot/editor/src/CodePanel.cs new file mode 100644 index 0000000..447b167 --- /dev/null +++ b/DungeonShooting_Godot/editor/src/CodePanel.cs @@ -0,0 +1,44 @@ +using Godot; + +namespace Editor +{ + public class CodePanel : Control + { + /// + /// 初始缩放 + /// + public Vector2 StartScale { get; private set; } + + private Control ScalePanel; + private TextEditPainter _editPainter; + + private CodeTextEditor _codeTextEditor; + + + public override void _Ready() + { + _codeTextEditor = GetNode("ScalePanel/TextEdit"); + _editPainter = _codeTextEditor.GetNode("TextEditPainter"); + + ScalePanel = GetNode("ScalePanel"); + StartScale = ScalePanel.RectScale; + + _editPainter.SetIdePanel(this); + _editPainter.SetTextEdit(_codeTextEditor); + } + + public override void _Process(float delta) + { + _editPainter.Update(); + } + + private void _on_ScalePanel_resized() + { + //更新textEditor的缩放 + if (ScalePanel != null) + { + ScalePanel.SetSize(RectSize / StartScale); + } + } + } +} diff --git a/DungeonShooting_Godot/editor/src/CodeTextEditor.cs b/DungeonShooting_Godot/editor/src/CodeTextEditor.cs new file mode 100644 index 0000000..eadde35 --- /dev/null +++ b/DungeonShooting_Godot/editor/src/CodeTextEditor.cs @@ -0,0 +1,206 @@ +using Godot; + +namespace Editor +{ + public class CodeTextEditor : TextEdit + { + private readonly Color KeyCodeColor = new Color(86 / 255f, 156 / 255f, 214 / 255f); + private readonly Color AnnotationColor = new Color(77 / 255f, 144 / 255f, 52 / 255f); + private readonly Color StringColor = new Color(214 / 255f, 157 / 255f, 133 / 255f); + + private readonly string[] KeyCodes = + { + "var", + "namespace", + "this", + "class", + "extends", + "func", + "get", + "set", + "import", + "static", + "new", + "return", + "for", + "switch", + "case", + "break", + "default", + "while", + "do", + "is", + "repeat", + "null", + "true", + "false", + "readonly", + "enum", + "private", + "super", + "if", + "else", + "continue", + "typeof" + }; + + private readonly string[] auto_compelete_right = { "'", "{", "\"", "(", "[" }; + private readonly string[] auto_compelete_left = { "'", "}", "\"", ")", "]" }; + + private TextEditPainter _editPainter; + + public override void _Ready() + { + _editPainter = GetNode("TextEditPainter"); + //添加关键字 + for (int i = 0; i < KeyCodes.Length; i++) + { + AddKeywordColor(KeyCodes[i], KeyCodeColor); + } + + AddColorRegion("//", "", AnnotationColor, true); + AddColorRegion("/*", "*/", AnnotationColor); + AddColorRegion("\"", "\"", StringColor); + Text = @" +//该样例演示如何声明一个类对象 + +//导入简化的命名空间后的类, global 命名空间下的成员不需要导入 +import Behavior = example.framework.Behavior; +//同样也可以直接导入简化名称的命名空间 +import myName = example.framework; +//导入整个命名空间 +import system; + +//除导入语句外, 脚本第一句必须是这个, 定义该文件所属的命名空间, 但是可以忽略, 默认为 global 命名空间 +namespace example.defineClass; +/* +这一句也必须写在文件的开头, 在声明 namespace 之后, +在命名空间 example.defineClass 下声明一个叫 MyClass 的类, 继承自 Behavior 类 +当一个文件内写过 class xxx 后, 就表名该文件是一个类, 逻辑代码和声明代码必须写在声明 class后面 +*/ +class MyClass extends Behavior; + +//在类中声明一个 a 变量, a 如果不赋值的话就默认为 null +var a; +var b = 1.5; +var c = null; +private var d = true; //私有属性 +readonly var e = false; //只读属性 + +//在类中声明一个叫 length 的 get 属性, get 属性必须有返回值 +get length() { + return b; +} +//在类中声明一个叫 length 的 set 属性, set 属性设置的数据变量叫 param +//param 关键字只能出现在 set 属性中, 并且只读 +set length(val) { + b = val; +} + +//在类中声明一个 say 的函数, 并且支持传入一个参数 +func say(str) { + var message = ""say: "" + str; + print(message); +} +//在类中声明一个 say 的函数重载, 该重载为 0 个参数 +//注意, 因为脚本数据类型为弱类型, 无法通过数据类型判断重载, 所以函数重载是根据参数长度来进行重载 +func say() { + say(""hello""); +} + +//在类中声明构造函数, 其他地方调用 MyClass(); 时就会调用该类的构造函数, 无参构造可省略 +//参数重载和函数的规范一致, MyClass() 构造函数可以被视为一个特殊函数, 其他非构造函数不能调用 MyClass() 函数 +func MyClass() { + +} +//构造继承, 构造函数继承该类的无参构造函数 +func MyClass(message) extends MyClass() { + print(""创建了MyClass, message: "" + message); +} + +//语法展示 +private func grammarExample() { + //调用父类函数 + super.say(); + //判断实例是否是该类型 + if (i is Map) { + print(""是字典""); + } else { + print(""不是字典""); + } + //for循环100次 + for (var i = 0; i < 100; i++) { + continue; + } + //while循环 + while (true) { + break; + } + //repeat循环, 执行100次 + repeat(100) { + + } + //函数表达式 + var f1 = (a1) => { + + } + //执行函数 + f1(1); + //将成员函数存入变量 + var f2 = func(say, 1); + //数组 + var array = [1, 2, ""str""]; + //匿名对象, 无法扩展和删除属性, 只能对已有的属性进行赋值 + var obj = { + x: 1, + y: -2.2, + list: [""str"", true], + }; + //字典, 允许扩展和删除属性, 性能比匿名对象低 + var map = @{ + a: """", + b: 1, + c: false + }; +} + +//静态部分注意, 如果声明了一个叫 a 的非静态成员, 那么就不能声明一个叫 a 的静态变量 + +//在类中声明一个静态的 sa 变量, 并附上初始值 1 +static var sa = 2; + +//静态函数, 参数重载和普通函数的规范一致 +static func staticSay() { + +} + +"; + } + + public override void _Process(float delta) + { + if (Input.IsMouseButtonPressed((int)ButtonList.Right)) + { + GD.Print(GetTotalVisibleRows()); + _editPainter.DrawTextEditErrorLine(CursorGetLine()); + } + } + + private void _on_TextEdit_text_changed() + { + // GD.Print(GetWordUnderCursor()); + // GD.Print(GetPosAtLineColumn(1, 1)); + Select(CursorGetLine(), CursorGetColumn() - 1, CursorGetLine(), CursorGetColumn()); + var key = GetSelectionText(); + Select(CursorGetLine(), CursorGetColumn(), CursorGetLine(), CursorGetColumn()); + for (int i = 0; i < 5; i++) + { + if (key == auto_compelete_right[i]) + { + InsertTextAtCursor(auto_compelete_left[i]); + CursorSetColumn(CursorGetColumn() - 1); + } + } + } + } +} \ No newline at end of file diff --git a/DungeonShooting_Godot/editor/src/IdePanel.cs b/DungeonShooting_Godot/editor/src/IdePanel.cs deleted file mode 100644 index 7b686c2..0000000 --- a/DungeonShooting_Godot/editor/src/IdePanel.cs +++ /dev/null @@ -1,24 +0,0 @@ -using Godot; - -namespace Editor -{ - public class IdePanel : Control - { - private Vector2 StartScale; - private Control ScalePanel; - - public override void _Ready() - { - ScalePanel = GetNode("ScalePanel"); - StartScale = ScalePanel.RectScale; - } - - private void _on_ScalePanel_resized() - { - if (ScalePanel != null) - { - ScalePanel.SetSize(RectSize / StartScale); - } - } - } -} diff --git a/DungeonShooting_Godot/editor/src/IdeTextEditor.cs b/DungeonShooting_Godot/editor/src/IdeTextEditor.cs deleted file mode 100644 index c520328..0000000 --- a/DungeonShooting_Godot/editor/src/IdeTextEditor.cs +++ /dev/null @@ -1,103 +0,0 @@ -using Godot; - -namespace Editor -{ - public class IdeTextEditor : TextEdit - { - private readonly Color KeyCodeColor = new Color(86 / 255f, 156 / 255f, 214 / 255f); - private readonly Color AnnotationColor = new Color(77 / 255f, 144 / 255f, 52 / 255f); - private readonly Color StringColor = new Color(214 / 255f, 157 / 255f, 133 / 255f); - - private readonly string[] KeyCodes = - { - "var", - "namespace", - "this", - "class", - "extends", - "func", - "get", - "set", - "import", - "static", - "new", - "return", - "for", - "switch", - "case", - "break", - "default", - "while", - "do", - "is", - "repeat", - "null", - "true", - "false", - "readonly", - "enum", - "private", - "super", - "if", - "else", - "continue", - "typeof" - }; - - private readonly string[] auto_compelete_right = { "'", "{", "\"", "(", "[" }; - private readonly string[] auto_compelete_left = { "'", "}", "\"", ")", "]" }; - - public override void _Ready() - { - //添加关键字 - for (int i = 0; i < KeyCodes.Length; i++) - { - AddKeywordColor(KeyCodes[i], KeyCodeColor); - } - - AddColorRegion("//", "", AnnotationColor, true); - AddColorRegion("/*", "*/", AnnotationColor); - AddColorRegion("\"", "\"", StringColor); - Text = @" -//导入命名空间 -import system; -//声明一个类, 继承Object -class MyClass extends Object; - -//声明变量 -var text = ""hello \""world\""""; - -func say(message) { - print(message); -} - -static test() { - var arr = [1, 2, 3]; - if (arr.length > 0) { - for (var i = 0; i < arr.length; i++) { - print(arr[i]); - } - } -} - -"; - } - - private void _on_TextEdit_text_changed() - { - GD.Print(GetWordUnderCursor()); - GD.Print(GetPosAtLineColumn(1, 1)); - Select(CursorGetLine(), CursorGetColumn() - 1, CursorGetLine(), CursorGetColumn()); - var key = GetSelectionText(); - Select(CursorGetLine(), CursorGetColumn(), CursorGetLine(), CursorGetColumn()); - for (int i = 0; i < 5; i++) - { - if (key == auto_compelete_right[i]) - { - InsertTextAtCursor(auto_compelete_left[i]); - CursorSetColumn(CursorGetColumn() - 1); - } - } - } - } -} \ No newline at end of file diff --git a/DungeonShooting_Godot/editor/src/TextEditPainter.cs b/DungeonShooting_Godot/editor/src/TextEditPainter.cs new file mode 100644 index 0000000..e93b00d --- /dev/null +++ b/DungeonShooting_Godot/editor/src/TextEditPainter.cs @@ -0,0 +1,91 @@ +using System.Collections.Generic; +using Godot; + +namespace Editor +{ + /// + /// 负责代码编辑器内的绘制操作 + /// + public class TextEditPainter : Node2D + { + private Color ErrorLineColor = new Color(1, 0, 0, 0.2f); + + //code面板 + private CodePanel _codePanel; + private TextEdit _textEdit; + //报错行数 + private List _errorLines = new List(); + + /// + /// 设置文本编辑器 + /// + public void SetTextEdit(CodeTextEditor textEdit) + { + _textEdit = textEdit; + } + + /// + /// 设置代码面板 + /// + public void SetIdePanel(CodePanel codePanel) + { + _codePanel = codePanel; + } + + /// + /// 绘制 TextEdit 中报错的行数 + /// + /// 报错所在行数 + public void DrawTextEditErrorLine(int line) + { + if (!_errorLines.Contains(line)) + { + _errorLines.Add(line); + _textEdit.SetLineAsSafe(line, true); + } + } + + /// + /// 取消绘制 TextEdit 中报错的行数 + /// + /// 报错所在行数 + public void UnDrawTextEditErrorLine(int line) + { + _errorLines.Remove(line); + _textEdit.SetLineAsSafe(line, false); + } + + public Vector2 ToPainterPosition(Vector2 v) + { + if (_codePanel != null) + { + return v / _codePanel.StartScale; + } + + return v; + } + + public override void _Draw() + { + if (_errorLines.Count > 0) + { + var lineHeight = _textEdit.GetLineHeight(); + var width = _textEdit.RectSize.x - _textEdit.MinimapWidth; + for (int i = 0; i < _errorLines.Count; i++) + { + var pos = _textEdit.GetPosAtLineColumn(_errorLines[i], 0); + if (pos.x > -1 && pos.y > -1) + { + DrawRect(new Rect2(0, pos.y - lineHeight, width, lineHeight), ErrorLineColor); + } + } + } + } + + //提交绘制 + private void CommitDrawLine(Vector2 start, Vector2 end, Color color, float width) + { + + } + } +} \ No newline at end of file diff --git a/DungeonShooting_Godot/scene/Main.tscn b/DungeonShooting_Godot/scene/Main.tscn index 8aa305d..71af9f1 100644 --- a/DungeonShooting_Godot/scene/Main.tscn +++ b/DungeonShooting_Godot/scene/Main.tscn @@ -1,9 +1,9 @@ [gd_scene load_steps=2 format=2] -[ext_resource path="res://editor/prefabs/IdePanel.tscn" type="PackedScene" id=1] +[ext_resource path="res://editor/prefabs/CodePanel.tscn" type="PackedScene" id=1] [node name="Main" type="Node2D"] [node name="CanvasLayer" type="CanvasLayer" parent="."] -[node name="IdePanel" parent="CanvasLayer" instance=ExtResource( 1 )] +[node name="CodePanel" parent="CanvasLayer" instance=ExtResource( 1 )]