mirror of
https://github.com/godotengine/godot-demo-projects.git
synced 2025-12-16 13:30:07 +01:00
Update plugin demos
This commit is contained in:
@@ -6,9 +6,12 @@ be used with [Godot Engine](https://godotengine.org), the open source
|
||||
|
||||
## Important note
|
||||
|
||||
- The `master` branch is compatible with the latest Godot version (currently 3.1).
|
||||
- Use the appropriate branch for your Godot version, such as the
|
||||
[`2.1`](https://github.com/godotengine/godot-demo-projects/tree/2.1) branch
|
||||
- The `master` branch is compatible with the latest stable Godot version (currently 3.1).
|
||||
- If you are using an older version of Godot, use the appropriate branch for your Godot version:
|
||||
|
||||
- [`3.0`](https://github.com/godotengine/godot-demo-projects/tree/3.0) branch
|
||||
for Godot 3.0.x.
|
||||
- [`2.1`](https://github.com/godotengine/godot-demo-projects/tree/2.1) branch
|
||||
for Godot 2.1.x.
|
||||
|
||||
## Useful links
|
||||
|
||||
9
plugins/README.md
Normal file
9
plugins/README.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# Plugin demos
|
||||
|
||||
To use these plugins, copy any of these folders to the `addons/` folder in a Godot project.
|
||||
|
||||
For example, the path would look like: `addons/custom_node`
|
||||
|
||||
Plugins can be distributed and installed from the UI. If you make a zip that contains the folder, Godot will recognize it as a plugin and will allow you to install it.
|
||||
|
||||
This can be done via the terminal: `zip -r custom_node.zip custom_node/*`
|
||||
@@ -1,56 +0,0 @@
|
||||
[gd_scene format=2]
|
||||
|
||||
[node name="CustomDock" type="VBoxContainer"]
|
||||
__meta__ = {
|
||||
"__editor_plugin_screen__": "2D"
|
||||
}
|
||||
|
||||
[node name="Title" type="Label" parent="."]
|
||||
margin_right = 141.0
|
||||
margin_bottom = 14.0
|
||||
text = "This is a Custom Dock"
|
||||
|
||||
[node name="Button" type="Button" parent="."]
|
||||
margin_top = 18.0
|
||||
margin_right = 141.0
|
||||
margin_bottom = 38.0
|
||||
text = "Really cool"
|
||||
|
||||
[node name="GridContainer" type="GridContainer" parent="."]
|
||||
margin_top = 42.0
|
||||
margin_right = 141.0
|
||||
margin_bottom = 74.0
|
||||
columns = 2
|
||||
|
||||
[node name="One" type="Label" parent="GridContainer"]
|
||||
margin_right = 36.0
|
||||
margin_bottom = 14.0
|
||||
text = "One"
|
||||
|
||||
[node name="Two" type="Label" parent="GridContainer"]
|
||||
margin_left = 40.0
|
||||
margin_right = 68.0
|
||||
margin_bottom = 14.0
|
||||
text = "Two"
|
||||
|
||||
[node name="Three" type="Label" parent="GridContainer"]
|
||||
margin_top = 18.0
|
||||
margin_right = 36.0
|
||||
margin_bottom = 32.0
|
||||
text = "Three"
|
||||
|
||||
[node name="Four" type="Label" parent="GridContainer"]
|
||||
margin_left = 40.0
|
||||
margin_top = 18.0
|
||||
margin_right = 68.0
|
||||
margin_bottom = 32.0
|
||||
text = "Four"
|
||||
|
||||
[node name="OptionButton" type="OptionButton" parent="."]
|
||||
margin_top = 78.0
|
||||
margin_right = 141.0
|
||||
margin_bottom = 98.0
|
||||
text = "Heho"
|
||||
items = [ "Heho", null, false, -1, null ]
|
||||
selected = 0
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
tool
|
||||
extends EditorPlugin
|
||||
|
||||
var dock = null
|
||||
|
||||
func _enter_tree():
|
||||
# When this plugin node enters tree, add the custom type
|
||||
dock = preload("res://addons/custom_dock/custom_dock.tscn").instance()
|
||||
add_control_to_dock(DOCK_SLOT_LEFT_UL, dock)
|
||||
|
||||
func _exit_tree():
|
||||
# Remove from docks (must be called so layout is updated and saved)
|
||||
remove_control_from_docks(dock)
|
||||
# Remove the node
|
||||
dock.free()
|
||||
@@ -1,7 +0,0 @@
|
||||
[plugin]
|
||||
|
||||
name="Custom Dock"
|
||||
description="Adds a new Customizable Dock"
|
||||
author="Juan Linietsky"
|
||||
version="1.0"
|
||||
script="dock_plugin.gd"
|
||||
@@ -1,14 +0,0 @@
|
||||
[remap]
|
||||
|
||||
importer="demos.sillymaterial"
|
||||
type="Material"
|
||||
path="res://.import/test.mtxt-0850936d050b34fd8096ae7fe7a591cc.res"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/custom_import_plugin/test.mtxt"
|
||||
dest_files=[ "res://.import/test.mtxt-0850936d050b34fd8096ae7fe7a591cc.res" ]
|
||||
|
||||
[params]
|
||||
|
||||
use_red_anyway=false
|
||||
@@ -1,308 +0,0 @@
|
||||
[gd_scene load_steps=2 format=2]
|
||||
|
||||
[ext_resource path="res://addons/custom_material_creator/silly_material_creator.gd" type="Script" id=1]
|
||||
|
||||
[node name="Silly Material Creator" type="Panel"]
|
||||
|
||||
anchor_left = 0.0
|
||||
anchor_top = 0.0
|
||||
anchor_right = 0.0
|
||||
anchor_bottom = 0.0
|
||||
margin_right = 220.0
|
||||
margin_bottom = 340.0
|
||||
rect_pivot_offset = Vector2( 0, 0 )
|
||||
rect_clip_content = false
|
||||
mouse_filter = 0
|
||||
size_flags_horizontal = 1
|
||||
size_flags_vertical = 1
|
||||
script = ExtResource( 1 )
|
||||
_sections_unfolded = [ "custom_styles" ]
|
||||
|
||||
[node name="Label_dock_name" type="Label" parent="."]
|
||||
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.0
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.0
|
||||
margin_left = -110.0
|
||||
margin_top = 10.0
|
||||
margin_right = 73.0
|
||||
margin_bottom = 24.0
|
||||
rect_scale = Vector2( 1.2, 1.2 )
|
||||
rect_pivot_offset = Vector2( 0, 0 )
|
||||
rect_clip_content = false
|
||||
mouse_filter = 2
|
||||
size_flags_horizontal = 1
|
||||
size_flags_vertical = 4
|
||||
custom_colors/font_color_shadow = Color( 0, 0, 0, 1 )
|
||||
custom_constants/shadow_as_outline = 1
|
||||
text = "Silly material creator"
|
||||
align = 1
|
||||
percent_visible = 1.0
|
||||
lines_skipped = 0
|
||||
max_lines_visible = -1
|
||||
_sections_unfolded = [ "Rect", "custom_colors" ]
|
||||
|
||||
[node name="Label_albedo" type="Label" parent="."]
|
||||
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.0
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.0
|
||||
margin_left = -100.0
|
||||
margin_top = 50.0
|
||||
margin_right = 100.0
|
||||
margin_bottom = 64.0
|
||||
rect_pivot_offset = Vector2( 0, 0 )
|
||||
rect_clip_content = false
|
||||
mouse_filter = 2
|
||||
size_flags_horizontal = 1
|
||||
size_flags_vertical = 4
|
||||
text = "Albedo color"
|
||||
align = 1
|
||||
percent_visible = 1.0
|
||||
lines_skipped = 0
|
||||
max_lines_visible = -1
|
||||
|
||||
[node name="ColorPicker_albedo" type="ColorPickerButton" parent="."]
|
||||
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.0
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.0
|
||||
margin_left = -100.0
|
||||
margin_top = 70.0
|
||||
margin_right = 100.0
|
||||
margin_bottom = 90.0
|
||||
rect_pivot_offset = Vector2( 0, 0 )
|
||||
rect_clip_content = false
|
||||
mouse_filter = 0
|
||||
size_flags_horizontal = 1
|
||||
size_flags_vertical = 1
|
||||
toggle_mode = false
|
||||
enabled_focus_mode = 2
|
||||
shortcut = null
|
||||
group = null
|
||||
flat = false
|
||||
color = Color( 1, 1, 1, 1 )
|
||||
edit_alpha = true
|
||||
|
||||
[node name="Label_metallic" type="Label" parent="."]
|
||||
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.0
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.0
|
||||
margin_left = -100.0
|
||||
margin_top = 100.0
|
||||
margin_right = 100.0
|
||||
margin_bottom = 114.0
|
||||
rect_pivot_offset = Vector2( 0, 0 )
|
||||
rect_clip_content = false
|
||||
mouse_filter = 2
|
||||
size_flags_horizontal = 1
|
||||
size_flags_vertical = 4
|
||||
text = "Metallic strength"
|
||||
align = 1
|
||||
percent_visible = 1.0
|
||||
lines_skipped = 0
|
||||
max_lines_visible = -1
|
||||
|
||||
[node name="HSlider_metallic" type="HSlider" parent="."]
|
||||
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.0
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.0
|
||||
margin_left = -100.0
|
||||
margin_top = 120.0
|
||||
margin_right = 100.0
|
||||
margin_bottom = 136.0
|
||||
rect_pivot_offset = Vector2( 0, 0 )
|
||||
rect_clip_content = false
|
||||
mouse_filter = 0
|
||||
size_flags_horizontal = 1
|
||||
size_flags_vertical = 0
|
||||
min_value = 0.0
|
||||
max_value = 1.0
|
||||
step = 0.05
|
||||
page = 0.0
|
||||
value = 0.0
|
||||
exp_edit = false
|
||||
rounded = false
|
||||
editable = true
|
||||
tick_count = 0
|
||||
ticks_on_borders = false
|
||||
focus_mode = 2
|
||||
|
||||
[node name="Label_roughness" type="Label" parent="."]
|
||||
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.0
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.0
|
||||
margin_left = -100.0
|
||||
margin_top = 150.0
|
||||
margin_right = 100.0
|
||||
margin_bottom = 164.0
|
||||
rect_pivot_offset = Vector2( 0, 0 )
|
||||
rect_clip_content = false
|
||||
mouse_filter = 2
|
||||
size_flags_horizontal = 1
|
||||
size_flags_vertical = 4
|
||||
text = "Roughness strength"
|
||||
align = 1
|
||||
percent_visible = 1.0
|
||||
lines_skipped = 0
|
||||
max_lines_visible = -1
|
||||
|
||||
[node name="HSlider_roughness" type="HSlider" parent="."]
|
||||
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.0
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.0
|
||||
margin_left = -100.0
|
||||
margin_top = 170.0
|
||||
margin_right = 100.0
|
||||
margin_bottom = 186.0
|
||||
rect_pivot_offset = Vector2( 0, 0 )
|
||||
rect_clip_content = false
|
||||
mouse_filter = 0
|
||||
size_flags_horizontal = 1
|
||||
size_flags_vertical = 0
|
||||
min_value = 0.0
|
||||
max_value = 1.0
|
||||
step = 0.05
|
||||
page = 0.0
|
||||
value = 0.0
|
||||
exp_edit = false
|
||||
rounded = false
|
||||
editable = true
|
||||
tick_count = 0
|
||||
ticks_on_borders = false
|
||||
focus_mode = 2
|
||||
|
||||
[node name="Button_save" type="Button" parent="."]
|
||||
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.0
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.0
|
||||
margin_left = -100.0
|
||||
margin_top = 210.0
|
||||
margin_right = 100.0
|
||||
margin_bottom = 260.0
|
||||
rect_pivot_offset = Vector2( 0, 0 )
|
||||
rect_clip_content = false
|
||||
mouse_filter = 0
|
||||
size_flags_horizontal = 1
|
||||
size_flags_vertical = 1
|
||||
toggle_mode = false
|
||||
enabled_focus_mode = 2
|
||||
shortcut = null
|
||||
group = null
|
||||
text = "Save silly material"
|
||||
flat = false
|
||||
|
||||
[node name="Button_load" type="Button" parent="."]
|
||||
|
||||
editor/display_folded = true
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.0
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.0
|
||||
margin_left = -100.0
|
||||
margin_top = 270.0
|
||||
margin_right = 100.0
|
||||
margin_bottom = 330.0
|
||||
rect_pivot_offset = Vector2( 0, 0 )
|
||||
rect_clip_content = false
|
||||
mouse_filter = 0
|
||||
size_flags_horizontal = 1
|
||||
size_flags_vertical = 1
|
||||
toggle_mode = false
|
||||
enabled_focus_mode = 2
|
||||
shortcut = null
|
||||
group = null
|
||||
flat = false
|
||||
clip_text = true
|
||||
__meta__ = {
|
||||
"_edit_group_": true
|
||||
}
|
||||
|
||||
[node name="Label" type="Label" parent="Button_load"]
|
||||
|
||||
anchor_left = 0.0
|
||||
anchor_top = 0.0
|
||||
anchor_right = 0.0
|
||||
anchor_bottom = 0.0
|
||||
margin_right = 200.0
|
||||
margin_bottom = 60.0
|
||||
rect_pivot_offset = Vector2( 0, 0 )
|
||||
rect_clip_content = false
|
||||
mouse_filter = 2
|
||||
size_flags_horizontal = 1
|
||||
size_flags_vertical = 4
|
||||
text = "Load silly material
|
||||
and apply to selected node(s)"
|
||||
align = 1
|
||||
valign = 1
|
||||
autowrap = true
|
||||
percent_visible = 1.0
|
||||
lines_skipped = 0
|
||||
max_lines_visible = -1
|
||||
|
||||
[node name="Save_FileDialog" type="FileDialog" parent="."]
|
||||
|
||||
visible = false
|
||||
anchor_left = 0.0
|
||||
anchor_top = 0.0
|
||||
anchor_right = 0.0
|
||||
anchor_bottom = 0.0
|
||||
margin_left = 150.0
|
||||
margin_top = 20.0
|
||||
margin_right = 600.0
|
||||
margin_bottom = 360.0
|
||||
rect_min_size = Vector2( 200, 70 )
|
||||
rect_pivot_offset = Vector2( 0, 0 )
|
||||
rect_clip_content = false
|
||||
mouse_filter = 0
|
||||
size_flags_horizontal = 1
|
||||
size_flags_vertical = 1
|
||||
popup_exclusive = false
|
||||
window_title = "Save a File"
|
||||
resizable = true
|
||||
dialog_hide_on_ok = false
|
||||
mode = 4
|
||||
access = 0
|
||||
filters = PoolStringArray( "*.silly_mat" )
|
||||
show_hidden_files = false
|
||||
|
||||
[node name="Load_FileDialog" type="FileDialog" parent="."]
|
||||
|
||||
visible = false
|
||||
anchor_left = 0.0
|
||||
anchor_top = 0.0
|
||||
anchor_right = 0.0
|
||||
anchor_bottom = 0.0
|
||||
margin_left = 150.0
|
||||
margin_top = 20.0
|
||||
margin_right = 600.0
|
||||
margin_bottom = 360.0
|
||||
rect_min_size = Vector2( 200, 70 )
|
||||
rect_pivot_offset = Vector2( 0, 0 )
|
||||
rect_clip_content = false
|
||||
mouse_filter = 0
|
||||
size_flags_horizontal = 1
|
||||
size_flags_vertical = 1
|
||||
popup_exclusive = false
|
||||
window_title = "Open a File"
|
||||
resizable = true
|
||||
dialog_hide_on_ok = false
|
||||
mode = 0
|
||||
access = 0
|
||||
filters = PoolStringArray( "*.silly_mat" )
|
||||
show_hidden_files = false
|
||||
|
||||
|
||||
@@ -1,91 +0,0 @@
|
||||
tool
|
||||
extends Panel
|
||||
|
||||
var silly_material_resource = preload("res://addons/custom_material_creator/silly_material_resource.gd")
|
||||
var editor_interface
|
||||
|
||||
func _ready():
|
||||
# Connect all of the signals we'll need to save and load silly materials
|
||||
get_node("Button_save").connect("pressed", self, "save_pressed")
|
||||
get_node("Button_load").connect("pressed", self, "load_pressed")
|
||||
get_node("Save_FileDialog").connect("file_selected", self, "save_file_selected")
|
||||
get_node("Load_FileDialog").connect("file_selected", self, "load_file_selected")
|
||||
|
||||
|
||||
func save_pressed():
|
||||
get_node("Save_FileDialog").popup_centered()
|
||||
|
||||
func load_pressed():
|
||||
get_node("Load_FileDialog").popup_centered()
|
||||
|
||||
|
||||
func save_file_selected(path):
|
||||
# Get the values from the sliders and color picker
|
||||
var color = get_node("ColorPicker_albedo").color
|
||||
var metallic = get_node("HSlider_metallic").value
|
||||
var roughness = get_node("HSlider_roughness").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
|
||||
|
||||
# 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):
|
||||
# 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()
|
||||
|
||||
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
|
||||
|
||||
# Tell the silly resource (actually a node) to make a material
|
||||
SpatialMaterial_Silly = silly_resource.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, SpatialMaterial_Silly)
|
||||
|
||||
# Close the file and return true (success!)
|
||||
file.close()
|
||||
return true
|
||||
|
||||
# If the file does not exist, then return false (failure)
|
||||
else:
|
||||
return false
|
||||
|
||||
# If we somehow get here, then return false (failure)
|
||||
return false
|
||||
20
plugins/custom_node/README.md
Normal file
20
plugins/custom_node/README.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# Custom Node Plugin Demo
|
||||
|
||||
This plugin demo shows one way to create a custom node type in Godot.
|
||||
For more information, see this documentation article: https://docs.godotengine.org/en/latest/tutorials/plugins/editor/making_plugins.html#a-custom-node
|
||||
|
||||
A custom node type:
|
||||
|
||||
* Derives from an existing node type.
|
||||
|
||||
* Shows up in the type list when adding a new node.
|
||||
|
||||
* Has a script attached to add new behavior.
|
||||
|
||||
* May have a custom icon.
|
||||
|
||||
The way it works in this plugin is using the `add_custom_type` and `remove_custom_type` in the plugin script file.
|
||||
Using this method you can specify any name, base type, script, and icon for your custom node.
|
||||
|
||||
There is also another way to add custom node types, which is using the `class_name` keyword in a script. However,
|
||||
the `class_name` system is newer, may change in the future, and it is not available for C# or VisualScript.
|
||||
@@ -6,6 +6,7 @@ var heart = preload("res://addons/custom_node/heart.png")
|
||||
func _draw():
|
||||
draw_texture(heart, -heart.get_size() / 2)
|
||||
|
||||
|
||||
func _get_item_rect():
|
||||
# override
|
||||
return Rect2(-heart.get_size() / 2, heart.get_size())
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
importer="texture"
|
||||
type="StreamTexture"
|
||||
path="res://.import/heart.png-53d6538480df02caf4bbbee10b65a623.stex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
importer="texture"
|
||||
type="StreamTexture"
|
||||
path="res://.import/heart_icon.png-8f04adf78b3bd1a5c39f790588a1fa78.stex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ func _enter_tree():
|
||||
# When this plugin node enters tree, add the custom type
|
||||
add_custom_type("Heart", "Node2D", preload("res://addons/custom_node/heart.gd"), preload("res://addons/custom_node/heart_icon.png"))
|
||||
|
||||
|
||||
func _exit_tree():
|
||||
# When the plugin node exits the tree, remove the custom type
|
||||
remove_custom_type("Heart")
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[plugin]
|
||||
|
||||
name="Heart"
|
||||
name="Heart Plugin Demo"
|
||||
description="Adds a new Heart node in 2D"
|
||||
author="Juan Linietsky"
|
||||
version="1.0"
|
||||
|
||||
13
plugins/material_creator/README.md
Normal file
13
plugins/material_creator/README.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# 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 silly 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 silly material to a file, and then load it back into the plugin later.
|
||||
100
plugins/material_creator/material_creator.gd
Normal file
100
plugins/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/material_creator/material_dock.tscn
Normal file
137
plugins/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" )
|
||||
@@ -14,9 +14,10 @@ extends EditorPlugin
|
||||
var io_material_dialog
|
||||
|
||||
func _enter_tree():
|
||||
io_material_dialog = preload("res://addons/custom_material_creator/custom_material_dock.tscn").instance()
|
||||
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)
|
||||
@@ -44,8 +44,6 @@ func from_json(json_dict_as_string):
|
||||
|
||||
metallic_strength = json_dict["metallic_strength"]
|
||||
roughness_strength = json_dict["roughness_strength"]
|
||||
|
||||
return
|
||||
|
||||
|
||||
# Make a SpatialMaterial using our variables.
|
||||
@@ -1,7 +1,7 @@
|
||||
[plugin]
|
||||
|
||||
name="Silly Spatial Material Creator"
|
||||
name="Material Creator Plugin Demo"
|
||||
description="Loads and saves a 3D Material from an external text file"
|
||||
author="TwistedTwigleg"
|
||||
version="1.0"
|
||||
script="material_import.gd"
|
||||
script="material_plugin.gd"
|
||||
6
plugins/material_import_plugin/README.md
Normal file
6
plugins/material_import_plugin/README.md
Normal file
@@ -0,0 +1,6 @@
|
||||
# Material Import Plugin Demo
|
||||
|
||||
This plugin demo shows how a custom import system can be added to the editor. In this case, it imports a material.
|
||||
For more information, see this documentation article: https://docs.godotengine.org/en/latest/tutorials/plugins/editor/import_plugins.html
|
||||
|
||||
In the editor, try opening `test.mtxt`. Godot will recognize it and import it as a material because of this plugin.
|
||||
@@ -6,25 +6,32 @@ enum Presets { PRESET_DEFAULT }
|
||||
func get_importer_name():
|
||||
return "demos.sillymaterial"
|
||||
|
||||
|
||||
func get_visible_name():
|
||||
return "Silly Material"
|
||||
|
||||
|
||||
func get_recognized_extensions():
|
||||
return ["mtxt"]
|
||||
|
||||
|
||||
func get_save_extension():
|
||||
return "res"
|
||||
|
||||
|
||||
func get_resource_type():
|
||||
return "Material"
|
||||
|
||||
|
||||
func get_preset_count():
|
||||
return 1
|
||||
return Presets.size()
|
||||
|
||||
|
||||
func get_preset_name(preset):
|
||||
match preset:
|
||||
Presets.PRESET_DEFAULT: return "Default"
|
||||
_ : return "Unknown"
|
||||
_: return "Unknown"
|
||||
|
||||
|
||||
func get_import_options(preset):
|
||||
match preset:
|
||||
@@ -35,9 +42,11 @@ func get_import_options(preset):
|
||||
}]
|
||||
_: return []
|
||||
|
||||
|
||||
func get_option_visibility(option, options):
|
||||
return true
|
||||
|
||||
|
||||
func import(source_file, save_path, options, r_platform_variants, r_gen_files):
|
||||
var file = File.new()
|
||||
var err = file.open(source_file, File.READ)
|
||||
@@ -1,7 +1,7 @@
|
||||
[plugin]
|
||||
|
||||
name="Silly Material Importer"
|
||||
name="Material Importer Plugin Demo"
|
||||
description="Imports a 3D Material from an external text file"
|
||||
author="George Marques"
|
||||
version="1.0"
|
||||
script="material_import.gd"
|
||||
script="plugin.gd"
|
||||
@@ -4,9 +4,10 @@ extends EditorPlugin
|
||||
var import_plugin
|
||||
|
||||
func _enter_tree():
|
||||
import_plugin = preload("import_plugin.gd").new()
|
||||
import_plugin = preload("import.gd").new()
|
||||
add_import_plugin(import_plugin)
|
||||
|
||||
|
||||
func _exit_tree():
|
||||
remove_import_plugin(import_plugin)
|
||||
import_plugin = null
|
||||
14
plugins/material_import_plugin/test.mtxt.import
Normal file
14
plugins/material_import_plugin/test.mtxt.import
Normal file
@@ -0,0 +1,14 @@
|
||||
[remap]
|
||||
|
||||
importer="demos.sillymaterial"
|
||||
type="Material"
|
||||
path="res://.import/test.mtxt-32ce4469df24b9f725d1e3476ff3b332.res"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/material_import_plugin/test.mtxt"
|
||||
dest_files=[ "res://.import/test.mtxt-32ce4469df24b9f725d1e3476ff3b332.res" ]
|
||||
|
||||
[params]
|
||||
|
||||
use_red_anyway=false
|
||||
@@ -1,13 +0,0 @@
|
||||
|
||||
To install these, copy each of these folders to a folder:
|
||||
|
||||
addons/
|
||||
|
||||
inside your projects, example:
|
||||
|
||||
addons/custom_node
|
||||
|
||||
To distribute and install from UI, make a zip that contains the folder,
|
||||
example:
|
||||
|
||||
zip -r custom_node.zip custom_node/*
|
||||
Reference in New Issue
Block a user