Files
godot-demo-projects/plugins/addons/material_creator/material_creator.gd
A Thousand Ships 0343cedd48 General proofreading (#1262)
* 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
2025-10-11 01:39:59 -07:00

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