Skip to content

Commit 5a466c1

Browse files
committed
Add color preview to shader editor
1 parent 8bd5739 commit 5a466c1

File tree

5 files changed

+70
-21
lines changed

5 files changed

+70
-21
lines changed

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
`! Note:` this plugin only works for Godot 4.x
44

55
Updated to 4.0.alpha15. Things may still break, older alphas may not be compatible right away.
6+
If something did break in a newer version, please open an issue.
67

78
Now available on the Godot Asset Library: [Color Preview](https://godotengine.org/asset-library/asset/1252)
89

@@ -23,7 +24,8 @@ Go to `Project > Project Settings... > Plugins` and press <kbd>Enable</kbd>
2324
Once you have done this, every line containing a Color will have a preview left of the breakpoint gutter.
2425
Click any preview to open a color picker where you can edit the color directly.
2526

26-
![Addon Preview](https://github.com/Qubus0/GodotColorPreview/blob/main/colors.png)
27+
![Color Preview in the main code editor](https://github.com/Qubus0/GodotColorPreview/blob/main/colors.png)
28+
![Color Preview in the shader editor](https://github.com/Qubus0/GodotColorPreview/blob/main/colors_shader.png)
2729

2830
***
2931

addons/ColorPreview/ColorPreview.gd

Lines changed: 48 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,11 @@ var picker_popup: Popup
1111

1212

1313
func _enter_tree() -> void:
14-
initialize_picker()
1514
initialize_gutter()
15+
initialize_picker()
16+
# the shader editor does not exist until opened for the first time
17+
# so, to get it consistently, check if it's there whenever the focus changes
18+
get_viewport().gui_focus_changed.connect(get_shader_editor_code_edit)
1619

1720

1821
func _exit_tree() -> void:
@@ -26,7 +29,7 @@ func initialize_picker() -> void:
2629
picker_popup.connect("popup_hide", on_picker_popup_close)
2730
picker_popup.hide()
2831

29-
var picker = picker_popup.get_node("ColorPicker")
32+
var picker: ColorPicker = picker_popup.get_node("ColorPicker")
3033
if not picker.is_connected("color_changed", picker_color_changed):
3134
picker.connect("color_changed", picker_color_changed)
3235

@@ -65,24 +68,30 @@ func get_all_text_editors(parent : Node) -> void:
6568
if child.get_child_count():
6669
get_all_text_editors(child)
6770

68-
if child is TextEdit:
69-
editors.append(child)
70-
71-
if child.is_connected("text_changed", text_changed):
72-
child.disconnect("text_changed", text_changed)
73-
child.text_changed.connect(text_changed.bind(child))
74-
75-
if child.is_connected("caret_changed", caret_changed):
76-
child.disconnect("caret_changed", caret_changed)
77-
child.caret_changed.connect(caret_changed.bind(child))
71+
if child is CodeEdit:
72+
add_code_edit_to_editors_array(child)
73+
74+
75+
func get_shader_editor_code_edit(node: Node):
76+
if not node is CodeEdit or not node.get_parent().get_class() == "ShaderTextEditor":
77+
return
78+
79+
if not editors.has(node):
80+
add_code_edit_to_editors_array(node)
81+
initialize_gutter()
82+
initialize_picker()
7883

7984

80-
func caret_changed(textedit: TextEdit) -> void:
81-
handle_change(textedit)
85+
func add_code_edit_to_editors_array(node: CodeEdit) -> void:
86+
editors.append(node)
8287

88+
if node.is_connected("text_changed", handle_change):
89+
node.disconnect("text_changed", handle_change)
90+
node.text_changed.connect(handle_change.bind(node))
8391

84-
func text_changed(textedit : TextEdit) -> void:
85-
handle_change(textedit)
92+
if node.is_connected("caret_changed", handle_change):
93+
node.disconnect("caret_changed", handle_change)
94+
node.caret_changed.connect(handle_change.bind(node))
8695

8796

8897
func handle_change(textedit : TextEdit) -> void:
@@ -98,8 +107,8 @@ func handle_change(textedit : TextEdit) -> void:
98107

99108

100109
func editor_script_changed(script: Script) -> void:
101-
initialize_picker()
102110
initialize_gutter()
111+
initialize_picker()
103112
if current_textedit:
104113
if current_textedit.is_connected("gui_input", textedit_clicked):
105114
current_textedit.disconnect("gui_input", textedit_clicked)
@@ -254,7 +263,17 @@ func on_picker_popup_close() -> void:
254263
var text := current_textedit.get_line(hovering_line)
255264
var color_match : RegExMatch = match_color_in_string(text)
256265
var new_color = get_line_color(current_textedit, hovering_line)
257-
text = text.replace(color_match.get_string(), "Color" + str(new_color))
266+
267+
if color_from_regex_match(color_match) == new_color:
268+
return # don't change if equal -> doesn't mess up constants, strings etc.
269+
270+
if color_match.get_string('const'): # replace the whole color string
271+
text = text.replace(color_match.get_string(), "Color" + str(new_color))
272+
273+
else: # only replace inside parenthesis to cover Color(...) and vec4(...)
274+
var color_string = str(new_color).replace("(", "").replace(")", "")
275+
text = text.replace(color_match.get_string("params"), color_string)
276+
258277
current_textedit.set_line(hovering_line, text)
259278

260279

@@ -315,10 +334,19 @@ func named_or_hex_color(string: String): # Color or null
315334

316335
func match_color_in_string(string: String) -> RegExMatch:
317336
var re = RegEx.new()
337+
var color
338+
318339
re.compile("Color\\((?<params>(?R)*.*?)\\)")
319-
var color = re.search(string)
340+
color = re.search(string)
320341
if color != null:
321342
return color
343+
322344
re.compile("Color\\.(?<const>[A-Z_]+)\\b")
323-
return re.search(string)
345+
color = re.search(string)
346+
if color != null:
347+
return color
348+
349+
re.compile("source_color.*?vec4\\((?<params>(?R)*.*?)\\)")
350+
color = re.search(string)
351+
return color
324352

colors_demo.gdshader

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
shader_type canvas_item;
2+
3+
// supports shader uniforms with type hint source_color
4+
uniform vec4 input_color : source_color = vec4(0.0952, 0.8355, 0.9494, 1);
5+
uniform vec4 transparent_color : source_color = vec4(0.95, 0.24, 0.52, 0.6);
6+
7+
// and any vec4 as color with this comment in front
8+
/* source_color */ uniform vec4 not_type_hinted = vec4(1, 0.8549, 0.102, 1);
9+
10+
// Color.BLACK <- technically you can also view these
11+
12+
13+
// picking and selecting also works the same
14+
uniform vec4 picker_color : source_color = vec4(0.9049, 0.5072, 0.0389, 1);

colors_shader.png

319 KB
Loading

project.godot

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ config/icon="res://icon.png"
1818

1919
enabled=PackedStringArray("res://addons/ColorPreview/plugin.cfg")
2020

21+
[filesystem]
22+
23+
import/blender/enabled=false
24+
import/fbx/enabled=false
25+
2126
[physics]
2227

2328
common/enable_pause_aware_picking=true

0 commit comments

Comments
 (0)