mirror of
https://github.com/godotengine/godot-demo-projects.git
synced 2025-12-16 13:30:07 +01:00
Refactor the plugin demos to be inside of a project for convenience
This commit is contained in:
20
plugins/addons/material_creator/README.md
Normal file
20
plugins/addons/material_creator/README.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# Material Creator Plugin Demo
|
||||
|
||||
This plugin demo contains a custom material creator
|
||||
interface using a custom dock in the editor.
|
||||
|
||||
Custom docks are made of Control nodes, they run in the
|
||||
editor, and any behavior must be done through `tool` scripts.
|
||||
For more information, see this documentation article:
|
||||
https://docs.godotengine.org/en/latest/tutorials/plugins/editor/making_plugins.html#a-custom-dock
|
||||
|
||||
This plugin allows you to specify color, metallic, and
|
||||
roughness values, and then use it as a material.
|
||||
|
||||
You can apply this material directly to Spatial
|
||||
nodes by selecting them and then clicking "Apply".
|
||||
This shows how a plugin can interact closely with the
|
||||
editor, manipulating nodes the user selects.
|
||||
|
||||
Alternatively, you can also save the material to
|
||||
a file, and then load it back into the plugin later.
|
||||
100
plugins/addons/material_creator/material_creator.gd
Normal file
100
plugins/addons/material_creator/material_creator.gd
Normal file
@@ -0,0 +1,100 @@
|
||||
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
|
||||
|
||||
func _ready():
|
||||
# Connect all of the signals we'll need to save and load silly materials
|
||||
get_node("VBoxContainer/ApplyButton").connect("pressed", self, "apply_pressed")
|
||||
get_node("VBoxContainer/SaveButton").connect("pressed", self, "save_pressed")
|
||||
get_node("VBoxContainer/LoadButton").connect("pressed", self, "load_pressed")
|
||||
get_node("SaveMaterialDialog").connect("file_selected", self, "save_file_selected")
|
||||
get_node("LoadMaterialDialog").connect("file_selected", self, "load_file_selected")
|
||||
VisualServer.canvas_item_set_clip(get_canvas_item(), true)
|
||||
|
||||
|
||||
func save_pressed():
|
||||
get_node("SaveMaterialDialog").popup_centered()
|
||||
|
||||
|
||||
func load_pressed():
|
||||
get_node("LoadMaterialDialog").popup_centered()
|
||||
|
||||
|
||||
func apply_pressed():
|
||||
# Using the passed in editor interface, get the selected nodes in the editor
|
||||
var editor_selection = editor_interface.get_selection()
|
||||
var selected_nodes = editor_selection.get_selected_nodes()
|
||||
if selected_nodes.size() == 0:
|
||||
printerr("Material Creator: Can't apply the material, because there are no nodes selected!")
|
||||
|
||||
var material = _silly_resource_from_values().make_material()
|
||||
# Go through the selected nodes and see if they have the 'set_surface_material'
|
||||
# function (which only MeshInstance 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_material"):
|
||||
node.set_surface_material(0, material)
|
||||
|
||||
|
||||
func save_file_selected(path):
|
||||
var silly_resource = _silly_resource_from_values()
|
||||
# Make a file, store the silly material as a json string, then close the file.
|
||||
var file = File.new()
|
||||
file.open(path, File.WRITE)
|
||||
file.store_string(silly_resource.make_json())
|
||||
file.close()
|
||||
|
||||
return true
|
||||
|
||||
|
||||
func load_file_selected(path):
|
||||
var file = File.new()
|
||||
var SpatialMaterial_Silly = null
|
||||
|
||||
# Make a new silly resource (which in this case actually is a node)
|
||||
# and initialize it
|
||||
var silly_resource = silly_material_resource.new()
|
||||
silly_resource.init()
|
||||
|
||||
# If the file exists, then open it
|
||||
if file.file_exists(path):
|
||||
file.open(path, File.READ)
|
||||
|
||||
# Get the JSON string and convert it into a silly material.
|
||||
var json_dict_as_string = file.get_line()
|
||||
if json_dict_as_string != null:
|
||||
silly_resource.from_json(json_dict_as_string)
|
||||
else:
|
||||
file.close()
|
||||
return false
|
||||
|
||||
get_node("VBoxContainer/AlbedoColorPicker").color = silly_resource.albedo_color
|
||||
get_node("VBoxContainer/MetallicSlider").value = silly_resource.metallic_strength
|
||||
get_node("VBoxContainer/RoughnessSlider").value = silly_resource.roughness_strength
|
||||
|
||||
# Close the file and return true (success!)
|
||||
file.close()
|
||||
return true
|
||||
|
||||
#else: If the file does not exist, then return false (failure)
|
||||
return false
|
||||
|
||||
|
||||
func _silly_resource_from_values():
|
||||
# Get the values from the sliders and color picker
|
||||
var color = get_node("VBoxContainer/AlbedoColorPicker").color
|
||||
var metallic = get_node("VBoxContainer/MetallicSlider").value
|
||||
var roughness = get_node("VBoxContainer/RoughnessSlider").value
|
||||
# Make a new silly resource (which in this case actually is a node) and initialize it
|
||||
var silly_resource = silly_material_resource.new()
|
||||
silly_resource.init()
|
||||
|
||||
# Assign the values
|
||||
silly_resource.albedo_color = color
|
||||
silly_resource.metallic_strength = metallic
|
||||
silly_resource.roughness_strength = roughness
|
||||
|
||||
return silly_resource
|
||||
137
plugins/addons/material_creator/material_dock.tscn
Normal file
137
plugins/addons/material_creator/material_dock.tscn
Normal file
@@ -0,0 +1,137 @@
|
||||
[gd_scene load_steps=2 format=2]
|
||||
|
||||
[ext_resource path="res://addons/material_creator/material_creator.gd" type="Script" id=1]
|
||||
|
||||
[node name="Material Creator Plugin" type="Panel"]
|
||||
margin_right = 220.0
|
||||
margin_bottom = 340.0
|
||||
rect_min_size = Vector2( 210, 410 )
|
||||
script = ExtResource( 1 )
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="."]
|
||||
anchor_left = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 1.0
|
||||
margin_left = -100.0
|
||||
margin_right = 100.0
|
||||
rect_min_size = Vector2( 0, 400 )
|
||||
|
||||
[node name="DockName" type="Label" parent="VBoxContainer"]
|
||||
margin_right = 200.0
|
||||
margin_bottom = 30.0
|
||||
rect_min_size = Vector2( 200, 30 )
|
||||
custom_colors/font_color_shadow = Color( 0, 0, 0, 1 )
|
||||
custom_constants/shadow_as_outline = 1
|
||||
text = "Material creator"
|
||||
align = 1
|
||||
valign = 2
|
||||
|
||||
[node name="AlbedoLabel" type="Label" parent="VBoxContainer"]
|
||||
margin_top = 34.0
|
||||
margin_right = 200.0
|
||||
margin_bottom = 64.0
|
||||
rect_min_size = Vector2( 200, 30 )
|
||||
text = "Albedo color"
|
||||
align = 1
|
||||
valign = 2
|
||||
|
||||
[node name="AlbedoColorPicker" type="ColorPickerButton" parent="VBoxContainer"]
|
||||
margin_top = 68.0
|
||||
margin_right = 200.0
|
||||
margin_bottom = 98.0
|
||||
rect_min_size = Vector2( 200, 30 )
|
||||
color = Color( 1, 1, 1, 1 )
|
||||
|
||||
[node name="MetallicLabel" type="Label" parent="VBoxContainer"]
|
||||
margin_top = 102.0
|
||||
margin_right = 200.0
|
||||
margin_bottom = 132.0
|
||||
rect_min_size = Vector2( 200, 30 )
|
||||
text = "Metallic strength"
|
||||
align = 1
|
||||
valign = 2
|
||||
|
||||
[node name="MetallicSlider" type="HSlider" parent="VBoxContainer"]
|
||||
margin_top = 136.0
|
||||
margin_right = 200.0
|
||||
margin_bottom = 166.0
|
||||
rect_min_size = Vector2( 200, 30 )
|
||||
max_value = 1.0
|
||||
step = 0.05
|
||||
|
||||
[node name="RoughnessLabel" type="Label" parent="VBoxContainer"]
|
||||
margin_top = 170.0
|
||||
margin_right = 200.0
|
||||
margin_bottom = 200.0
|
||||
rect_min_size = Vector2( 200, 30 )
|
||||
text = "Roughness strength"
|
||||
align = 1
|
||||
valign = 2
|
||||
|
||||
[node name="RoughnessSlider" type="HSlider" parent="VBoxContainer"]
|
||||
margin_top = 204.0
|
||||
margin_right = 200.0
|
||||
margin_bottom = 234.0
|
||||
rect_min_size = Vector2( 200, 30 )
|
||||
max_value = 1.0
|
||||
step = 0.05
|
||||
ticks_on_borders = true
|
||||
|
||||
[node name="HSeparator" type="HSeparator" parent="VBoxContainer"]
|
||||
margin_top = 238.0
|
||||
margin_right = 200.0
|
||||
margin_bottom = 258.0
|
||||
rect_min_size = Vector2( 200, 20 )
|
||||
|
||||
[node name="ApplyButton" type="Button" parent="VBoxContainer"]
|
||||
margin_top = 262.0
|
||||
margin_right = 200.0
|
||||
margin_bottom = 312.0
|
||||
rect_min_size = Vector2( 200, 50 )
|
||||
text = "Apply material"
|
||||
|
||||
[node name="SaveButton" type="Button" parent="VBoxContainer"]
|
||||
margin_top = 316.0
|
||||
margin_right = 200.0
|
||||
margin_bottom = 366.0
|
||||
rect_min_size = Vector2( 200, 50 )
|
||||
text = "Save material"
|
||||
|
||||
[node name="LoadButton" type="Button" parent="VBoxContainer"]
|
||||
margin_top = 370.0
|
||||
margin_right = 200.0
|
||||
margin_bottom = 420.0
|
||||
rect_min_size = Vector2( 200, 50 )
|
||||
text = "Load material"
|
||||
clip_text = true
|
||||
|
||||
[node name="Label" type="Label" parent="VBoxContainer/LoadButton"]
|
||||
visible = false
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
margin_bottom = -10.0
|
||||
rect_min_size = Vector2( 0, 50 )
|
||||
text = "Load silly material and
|
||||
apply to selected node(s)"
|
||||
align = 1
|
||||
valign = 1
|
||||
autowrap = true
|
||||
|
||||
[node name="SaveMaterialDialog" type="FileDialog" parent="."]
|
||||
margin_left = 150.0
|
||||
margin_top = 20.0
|
||||
margin_right = 600.0
|
||||
margin_bottom = 360.0
|
||||
resizable = true
|
||||
filters = PoolStringArray( "*.silly_mat" )
|
||||
|
||||
[node name="LoadMaterialDialog" type="FileDialog" parent="."]
|
||||
margin_left = 150.0
|
||||
margin_top = 20.0
|
||||
margin_right = 600.0
|
||||
margin_bottom = 360.0
|
||||
rect_min_size = Vector2( 200, 100 )
|
||||
window_title = "Open a File"
|
||||
resizable = true
|
||||
mode = 0
|
||||
filters = PoolStringArray( "*.silly_mat" )
|
||||
23
plugins/addons/material_creator/material_plugin.gd
Normal file
23
plugins/addons/material_creator/material_plugin.gd
Normal file
@@ -0,0 +1,23 @@
|
||||
# A simple (and silly) material resource plugin. Allows you to make a really simple material
|
||||
# from a custom dock, that you can save and load, and apply to selected MeshInstances.
|
||||
#
|
||||
# SPECIAL NOTE: This technically should be using EditorImportPlugin and EditorExportPlugin
|
||||
# to handle the input and output of the silly material. However, currently you cannot export
|
||||
# custom resources in Godot, so instead we're using JSON files instead.
|
||||
#
|
||||
# This example should be replaced when EditorImportPlugin and EditorExportPlugin are both
|
||||
# fully working and you can save custom resources.
|
||||
|
||||
tool
|
||||
extends EditorPlugin
|
||||
|
||||
var io_material_dialog
|
||||
|
||||
func _enter_tree():
|
||||
io_material_dialog = preload("res://addons/material_creator/material_dock.tscn").instance()
|
||||
io_material_dialog.editor_interface = get_editor_interface()
|
||||
add_control_to_dock(DOCK_SLOT_LEFT_UL, io_material_dialog)
|
||||
|
||||
|
||||
func _exit_tree():
|
||||
remove_control_from_docks(io_material_dialog)
|
||||
57
plugins/addons/material_creator/material_resource.gd
Normal file
57
plugins/addons/material_creator/material_resource.gd
Normal file
@@ -0,0 +1,57 @@
|
||||
tool
|
||||
extends Node
|
||||
|
||||
# NOTE: in theory this would extend from resource, but until saving and loading resources
|
||||
# works in godot, we'll stick with extending from node
|
||||
# and using JSON files to save/load data
|
||||
#
|
||||
# See material_import.gd for more information
|
||||
|
||||
var albedo_color
|
||||
var metallic_strength
|
||||
var roughness_strength
|
||||
|
||||
func init():
|
||||
albedo_color = Color()
|
||||
metallic_strength = 0
|
||||
roughness_strength = 0
|
||||
|
||||
|
||||
# Convert our data into an dictonary so we can convert it
|
||||
# into the JSON format
|
||||
func make_json():
|
||||
var json_dict = {}
|
||||
|
||||
json_dict["albedo_color"] = {}
|
||||
json_dict["albedo_color"]["r"] = albedo_color.r
|
||||
json_dict["albedo_color"]["g"] = albedo_color.g
|
||||
json_dict["albedo_color"]["b"] = albedo_color.b
|
||||
|
||||
json_dict["metallic_strength"] = metallic_strength
|
||||
json_dict["roughness_strength"] = roughness_strength
|
||||
|
||||
return to_json(json_dict)
|
||||
|
||||
|
||||
# Convert the passed in string to a json dictonary, and then
|
||||
# fill in our data.
|
||||
func from_json(json_dict_as_string):
|
||||
var json_dict = parse_json(json_dict_as_string)
|
||||
|
||||
albedo_color.r = json_dict["albedo_color"]["r"]
|
||||
albedo_color.g = json_dict["albedo_color"]["g"]
|
||||
albedo_color.b = json_dict["albedo_color"]["b"]
|
||||
|
||||
metallic_strength = json_dict["metallic_strength"]
|
||||
roughness_strength = json_dict["roughness_strength"]
|
||||
|
||||
|
||||
# Make a SpatialMaterial using our variables.
|
||||
func make_material():
|
||||
var mat = SpatialMaterial.new()
|
||||
|
||||
mat.albedo_color = albedo_color
|
||||
mat.metallic = metallic_strength
|
||||
mat.roughness = roughness_strength
|
||||
|
||||
return mat
|
||||
7
plugins/addons/material_creator/plugin.cfg
Normal file
7
plugins/addons/material_creator/plugin.cfg
Normal file
@@ -0,0 +1,7 @@
|
||||
[plugin]
|
||||
|
||||
name="Material Creator Plugin Demo"
|
||||
description="Loads and saves a 3D Material from an external text file"
|
||||
author="TwistedTwigleg"
|
||||
version="1.0"
|
||||
script="material_plugin.gd"
|
||||
Reference in New Issue
Block a user