mirror of
https://github.com/godotengine/godot-demo-projects.git
synced 2025-12-15 13:00:07 +01:00
* General proofreading for grammar and spelling * General formatting * Addition of appropriate literals where appropriate, i.e. `&"foo"` for `StringName` cases and `^"foo/bar"` for `NodePath` cases
166 lines
6.1 KiB
GDScript
166 lines
6.1 KiB
GDScript
@tool
|
|
extends Panel
|
|
# In this file, the word "silly" is used to make it obvious that the name is arbitrary.
|
|
|
|
var silly_material_resource := preload("res://addons/material_creator/material_resource.gd")
|
|
var editor_interface: EditorInterface
|
|
|
|
|
|
func _ready() -> void:
|
|
# Connect all of the signals we'll need to save and load silly materials.
|
|
$VBoxContainer/ApplyButton.pressed.connect(apply_pressed)
|
|
$VBoxContainer/SaveButton.pressed.connect(save_pressed)
|
|
$VBoxContainer/LoadButton.pressed.connect(load_pressed)
|
|
|
|
$SaveMaterialDialog.file_mode = FileDialog.FILE_MODE_SAVE_FILE
|
|
$SaveMaterialDialog.access = FileDialog.ACCESS_RESOURCES
|
|
$SaveMaterialDialog.current_dir = "res://materials"
|
|
$SaveMaterialDialog.current_file = "new_material.silly_mat"
|
|
$SaveMaterialDialog.filters = PackedStringArray([
|
|
"*.silly_mat ; Silly Material (resource)",
|
|
"*.tres ; Godot Resource (resource)",
|
|
"*.mtxt ; Silly Material (source)",
|
|
])
|
|
$SaveMaterialDialog.confirmed.connect(_on_save_confirmed)
|
|
|
|
$LoadMaterialDialog.access = FileDialog.ACCESS_RESOURCES
|
|
$LoadMaterialDialog.filters = PackedStringArray([
|
|
"*.silly_mat ; Silly Material (resource)",
|
|
"*.tres ; Godot Resource (resource)",
|
|
"*.mtxt ; Silly Material (source)",
|
|
])
|
|
$LoadMaterialDialog.file_selected.connect(load_file_selected)
|
|
|
|
RenderingServer.canvas_item_set_clip(get_canvas_item(), true)
|
|
|
|
|
|
func save_pressed() -> void:
|
|
$SaveMaterialDialog.popup_centered_ratio()
|
|
|
|
|
|
func load_pressed() -> void:
|
|
$LoadMaterialDialog.popup_centered_ratio()
|
|
|
|
|
|
func _on_save_confirmed() -> void:
|
|
var path = $SaveMaterialDialog.get_current_path()
|
|
if path.is_empty():
|
|
push_error("Material Creator: No path chosen for saving.")
|
|
return
|
|
|
|
# If user typed no extension, default to .silly_mat (resource path).
|
|
if not path.get_file().contains("."):
|
|
path += ".silly_mat"
|
|
|
|
var ext = path.get_extension().to_lower()
|
|
|
|
# Ensure directory exists under res:// when saving inside project.
|
|
var dir = path.get_base_dir()
|
|
if path.begins_with("res://") and not DirAccess.dir_exists_absolute(dir):
|
|
var mk := DirAccess.make_dir_recursive_absolute(dir)
|
|
if mk != OK:
|
|
push_error("Material Creator: Can't create folder: \"%s\" (%s)." % [dir, error_string(mk)])
|
|
return
|
|
|
|
var res: Resource = _silly_resource_from_values()
|
|
|
|
match ext:
|
|
"mtxt":
|
|
# Write SOURCE file (no ResourceSaver, works anywhere).
|
|
var ok := _write_source_silly(path, res)
|
|
if not ok:
|
|
push_error("Material Creator: Failed to write source .mtxt at \"%s\"." % path)
|
|
else:
|
|
print("Material Creator: Wrote source to ", path)
|
|
"silly_mat", "tres":
|
|
# Save RESOURCE (requires your custom saver for .silly_mat).
|
|
res.resource_path = path
|
|
var err := ResourceSaver.save(res, path)
|
|
if err != OK:
|
|
push_error("Material Creator: Failed to save resource: \"%s\" (%s)." % [path, error_string(err)])
|
|
else:
|
|
print("Material Creator: Saved resource to ", path)
|
|
_:
|
|
push_error("Material Creator: Unsupported extension: ." + ext)
|
|
|
|
|
|
func apply_pressed() -> void:
|
|
# Using the passed in editor interface, get the selected nodes in the editor.
|
|
var editor_selection: EditorSelection = editor_interface.get_selection()
|
|
var selected_nodes := editor_selection.get_selected_nodes()
|
|
if selected_nodes.is_empty():
|
|
push_error("Material Creator: Can't apply the material, because there are no nodes selected!")
|
|
return
|
|
|
|
var new_material: StandardMaterial3D = _silly_resource_from_values().make_material()
|
|
# Go through the selected nodes and see if they have the "set_surface_override_material"
|
|
# function (which only MeshInstance3D has by default). If they do, then set the material
|
|
# to the silly material.
|
|
for node in selected_nodes:
|
|
if node.has_method(&"set_surface_override_material"):
|
|
node.set_surface_override_material(0, new_material)
|
|
|
|
|
|
func load_file_selected(path: String) -> bool:
|
|
var ext := path.get_extension().to_lower()
|
|
|
|
if ext == "mtxt":
|
|
# Load SOURCE by manual parse (works inside/outside res://)
|
|
var loaded := _read_source_silly(path)
|
|
if loaded == null:
|
|
push_error("Material Creator: Failed to parse source at \"%s\"." % path)
|
|
return false
|
|
$VBoxContainer/AlbedoColorPicker.color = loaded.albedo_color
|
|
$VBoxContainer/MetallicSlider.value = loaded.metallic_strength
|
|
$VBoxContainer/RoughnessSlider.value = loaded.roughness_strength
|
|
return true
|
|
else:
|
|
# Load RESOURCE via ResourceLoader (silly_mat via your loader, tres via built-in)
|
|
var silly_resource: Resource = ResourceLoader.load(path)
|
|
if silly_resource == null:
|
|
push_error("Material Creator: Failed to load resource at \"%s\"." % path)
|
|
return false
|
|
$VBoxContainer/AlbedoColorPicker.color = silly_resource.albedo_color
|
|
$VBoxContainer/MetallicSlider.value = silly_resource.metallic_strength
|
|
$VBoxContainer/RoughnessSlider.value = silly_resource.roughness_strength
|
|
return true
|
|
|
|
|
|
func _silly_resource_from_values() -> Resource:
|
|
var color: Color = $VBoxContainer/AlbedoColorPicker.color
|
|
var metallic: float = $VBoxContainer/MetallicSlider.value
|
|
var roughness: float = $VBoxContainer/RoughnessSlider.value
|
|
var silly_res: Resource = silly_material_resource.new()
|
|
silly_res.albedo_color = color
|
|
silly_res.metallic_strength = metallic
|
|
silly_res.roughness_strength = roughness
|
|
return silly_res
|
|
|
|
# ---------------------------------------------------------------
|
|
# Source (.mtxt) helpers.
|
|
# ---------------------------------------------------------------
|
|
|
|
func _write_source_silly(path: String, res: Resource) -> bool:
|
|
var mat_file := FileAccess.open(path, FileAccess.WRITE)
|
|
if mat_file == null:
|
|
return false
|
|
mat_file.store_line("SILLY_MAT v1")
|
|
mat_file.store_line(res.albedo_color.to_html(true)) # RGBA hex
|
|
mat_file.store_line(str(res.metallic_strength))
|
|
mat_file.store_line(str(res.roughness_strength))
|
|
return true
|
|
|
|
|
|
func _read_source_silly(path: String) -> Resource:
|
|
var mat_file := FileAccess.open(path, FileAccess.READ)
|
|
if mat_file == null:
|
|
return null
|
|
var header := mat_file.get_line()
|
|
if not header.begins_with("SILLY_MAT"):
|
|
return null
|
|
var mat_res := silly_material_resource.new()
|
|
mat_res.albedo_color = Color(mat_file.get_line()) # from hex string
|
|
mat_res.metallic_strength = float(mat_file.get_line())
|
|
mat_res.roughness_strength = float(mat_file.get_line())
|
|
return mat_res
|