diff --git a/README.md b/README.md
index a1478aa..86a9b41 100644
--- a/README.md
+++ b/README.md
@@ -3,6 +3,7 @@
`! Note:` this plugin only works for Godot 4.x
Updated to 4.0.alpha15. Things may still break, older alphas may not be compatible right away.
+If something did break in a newer version, please open an issue.
Now available on the Godot Asset Library: [Color Preview](https://godotengine.org/asset-library/asset/1252)
@@ -23,7 +24,8 @@ Go to `Project > Project Settings... > Plugins` and press Enable
Once you have done this, every line containing a Color will have a preview left of the breakpoint gutter.
Click any preview to open a color picker where you can edit the color directly.
-![Addon Preview](https://github.com/Qubus0/GodotColorPreview/blob/main/colors.png)
+![Color Preview in the main code editor](https://github.com/Qubus0/GodotColorPreview/blob/main/colors.png)
+![Color Preview in the shader editor](https://github.com/Qubus0/GodotColorPreview/blob/main/colors_shader.png)
***
diff --git a/addons/ColorPreview/ColorPreview.gd b/addons/ColorPreview/ColorPreview.gd
index 0923ef3..f500d9f 100644
--- a/addons/ColorPreview/ColorPreview.gd
+++ b/addons/ColorPreview/ColorPreview.gd
@@ -11,8 +11,11 @@ var picker_popup: Popup
func _enter_tree() -> void:
- initialize_picker()
initialize_gutter()
+ initialize_picker()
+ # the shader editor does not exist until opened for the first time
+ # so, to get it consistently, check if it's there whenever the focus changes
+ get_viewport().gui_focus_changed.connect(get_shader_editor_code_edit)
func _exit_tree() -> void:
@@ -26,7 +29,7 @@ func initialize_picker() -> void:
picker_popup.connect("popup_hide", on_picker_popup_close)
picker_popup.hide()
- var picker = picker_popup.get_node("ColorPicker")
+ var picker: ColorPicker = picker_popup.get_node("ColorPicker")
if not picker.is_connected("color_changed", picker_color_changed):
picker.connect("color_changed", picker_color_changed)
@@ -65,24 +68,30 @@ func get_all_text_editors(parent : Node) -> void:
if child.get_child_count():
get_all_text_editors(child)
- if child is TextEdit:
- editors.append(child)
-
- if child.is_connected("text_changed", text_changed):
- child.disconnect("text_changed", text_changed)
- child.text_changed.connect(text_changed.bind(child))
-
- if child.is_connected("caret_changed", caret_changed):
- child.disconnect("caret_changed", caret_changed)
- child.caret_changed.connect(caret_changed.bind(child))
+ if child is CodeEdit:
+ add_code_edit_to_editors_array(child)
+
+
+func get_shader_editor_code_edit(node: Node):
+ if not node is CodeEdit or not node.get_parent().get_class() == "ShaderTextEditor":
+ return
+
+ if not editors.has(node):
+ add_code_edit_to_editors_array(node)
+ initialize_gutter()
+ initialize_picker()
-func caret_changed(textedit: TextEdit) -> void:
- handle_change(textedit)
+func add_code_edit_to_editors_array(node: CodeEdit) -> void:
+ editors.append(node)
+ if node.is_connected("text_changed", handle_change):
+ node.disconnect("text_changed", handle_change)
+ node.text_changed.connect(handle_change.bind(node))
-func text_changed(textedit : TextEdit) -> void:
- handle_change(textedit)
+ if node.is_connected("caret_changed", handle_change):
+ node.disconnect("caret_changed", handle_change)
+ node.caret_changed.connect(handle_change.bind(node))
func handle_change(textedit : TextEdit) -> void:
@@ -98,8 +107,8 @@ func handle_change(textedit : TextEdit) -> void:
func editor_script_changed(script: Script) -> void:
- initialize_picker()
initialize_gutter()
+ initialize_picker()
if current_textedit:
if current_textedit.is_connected("gui_input", textedit_clicked):
current_textedit.disconnect("gui_input", textedit_clicked)
@@ -254,7 +263,17 @@ func on_picker_popup_close() -> void:
var text := current_textedit.get_line(hovering_line)
var color_match : RegExMatch = match_color_in_string(text)
var new_color = get_line_color(current_textedit, hovering_line)
- text = text.replace(color_match.get_string(), "Color" + str(new_color))
+
+ if color_from_regex_match(color_match) == new_color:
+ return # don't change if equal -> doesn't mess up constants, strings etc.
+
+ if color_match.get_string('const'): # replace the whole color string
+ text = text.replace(color_match.get_string(), "Color" + str(new_color))
+
+ else: # only replace inside parenthesis to cover Color(...) and vec4(...)
+ var color_string = str(new_color).replace("(", "").replace(")", "")
+ text = text.replace(color_match.get_string("params"), color_string)
+
current_textedit.set_line(hovering_line, text)
@@ -315,10 +334,19 @@ func named_or_hex_color(string: String): # Color or null
func match_color_in_string(string: String) -> RegExMatch:
var re = RegEx.new()
+ var color
+
re.compile("Color\\((?(?R)*.*?)\\)")
- var color = re.search(string)
+ color = re.search(string)
if color != null:
return color
+
re.compile("Color\\.(?[A-Z_]+)\\b")
- return re.search(string)
+ color = re.search(string)
+ if color != null:
+ return color
+
+ re.compile("source_color.*?vec4\\((?(?R)*.*?)\\)")
+ color = re.search(string)
+ return color
diff --git a/colors_demo.gdshader b/colors_demo.gdshader
new file mode 100644
index 0000000..015b475
--- /dev/null
+++ b/colors_demo.gdshader
@@ -0,0 +1,14 @@
+shader_type canvas_item;
+
+// supports shader uniforms with type hint source_color
+uniform vec4 input_color : source_color = vec4(0.0952, 0.8355, 0.9494, 1);
+uniform vec4 transparent_color : source_color = vec4(0.95, 0.24, 0.52, 0.6);
+
+// and any vec4 as color with this comment in front
+/* source_color */ uniform vec4 not_type_hinted = vec4(1, 0.8549, 0.102, 1);
+
+// Color.BLACK <- technically you can also view these
+
+
+// picking and selecting also works the same
+uniform vec4 picker_color : source_color = vec4(0.9049, 0.5072, 0.0389, 1);
\ No newline at end of file
diff --git a/colors_shader.png b/colors_shader.png
new file mode 100644
index 0000000..ac1ab13
Binary files /dev/null and b/colors_shader.png differ
diff --git a/project.godot b/project.godot
index b4203f8..037e984 100644
--- a/project.godot
+++ b/project.godot
@@ -18,6 +18,11 @@ config/icon="res://icon.png"
enabled=PackedStringArray("res://addons/ColorPreview/plugin.cfg")
+[filesystem]
+
+import/blender/enabled=false
+import/fbx/enabled=false
+
[physics]
common/enable_pause_aware_picking=true