From 95a737029ad1f8dcfd7ade72e08513832761a3d3 Mon Sep 17 00:00:00 2001 From: RodZill4 Date: Sat, 8 Sep 2018 12:25:28 +0200 Subject: [PATCH] Started adding the "remote node" Started adding the "remote" node, that can control important parameters of the graph and save/restore configurations of groups of parameters. This should help creating easily configurable materials. Added new "mosaic" example --- addons/material_maker/examples/bricks.ptex | 2 +- addons/material_maker/examples/mosaic.ptex | 1 + addons/material_maker/icons/add.png | Bin 0 -> 203 bytes addons/material_maker/icons/add_config.png | Bin 0 -> 458 bytes addons/material_maker/icons/add_link.png | Bin 0 -> 505 bytes addons/material_maker/icons/config.png | Bin 0 -> 441 bytes addons/material_maker/icons/icons.svg | 121 +++++++++++++++ addons/material_maker/icons/link.png | Bin 0 -> 476 bytes addons/material_maker/icons/remove.png | Bin 0 -> 399 bytes addons/material_maker/library/base.json | 4 + addons/material_maker/main_window.tscn | 2 +- addons/material_maker/nodes/remote.gd | 63 ++++++++ addons/material_maker/nodes/remote.tscn | 139 ++++++++++++++++++ addons/material_maker/widgets/line_dialog.gd | 11 +- .../material_maker/widgets/line_dialog.tscn | 2 + .../widgets/linked_widgets/config_control.gd | 121 +++++++++++++++ .../linked_widgets/config_control.tscn | 22 +++ .../widgets/linked_widgets/link.gd | 22 +++ .../widgets/linked_widgets/linked_control.gd | 52 +++++++ .../linked_widgets/linked_control.tscn | 22 +++ .../linked_widgets/linked_control_base.gd | 134 +++++++++++++++++ .../linked_widgets/linked_control_buttons.gd | 15 ++ .../linked_control_buttons.tscn | 75 ++++++++++ 23 files changed, 805 insertions(+), 3 deletions(-) create mode 100644 addons/material_maker/examples/mosaic.ptex create mode 100644 addons/material_maker/icons/add.png create mode 100644 addons/material_maker/icons/add_config.png create mode 100644 addons/material_maker/icons/add_link.png create mode 100644 addons/material_maker/icons/config.png create mode 100644 addons/material_maker/icons/icons.svg create mode 100644 addons/material_maker/icons/link.png create mode 100644 addons/material_maker/icons/remove.png create mode 100644 addons/material_maker/nodes/remote.gd create mode 100644 addons/material_maker/nodes/remote.tscn create mode 100644 addons/material_maker/widgets/linked_widgets/config_control.gd create mode 100644 addons/material_maker/widgets/linked_widgets/config_control.tscn create mode 100644 addons/material_maker/widgets/linked_widgets/link.gd create mode 100644 addons/material_maker/widgets/linked_widgets/linked_control.gd create mode 100644 addons/material_maker/widgets/linked_widgets/linked_control.tscn create mode 100644 addons/material_maker/widgets/linked_widgets/linked_control_base.gd create mode 100644 addons/material_maker/widgets/linked_widgets/linked_control_buttons.gd create mode 100644 addons/material_maker/widgets/linked_widgets/linked_control_buttons.tscn 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 0000000000000000000000000000000000000000..c4b0c58264887f7688659ba3639e06f824dc8f17 GIT binary patch literal 203 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`EX7WqAsj$Z!;#Vf4nJ zFvWr}9gP2NC6djc)B=- zSo9_*9ANzS|G)ifd!{pomiBQ@XW5u=g@KLD%|jBqUh$oNo9(Wk*Aj r{ssdBgEPkz-KU5bG+mtH;m*w9CZ#p~x!Se>pqUJwu6{1-oD!M=mt{=GE?~U-z?e>X7;t`jtO( zsk4zmL4A$-(U_YFf)=1JU=KiJ#3@hwcjBfb7%Tv}Z;V6!4e%ltym>Muv2_`iU vql-1oI~m#3TqW77d7?dh#{*3K*O=rV-*#qo_p?j&wGp zE+0H6-T%9!JKyXB&Lu6T1bUT}l{9Mgi=+cdbxCiM?ggCE8CyUG$N@VknxuX2RiN$~ zUqHd_Wjw{;$}evas9B>0Ot@ar4YhzOupGC)Vkft83CsZtz^&sq|7;2<0nL<{5e=VC zKmm9PqK_UX$1%a4C8z*PKsgL-1N-5M^WLBz7;tqS_%vY)m@ + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + diff --git a/addons/material_maker/icons/link.png b/addons/material_maker/icons/link.png new file mode 100644 index 0000000000000000000000000000000000000000..062da20f7f97db90875adda5c80ac2af7c8b4f93 GIT binary patch literal 476 zcmV<20VDp2P)AMzw&cHc6N@FWi<_nMORVAsPU9Z_6yL*cfpz@ALix7p<7stwSi_laf%|w@ znRf6*Gs5;w_HYNIH8@&=d&P8s=XhL-w0euVZr8K;SeZ7;6>9J&9^orK)%=MhcavO9 z@;AwYB#TL|CwZUbWRed_dP$a&oJz9NJ;C?V<<^jKO=w2h>I=rZre7s_wTg{sM%b_3 zWO)EC=GVoviOaa6`E6TmVR`_p3QTDhqpN+*B8~kMu8N%3tY{D0c!9|y!6b)A_cP*8 SW+`d_00005Ph~N5bs!<%GMmXp5Cp*wmcW4EMqT(V zic!fz@Ve+2GkMLzhF)}a-BY)#3jjf(7>^3!f-_6*wcPJimKB58{Za0c`^OeU?zLik z>vNw~mK6%2=>ut}g!+s)?GPFi<6iDBCl?bZi{f-X7=U8jBOQTiRP+<+2D2~B8l+;l zF>8^ot?Qm_sIm;{fNvmQ5(C&Mc@4svc)8Ot?iE5i=}GE~`(c`&%?a9JHjhJwwA%#8 zy~eCz{N}&qnB7k2WB?4}aktY?ypPWL6q2oq&064!EV~3=S0P(NGPv6sw*QYZ") + 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"] + +