Files
godot-demo-projects/plugins/addons/material_creator/silly_material_resource.gd
2025-10-11 03:22:04 -07:00

110 lines
4.8 KiB
GDScript

## Example class that can be imported, exported, loaded, saved, etc, in various ways.
##
## - To perform an editor import as a `SillyMaterialResource`, the class
## `ImportSillyMatAsSillyMaterialResource` will handle files in the `res://`
## folder ending in `.silly_mat_importable` and import them.
## as long as "Silly Material Resource" is selected in the Import dock.
## Then `ResourceLoader.load()` will return a read-only `SillyMaterialResource`.
##
## - To perform an editor import as a `StandardMaterial3D`, the class
## `ImportSillyMatAsStandardMaterial3D` will handle files in the `res://`
## folder ending in `.silly_mat_importable` and import them,
## as long as "Standard Material 3D" is selected in the Import dock.
## Then `ResourceLoader.load()` will return a read-only `StandardMaterial3D`.
##
## - To perform an editor load as a SillyMaterialResource, the class
## `SillyMatFormatLoader` will handle files in the `res://`
## folder ending in `.silly_mat_loadable` and load them.
## Then `ResourceLoader.load()` will return a writeable `SillyMaterialResource`.
## This can then be saved back to a file with `SillyMatFormatSaver`.
##
## - To perform a runtime (or editor) import into a StandardMaterial3D, run the
## `read_from_file` function, which reads the data from a file and runs
## `from_json_dictionary`, then run `to_material` to generate a material.
##
## - To perform a runtime (or editor) export of a StandardMaterial3D, run
## `from_material` to convert a material, then run the `write_to_file`
## function, which runs `to_json_dictionary` and saves this to a file.
##
## These functions should be placed in this class to support runtime imports
## and exports, but the editor classes can also make use of these functions,
## allowing the editor-only classes to be lightweight wrappers.
##
## For a more comprehensive example, see the GLTF module in Godot's source code.
## For a less comprehensive example, see the "simple_import_plugin" folder.
@tool
class_name SillyMaterialResource
extends Resource
# Use export to make properties visible in the inspector
# and serializable for resource saving/loading.
@export var albedo_color: Color = Color.BLACK
@export var metallic_strength: float = 0.0
@export var roughness_strength: float = 0.0
## Given a Dictionary parsed from JSON data, read in the data as a new SillyMaterialResource.
static func from_json_dictionary(json_dictionary: Dictionary) -> SillyMaterialResource:
var ret := SillyMaterialResource.new()
# Note: In an actual importer where you need to handle arbitrary user data,
# you may wish to do things like checking if the key exists, checking if
# the value is an array, checking if the array has a length of 3, checking
# if each value in the array is a number, and so on.
# For simplicity, these things are omitted from this demo's example code.
var albedo_array: Array = json_dictionary["albedo_color"]
ret.albedo_color.r = albedo_array[0]
ret.albedo_color.g = albedo_array[1]
ret.albedo_color.b = albedo_array[2]
ret.metallic_strength = json_dictionary["metallic_strength"]
ret.roughness_strength = json_dictionary["roughness_strength"]
return ret
## Convert SillyMaterialResource data into a Dictionary for saving as JSON.
## To perform a runtime export of a StandardMaterial3D, run this function after `from_material`.
func to_json_dictionary() -> Dictionary:
return {
"albedo_color": [albedo_color.r, albedo_color.g, albedo_color.b],
"metallic_strength": metallic_strength,
"roughness_strength": roughness_strength,
}
## Given a StandardMaterial3D, copy its data to a new SillyMaterialResource.
static func from_material(mat: StandardMaterial3D) -> SillyMaterialResource:
var ret := SillyMaterialResource.new()
ret.albedo_color = mat.albedo_color
ret.metallic_strength = mat.metallic
ret.roughness_strength = mat.roughness
return ret
## Create a new StandardMaterial3D using the data in this SillyMaterialResource.
func to_material() -> StandardMaterial3D:
var mat = StandardMaterial3D.new()
mat.albedo_color = albedo_color
mat.metallic = metallic_strength
mat.roughness = roughness_strength
return mat
## Wrapper around `from_json_dictionary` that reads from a file at the given path.
static func read_from_file(path: String) -> SillyMaterialResource:
var mat_file := FileAccess.open(path, FileAccess.READ)
if mat_file == null:
return null
var json_dict: Dictionary = JSON.parse_string(mat_file.get_as_text())
return from_json_dictionary(json_dict)
## Wrapper around `to_json_dictionary` that writes to a file at the given path.
func write_to_file(path: String) -> Error:
var mat_file := FileAccess.open(path, FileAccess.WRITE)
if mat_file == null:
return ERR_CANT_OPEN
var json_dict: Dictionary = to_json_dictionary()
mat_file.store_string(JSON.stringify(json_dict))
mat_file.store_string("\n")
return OK