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 )]