Merge branch 'master' into dev-generic

This commit is contained in:
RodZill4 2020-02-04 07:48:10 +01:00
commit 6b183aa7a0
17 changed files with 37343 additions and 68 deletions

View File

@ -7,9 +7,20 @@ be used to create textures procedurally. It can also be used as a Godot addon
Its user interface is based on Godot's GraphEdit node: textures are described
as interconnected texture generators and operators.
## Download
- **[Download on itch.io](https://rodzilla.itch.io/material-maker)**
On Windows, you can also install Material Maker using [Scoop](https://scoop.sh):
```text
scoop bucket add extras
scoop install material-maker
```
## Documentation
- **[User manual](https://rodzill4.github.io/godot-procedural-textures/doc/)**
- **[User manual](https://rodzill4.github.io/material-maker/doc/)**
## Screenshot
@ -17,7 +28,7 @@ as interconnected texture generators and operators.
## License
Copyright (c) 2018-2020 Rodz Labs and contributors
Copyright (c) 2018-2020 Rodolphe Suescun and contributors
Unless otherwise specified, files in this repository are licensed under the
MIT license. See [LICENSE.md](LICENSE.md) for more information.

View File

@ -8,6 +8,8 @@ Comments to put in the graph
var text : String = "Double-click to write a comment"
var size : Vector2 = Vector2(0, 0)
var title : String = "Comment"
var color : Color = Color(1.0, 0.5, 0.0)
func _ready() -> void:
if !parameters.has("size"):
@ -30,6 +32,8 @@ func get_output_defs() -> Array:
func _serialize(data: Dictionary) -> Dictionary:
data.type = "comment"
data.title = title
data.color = MMType.serialize_value(color)
data.text = text
data.size = { x=size.x, y=size.y }
return data
@ -39,3 +43,7 @@ func _deserialize(data : Dictionary) -> void:
text = data.text
if data.has("size"):
size = Vector2(data.size.x, data.size.y)
if data.has("title"):
title = data.title
if data.has("color"):
color = MMType.deserialize_value(data.color)

File diff suppressed because one or more lines are too long

View File

@ -12,6 +12,8 @@ var generator = null
var last_selected = null
onready var node_popup = $"../AddNodePopup"
onready var timer : Timer = $Timer
onready var subgraph_ui : HBoxContainer = $GraphUI/SubGraphUI
@ -34,7 +36,6 @@ func _gui_input(event) -> void:
remove_selection()
# Misc. useful functions
func get_source(node, port) -> Dictionary:
for c in get_connection_list():
if c.to == node and c.to_port == port:
@ -165,6 +166,7 @@ func update_graph(generators, connections) -> Array:
rv.push_back(node)
for c in connections:
.connect_node("node_"+c.from, c.from_port, "node_"+c.to, c.to_port)
return rv
func new_material() -> void:
@ -371,10 +373,20 @@ func set_last_selected(node) -> void:
last_selected = null
func _on_GraphEdit_gui_input(event) -> void:
if event.is_action_pressed("ui_library_popup") && get_rect().has_point(get_local_mouse_position()):
node_popup.rect_global_position = get_global_mouse_position()
node_popup.show()
if event is InputEventMouseButton:
call_deferred("check_last_selected")
func request_popup(from, from_slot, release_position) -> void:
node_popup.rect_global_position = get_global_mouse_position()
node_popup.show()
node_popup.set_quick_connect(from, from_slot)
func check_last_selected() -> void:
if last_selected != null and !(is_instance_valid(last_selected) and last_selected.selected):
last_selected = null
emit_signal("node_selected", null)

View File

@ -79,6 +79,7 @@ margin_bottom = 24.0
hint_tooltip = "Show hierarchy"
icon = SubResource( 4 )
[connection signal="connection_request" from="." to="." method="connect_node"]
[connection signal="connection_to_empty" from="." to="." method="request_popup"]
[connection signal="disconnection_request" from="." to="." method="disconnect_node"]
[connection signal="duplicate_nodes_request" from="." to="." method="duplicate_selected"]
[connection signal="gui_input" from="." to="." method="_on_GraphEdit_gui_input"]

View File

@ -0,0 +1,8 @@
[gd_resource type="AtlasTexture" load_steps=2 format=2]
[ext_resource path="res://material_maker/icons/icons.svg" type="Texture" id=1]
[resource]
flags = 4
atlas = ExtResource( 1 )
region = Rect2( 16, 16, 16, 16 )

View File

@ -18,6 +18,8 @@ onready var preview_3d = $VBoxContainer/HBoxContainer/VBoxContainer/Preview/Prev
const RECENT_FILES_COUNT = 15
const THEMES = [ "Dark", "Default", "Light" ]
const MENU = [
{ menu="File", command="new_material", description="New material" },
{ menu="File", command="load_material", shortcut="Control+O", description="Load material" },
@ -36,6 +38,8 @@ const MENU = [
{ menu="Edit", command="edit_copy", shortcut="Control+C", description="Copy" },
{ menu="Edit", command="edit_paste", shortcut="Control+V", description="Paste" },
{ menu="Edit", command="edit_duplicate", shortcut="Control+D", description="Duplicate" },
{ menu="Edit" },
{ menu="Edit", submenu="set_theme", description="Set theme" },
{ menu="View", command="view_center", shortcut="C", description="Center view" },
{ menu="View", command="view_reset_zoom", shortcut="Control+0", description="Reset zoom" },
@ -61,19 +65,22 @@ var is_mac = false
func _ready() -> void:
# Restore the window position/size if values are present in the configuration cache
config_cache.load("user://cache.ini")
if Engine.editor_hint:
set_process_input(false)
else:
if config_cache.has_section_key("window", "screen"):
OS.current_screen = config_cache.get_value("window", "screen")
if config_cache.has_section_key("window", "maximized"):
OS.window_maximized = config_cache.get_value("window", "maximized")
if config_cache.has_section_key("window", "screen"):
OS.current_screen = config_cache.get_value("window", "screen")
if config_cache.has_section_key("window", "maximized"):
OS.window_maximized = config_cache.get_value("window", "maximized")
if !OS.window_maximized:
if config_cache.has_section_key("window", "position"):
OS.window_position = config_cache.get_value("window", "position")
if config_cache.has_section_key("window", "size"):
OS.window_size = config_cache.get_value("window", "size")
if !OS.window_maximized:
if config_cache.has_section_key("window", "position"):
OS.window_position = config_cache.get_value("window", "position")
if config_cache.has_section_key("window", "size"):
OS.window_size = config_cache.get_value("window", "size")
# Restore the theme
var theme_name : String = "default"
if config_cache.has_section_key("window", "theme"):
theme_name = config_cache.get_value("window", "theme")
set_theme(theme_name)
if OS.get_name() == "OSX":
is_mac = true
@ -103,8 +110,7 @@ func _ready() -> void:
# This property is only available in 3.2alpha or later, so use `set()` to fail gracefully if it doesn't exist.
OS.set("min_window_size", Vector2(1024, 600))
if !Engine.editor_hint:
OS.set_window_title(ProjectSettings.get_setting("application/config/name")+" v"+ProjectSettings.get_setting("application/config/release"))
OS.set_window_title(ProjectSettings.get_setting("application/config/name")+" v"+ProjectSettings.get_setting("application/config/release"))
load_recents()
for m in $VBoxContainer/Menu.get_children():
var menu = m.get_popup()
@ -194,6 +200,21 @@ func add_recent(path) -> void:
f.store_string(to_json(recent_files))
f.close()
func create_menu_set_theme(menu) -> void:
menu.clear()
for t in THEMES:
menu.add_item(t)
if !menu.is_connected("id_pressed", self, "_on_SetTheme_id_pressed"):
menu.connect("id_pressed", self, "_on_SetTheme_id_pressed")
func set_theme(theme_name) -> void:
theme = load("res://material_maker/theme/"+theme_name+".tres")
func _on_SetTheme_id_pressed(id) -> void:
var theme_name : String = THEMES[id].to_lower()
set_theme(theme_name)
config_cache.set_value("window", "theme", theme_name)
func create_menu_create(menu) -> void:
var gens = mm_loader.get_generator_list()
menu.clear()
@ -295,11 +316,8 @@ func export_material_is_disabled() -> bool:
return graph_edit == null or graph_edit.save_path == null
func quit() -> void:
if Engine.editor_hint:
emit_signal("quit")
else:
dim_window()
get_tree().quit()
dim_window()
get_tree().quit()
func edit_cut() -> void:
var graph_edit : MMGraphEdit = get_current_graph_edit()
@ -521,17 +539,15 @@ func _on_Projects_tab_changed(tab) -> void:
func _exit_tree() -> void:
# Save the window position and size to remember it when restarting the application
if !Engine.editor_hint:
config_cache.set_value("window", "screen", OS.current_screen)
config_cache.set_value("window", "maximized", OS.window_maximized || OS.window_fullscreen)
config_cache.set_value("window", "position", OS.window_position)
config_cache.set_value("window", "size", OS.window_size)
config_cache.save("user://cache.ini")
config_cache.set_value("window", "screen", OS.current_screen)
config_cache.set_value("window", "maximized", OS.window_maximized || OS.window_fullscreen)
config_cache.set_value("window", "position", OS.window_position)
config_cache.set_value("window", "size", OS.window_size)
config_cache.save("user://cache.ini")
func _notification(what : int) -> void:
if !Engine.editor_hint:
if what == MainLoop.NOTIFICATION_WM_QUIT_REQUEST:
dim_window()
if what == MainLoop.NOTIFICATION_WM_QUIT_REQUEST:
dim_window()
func dim_window() -> void:
# Darken the UI to denote that the application is currently exiting

View File

@ -1,4 +1,4 @@
[gd_scene load_steps=11 format=2]
[gd_scene load_steps=13 format=2]
[ext_resource path="res://material_maker/main_window.gd" type="Script" id=1]
[ext_resource path="res://material_maker/library.tscn" type="PackedScene" id=2]
@ -6,17 +6,19 @@
[ext_resource path="res://material_maker/preview/preview_3d.tscn" type="PackedScene" id=4]
[ext_resource path="res://material_maker/preview/preview_3d_ui.tscn" type="PackedScene" id=5]
[ext_resource path="res://material_maker/widgets/tabs.gd" type="Script" id=6]
[ext_resource path="res://material_maker/icons/icons.svg" type="Texture" id=7]
[ext_resource path="res://material_maker/node_factory.gd" type="Script" id=8]
[ext_resource path="res://material_maker/widgets/add_node_popup.tscn" type="PackedScene" id=7]
[ext_resource path="res://material_maker/icons/icons.svg" type="Texture" id=8]
[ext_resource path="res://material_maker/node_factory.gd" type="Script" id=9]
[ext_resource path="res://material_maker/theme/default.tres" type="Theme" id=10]
[sub_resource type="AtlasTexture" id=1]
flags = 4
atlas = ExtResource( 7 )
atlas = ExtResource( 8 )
region = Rect2( 96, 32, 32, 32 )
[sub_resource type="AtlasTexture" id=2]
flags = 4
atlas = ExtResource( 7 )
atlas = ExtResource( 8 )
region = Rect2( 96, 64, 32, 32 )
[node name="MainWindow" type="Panel"]
@ -24,6 +26,7 @@ anchor_right = 1.0
anchor_bottom = 1.0
size_flags_horizontal = 3
size_flags_vertical = 3
theme = ExtResource( 10 )
script = ExtResource( 1 )
__meta__ = {
"_edit_use_anchors_": false
@ -38,14 +41,17 @@ margin_right = -6.0
margin_bottom = -6.0
size_flags_horizontal = 3
size_flags_vertical = 3
__meta__ = {
"_edit_use_anchors_": false
}
[node name="Menu" type="HBoxContainer" parent="VBoxContainer"]
margin_right = 1268.0
margin_bottom = 20.0
margin_bottom = 22.0
[node name="File" type="MenuButton" parent="VBoxContainer/Menu"]
margin_right = 35.0
margin_bottom = 20.0
margin_bottom = 22.0
text = "File"
items = [ "New material", null, 0, false, false, 0, 0, null, "", false, "Load material", null, 0, false, false, 1, 268435535, null, "", false, "", null, 0, false, false, -1, 0, null, "", true, "Save material", null, 0, false, false, 4, 268435539, null, "", false, "Save material as...", null, 0, false, false, 5, 301989971, null, "", false, "Save all materials...", null, 0, false, false, 6, 0, null, "", false, "", null, 0, false, false, -1, 0, null, "", true, "Export material", null, 0, false, false, 8, 268435525, null, "", false, "", null, 0, false, false, -1, 0, null, "", true, "Close material", null, 0, false, false, 10, 0, null, "", false, "Quit", null, 0, false, false, 11, 268435537, null, "", false ]
switch_on_hover = true
@ -53,7 +59,7 @@ switch_on_hover = true
[node name="Edit" type="MenuButton" parent="VBoxContainer/Menu"]
margin_left = 39.0
margin_right = 75.0
margin_bottom = 20.0
margin_bottom = 22.0
text = "Edit"
items = [ "Cut", null, 0, false, false, 12, 268435544, null, "", false, "Copy", null, 0, false, false, 13, 268435523, null, "", false, "Paste", null, 0, false, false, 14, 268435542, null, "", false, "Duplicate", null, 0, false, false, 15, 268435524, null, "", false ]
switch_on_hover = true
@ -61,7 +67,7 @@ switch_on_hover = true
[node name="View" type="MenuButton" parent="VBoxContainer/Menu"]
margin_left = 79.0
margin_right = 121.0
margin_bottom = 20.0
margin_bottom = 22.0
text = "View"
items = [ "Center view", null, 0, false, false, 16, 67, null, "", false, "Reset zoom", null, 0, false, false, 17, 268435504, null, "", false ]
switch_on_hover = true
@ -69,7 +75,7 @@ switch_on_hover = true
[node name="Tools" type="MenuButton" parent="VBoxContainer/Menu"]
margin_left = 125.0
margin_right = 171.0
margin_bottom = 20.0
margin_bottom = 22.0
text = "Tools"
items = [ "Create", null, 0, false, false, 0, 0, null, "PopupMenu", false, "Create group", null, 0, false, false, 19, 268435527, null, "", false, "Make selected nodes editable", null, 0, false, false, 20, 268435543, null, "", false, "", null, 0, false, false, -1, 0, null, "", true, "Add selected node to user library", null, 0, false, false, 22, 0, null, "", false, "Export the nodes library", null, 0, false, false, 23, 0, null, "", false ]
switch_on_hover = true
@ -77,51 +83,55 @@ switch_on_hover = true
[node name="Help" type="MenuButton" parent="VBoxContainer/Menu"]
margin_left = 175.0
margin_right = 217.0
margin_bottom = 20.0
margin_bottom = 22.0
text = "Help"
items = [ "User manual", null, 0, false, false, 24, 16777244, null, "", false, "Show selected library item documentation", null, 0, false, false, 25, 285212700, null, "", false, "Report a bug", null, 0, false, false, 26, 0, null, "", false, "", null, 0, false, false, -1, 0, null, "", true, "About", null, 0, false, false, 28, 0, null, "", false ]
switch_on_hover = true
[node name="HBoxContainer" type="HSplitContainer" parent="VBoxContainer"]
margin_top = 24.0
margin_top = 26.0
margin_right = 1268.0
margin_bottom = 708.0
size_flags_vertical = 3
[node name="VBoxContainer" type="VSplitContainer" parent="VBoxContainer/HBoxContainer"]
margin_right = 311.0
margin_bottom = 684.0
margin_right = 313.0
margin_bottom = 682.0
size_flags_horizontal = 3
size_flags_vertical = 3
[node name="Library" parent="VBoxContainer/HBoxContainer/VBoxContainer" instance=ExtResource( 2 )]
margin_right = 311.0
margin_bottom = 386.0
margin_right = 313.0
margin_bottom = 390.0
size_flags_vertical = 3
size_flags_stretch_ratio = 1.5
[node name="Preview" type="TabContainer" parent="VBoxContainer/HBoxContainer/VBoxContainer"]
margin_top = 398.0
margin_right = 311.0
margin_bottom = 684.0
margin_right = 313.0
margin_bottom = 682.0
tab_align = 0
[node name="Preview2D" parent="VBoxContainer/HBoxContainer/VBoxContainer/Preview" instance=ExtResource( 3 )]
margin_left = 4.0
margin_top = 32.0
margin_right = -4.0
margin_bottom = -4.0
margin_left = 5.0
margin_top = 29.0
margin_right = -5.0
margin_bottom = -5.0
rect_min_size = Vector2( 250, 250 )
[node name="Preview3D" parent="VBoxContainer/HBoxContainer/VBoxContainer/Preview" instance=ExtResource( 4 )]
margin_left = 5.0
margin_top = 29.0
margin_right = -5.0
margin_bottom = -5.0
rect_min_size = Vector2( 250, 250 )
[node name="Preview3DUI" parent="VBoxContainer/HBoxContainer/VBoxContainer/Preview/Preview3D" instance=ExtResource( 5 )]
[node name="ProjectsPane" type="Control" parent="VBoxContainer/HBoxContainer"]
margin_left = 323.0
margin_left = 321.0
margin_right = 1268.0
margin_bottom = 684.0
margin_bottom = 682.0
size_flags_horizontal = 3
size_flags_vertical = 3
size_flags_stretch_ratio = 3.0
@ -152,6 +162,8 @@ margin_bottom = 24.0
tab_align = 0
tab_close_display_policy = 1
[node name="AddNodePopup" parent="VBoxContainer/HBoxContainer/ProjectsPane/Projects" instance=ExtResource( 7 )]
[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer/HBoxContainer/ProjectsPane"]
anchor_top = 1.0
anchor_bottom = 1.0
@ -163,7 +175,7 @@ custom_constants/separation = 7
[node name="Button" type="Button" parent="VBoxContainer/HBoxContainer/ProjectsPane/HBoxContainer"]
margin_right = 44.0
margin_bottom = 38.0
margin_bottom = 40.0
hint_tooltip = "Show 3D preview"
toggle_mode = true
icon = SubResource( 1 )
@ -191,7 +203,7 @@ margin_bottom = 30.0
size_flags_vertical = 4
[node name="NodeFactory" type="Node" parent="."]
script = ExtResource( 8 )
script = ExtResource( 9 )
[connection signal="need_update" from="VBoxContainer/HBoxContainer/VBoxContainer/Preview/Preview3D" to="." method="update_preview_3d"]
[connection signal="environment_selected" from="VBoxContainer/HBoxContainer/VBoxContainer/Preview/Preview3D/Preview3DUI" to="VBoxContainer/HBoxContainer/VBoxContainer/Preview/Preview3D" method="_on_Environment_item_selected"]
[connection signal="model_selected" from="VBoxContainer/HBoxContainer/VBoxContainer/Preview/Preview3D/Preview3DUI" to="VBoxContainer/HBoxContainer/VBoxContainer/Preview/Preview3D" method="_on_Model_item_selected"]

View File

@ -1,4 +1,3 @@
tool
extends GraphNode
class_name MMGraphNodeBase
@ -30,3 +29,4 @@ func _on_gui_input(event) -> void:
if event is InputEventMouseButton and event.pressed and event.button_index == BUTTON_LEFT and Rect2(rect_size.x-48, 4, 16, 16).has_point(event.position):
generator.toggle_lock_seed()
update()
get_parent().send_changed_signal()

View File

@ -1,13 +1,21 @@
tool
extends MMGraphNodeBase
onready var label = $VBox/Label
onready var editor = $VBox/TextEdit
func _draw() -> void:
var icon = preload("res://material_maker/icons/edit.tres")
draw_texture_rect(icon, Rect2(rect_size.x-68, 4, 16, 16), false)
draw_rect(Rect2(rect_size.x-48, 4, 16, 16), generator.color)
if !is_connected("gui_input", self, "_on_gui_input"):
connect("gui_input", self, "_on_gui_input")
func set_generator(g) -> void:
generator = g
label.text = generator.text
rect_size = generator.size
title = generator.title
set_color(generator.color)
func _on_resize_request(new_size) -> void:
rect_size = new_size
@ -27,3 +35,32 @@ func _on_TextEdit_focus_exited() -> void:
generator.text = editor.text
label.visible = true
editor.visible = false
func _on_gui_input(event) -> void:
if event is InputEventMouseButton and event.pressed and event.button_index == BUTTON_LEFT:
if Rect2(rect_size.x-48, 4, 16, 16).has_point(event.position):
$Popup/ColorPicker.color = generator.color
$Popup/ColorPicker.connect("color_changed", self, "set_color")
$Popup.rect_position = event.global_position
$Popup.popup()
accept_event()
elif Rect2(rect_size.x-68, 4, 16, 16).has_point(event.position):
var dialog = preload("res://material_maker/widgets/line_dialog.tscn").instance()
dialog.set_value(generator.title)
dialog.set_texts("Comment", "Enter the comment node title")
add_child(dialog)
dialog.connect("ok", self, "set_title")
dialog.popup_centered()
accept_event()
func set_color(c):
generator.color = c
var color = c
color.a = 0.3
get_stylebox("comment").bg_color = color
get_parent().send_changed_signal()
func set_title(t):
title = t
generator.title = t
get_parent().send_changed_signal()

View File

@ -1,18 +1,32 @@
[gd_scene load_steps=3 format=2]
[gd_scene load_steps=4 format=2]
[ext_resource path="res://material_maker/nodes/comment.gd" type="Script" id=1]
[sub_resource type="StyleBoxFlat" id=1]
resource_local_to_scene = true
content_margin_left = 28.0
content_margin_right = 28.0
content_margin_top = 24.0
content_margin_bottom = 5.0
bg_color = Color( 0, 0, 0, 0.3 )
border_width_left = 1
border_width_top = 1
border_width_right = 1
border_width_bottom = 1
border_color = Color( 1, 1, 1, 0.9 )
[sub_resource type="StyleBoxFlat" id=2]
bg_color = Color( 1, 1, 1, 0.0627451 )
[node name="GraphNode" type="GraphNode"]
margin_left = 1.0
margin_top = 1.0
margin_right = 250.0
margin_bottom = 44.0
margin_right = 256.0
margin_bottom = 82.0
size_flags_horizontal = 3
size_flags_vertical = 3
custom_styles/commentfocus = SubResource( 1 )
custom_styles/comment = SubResource( 1 )
title = "Comment"
show_close = true
resizable = true
@ -23,16 +37,25 @@ slot/0/left_color = Color( 1, 1, 1, 1 )
slot/0/right_enabled = false
slot/0/right_type = 0
slot/0/right_color = Color( 1, 1, 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 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="VBox" type="VBoxContainer" parent="."]
margin_left = 16.0
margin_top = 24.0
margin_right = 233.0
margin_right = 239.0
margin_bottom = 38.0
[node name="Label" type="Label" parent="VBox"]
margin_right = 217.0
margin_right = 223.0
margin_bottom = 14.0
mouse_filter = 0
text = "Double-click to write a comment"
@ -43,9 +66,22 @@ visible = false
margin_top = 18.0
margin_right = 221.0
margin_bottom = 18.0
custom_styles/focus = SubResource( 1 )
custom_styles/normal = SubResource( 1 )
custom_styles/focus = SubResource( 2 )
custom_styles/normal = SubResource( 2 )
wrap_enabled = true
[node name="Popup" type="Popup" parent="."]
margin_left = 16.0
margin_top = 39.0
margin_right = 239.0
margin_bottom = 39.0
[node name="ColorPicker" type="ColorPicker" parent="Popup"]
margin_left = 4.0
margin_top = 4.0
margin_right = 4.0
margin_bottom = 4.0
rect_scale = Vector2( 0.75, 0.75 )
[connection signal="resize_request" from="." to="." method="_on_resize_request"]
[connection signal="gui_input" from="VBox/Label" to="." method="_on_Label_gui_input"]
[connection signal="focus_exited" from="VBox/TextEdit" to="." method="_on_TextEdit_focus_exited"]

12358
material_maker/theme/dark.tres Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,146 @@
extends Popup
var libraries = []
var data = []
onready var itemlist : ItemList = $PanelContainer/VBoxContainer/ItemList
onready var filter_line_edit : LineEdit = $PanelContainer/VBoxContainer/Filter
var insert_position : Vector2
func get_current_graph():
return get_parent().get_current_tab_control()
func _ready() -> void:
var lib_path = OS.get_executable_path().get_base_dir()+"/library/base.json"
if !add_library(lib_path):
add_library("res://material_maker/library/base.json")
add_library("user://library/user.json")
filter_line_edit.connect("text_changed" ,self,"update_list")
filter_line_edit.connect("text_entered",self,"filter_entered")
itemlist.connect("item_selected",self,"item_selected")
itemlist.connect("item_activated",self,"item_selected")
update_list()
func filter_entered(filter) -> void:
item_selected(0)
func add_node(data) -> void:
var node : GraphNode = get_current_graph().create_nodes(data, get_current_graph().offset_from_global_position(insert_position))[0]
# if this node created by dragging to an empty space
if quick_connect_node != null:
var type = quick_connect_node.get_connection_output_type(quick_connect_slot)
for new_slot in node.get_connection_input_count():
if type == node.get_connection_input_type(new_slot):
#connect the first two slots with the same type
get_current_graph().connect_node(quick_connect_node.name, quick_connect_slot, node.name, new_slot)
break
quick_connect_node = null
hide()
func item_selected(index) -> void:
# checks if mouse left | enter pressed. it prevents
# adding nodes just by using arrow keys as it selects the item
if Input.is_mouse_button_pressed(BUTTON_LEFT) || Input.is_key_pressed(KEY_ENTER):
if (index>=itemlist.get_item_count()):
return
if (itemlist.is_item_selectable(index) == false):
item_selected(index+1)
return
add_node(data[index])
hide()
func hide() -> void:
.hide()
# clearing the quick connect data after hiding to prevent unintended autoconnection
quick_connect_node = null
# grabbing the focus for the graph again as creating popup removes the focus.
get_current_graph().grab_focus()
clear()
func show() -> void:
.show()
update_list()
filter_line_edit.grab_focus()
var parent_rect = get_parent().get_parent().get_global_rect()
var clipped = parent_rect.clip(get_global_rect())
var offset = (get_rect().size-clipped.size)
insert_position = rect_position
rect_position = rect_position - offset
func update_list(filter : String = "") -> void:
clear_list()
data.clear()
for library in libraries:
for obj in library:
if !obj.has("type"):
continue
var show : bool = true
for f in filter.to_lower().split(" ", false):
if f != "" && obj.tree_item.to_lower().find(f) == -1:
show = false
break
if show:
data.append(obj)
itemlist.add_item(obj.tree_item, get_preview_texture(obj))
func get_preview_texture(data : Dictionary) -> ImageTexture:
if data.has("icon") and data.has("library"):
var image_path = data.library.left(data.library.rfind("."))+"/"+data.icon+".png"
var t : ImageTexture
if image_path.left(6) == "res://":
image_path = ProjectSettings.globalize_path(image_path)
t = ImageTexture.new()
var image : Image = Image.new()
if image.load(image_path) == OK:
image.resize(16, 16)
t.create_from_image(image)
else:
print("Cannot load image "+image_path)
return t
return null
func clear_list() -> void:
itemlist.clear()
func add_library(file_name : String, filter : String = "") -> bool:
var file = File.new()
if file.open(file_name, File.READ) != OK:
return false
var lib = parse_json(file.get_as_text())
file.close()
if lib != null and lib.has("lib"):
for m in lib.lib:
m.library = file_name
libraries.push_back(lib.lib)
return true
return false
# Quickly connecting when tried to connect to empty
var quick_connect_node : GraphNode
var quick_connect_slot = 0
func set_quick_connect(from, from_slot) -> void:
quick_connect_node = get_current_graph().get_node(from)
quick_connect_slot = from_slot
func _input(event) -> void:
if event is InputEventMouseButton and event.is_pressed() and event.button_index == BUTTON_LEFT:
if !get_rect().has_point(event.position):
clear()
hide()
func _unhandled_input(event) -> void:
if event is InputEventKey and event.scancode == KEY_ESCAPE:
clear()
hide()
func clear() -> void:
filter_line_edit.text = ""
func _on_itemlist_focus_entered() -> void:
# if itemlist received focus and no item is yet selected
# select the first item
if itemlist.get_selected_items().size() == 0:
itemlist.select(0)

View File

@ -0,0 +1,34 @@
[gd_scene load_steps=2 format=2]
[ext_resource path="res://material_maker/widgets/add_node_popup.gd" type="Script" id=1]
[node name="AddNodePopup" type="Popup"]
margin_right = 228.0
margin_bottom = 319.0
mouse_filter = 1
script = ExtResource( 1 )
[node name="PanelContainer" type="PanelContainer" parent="."]
anchor_right = 1.0
anchor_bottom = 1.0
[node name="VBoxContainer" type="VBoxContainer" parent="PanelContainer"]
margin_left = 7.0
margin_top = 7.0
margin_right = 221.0
margin_bottom = 312.0
[node name="Filter" type="LineEdit" parent="PanelContainer/VBoxContainer"]
margin_right = 214.0
margin_bottom = 24.0
rect_min_size = Vector2( 0, 20 )
size_flags_horizontal = 3
[node name="ItemList" type="ItemList" parent="PanelContainer/VBoxContainer"]
margin_top = 28.0
margin_right = 214.0
margin_bottom = 305.0
size_flags_horizontal = 3
size_flags_vertical = 3
allow_reselect = true
[connection signal="focus_entered" from="PanelContainer/VBoxContainer/ItemList" to="." method="_on_itemlist_focus_entered"]

View File

@ -216,6 +216,11 @@ toggle_fullscreen={
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":true,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777221,"unicode":0,"echo":false,"script":null)
]
}
ui_library_popup={
"deadzone": 0.5,
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":32,"unicode":0,"echo":false,"script":null)
]
}
[logging]