diff --git a/addons/material_maker/examples/bricks.ptex b/addons/material_maker/examples/bricks.ptex index 98adb62..a8957c6 100644 --- a/addons/material_maker/examples/bricks.ptex +++ b/addons/material_maker/examples/bricks.ptex @@ -1 +1 @@ -{"connections":[{"from":"Perlin","from_port":0,"to":"Warp","to_port":1},{"from":"Warp","from_port":0,"to":"colorize_2","to_port":0},{"from":"colorize_2","from_port":0,"to":"blend_0","to_port":2},{"from":"colorize_1","from_port":0,"to":"blend_0","to_port":0},{"from":"colorize_0","from_port":0,"to":"blend_0","to_port":1},{"from":"blend_0","from_port":0,"to":"Material","to_port":0},{"from":"colorize_2","from_port":0,"to":"colorize_4","to_port":0},{"from":"colorize_4","from_port":0,"to":"Material","to_port":2},{"from":"Bricks","from_port":0,"to":"Warp","to_port":0},{"from":"blend_1","from_port":0,"to":"colorize_1","to_port":0},{"from":"Bricks","from_port":1,"to":"blend_1","to_port":1},{"from":"Warp","from_port":0,"to":"blend_2","to_port":0},{"from":"Perlin","from_port":0,"to":"blend_2","to_port":1},{"from":"blend_2","from_port":0,"to":"colorize_3","to_port":0},{"from":"blend_2","from_port":0,"to":"colorize_6","to_port":0},{"from":"Perlin","from_port":0,"to":"blend_1","to_port":0},{"from":"Perlin","from_port":0,"to":"colorize_0","to_port":0},{"from":"uniform_0","from_port":0,"to":"Material","to_port":1},{"from":"colorize_3","from_port":0,"to":"Material","to_port":5},{"from":"uniform_0","from_port":0,"to":"combine_0","to_port":0},{"from":"colorize_4","from_port":0,"to":"combine_0","to_port":1},{"from":"combine_0","from_port":0,"to":"export_0","to_port":0},{"from":"normal_map_0","from_port":0,"to":"Material","to_port":4},{"from":"colorize_6","from_port":0,"to":"normal_map_0","to_port":0}],"nodes":[{"gradient":[{"b":0,"g":0,"pos":0,"r":0},{"b":1,"g":1,"pos":1,"r":1}],"name":"colorize_0","node_position":{"x":560.943665,"y":50},"type":"colorize"},{"gradient":[{"b":0.0016,"g":0.0016,"pos":0,"r":0.307292},{"b":0,"g":0.180135,"pos":0.2,"r":0.606771},{"b":0,"g":0,"pos":0.345455,"r":0.3125},{"b":0,"g":0.19869,"pos":0.545455,"r":0.669271},{"b":0.019368,"g":0.060224,"pos":0.745455,"r":0.309896},{"b":0,"g":0.180135,"pos":1,"r":0.606771}],"name":"colorize_1","node_position":{"x":562.943665,"y":-65},"type":"colorize"},{"amount":0.04,"name":"Warp","node_position":{"x":384,"y":10.75},"type":"warp"},{"albedo_color":{"a":1,"b":1,"g":1,"r":1,"type":"Color"},"ao_light_affect":1,"depth_scale":0,"emission_energy":1,"metallic":1,"name":"Material","node_position":{"x":1081,"y":208},"normal_scale":1,"resolution":1,"roughness":1,"type":"material"},{"amount":0.5,"blend_type":0,"name":"blend_2","node_position":{"x":536,"y":331},"type":"blend"},{"amount":0.5,"blend_type":0,"name":"blend_0","node_position":{"x":836.943726,"y":-71},"type":"blend"},{"gradient":[{"b":0,"g":0,"pos":0,"r":0},{"b":1,"g":1,"pos":0.1,"r":1}],"name":"colorize_2","node_position":{"x":544.943665,"y":159},"type":"colorize"},{"amount":0.5,"blend_type":6,"name":"blend_1","node_position":{"x":349,"y":215},"type":"blend"},{"color":{"a":1,"b":0,"g":0,"r":0,"type":"Color"},"name":"uniform_0","node_position":{"x":764,"y":164},"type":"uniform"},{"name":"combine_0","node_position":{"x":896,"y":86},"type":"combine"},{"name":"export_0","node_position":{"x":1050,"y":79},"resolution":1,"suffix":"mr","type":"export"},{"bevel":0.2,"columns":3,"mortar":0.05,"name":"Bricks","node_position":{"x":69,"y":-46},"pattern":0,"repeat":1,"row_offset":0.5,"rows":6,"type":"bricks"},{"iterations":6,"name":"Perlin","node_position":{"x":70,"y":192},"persistence":0.85,"scale_x":4,"scale_y":4,"type":"perlin"},{"gradient":[{"b":1,"g":1,"pos":0,"r":1},{"b":0.546875,"g":0.546875,"pos":1,"r":0.546875}],"name":"colorize_4","node_position":{"x":711,"y":215},"type":"colorize"},{"gradient":[{"b":1,"g":1,"pos":0,"r":1},{"b":0,"g":0,"pos":1,"r":0}],"name":"colorize_6","node_position":{"x":708,"y":289},"type":"colorize"},{"gradient":[{"b":0.838542,"g":0.838542,"pos":0.190909,"r":0.838542},{"b":1,"g":1,"pos":0.536364,"r":1}],"name":"colorize_3","node_position":{"x":711,"y":361},"type":"colorize"},{"amount":0.35,"name":"normal_map_0","node_position":{"x":881.045654,"y":309.691162},"size":4,"type":"normal_map"}]} \ No newline at end of file +{"connections":[{"from":"Perlin","from_port":0,"to":"Warp","to_port":1},{"from":"Warp","from_port":0,"to":"colorize_2","to_port":0},{"from":"colorize_2","from_port":0,"to":"blend_0","to_port":2},{"from":"colorize_0","from_port":0,"to":"blend_0","to_port":1},{"from":"blend_0","from_port":0,"to":"Material","to_port":0},{"from":"colorize_2","from_port":0,"to":"colorize_4","to_port":0},{"from":"colorize_4","from_port":0,"to":"Material","to_port":2},{"from":"Bricks","from_port":0,"to":"Warp","to_port":0},{"from":"blend_1","from_port":0,"to":"colorize_1","to_port":0},{"from":"Bricks","from_port":1,"to":"blend_1","to_port":1},{"from":"Warp","from_port":0,"to":"blend_2","to_port":0},{"from":"Perlin","from_port":0,"to":"blend_2","to_port":1},{"from":"blend_2","from_port":0,"to":"colorize_3","to_port":0},{"from":"blend_2","from_port":0,"to":"colorize_6","to_port":0},{"from":"Perlin","from_port":0,"to":"blend_1","to_port":0},{"from":"Perlin","from_port":0,"to":"colorize_0","to_port":0},{"from":"uniform_0","from_port":0,"to":"Material","to_port":1},{"from":"colorize_3","from_port":0,"to":"Material","to_port":5},{"from":"uniform_0","from_port":0,"to":"combine_0","to_port":0},{"from":"colorize_4","from_port":0,"to":"combine_0","to_port":1},{"from":"combine_0","from_port":0,"to":"export_0","to_port":0},{"from":"normal_map_0","from_port":0,"to":"Material","to_port":4},{"from":"colorize_6","from_port":0,"to":"normal_map_0","to_port":0},{"from":"colorize_1","from_port":0,"to":"adjust_hsv_0","to_port":0},{"from":"adjust_hsv_0","from_port":0,"to":"blend_0","to_port":0}],"nodes":[{"gradient":[{"b":0,"g":0,"pos":0,"r":0},{"b":1,"g":1,"pos":1,"r":1}],"name":"colorize_0","node_position":{"x":560.943665,"y":50},"type":"colorize"},{"albedo_color":{"a":1,"b":1,"g":1,"r":1,"type":"Color"},"ao_light_affect":1,"depth_scale":0,"emission_energy":1,"metallic":1,"name":"Material","node_position":{"x":1081,"y":208},"normal_scale":1,"resolution":1,"roughness":1,"type":"material"},{"amount":0.5,"blend_type":0,"name":"blend_2","node_position":{"x":536,"y":331},"type":"blend"},{"amount":0.5,"blend_type":0,"name":"blend_0","node_position":{"x":836.943726,"y":-71},"type":"blend"},{"gradient":[{"b":0,"g":0,"pos":0,"r":0},{"b":1,"g":1,"pos":0.1,"r":1}],"name":"colorize_2","node_position":{"x":544.943665,"y":159},"type":"colorize"},{"color":{"a":1,"b":0,"g":0,"r":0,"type":"Color"},"name":"uniform_0","node_position":{"x":764,"y":164},"type":"uniform"},{"name":"combine_0","node_position":{"x":896,"y":86},"type":"combine"},{"name":"export_0","node_position":{"x":1050,"y":79},"resolution":1,"suffix":"mr","type":"export"},{"iterations":6,"name":"Perlin","node_position":{"x":70,"y":192},"persistence":0.85,"scale_x":4,"scale_y":4,"type":"perlin"},{"gradient":[{"b":1,"g":1,"pos":0,"r":1},{"b":0.546875,"g":0.546875,"pos":1,"r":0.546875}],"name":"colorize_4","node_position":{"x":711,"y":215},"type":"colorize"},{"gradient":[{"b":1,"g":1,"pos":0,"r":1},{"b":0,"g":0,"pos":1,"r":0}],"name":"colorize_6","node_position":{"x":708,"y":289},"type":"colorize"},{"gradient":[{"b":0.838542,"g":0.838542,"pos":0.145455,"r":0.838542},{"b":1,"g":1,"pos":0.536364,"r":1}],"name":"colorize_3","node_position":{"x":711,"y":361},"type":"colorize"},{"amount":0.35,"name":"normal_map_0","node_position":{"x":881.045654,"y":309.691162},"size":4,"type":"normal_map"},{"amount":0.04,"name":"Warp","node_position":{"x":306,"y":55.75},"type":"warp"},{"hue":0,"name":"adjust_hsv_0","node_position":{"x":583.224792,"y":-74.268188},"saturation":1,"type":"adjust_hsv","value":1},{"gradient":[{"b":0.0016,"g":0.0016,"pos":0,"r":0.307292},{"b":0,"g":0.180135,"pos":0.2,"r":0.606771},{"b":0,"g":0,"pos":0.345455,"r":0.3125},{"b":0,"g":0.19869,"pos":0.545455,"r":0.669271},{"b":0.019368,"g":0.060224,"pos":0.745455,"r":0.309896},{"b":0,"g":0.180135,"pos":1,"r":0.606771}],"name":"colorize_1","node_position":{"x":406.943665,"y":-80},"type":"colorize"},{"bevel":0.2,"columns":4,"mortar":0.05,"name":"Bricks","node_position":{"x":79,"y":-36},"pattern":0,"repeat":1,"row_offset":0.5,"rows":8,"type":"bricks"},{"amount":0.5,"blend_type":6,"name":"blend_1","node_position":{"x":316,"y":217},"type":"blend"},{"editable":true,"node_position":{"x":496.669189,"y":-340.657043},"type":"remote","widgets":[{"configurations":{"Basket weave":[{"node":"Bricks","value":3,"widget":"pattern"},{"node":"Bricks","value":2,"widget":"repeat"},{"node":"Bricks","value":2,"widget":"rows"},{"node":"Bricks","value":2,"widget":"columns"}],"Herring bone":[{"node":"Bricks","value":2,"widget":"pattern"},{"node":"Bricks","value":2,"widget":"repeat"},{"node":"Bricks","value":2,"widget":"rows"},{"node":"Bricks","value":2,"widget":"columns"}],"Running bond 1":[{"node":"Bricks","value":0,"widget":"pattern"},{"node":"Bricks","value":1,"widget":"repeat"},{"node":"Bricks","value":8,"widget":"rows"},{"node":"Bricks","value":4,"widget":"columns"}],"Running bond 2":[{"node":"Bricks","value":1,"widget":"pattern"},{"node":"Bricks","value":1,"widget":"repeat"},{"node":"Bricks","value":8,"widget":"rows"},{"node":"Bricks","value":4,"widget":"columns"}],"Spanish bond":[{"node":"Bricks","value":4,"widget":"pattern"},{"node":"Bricks","value":3,"widget":"repeat"},{"node":"Bricks","value":2,"widget":"rows"},{"node":"Bricks","value":2,"widget":"columns"}]},"linked_widgets":[{"node":"Bricks","widget":"pattern"},{"node":"Bricks","widget":"repeat"},{"node":"Bricks","widget":"rows"},{"node":"Bricks","widget":"columns"}],"type":"config_control"},{"linked_widgets":[{"node":"adjust_hsv_0","widget":"hue"}],"type":"linked_control"},{"linked_widgets":[{"node":"adjust_hsv_0","widget":"saturation"}],"type":"linked_control"},{"linked_widgets":[{"node":"adjust_hsv_0","widget":"value"}],"type":"linked_control"}]}]} \ No newline at end of file diff --git a/addons/material_maker/examples/mosaic.ptex b/addons/material_maker/examples/mosaic.ptex new file mode 100644 index 0000000..b307d96 --- /dev/null +++ b/addons/material_maker/examples/mosaic.ptex @@ -0,0 +1 @@ +{"connections":[{"from":"blend_0","from_port":0,"to":"Material","to_port":0},{"from":"voronoi_0","from_port":2,"to":"blend_0","to_port":1},{"from":"voronoi_0","from_port":1,"to":"colorize_0","to_port":0},{"from":"colorize_0","from_port":0,"to":"blend_0","to_port":0},{"from":"voronoi_0","from_port":1,"to":"colorize_1","to_port":0},{"from":"colorize_1","from_port":0,"to":"normal_map_0","to_port":0},{"from":"normal_map_0","from_port":0,"to":"Material","to_port":4},{"from":"uniform_0","from_port":0,"to":"Material","to_port":1},{"from":"voronoi_0","from_port":1,"to":"colorize_2","to_port":0},{"from":"colorize_2","from_port":0,"to":"Material","to_port":2}],"nodes":[{"intensity":1,"name":"voronoi_0","node_position":{"x":-543.5,"y":-11.5},"scale_x":32,"scale_y":32,"type":"voronoi"},{"amount":0.5,"name":"normal_map_0","node_position":{"x":-165.5,"y":133.5},"size":5,"type":"normal_map"},{"albedo_color":{"a":1,"b":1,"g":1,"r":1,"type":"Color"},"ao_light_affect":1,"depth_scale":1,"emission_energy":1,"metallic":1,"name":"Material","node_position":{"x":30,"y":-44},"normal_scale":1,"resolution":1,"roughness":1,"type":"material"},{"gradient":[{"b":1,"g":1,"pos":0.045455,"r":1},{"b":0,"g":0,"pos":0.109091,"r":0}],"name":"colorize_1","node_position":{"x":-349.5,"y":138.5},"type":"colorize"},{"gradient":[{"b":1,"g":1,"pos":0.063636,"r":1},{"b":0,"g":0,"pos":0.072727,"r":0}],"name":"colorize_0","node_position":{"x":-317.5,"y":-169.5},"type":"colorize"},{"color":{"a":1,"b":0.109375,"g":0.109375,"r":0.109375,"type":"Color"},"name":"uniform_0","node_position":{"x":-127.5,"y":-3.5},"type":"uniform"},{"gradient":[{"b":1,"g":1,"pos":0,"r":1},{"b":0.109375,"g":0.109375,"pos":0.236364,"r":0.109375}],"name":"colorize_2","node_position":{"x":-306.5,"y":39.5},"type":"colorize"},{"amount":1,"blend_type":3,"name":"blend_0","node_position":{"x":-294.5,"y":-94.5},"type":"blend"}]} \ No newline at end of file diff --git a/addons/material_maker/icons/add.png b/addons/material_maker/icons/add.png new file mode 100644 index 0000000..c4b0c58 Binary files /dev/null and b/addons/material_maker/icons/add.png differ diff --git a/addons/material_maker/icons/add_config.png b/addons/material_maker/icons/add_config.png new file mode 100644 index 0000000..358c235 Binary files /dev/null and b/addons/material_maker/icons/add_config.png differ diff --git a/addons/material_maker/icons/add_link.png b/addons/material_maker/icons/add_link.png new file mode 100644 index 0000000..6555533 Binary files /dev/null and b/addons/material_maker/icons/add_link.png differ diff --git a/addons/material_maker/icons/config.png b/addons/material_maker/icons/config.png new file mode 100644 index 0000000..c565d96 Binary files /dev/null and b/addons/material_maker/icons/config.png differ diff --git a/addons/material_maker/icons/icons.svg b/addons/material_maker/icons/icons.svg new file mode 100644 index 0000000..4a56982 --- /dev/null +++ b/addons/material_maker/icons/icons.svg @@ -0,0 +1,121 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + diff --git a/addons/material_maker/icons/link.png b/addons/material_maker/icons/link.png new file mode 100644 index 0000000..062da20 Binary files /dev/null and b/addons/material_maker/icons/link.png differ diff --git a/addons/material_maker/icons/remove.png b/addons/material_maker/icons/remove.png new file mode 100644 index 0000000..8fceffe Binary files /dev/null and b/addons/material_maker/icons/remove.png differ diff --git a/addons/material_maker/library/base.json b/addons/material_maker/library/base.json index 2deb903..e55df49 100644 --- a/addons/material_maker/library/base.json +++ b/addons/material_maker/library/base.json @@ -197,5 +197,9 @@ { "tree_item":"Miscellaneous/Export", "type":"export" + }, + { + "tree_item":"Miscellaneous/Remote", + "type":"remote" } ]} \ No newline at end of file diff --git a/addons/material_maker/main_window.tscn b/addons/material_maker/main_window.tscn index 5ae8cf6..43850a8 100644 --- a/addons/material_maker/main_window.tscn +++ b/addons/material_maker/main_window.tscn @@ -6,7 +6,7 @@ [ext_resource path="res://addons/material_maker/widgets/tabs.gd" type="Script" id=4] [ext_resource path="res://addons/material_maker/renderer.tscn" type="PackedScene" id=5] -[node name="MainWindow" type="Panel" index="0"] +[node name="MainWindow" type="Panel"] anchor_left = 0.0 anchor_top = 0.0 diff --git a/addons/material_maker/nodes/remote.gd b/addons/material_maker/nodes/remote.gd new file mode 100644 index 0000000..0808b6f --- /dev/null +++ b/addons/material_maker/nodes/remote.gd @@ -0,0 +1,63 @@ +tool +extends "res://addons/material_maker/node_base.gd" + +const LinkedControl = preload("res://addons/material_maker/widgets/linked_widgets/linked_control.tscn") +const ConfigControl = preload("res://addons/material_maker/widgets/linked_widgets/config_control.tscn") + +func _ready(): + pass + +func _get_shader_code(uv): + var rv = { defs="", code="" } + rv.rgb = "vec3(1.0)" + return rv + +func add_control(widget): + var controls = widget.get_associated_controls() + $Controls.add_child(controls.label) + $Controls.add_child(widget) + $Controls.add_child(controls.buttons) + + +func _on_AddLink_pressed(): + var widget = LinkedControl.instance() + add_control(widget) + widget.pick_linked() + +func _on_AddConfig_pressed(): + var widget = ConfigControl.instance() + add_control(widget) + widget.pick_linked() + +func _on_Remote_resize_request(new_minsize): + print("_on_Remote_resize_request") + rect_size = new_minsize + +func _on_HBoxContainer_minimum_size_changed(): + print("_on_HBoxContainer_minimum_size_changed "+str($HBoxContainer.rect_min_size)) + +func serialize(): + var widgets = [] + for i in range(1, $Controls.get_child_count(), 3): + widgets.append($Controls.get_child(i).serialize()) + var data = { type="remote", node_position={x=offset.x,y=offset.y}, editable=true, widgets=widgets } + return data + +func deserialize(data): + if data.has("node_position"): + offset.x = data.node_position.x + offset.y = data.node_position.y + call_deferred("do_deserialize", data) + +func do_deserialize(data): + if data.has("widgets"): + for w in data.widgets: + var widget + if w.type == "linked_control": + widget = LinkedControl.instance() + elif w.type == "config_control": + widget = ConfigControl.instance() + else: + continue + add_control(widget) + widget.deserialize(w) diff --git a/addons/material_maker/nodes/remote.tscn b/addons/material_maker/nodes/remote.tscn new file mode 100644 index 0000000..e19728c --- /dev/null +++ b/addons/material_maker/nodes/remote.tscn @@ -0,0 +1,139 @@ +[gd_scene load_steps=5 format=2] + +[ext_resource path="res://addons/material_maker/nodes/remote.gd" type="Script" id=1] +[ext_resource path="res://addons/material_maker/icons/link.png" type="Texture" id=2] +[ext_resource path="res://addons/material_maker/icons/config.png" type="Texture" id=3] + +[sub_resource type="Theme" id=1] + + +[node name="Remote" type="GraphNode"] + +anchor_left = 0.0 +anchor_top = 0.0 +anchor_right = 0.0 +anchor_bottom = 0.0 +margin_right = 95.0 +margin_bottom = 55.0 +rect_pivot_offset = Vector2( 0, 0 ) +rect_clip_content = false +mouse_filter = 1 +mouse_default_cursor_shape = 0 +size_flags_horizontal = 1 +size_flags_vertical = 1 +theme = SubResource( 1 ) +title = "Remote" +offset = Vector2( 0, 0 ) +show_close = true +resizable = false +selected = false +comment = false +overlay = 0 +slot/0/left_enabled = false +slot/0/left_type = 0 +slot/0/left_color = Color( 0.5, 0.5, 1, 1 ) +slot/0/right_enabled = false +slot/0/right_type = 0 +slot/0/right_color = Color( 0.5, 0.5, 1, 1 ) +slot/1/left_enabled = false +slot/1/left_type = 0 +slot/1/left_color = Color( 1, 1, 1, 1 ) +slot/1/right_enabled = false +slot/1/right_type = 0 +slot/1/right_color = Color( 1, 1, 1, 1 ) +script = ExtResource( 1 ) +_sections_unfolded = [ "Theme", "slot" ] + +[node name="Controls" type="GridContainer" parent="." index="0"] + +anchor_left = 0.0 +anchor_top = 0.0 +anchor_right = 0.0 +anchor_bottom = 0.0 +margin_left = 16.0 +margin_top = 24.0 +margin_right = 79.0 +margin_bottom = 24.0 +rect_pivot_offset = Vector2( 0, 0 ) +rect_clip_content = false +mouse_filter = 1 +mouse_default_cursor_shape = 0 +size_flags_horizontal = 1 +size_flags_vertical = 1 +columns = 3 +_sections_unfolded = [ "Hint" ] + +[node name="HBoxContainer" type="HBoxContainer" parent="." index="1"] + +anchor_left = 0.0 +anchor_top = 0.0 +anchor_right = 0.0 +anchor_bottom = 0.0 +margin_left = 16.0 +margin_top = 24.0 +margin_right = 79.0 +margin_bottom = 46.0 +rect_pivot_offset = Vector2( 0, 0 ) +rect_clip_content = false +mouse_filter = 1 +mouse_default_cursor_shape = 0 +size_flags_horizontal = 1 +size_flags_vertical = 1 +alignment = 0 + +[node name="AddLink" type="Button" parent="HBoxContainer" index="0"] + +anchor_left = 0.0 +anchor_top = 0.0 +anchor_right = 0.0 +anchor_bottom = 0.0 +margin_right = 28.0 +margin_bottom = 22.0 +rect_pivot_offset = Vector2( 0, 0 ) +rect_clip_content = false +hint_tooltip = "Add linked control" +focus_mode = 2 +mouse_filter = 0 +mouse_default_cursor_shape = 0 +size_flags_horizontal = 0 +size_flags_vertical = 1 +toggle_mode = false +enabled_focus_mode = 2 +shortcut = null +group = null +icon = ExtResource( 2 ) +flat = false +align = 1 +_sections_unfolded = [ "Hint", "Rect", "Size Flags" ] + +[node name="AddConfig" type="Button" parent="HBoxContainer" index="1"] + +anchor_left = 0.0 +anchor_top = 0.0 +anchor_right = 0.0 +anchor_bottom = 0.0 +margin_left = 32.0 +margin_right = 60.0 +margin_bottom = 22.0 +rect_pivot_offset = Vector2( 0, 0 ) +rect_clip_content = false +hint_tooltip = "Add configurations" +focus_mode = 2 +mouse_filter = 0 +mouse_default_cursor_shape = 0 +size_flags_horizontal = 1 +size_flags_vertical = 1 +toggle_mode = false +enabled_focus_mode = 2 +shortcut = null +group = null +icon = ExtResource( 3 ) +flat = false +align = 1 +_sections_unfolded = [ "Hint" ] + +[connection signal="pressed" from="HBoxContainer/AddLink" to="." method="_on_AddLink_pressed"] + +[connection signal="pressed" from="HBoxContainer/AddConfig" to="." method="_on_AddConfig_pressed"] + + diff --git a/addons/material_maker/widgets/line_dialog.gd b/addons/material_maker/widgets/line_dialog.gd index bebcb6e..add7dc0 100644 --- a/addons/material_maker/widgets/line_dialog.gd +++ b/addons/material_maker/widgets/line_dialog.gd @@ -6,6 +6,15 @@ signal ok func _ready(): pass +func set_texts(title, label): + window_title = title + $VBoxContainer/Label.text = label + $VBoxContainer/LineEdit.grab_focus() + $VBoxContainer/LineEdit.grab_click_focus() + func _on_OK_pressed(): - emit_signal("ok", $VBoxContainer/LineEdit.text) + _on_LineEdit_text_entered($VBoxContainer/LineEdit.text) + +func _on_LineEdit_text_entered(new_text): + emit_signal("ok", new_text) queue_free() diff --git a/addons/material_maker/widgets/line_dialog.tscn b/addons/material_maker/widgets/line_dialog.tscn index d0573c1..d008b5d 100644 --- a/addons/material_maker/widgets/line_dialog.tscn +++ b/addons/material_maker/widgets/line_dialog.tscn @@ -146,6 +146,8 @@ flat = false align = 1 _sections_unfolded = [ "Rect" ] +[connection signal="text_entered" from="VBoxContainer/LineEdit" to="." method="_on_LineEdit_text_entered"] + [connection signal="pressed" from="VBoxContainer/HBoxContainer/OK" to="." method="_on_OK_pressed"] [connection signal="pressed" from="VBoxContainer/HBoxContainer/Cancel" to="." method="queue_free"] diff --git a/addons/material_maker/widgets/linked_widgets/config_control.gd b/addons/material_maker/widgets/linked_widgets/config_control.gd new file mode 100644 index 0000000..dd9562c --- /dev/null +++ b/addons/material_maker/widgets/linked_widgets/config_control.gd @@ -0,0 +1,121 @@ +tool +extends "res://addons/material_maker/widgets/linked_widgets/linked_control_base.gd" + +var configurations = {} + +var current = null +onready var button = null + +func _ready(): + update_options() + +func update_options(): + # Seems "clear" might cause crashes, so we create a new button... + if button != null: + button.hide() + button.queue_free() + button = OptionButton.new() + button.connect("item_selected", self, "_on_item_selected") + button.connect("mouse_entered", self, "_on_mouse_entered") + button.connect("mouse_exited", self, "_on_mouse_exited") + add_child(button) + # Create list of configurations + var keys = configurations.keys() + keys.sort() + # if no configuration is selected, select the first one + if current == null and !keys.empty(): + current = keys[0] + for c in keys: + button.add_item(c) + button.add_separator() + button.add_item("") + if current != null: + button.add_separator() + button.add_item("") + button.add_item("") + for i in range(button.get_item_count()): + if button.get_item_text(i) == current: + button.selected = i + break + +func add_linked(node, widget): + linked_widgets.append({ node=node, widget=widget }) + +func apply_configuration(c): + for w in configurations[c]: + w.widget.set(WIDGETS[get_widget_type(w.widget)].value_attr , w.value) + w.node.set(w.widget.name, w.value) + var graph_node = get_parent() + while !(graph_node is GraphNode): + graph_node = graph_node.get_parent() + graph_node.update_shaders() + +func do_update_configuration(name): + var configuration = [] + for w in linked_widgets: + configuration.append({ node=w.node, widget=w.widget, value=w.node.get(w.widget.name) }) + configurations[name] = configuration + current = name + update_options() + +func update_configuration(): + var dialog = preload("res://addons/material_maker/widgets/line_dialog.tscn").instance() + add_child(dialog) + dialog.set_texts("Configuration", "Enter a name for the new configuration") + dialog.connect("ok", self, "do_update_configuration", []) + dialog.popup_centered() + +func _on_item_selected(ID): + var count = configurations.keys().size() + if ID >= 0 && ID < count: + current = button.get_item_text(ID) + update_options() + apply_configuration(current) + elif ID == count+1: + button.selected = 0 + update_configuration() + elif ID == count+3: + do_update_configuration(current) + else: + configurations.erase(current) + current = null + update_options() + +func serialize(): + var data = .serialize() + data.type = "config_control" + var data_configurations = {} + var keys = configurations.keys() + for k in keys: + var c = configurations[k] + var data_configuration = [] + for e in c: + data_configuration.append({ node=e.node.name, widget=e.widget.name, value=e.value }) + data_configurations[k] = data_configuration + data.configurations = data_configurations + return data + +func deserialize(data): + .deserialize(data) + graph_edit = get_parent() + while graph_edit != null && !(graph_edit is GraphEdit): + graph_edit = graph_edit.get_parent() + if graph_edit == null: + return + var keys = data.configurations.keys() + for k in keys: + var c = data.configurations[k] + var configuration = [] + for e in c: + var node = graph_edit.get_node(e.node) + var widget = null + for w in node.property_widgets: + if w.name == e.widget: + widget = w + break + configuration.append({ node=node, widget=widget, value=e.value }) + configurations[k] = configuration + update_options() + + + diff --git a/addons/material_maker/widgets/linked_widgets/config_control.tscn b/addons/material_maker/widgets/linked_widgets/config_control.tscn new file mode 100644 index 0000000..df482b1 --- /dev/null +++ b/addons/material_maker/widgets/linked_widgets/config_control.tscn @@ -0,0 +1,22 @@ +[gd_scene load_steps=2 format=2] + +[ext_resource path="res://addons/material_maker/widgets/linked_widgets/config_control.gd" type="Script" id=1] + +[node name="ConfigControl" type="VBoxContainer"] + +anchor_left = 0.0 +anchor_top = 0.0 +anchor_right = 0.0 +anchor_bottom = 0.0 +rect_min_size = Vector2( 70, 0 ) +rect_pivot_offset = Vector2( 0, 0 ) +rect_clip_content = false +mouse_filter = 1 +mouse_default_cursor_shape = 0 +size_flags_horizontal = 3 +size_flags_vertical = 1 +alignment = 0 +script = ExtResource( 1 ) +_sections_unfolded = [ "Rect", "Size Flags" ] + + diff --git a/addons/material_maker/widgets/linked_widgets/link.gd b/addons/material_maker/widgets/linked_widgets/link.gd new file mode 100644 index 0000000..18e5a3e --- /dev/null +++ b/addons/material_maker/widgets/linked_widgets/link.gd @@ -0,0 +1,22 @@ +extends Node2D + +var end +var source = null +var target = null + +func closest(rect, point): + return Vector2(max(rect.position.x, min(rect.end.x, point.x)), max(rect.position.y, min(rect.end.y, point.y))) + +func _draw(): + var start = source.rect_global_position+0.5*source.rect_size*source.get_global_transform().get_scale() + var color = Color(1, 0.5, 0.5, 0.5) + var rect + if target != null: + color = Color(0.5, 1, 0.5, 0.5) + rect = Rect2(target.rect_global_position, target.rect_size*target.get_global_transform().get_scale()) + draw_rect(rect, color, false) + end = closest(rect, start) + rect = Rect2(source.rect_global_position, source.rect_size*source.get_global_transform().get_scale()) + draw_rect(rect, color, false) + start = closest(rect, end) + draw_line(start, end, color, 1, true) diff --git a/addons/material_maker/widgets/linked_widgets/linked_control.gd b/addons/material_maker/widgets/linked_widgets/linked_control.gd new file mode 100644 index 0000000..852a49a --- /dev/null +++ b/addons/material_maker/widgets/linked_widgets/linked_control.gd @@ -0,0 +1,52 @@ +tool +extends "res://addons/material_maker/widgets/linked_widgets/linked_control_base.gd" + +func add_linked(node, widget): + if linked_widgets.empty(): + var new_widget = null + var type + if widget is SpinBox: + new_widget = SpinBox.new() + type = "SpinBox" + elif widget is ColorPickerButton: + new_widget = ColorPickerButton.new() + type = "ColorPickerButton" + elif widget is HSlider: + new_widget = HSlider.new() + type = "HSlider" + elif widget is OptionButton: + new_widget = OptionButton.new() + type = "OptionButton" + for i in range(widget.get_item_count()): + new_widget.add_item(widget.get_item_text(i), widget.get_item_id(i)) + if new_widget != null: + add_child(new_widget) + mirror(new_widget, widget, type) + new_widget.connect("mouse_entered", self, "_on_mouse_entered") + new_widget.connect("mouse_exited", self, "_on_mouse_exited") + new_widget.connect(WIDGETS[type].sig, self, WIDGETS[type].sig_handler) + linked_widgets.append({ node=node, widget=widget }) + +func mirror(to, from, type): + for a in WIDGETS[type].attrs: + to.set(a, from.get(a)) + +func _on_value_changed(v): + for l in linked_widgets: + l.widget.value = v + l.node.set(l.widget.name, v) + +func _on_color_changed(c): + for l in linked_widgets: + l.widget.color = c + l.node.set(l.widget.name, c) + +func _on_item_selected(i): + for l in linked_widgets: + l.widget.selected = i + l.node.set(l.widget.name, i) + +func serialize(): + var data = .serialize() + data.type = "linked_control" + return data diff --git a/addons/material_maker/widgets/linked_widgets/linked_control.tscn b/addons/material_maker/widgets/linked_widgets/linked_control.tscn new file mode 100644 index 0000000..c55268c --- /dev/null +++ b/addons/material_maker/widgets/linked_widgets/linked_control.tscn @@ -0,0 +1,22 @@ +[gd_scene load_steps=2 format=2] + +[ext_resource path="res://addons/material_maker/widgets/linked_widgets/linked_control.gd" type="Script" id=1] + +[node name="LinkedControl" type="VBoxContainer"] + +anchor_left = 0.0 +anchor_top = 0.0 +anchor_right = 0.0 +anchor_bottom = 0.0 +rect_min_size = Vector2( 70, 0 ) +rect_pivot_offset = Vector2( 0, 0 ) +rect_clip_content = false +mouse_filter = 1 +mouse_default_cursor_shape = 0 +size_flags_horizontal = 3 +size_flags_vertical = 1 +alignment = 0 +script = ExtResource( 1 ) +_sections_unfolded = [ "Rect", "Size Flags" ] + + diff --git a/addons/material_maker/widgets/linked_widgets/linked_control_base.gd b/addons/material_maker/widgets/linked_widgets/linked_control_base.gd new file mode 100644 index 0000000..827dca8 --- /dev/null +++ b/addons/material_maker/widgets/linked_widgets/linked_control_base.gd @@ -0,0 +1,134 @@ +tool +extends VBoxContainer + +var label = null +var buttons = null + +var linked_widgets = [] +var links = null + +const Link = preload("res://addons/material_maker/widgets/linked_widgets/link.gd") + +const WIDGETS = { + SpinBox={ attrs=[ "min_value", "max_value", "step", "value" ], value_attr="value", sig="value_changed", sig_handler="_on_value_changed" }, + HSlider={ attrs=[ "min_value", "max_value", "step", "value" ], value_attr="value", sig="value_changed", sig_handler="_on_value_changed" }, + ColorPickerButton={ attrs=[ "edit_alpha", "color" ], value_attr="color", sig="color_changed", sig_handler="_on_color_changed" }, + OptionButton={ attrs=[ "selected" ], value_attr="selected", sig="item_selected", sig_handler="_on_item_selected" } +} + +func get_widget_type(widget): + if widget is SpinBox: + return "SpinBox" + elif widget is ColorPickerButton: + return "ColorPickerButton" + elif widget is OptionButton: + return "OptionButton" + else: + return null + +func _ready(): + set_process_input(false) + +func get_associated_controls(): + label = Label.new() + label.set_text("Unnamed") + buttons = preload("res://addons/material_maker/widgets/linked_widgets/linked_control_buttons.tscn").instance() + buttons.control = self + return { label=label, buttons=buttons } + +func delete(): + var parent = get_parent() + label.queue_free() + buttons.queue_free() + queue_free() + +func _on_mouse_entered(): + _on_mouse_exited() + links = [] + var viewport = get_viewport() + for w in linked_widgets: + var link = Link.new() + link.source = self + link.target = w.widget + viewport.add_child(link) + links.append(link) + +func _on_mouse_exited(): + if links != null: + for l in links: + l.queue_free() + links = null + +# Capture mouse to link to a control + +var link = null +var graph_edit = null +var pointed_control = null + +const Link = preload("res://addons/material_maker/widgets/linked_widgets/link.gd") + +func find_control(gp): + for c in graph_edit.get_children(): + if c is GraphNode: + if c.get("property_widgets") != null: + for w in c.property_widgets: + if Rect2(w.rect_global_position, w.rect_size*w.get_global_transform().get_scale()).has_point(gp): + return { node=c, widget=w } + return null + +func _input(event): + if event is InputEventKey: + if event.scancode == KEY_ESCAPE: + set_process_input(false) + link.queue_free() + link = null + elif event is InputEventMouseMotion: + var control = find_control(event.global_position) + link.end = event.global_position + link.target = control.widget if control != null else null + link.update() + elif event is InputEventMouseButton: + if event.pressed: + if event.button_index == BUTTON_LEFT: + var control = find_control(event.global_position) + if control != null: + add_linked(control.node, control.widget) + set_process_input(false) + link.queue_free() + link = null + get_tree().set_input_as_handled() + +func pick_linked(): + # Verify we are in a graph edit + graph_edit = get_parent() + while graph_edit != null && !(graph_edit is GraphEdit): + graph_edit = graph_edit.get_parent() + if graph_edit == null: + return + # Create line that will be shown when looking for a target + var viewport = get_viewport() + link = Link.new() + link.source = self + link.end = rect_global_position+0.5*rect_size*get_global_transform().get_scale() + viewport.add_child(link) + set_process_input(true) + pointed_control = null + +func serialize(): + var data = { linked_widgets=[] } + for w in linked_widgets: + data.linked_widgets.append( { node=w.node.name, widget=w.widget.name } ) + return data + +func deserialize(data): + if !data.has("linked_widgets"): + return + var graph_edit = get_parent() + while !(graph_edit is GraphEdit): + graph_edit = graph_edit.get_parent() + for w in data.linked_widgets: + var node = graph_edit.get_node(w.node) + if node != null && node.get("property_widgets") != null: + for widget in node.property_widgets: + if widget.name == w.widget: + add_linked(node, widget) diff --git a/addons/material_maker/widgets/linked_widgets/linked_control_buttons.gd b/addons/material_maker/widgets/linked_widgets/linked_control_buttons.gd new file mode 100644 index 0000000..d4fcfdc --- /dev/null +++ b/addons/material_maker/widgets/linked_widgets/linked_control_buttons.gd @@ -0,0 +1,15 @@ +tool +extends HBoxContainer + +var control = null + +func _ready(): + # Called when the node is added to the scene for the first time. + # Initialization here + pass + +func _on_Link_pressed(): + control.pick_linked() + +func _on_Remove_pressed(): + control.delete() diff --git a/addons/material_maker/widgets/linked_widgets/linked_control_buttons.tscn b/addons/material_maker/widgets/linked_widgets/linked_control_buttons.tscn new file mode 100644 index 0000000..df95de9 --- /dev/null +++ b/addons/material_maker/widgets/linked_widgets/linked_control_buttons.tscn @@ -0,0 +1,75 @@ +[gd_scene load_steps=4 format=2] + +[ext_resource path="res://addons/material_maker/widgets/linked_widgets/linked_control_buttons.gd" type="Script" id=1] +[ext_resource path="res://addons/material_maker/icons/link.png" type="Texture" id=2] +[ext_resource path="res://addons/material_maker/icons/remove.png" type="Texture" id=3] + +[node name="Buttons" type="HBoxContainer"] + +anchor_left = 0.0 +anchor_top = 0.0 +anchor_right = 0.0 +anchor_bottom = 0.0 +margin_right = 60.0 +margin_bottom = 22.0 +rect_pivot_offset = Vector2( 0, 0 ) +rect_clip_content = false +mouse_filter = 1 +mouse_default_cursor_shape = 0 +size_flags_horizontal = 1 +size_flags_vertical = 1 +alignment = 0 +script = ExtResource( 1 ) + +[node name="Link" type="Button" parent="." index="0"] + +anchor_left = 0.0 +anchor_top = 0.0 +anchor_right = 0.0 +anchor_bottom = 0.0 +margin_right = 28.0 +margin_bottom = 22.0 +rect_pivot_offset = Vector2( 0, 0 ) +rect_clip_content = false +focus_mode = 2 +mouse_filter = 0 +mouse_default_cursor_shape = 0 +size_flags_horizontal = 1 +size_flags_vertical = 1 +toggle_mode = false +enabled_focus_mode = 2 +shortcut = null +group = null +icon = ExtResource( 2 ) +flat = false +align = 1 + +[node name="Remove" type="Button" parent="." index="1"] + +anchor_left = 0.0 +anchor_top = 0.0 +anchor_right = 0.0 +anchor_bottom = 0.0 +margin_left = 32.0 +margin_right = 60.0 +margin_bottom = 22.0 +rect_pivot_offset = Vector2( 0, 0 ) +rect_clip_content = false +focus_mode = 2 +mouse_filter = 0 +mouse_default_cursor_shape = 0 +size_flags_horizontal = 1 +size_flags_vertical = 1 +toggle_mode = false +enabled_focus_mode = 2 +shortcut = null +group = null +icon = ExtResource( 3 ) +flat = false +align = 1 + +[connection signal="pressed" from="Link" to="." method="_on_Link_pressed"] + +[connection signal="pressed" from="Remove" to="." method="_on_Remove_pressed"] + +