diff --git a/addons/material_maker/engine/gen_graph.gd b/addons/material_maker/engine/gen_graph.gd index 8136463..cd26cd0 100644 --- a/addons/material_maker/engine/gen_graph.gd +++ b/addons/material_maker/engine/gen_graph.gd @@ -10,7 +10,13 @@ var editable : bool = false var transmits_seed : bool = true signal connections_changed(removed_connections, added_connections) +signal hierarchy_changed +func emit_hierarchy_changed(): + var top = self + while top.get_parent() != null and top.get_parent().get_script() == get_script(): + top = top.get_parent() + top.emit_signal("hierarchy_changed") func fix_remotes() -> void: for c in get_children(): @@ -111,6 +117,8 @@ func add_generator(generator : MMGenBase) -> bool: name = generator.name + "_" + str(index) generator.name = name add_child(generator) + if generator.get_script() == get_script(): + emit_hierarchy_changed() return true func remove_generator(generator : MMGenBase) -> bool: @@ -123,6 +131,8 @@ func remove_generator(generator : MMGenBase) -> bool: connections = new_connections remove_child(generator) fix_remotes() + if generator.get_script() == get_script(): + emit_hierarchy_changed() generator.queue_free() return true @@ -130,8 +140,10 @@ func replace_generator(old : MMGenBase, new : MMGenBase) -> void: new.name = old.name new.position = old.position remove_child(old) - old.free() add_child(new) + if old.get_script() == get_script() or new.get_script() == get_script(): + emit_hierarchy_changed() + old.free() func get_connected_inputs(generator) -> Array: var rv : Array = [] @@ -312,10 +324,11 @@ func create_subgraph(gens : Array) -> MMGenGraph: if !found_remote: var gen_parameters = remote_script.new() gen_parameters.name = "gen_parameters" - gen_parameters.position = Vector2(center.x - 200, upper_bound-300) + gen_parameters.position = Vector2(center.x-200, upper_bound-300) new_graph.add_child(gen_parameters) fix_remotes() new_graph.fix_remotes() + emit_hierarchy_changed() return new_graph diff --git a/material_maker/graph_edit.gd b/material_maker/graph_edit.gd index 6138fbd..49d39e2 100644 --- a/material_maker/graph_edit.gd +++ b/material_maker/graph_edit.gd @@ -21,6 +21,7 @@ onready var button_transmits_seed : Button = $GraphUI/SubGraphUI/ButtonTransmits signal save_path_changed signal graph_changed +signal view_updated func _ready() -> void: OS.low_processor_usage_mode = true @@ -151,6 +152,7 @@ func update_view(g) -> void: button_transmits_seed.pressed = generator.transmits_seed else: button_transmits_seed.visible = false + emit_signal("view_updated", generator) func clear_material() -> void: diff --git a/material_maker/main_window.gd b/material_maker/main_window.gd index f95eea5..10e855b 100644 --- a/material_maker/main_window.gd +++ b/material_maker/main_window.gd @@ -314,9 +314,10 @@ func load_material() -> void: func do_load_materials(filenames) -> void: for f in filenames: - do_load_material(f) + do_load_material(f, false) + hierarchy.update_from_graph_edit(get_current_graph_edit()) -func do_load_material(filename) -> void: +func do_load_material(filename : String, update_hierarchy : bool = true) -> void: var graph_edit : MMGraphEdit = get_current_graph_edit() var node_count = 2 # So test below succeeds if graph_edit is null... if graph_edit != null: @@ -330,12 +331,15 @@ func do_load_material(filename) -> void: graph_edit = new_pane() graph_edit.load_file(filename) add_recent(filename) + if update_hierarchy: + hierarchy.update_from_graph_edit(get_current_graph_edit()) func save_material() -> void: var graph_edit : MMGraphEdit = get_current_graph_edit() if graph_edit != null: if graph_edit.save_path != null: graph_edit.save_file(graph_edit.save_path) + add_recent(graph_edit.save_path) else: save_material_as() @@ -524,7 +528,6 @@ func _on_PopupMenu_id_pressed(id) -> void: # Preview func update_preview() -> void: - hierarchy.update_from_graph_edit(get_current_graph_edit()) var status need_update = true if updating: @@ -590,6 +593,7 @@ func _on_Projects_tab_changed(tab) -> void: new_tab.connect("node_selected", self, "on_selected_node_change") current_tab = new_tab update_preview() + hierarchy.update_from_graph_edit(get_current_graph_edit()) func on_group_selected(generator) -> void: var graph_edit : MMGraphEdit = get_current_graph_edit() diff --git a/material_maker/widgets/graph_tree/hierarchy_pane.gd b/material_maker/widgets/graph_tree/hierarchy_pane.gd index a64baaf..919b9d0 100644 --- a/material_maker/widgets/graph_tree/hierarchy_pane.gd +++ b/material_maker/widgets/graph_tree/hierarchy_pane.gd @@ -2,67 +2,115 @@ extends Tree export(int, 0, 3) var preview : int = 0 -var update_index : int = 0 +var default_texture : ImageTexture = null +var current_graph_edit = null +var current_generator = null +var item_from_gen : Dictionary = {} + +var pending_updates = {} signal group_selected +func _ready() -> void: + var default_image = Image.new() + default_image.create(24, 24, false, Image.FORMAT_RGBA8) + default_image.fill(Color(0.0, 0.0, 0.0, 0.0)) + default_texture = ImageTexture.new() + default_texture.create_from_image(default_image) + func update_from_graph_edit(graph_edit) -> void: - update_index += 1 + for g in item_from_gen.keys(): + if is_instance_valid(g): + g.disconnect("output_changed", self, "on_gen_output_changed") + item_from_gen = {} set_column_expand(0, true) columns = preview+1 for i in range(1, columns): set_column_expand(i, false) set_column_min_width(i, 28) - if graph_edit == null: + clear() + pending_updates = {} + if current_graph_edit != null and is_instance_valid(current_graph_edit): + current_graph_edit.disconnect("view_updated", self, "on_view_updated") + if graph_edit == null or graph_edit.top_generator == null or graph_edit.generator == null: + current_graph_edit = null + current_generator = null return + current_graph_edit = graph_edit + current_graph_edit.connect("view_updated", self, "on_view_updated") + current_generator = graph_edit.generator var file_name = "PTex" if graph_edit.save_path != null: file_name = graph_edit.save_path.get_file() - fill_tree(graph_edit.top_generator, graph_edit.generator, file_name) + fill_item(create_item(null), graph_edit.top_generator, graph_edit.generator, file_name) -func fill_tree(top : MMGenGraph, selected : MMGenGraph, top_name : String) -> void: - clear() - if top == null or selected == null: +func set_icon(item : TreeItem, generator : MMGenGraph, output : int) -> void: + if output >= preview: return - var root : TreeItem = create_item(null) - root.set_text(0, top_name) - if top == selected: - root.set_custom_color(0, Color(0.5, 0.5, 1)) + var result = generator.render(output, 24, true) + while result is GDScriptFunctionState: + result = yield(result, "completed") + var tex = ImageTexture.new() + result.copy_to_texture(tex) + item.set_icon(1-min(generator.get_output_defs().size()-preview, 0)+output, tex) + result.release() + +func set_icons(item : TreeItem, generator : MMGenGraph) -> void: + var output_count = min(generator.get_output_defs().size(), preview) + for output in range(output_count): + set_icon(item, generator, output) + +func fill_item(item : TreeItem, generator : MMGenGraph, selected : MMGenGraph, name = null) -> void: + item.set_text(0, name if name != null else generator.get_type_name()) + if generator == selected: + item.set_custom_color(0, Color(0.5, 0.5, 1)) else: - root.set_custom_color(0, Color(1, 1, 1)) - root.set_metadata(0, top) - fill_item(root, top, selected) - -func set_icon(item, generator) -> void: - var index = update_index - var output_count = min(generator.get_output_defs().size(), 3) - for o in range(output_count): - var result = generator.render(o, 24, true) - while result is GDScriptFunctionState: - if index != update_index: - return - result = yield(result, "completed") - if index == update_index: - var tex = ImageTexture.new() - result.copy_to_texture(tex) - item.set_icon(1+preview-output_count+o, tex) - result.release() - -func fill_item(parent : TreeItem, generator : MMGenGraph, selected : MMGenGraph) -> void: + item.set_custom_color(0, Color(1, 1, 1)) + item.set_metadata(0, generator) + item_from_gen[generator] = item + generator.connect("output_changed", self, "on_gen_output_changed", [ generator ]) + if preview > 0 and generator.get_output_defs().size() > 0: + for i in range(min(preview, generator.get_output_defs().size())): + item.set_icon(i+1, default_texture) + call_deferred("set_icons", item, generator) for c in generator.get_children(): if c is MMGenGraph: if c.is_template(): continue - var item : TreeItem = create_item(parent) - item.set_text(0, c.get_type_name()) - if c == selected: - item.set_custom_color(0, Color(0.5, 0.5, 1)) - elif c.is_editable(): - item.set_custom_color(0, Color(1, 1, 1)) - item.set_metadata(0, c) - if preview > 0 and c.get_output_defs().size() > 0: - call_deferred("set_icon", item, c) - fill_item(item, c, selected) + fill_item(create_item(item), c, selected) -func _on_Hierarchy_item_double_clicked(): +func _on_Hierarchy_item_double_clicked() -> void: emit_signal("group_selected", get_selected().get_metadata(0)) + +func on_view_updated(generator) -> void: + if item_from_gen.has(current_generator): + item_from_gen[current_generator].set_custom_color(0, Color(1, 1, 1)) + current_generator = generator + if item_from_gen.has(current_generator): + item_from_gen[current_generator].set_custom_color(0, Color(0.5, 0.5, 1)) + +func on_gen_output_changed(index, generator) -> void: + if item_from_gen.has(generator) and index < preview: + if !pending_updates.has(generator): + pending_updates[generator] = [index] + elif pending_updates[generator].find(index) == -1: + pending_updates[generator].push_back(index) + $Delay.stop() + $Delay.start() + +func _on_Delay_timeout() -> void: + for generator in pending_updates.keys(): + var item = item_from_gen[generator] + for index in pending_updates[generator]: + set_icon(item, generator, index) + +func _on_Hierarchy_gui_input(event): + if event is InputEventMouseButton and event.button_index == BUTTON_RIGHT and event.pressed: + $ContextMenu.rect_position = get_global_mouse_position() + $ContextMenu.popup() + +func _on_ContextMenu_id_pressed(id): + preview = id + update_from_graph_edit(current_graph_edit) + + diff --git a/material_maker/widgets/graph_tree/hierarchy_pane.tscn b/material_maker/widgets/graph_tree/hierarchy_pane.tscn index efda9e1..bbb0917 100644 --- a/material_maker/widgets/graph_tree/hierarchy_pane.tscn +++ b/material_maker/widgets/graph_tree/hierarchy_pane.tscn @@ -11,5 +11,18 @@ script = ExtResource( 1 ) __meta__ = { "_edit_use_anchors_": false } +preview = 2 + +[node name="ContextMenu" type="PopupMenu" parent="."] +margin_right = 20.0 +margin_bottom = 20.0 +items = [ "No preview", null, 0, false, false, 0, 0, null, "", false, "1 preview", null, 0, false, false, 1, 0, null, "", false, "2 previews", null, 0, false, false, 2, 0, null, "", false, "3 previews", null, 0, false, false, 3, 0, null, "", false ] + +[node name="Delay" type="Timer" parent="."] +wait_time = 0.5 +one_shot = true +[connection signal="gui_input" from="." to="." method="_on_Hierarchy_gui_input"] [connection signal="item_activated" from="." to="." method="_on_Hierarchy_item_double_clicked"] [connection signal="item_double_clicked" from="." to="." method="_on_Hierarchy_item_double_clicked"] +[connection signal="id_pressed" from="ContextMenu" to="." method="_on_ContextMenu_id_pressed"] +[connection signal="timeout" from="Delay" to="." method="_on_Delay_timeout"]