Adds missing data
This commit is contained in:
parent
e6391d9fdd
commit
53cdcc3433
620 changed files with 47293 additions and 151 deletions
|
|
@ -0,0 +1,124 @@
|
|||
# MIT License
|
||||
#
|
||||
# Copyright (c) 2023 Mark McKay
|
||||
# https://github.com/blackears/cyclopsLevelBuilder
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in all
|
||||
# copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
@tool
|
||||
extends Window
|
||||
class_name CreateMaterialDialog
|
||||
|
||||
signal create_material(params:Dictionary)
|
||||
|
||||
var texture_list:Array[Texture2D]
|
||||
var parent_dir_path:String
|
||||
|
||||
var plugin:CyclopsLevelBuilder:
|
||||
get:
|
||||
return plugin
|
||||
set(value):
|
||||
if value == plugin:
|
||||
return
|
||||
|
||||
plugin = value
|
||||
#print("CreateMaterialDialog setting plugin")
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready():
|
||||
pass # Replace with function body.
|
||||
|
||||
|
||||
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||
func _process(delta):
|
||||
pass
|
||||
|
||||
|
||||
func _on_bn_okay_pressed():
|
||||
var mat_type:String = "standard" if %radio_stdMat.is_pressed() else "shader"
|
||||
var tgt_param:String = "albedo_texture"
|
||||
|
||||
|
||||
create_material.emit({
|
||||
"name": %line_material_name.text,
|
||||
"material_type" : mat_type,
|
||||
"shader_res_path" : %line_shader_path.text,
|
||||
"texture_parameter" : %target_slot.get_item_text(%target_slot.selected),
|
||||
"uv_parameter" : %uv_slot.get_item_text(%uv_slot.selected),
|
||||
"uv_type" : "1x1" if %radio_uv_1x1.is_pressed() else "pix_per_game_unit",
|
||||
"pix_per_game_unit" : %line_pix_per_game_unit.text.to_int(),
|
||||
"parent_dir" : parent_dir_path,
|
||||
"textures" : texture_list
|
||||
#material_type: ""
|
||||
})
|
||||
|
||||
hide()
|
||||
|
||||
|
||||
func _on_bn_cancel_pressed():
|
||||
hide()
|
||||
|
||||
|
||||
func _on_bn_browse_shader_pressed():
|
||||
%FileDialog.popup_centered()
|
||||
|
||||
|
||||
func _on_about_to_popup():
|
||||
#print("CreateMaterialDialog about to popup")
|
||||
|
||||
var ed_iface:EditorInterface = plugin.get_editor_interface()
|
||||
var efs:EditorFileSystem = ed_iface.get_resource_filesystem()
|
||||
|
||||
var root_dir:EditorFileSystemDirectory = efs.get_filesystem()
|
||||
|
||||
if !texture_list.is_empty():
|
||||
%line_material_name.text = texture_list[0].resource_path.get_file().get_basename()
|
||||
|
||||
|
||||
func _on_file_dialog_file_selected(path:String):
|
||||
var shader:Shader = ResourceLoader.load(path, "Shader")
|
||||
if !shader:
|
||||
return
|
||||
|
||||
%line_shader_path.text = path
|
||||
update_shader_slot_list()
|
||||
|
||||
func update_shader_slot_list():
|
||||
var path:String = %line_shader_path.text
|
||||
var shader:Shader = ResourceLoader.load(path, "Shader")
|
||||
%target_slot.clear()
|
||||
%uv_slot.clear()
|
||||
|
||||
#TYPE_VECTOR2
|
||||
if shader:
|
||||
#Array of dictionaries
|
||||
var params:Array = shader.get_shader_uniform_list()
|
||||
|
||||
for p in params:
|
||||
#print("shader param ", str(p))
|
||||
if p["hint_string"] == "Texture2D":
|
||||
%target_slot.add_item(p["name"])
|
||||
if p["type"] == TYPE_VECTOR2 || p["type"] == TYPE_VECTOR3:
|
||||
%uv_slot.add_item(p["name"])
|
||||
|
||||
|
||||
|
||||
|
||||
func _on_line_shader_path_text_changed(new_text):
|
||||
update_shader_slot_list()
|
||||
|
|
@ -0,0 +1,182 @@
|
|||
[gd_scene load_steps=6 format=3 uid="uid://b510d4yme5xtx"]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/cyclops_level_builder/docks/material_palette/material_viewer/create_material_dialog.gd" id="1_ysdvw"]
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_7cu3j"]
|
||||
bg_color = Color(0.309804, 0.309804, 0.309804, 0)
|
||||
border_width_left = 2
|
||||
border_width_top = 2
|
||||
border_width_right = 2
|
||||
border_width_bottom = 2
|
||||
|
||||
[sub_resource type="Theme" id="Theme_u2063"]
|
||||
PanelContainer/styles/panel = SubResource("StyleBoxFlat_7cu3j")
|
||||
|
||||
[sub_resource type="ButtonGroup" id="ButtonGroup_hlttb"]
|
||||
|
||||
[sub_resource type="ButtonGroup" id="ButtonGroup_rde8s"]
|
||||
|
||||
[node name="CreateMaterialDialog" type="Window"]
|
||||
title = "Create Material"
|
||||
position = Vector2i(0, 36)
|
||||
size = Vector2i(600, 400)
|
||||
script = ExtResource("1_ysdvw")
|
||||
|
||||
[node name="PanelContainer" type="PanelContainer" parent="."]
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="PanelContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="HBoxContainer2" type="HBoxContainer" parent="PanelContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Label" type="Label" parent="PanelContainer/VBoxContainer/HBoxContainer2"]
|
||||
layout_mode = 2
|
||||
text = "Material Name:"
|
||||
|
||||
[node name="line_material_name" type="LineEdit" parent="PanelContainer/VBoxContainer/HBoxContainer2"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
|
||||
[node name="PanelContainer2" type="PanelContainer" parent="PanelContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
theme = SubResource("Theme_u2063")
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="PanelContainer/VBoxContainer/PanelContainer2"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Label" type="Label" parent="PanelContainer/VBoxContainer/PanelContainer2/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
text = "Material Type"
|
||||
|
||||
[node name="radio_stdMat" type="CheckBox" parent="PanelContainer/VBoxContainer/PanelContainer2/VBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
button_pressed = true
|
||||
button_group = SubResource("ButtonGroup_hlttb")
|
||||
text = "StandardMaterial3D"
|
||||
|
||||
[node name="radio_shaderMat" type="CheckBox" parent="PanelContainer/VBoxContainer/PanelContainer2/VBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
button_group = SubResource("ButtonGroup_hlttb")
|
||||
text = "ShaderMaterial"
|
||||
|
||||
[node name="MarginContainer" type="MarginContainer" parent="PanelContainer/VBoxContainer/PanelContainer2/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
theme_override_constants/margin_left = 64
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="PanelContainer/VBoxContainer/PanelContainer2/VBoxContainer/MarginContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="PanelContainer/VBoxContainer/PanelContainer2/VBoxContainer/MarginContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Label" type="Label" parent="PanelContainer/VBoxContainer/PanelContainer2/VBoxContainer/MarginContainer/VBoxContainer/HBoxContainer"]
|
||||
layout_mode = 2
|
||||
text = "Shader:"
|
||||
|
||||
[node name="line_shader_path" type="LineEdit" parent="PanelContainer/VBoxContainer/PanelContainer2/VBoxContainer/MarginContainer/VBoxContainer/HBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
|
||||
[node name="bn_browse_shader" type="Button" parent="PanelContainer/VBoxContainer/PanelContainer2/VBoxContainer/MarginContainer/VBoxContainer/HBoxContainer"]
|
||||
layout_mode = 2
|
||||
tooltip_text = "Pick shader to use for material"
|
||||
text = "..."
|
||||
|
||||
[node name="HBoxContainer2" type="HBoxContainer" parent="PanelContainer/VBoxContainer/PanelContainer2/VBoxContainer/MarginContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Label" type="Label" parent="PanelContainer/VBoxContainer/PanelContainer2/VBoxContainer/MarginContainer/VBoxContainer/HBoxContainer2"]
|
||||
layout_mode = 2
|
||||
text = "Texture Parameter:"
|
||||
|
||||
[node name="target_slot" type="OptionButton" parent="PanelContainer/VBoxContainer/PanelContainer2/VBoxContainer/MarginContainer/VBoxContainer/HBoxContainer2"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
|
||||
[node name="HBoxContainer3" type="HBoxContainer" parent="PanelContainer/VBoxContainer/PanelContainer2/VBoxContainer/MarginContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Label" type="Label" parent="PanelContainer/VBoxContainer/PanelContainer2/VBoxContainer/MarginContainer/VBoxContainer/HBoxContainer3"]
|
||||
layout_mode = 2
|
||||
text = "UV Parameter:"
|
||||
|
||||
[node name="uv_slot" type="OptionButton" parent="PanelContainer/VBoxContainer/PanelContainer2/VBoxContainer/MarginContainer/VBoxContainer/HBoxContainer3"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
|
||||
[node name="PanelContainer" type="PanelContainer" parent="PanelContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
theme = SubResource("Theme_u2063")
|
||||
|
||||
[node name="VBoxContainer2" type="VBoxContainer" parent="PanelContainer/VBoxContainer/PanelContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Label" type="Label" parent="PanelContainer/VBoxContainer/PanelContainer/VBoxContainer2"]
|
||||
layout_mode = 2
|
||||
text = "UVs"
|
||||
|
||||
[node name="radio_uv_1x1" type="CheckBox" parent="PanelContainer/VBoxContainer/PanelContainer/VBoxContainer2"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
button_group = SubResource("ButtonGroup_rde8s")
|
||||
text = "1 x 1"
|
||||
|
||||
[node name="radio_uv_scale_to_pix" type="CheckBox" parent="PanelContainer/VBoxContainer/PanelContainer/VBoxContainer2"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
button_pressed = true
|
||||
button_group = SubResource("ButtonGroup_rde8s")
|
||||
text = "Scale to pixel size"
|
||||
|
||||
[node name="MarginContainer" type="MarginContainer" parent="PanelContainer/VBoxContainer/PanelContainer/VBoxContainer2"]
|
||||
layout_mode = 2
|
||||
theme_override_constants/margin_left = 64
|
||||
|
||||
[node name="HBoxContainer2" type="HBoxContainer" parent="PanelContainer/VBoxContainer/PanelContainer/VBoxContainer2/MarginContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Label" type="Label" parent="PanelContainer/VBoxContainer/PanelContainer/VBoxContainer2/MarginContainer/HBoxContainer2"]
|
||||
layout_mode = 2
|
||||
text = "Pixels per game unit"
|
||||
|
||||
[node name="line_pix_per_game_unit" type="LineEdit" parent="PanelContainer/VBoxContainer/PanelContainer/VBoxContainer2/MarginContainer/HBoxContainer2"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
text = "32"
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="PanelContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
alignment = 1
|
||||
|
||||
[node name="bn_okay" type="Button" parent="PanelContainer/VBoxContainer/HBoxContainer"]
|
||||
layout_mode = 2
|
||||
text = "Okay"
|
||||
|
||||
[node name="bn_cancel" type="Button" parent="PanelContainer/VBoxContainer/HBoxContainer"]
|
||||
layout_mode = 2
|
||||
text = "Cancel
|
||||
"
|
||||
|
||||
[node name="FileDialog" type="FileDialog" parent="."]
|
||||
unique_name_in_owner = true
|
||||
title = "Open a File"
|
||||
size = Vector2i(600, 400)
|
||||
ok_button_text = "Open"
|
||||
file_mode = 0
|
||||
|
||||
[connection signal="about_to_popup" from="." to="." method="_on_about_to_popup"]
|
||||
[connection signal="text_changed" from="PanelContainer/VBoxContainer/PanelContainer2/VBoxContainer/MarginContainer/VBoxContainer/HBoxContainer/line_shader_path" to="." method="_on_line_shader_path_text_changed"]
|
||||
[connection signal="pressed" from="PanelContainer/VBoxContainer/PanelContainer2/VBoxContainer/MarginContainer/VBoxContainer/HBoxContainer/bn_browse_shader" to="." method="_on_bn_browse_shader_pressed"]
|
||||
[connection signal="pressed" from="PanelContainer/VBoxContainer/HBoxContainer/bn_okay" to="." method="_on_bn_okay_pressed"]
|
||||
[connection signal="pressed" from="PanelContainer/VBoxContainer/HBoxContainer/bn_cancel" to="." method="_on_bn_cancel_pressed"]
|
||||
[connection signal="file_selected" from="FileDialog" to="." method="_on_file_dialog_file_selected"]
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
# MIT License
|
||||
#
|
||||
# Copyright (c) 2023 Mark McKay
|
||||
# https://github.com/blackears/cyclopsLevelBuilder
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in all
|
||||
# copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
|
||||
@tool
|
||||
extends PopupPanel
|
||||
class_name LineInput
|
||||
|
||||
@export var text:String:
|
||||
get:
|
||||
return text
|
||||
set(value):
|
||||
text = value
|
||||
title = value
|
||||
#%Label.text = text
|
||||
|
||||
@export var edit_text:String:
|
||||
get:
|
||||
return edit_text
|
||||
set(value):
|
||||
edit_text = value
|
||||
%LineEdit.text = text
|
||||
|
||||
signal text_chosen(text:String)
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready():
|
||||
#%Label.text = text
|
||||
#%LineEdit.text = edit_text
|
||||
pass # Replace with function body.
|
||||
|
||||
|
||||
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||
func _process(delta):
|
||||
pass
|
||||
|
||||
|
||||
func _on_line_edit_text_submitted(new_text):
|
||||
text_chosen.emit(%LineEdit.text)
|
||||
hide()
|
||||
|
||||
|
||||
func _on_bn_accept_pressed():
|
||||
text_chosen.emit(%LineEdit.text)
|
||||
hide()
|
||||
|
||||
|
||||
func _on_bn_cancel_pressed():
|
||||
hide()
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
[gd_scene load_steps=2 format=3 uid="uid://tkp4i7e1fs5"]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/cyclops_level_builder/docks/material_palette/material_viewer/line_input.gd" id="1_5x46h"]
|
||||
|
||||
[node name="LineInput" type="PopupPanel"]
|
||||
title = "Input"
|
||||
size = Vector2i(200, 74)
|
||||
visible = true
|
||||
unresizable = false
|
||||
borderless = false
|
||||
always_on_top = true
|
||||
script = ExtResource("1_5x46h")
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="."]
|
||||
offset_left = 4.0
|
||||
offset_top = 4.0
|
||||
offset_right = 196.0
|
||||
offset_bottom = 70.0
|
||||
|
||||
[node name="LineEdit" type="LineEdit" parent="VBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
|
||||
[node name="CenterContainer" type="CenterContainer" parent="VBoxContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer/CenterContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="bn_accept" type="Button" parent="VBoxContainer/CenterContainer/HBoxContainer"]
|
||||
layout_mode = 2
|
||||
text = "Okay"
|
||||
|
||||
[node name="bn_cancel" type="Button" parent="VBoxContainer/CenterContainer/HBoxContainer"]
|
||||
layout_mode = 2
|
||||
text = "Cancel"
|
||||
|
||||
[connection signal="text_submitted" from="VBoxContainer/LineEdit" to="." method="_on_line_edit_text_submitted"]
|
||||
[connection signal="pressed" from="VBoxContainer/CenterContainer/HBoxContainer/bn_accept" to="." method="_on_bn_accept_pressed"]
|
||||
[connection signal="pressed" from="VBoxContainer/CenterContainer/HBoxContainer/bn_cancel" to="." method="_on_bn_cancel_pressed"]
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
[gd_resource type="Theme" load_steps=2 format=3 uid="uid://eajwlh2rlu3a"]
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_amf1g"]
|
||||
bg_color = Color(0, 0, 0, 1)
|
||||
border_width_left = 4
|
||||
border_width_top = 4
|
||||
border_width_right = 4
|
||||
border_width_bottom = 4
|
||||
border_color = Color(1, 0.890196, 0.729412, 1)
|
||||
corner_radius_top_left = 4
|
||||
corner_radius_top_right = 4
|
||||
corner_radius_bottom_right = 4
|
||||
corner_radius_bottom_left = 4
|
||||
|
||||
[resource]
|
||||
PanelContainer/styles/panel = SubResource("StyleBoxFlat_amf1g")
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
[gd_resource type="Theme" load_steps=2 format=3 uid="uid://di7ydnvl4n54r"]
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_amf1g"]
|
||||
bg_color = Color(0, 0, 0, 1)
|
||||
border_width_left = 4
|
||||
border_width_top = 4
|
||||
border_width_right = 4
|
||||
border_width_bottom = 4
|
||||
border_color = Color(0, 0, 0, 1)
|
||||
border_blend = true
|
||||
corner_radius_top_left = 4
|
||||
corner_radius_top_right = 4
|
||||
corner_radius_bottom_right = 4
|
||||
corner_radius_bottom_left = 4
|
||||
|
||||
[resource]
|
||||
PanelContainer/styles/panel = SubResource("StyleBoxFlat_amf1g")
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
[gd_resource type="Theme" load_steps=2 format=3 uid="uid://8ufqa1nourhn"]
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_amf1g"]
|
||||
bg_color = Color(0, 0, 0, 1)
|
||||
border_width_left = 4
|
||||
border_width_top = 4
|
||||
border_width_right = 4
|
||||
border_width_bottom = 4
|
||||
border_color = Color(1, 0.533333, 0, 1)
|
||||
corner_radius_top_left = 4
|
||||
corner_radius_top_right = 4
|
||||
corner_radius_bottom_right = 4
|
||||
corner_radius_bottom_left = 4
|
||||
|
||||
[resource]
|
||||
PanelContainer/styles/panel = SubResource("StyleBoxFlat_amf1g")
|
||||
|
|
@ -0,0 +1,154 @@
|
|||
# MIT License
|
||||
#
|
||||
# Copyright (c) 2023 Mark McKay
|
||||
# https://github.com/blackears/cyclopsLevelBuilder
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in all
|
||||
# copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
@tool
|
||||
extends PanelContainer
|
||||
class_name MaterialButton
|
||||
|
||||
signal apply_material(mat_bn:MaterialButton)
|
||||
signal select_material(mat_bn:MaterialButton, selection_type:SelectionList.Type)
|
||||
|
||||
@export var selected:bool = false:
|
||||
get:
|
||||
return selected
|
||||
set(value):
|
||||
if selected == value:
|
||||
return
|
||||
selected = value
|
||||
update_border()
|
||||
|
||||
@export var active:bool = false:
|
||||
get:
|
||||
return active
|
||||
set(value):
|
||||
if active == value:
|
||||
return
|
||||
active = value
|
||||
update_border()
|
||||
|
||||
@export_file("*.tres") var material_path:String:
|
||||
get:
|
||||
return material_path
|
||||
set(value):
|
||||
if material_path == value:
|
||||
return
|
||||
|
||||
material_path = value
|
||||
|
||||
dirty = true
|
||||
|
||||
|
||||
@export var group:RadioButtonGroup:
|
||||
get:
|
||||
return group
|
||||
set(value):
|
||||
if group == value:
|
||||
return
|
||||
|
||||
if group != null:
|
||||
group.remove_button(self)
|
||||
|
||||
group = value
|
||||
|
||||
if group != null:
|
||||
group.add_button(self)
|
||||
|
||||
@export var theme_normal:Theme = preload("res://addons/cyclops_level_builder/docks/material_palette/material_viewer/mat_bn_normal_theme.tres")
|
||||
@export var theme_selected:Theme = preload("res://addons/cyclops_level_builder/docks/material_palette/material_viewer/mat_bn_selected_theme.tres")
|
||||
@export var theme_active:Theme = preload("res://addons/cyclops_level_builder/docks/material_palette/material_viewer/mat_bn_active_theme.tres")
|
||||
|
||||
var plugin:CyclopsLevelBuilder:
|
||||
get:
|
||||
return plugin
|
||||
set(value):
|
||||
if value == plugin:
|
||||
return
|
||||
|
||||
plugin = value
|
||||
|
||||
dirty = true
|
||||
|
||||
var dirty:bool = true
|
||||
|
||||
var material_local:Material
|
||||
|
||||
func rebuild_thumbnail():
|
||||
if !plugin:
|
||||
return
|
||||
|
||||
var rp:EditorResourcePreview = plugin.get_editor_interface().get_resource_previewer()
|
||||
rp.queue_resource_preview(material_path, self, "resource_preview_callback", null)
|
||||
|
||||
material_local = ResourceLoader.load(material_path, "Material")
|
||||
# material_local = load(material_path)
|
||||
%MaterialName.text = GeneralUtil.calc_resource_name(material_local)
|
||||
tooltip_text = material_path
|
||||
|
||||
func resource_preview_callback(path:String, preview:Texture2D, thumbnail_preview:Texture2D, userdata:Variant):
|
||||
#print("Set bn tex ", path)
|
||||
%TextureRect.texture = preview
|
||||
|
||||
|
||||
func _gui_input(event:InputEvent):
|
||||
if event is InputEventMouseButton:
|
||||
var e:InputEventMouseButton = event
|
||||
|
||||
if e.button_index == MOUSE_BUTTON_LEFT:
|
||||
|
||||
if e.pressed:
|
||||
if e.double_click:
|
||||
#apply_material_to_selected()
|
||||
apply_material.emit(self)
|
||||
else:
|
||||
#if group:
|
||||
#group.select_thumbnail(self)
|
||||
#else:
|
||||
#selected = true
|
||||
|
||||
# builder.tool_material_path = material_path
|
||||
|
||||
select_material.emit(self, SelectionList.choose_type(e.shift_pressed, e.ctrl_pressed))
|
||||
|
||||
get_viewport().set_input_as_handled()
|
||||
|
||||
func update_border():
|
||||
if active:
|
||||
theme = theme_active
|
||||
elif selected:
|
||||
theme = theme_selected
|
||||
else:
|
||||
theme = theme_normal
|
||||
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready():
|
||||
update_border()
|
||||
pass # Replace with function body.
|
||||
|
||||
|
||||
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||
func _process(delta):
|
||||
if dirty:
|
||||
rebuild_thumbnail()
|
||||
dirty = false
|
||||
pass
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,58 @@
|
|||
# MIT License
|
||||
#
|
||||
# Copyright (c) 2023 Mark McKay
|
||||
# https://github.com/blackears/cyclopsLevelBuilder
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in all
|
||||
# copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
@tool
|
||||
extends RefCounted
|
||||
class_name MaterialGroup
|
||||
|
||||
class Tier:
|
||||
var name:String
|
||||
var children:Array[MaterialGroup]
|
||||
|
||||
func _init(name:String = ""):
|
||||
self.name = name
|
||||
|
||||
func create_child_with_name(name:String)->Tier:
|
||||
var child:Tier = Tier.new(name)
|
||||
children.append(child)
|
||||
return child
|
||||
|
||||
func get_child_with_name(name:String):
|
||||
for child in children:
|
||||
if child.name == name:
|
||||
return child
|
||||
return null
|
||||
|
||||
func get_child_index_with_name(name:String)->int:
|
||||
for i in children.size():
|
||||
if children[i].name == name:
|
||||
return i
|
||||
return -1
|
||||
|
||||
func remove_child_with_name(name:String):
|
||||
var idx:int = get_child_index_with_name(name)
|
||||
if idx > -1:
|
||||
children.remove_at(idx)
|
||||
|
||||
var root:Tier = Tier.new("Any")
|
||||
|
||||
|
|
@ -0,0 +1,321 @@
|
|||
# MIT License
|
||||
#
|
||||
# Copyright (c) 2023 Mark McKay
|
||||
# https://github.com/blackears/cyclopsLevelBuilder
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in all
|
||||
# copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
@tool
|
||||
extends Tree
|
||||
class_name MaterialGroupsTree
|
||||
|
||||
signal visiblity_changed
|
||||
|
||||
enum ButtonType { VISIBLE }
|
||||
|
||||
const bn_vis_off = preload("res://addons/cyclops_level_builder/art/icons/eye_closed.svg")
|
||||
const bn_vis_on = preload("res://addons/cyclops_level_builder/art/icons/eye_open.svg")
|
||||
|
||||
@export var show_unused_dirs:bool = true:
|
||||
get:
|
||||
return show_unused_dirs
|
||||
set(value):
|
||||
if value == show_unused_dirs:
|
||||
return
|
||||
show_unused_dirs = value
|
||||
|
||||
reload_materials()
|
||||
|
||||
var plugin:CyclopsLevelBuilder:
|
||||
get:
|
||||
return plugin
|
||||
set(value):
|
||||
if value == plugin:
|
||||
return
|
||||
|
||||
if plugin:
|
||||
var ed_iface:EditorInterface = plugin.get_editor_interface()
|
||||
var efs:EditorFileSystem = ed_iface.get_resource_filesystem()
|
||||
efs.filesystem_changed.disconnect(on_filesystem_changed)
|
||||
efs.resources_reimported.disconnect(on_resources_reimported)
|
||||
efs.resources_reload.disconnect(on_resources_reload)
|
||||
|
||||
plugin = value
|
||||
%CreateMaterialDialog.plugin = plugin
|
||||
|
||||
if plugin:
|
||||
var ed_iface:EditorInterface = plugin.get_editor_interface()
|
||||
var efs:EditorFileSystem = ed_iface.get_resource_filesystem()
|
||||
efs.filesystem_changed.connect(on_filesystem_changed)
|
||||
efs.resources_reimported.connect(on_resources_reimported)
|
||||
efs.resources_reload.connect(on_resources_reload)
|
||||
|
||||
reload_materials()
|
||||
|
||||
var tree_item_to_path_map:Dictionary
|
||||
var path_to_tree_item_map:Dictionary
|
||||
|
||||
|
||||
func reload_materials():
|
||||
#print("reload_materials")
|
||||
clear()
|
||||
tree_item_to_path_map.clear()
|
||||
path_to_tree_item_map.clear()
|
||||
|
||||
if !plugin:
|
||||
return
|
||||
|
||||
var ed_iface:EditorInterface = plugin.get_editor_interface()
|
||||
var efs:EditorFileSystem = ed_iface.get_resource_filesystem()
|
||||
|
||||
var root_dir:EditorFileSystemDirectory = efs.get_filesystem()
|
||||
|
||||
var root_tree_item:TreeItem = create_item()
|
||||
root_tree_item.set_text(0, root_dir.get_name())
|
||||
root_tree_item.set_checked(1, true)
|
||||
root_tree_item.set_editable(1, true)
|
||||
|
||||
tree_item_to_path_map[root_tree_item] = root_dir.get_path()
|
||||
path_to_tree_item_map[root_dir.get_path()] = root_tree_item
|
||||
|
||||
build_tree_recursive(root_dir, root_tree_item)
|
||||
|
||||
collapse_unused_dirs()
|
||||
|
||||
|
||||
func build_tree_recursive(parent_dir:EditorFileSystemDirectory, tree_item_parent:TreeItem):
|
||||
#print("par_dir count ", parent_dir.get_path(), parent_dir.get_subdir_count())
|
||||
|
||||
for i in parent_dir.get_subdir_count():
|
||||
var child_dir:EditorFileSystemDirectory = parent_dir.get_subdir(i)
|
||||
#print("add child ", child_dir.get_path())
|
||||
|
||||
if !show_unused_dirs && !dir_has_materials_recursive(child_dir):
|
||||
continue
|
||||
|
||||
var item:TreeItem = create_item(tree_item_parent)
|
||||
item.set_text(0, child_dir.get_name())
|
||||
item.set_checked(1, true)
|
||||
#item.set_editable(1, true)
|
||||
item.add_button(1, bn_vis_on, ButtonType.VISIBLE, false, "Visible")
|
||||
|
||||
tree_item_to_path_map[item] = child_dir.get_path()
|
||||
path_to_tree_item_map[child_dir.get_path()] = item
|
||||
#print("path ", child_dir.get_path())
|
||||
|
||||
build_tree_recursive(child_dir, item)
|
||||
|
||||
|
||||
func on_filesystem_changed():
|
||||
reload_materials()
|
||||
pass
|
||||
|
||||
func on_resources_reimported(resources: PackedStringArray):
|
||||
pass
|
||||
|
||||
func on_resources_reload(resources: PackedStringArray):
|
||||
pass
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready():
|
||||
pass # Replace with function body.
|
||||
|
||||
|
||||
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||
func _process(delta):
|
||||
pass
|
||||
|
||||
func create_new_group():
|
||||
pass
|
||||
|
||||
func delete_selected_group():
|
||||
pass
|
||||
|
||||
func rename_selected_group():
|
||||
pass
|
||||
|
||||
func _on_item_selected():
|
||||
var item:TreeItem = get_selected()
|
||||
item.get_index()
|
||||
pass # Replace with function body.
|
||||
|
||||
|
||||
func _on_item_edited():
|
||||
var item:TreeItem = get_edited()
|
||||
pass # Replace with function body.
|
||||
|
||||
|
||||
func _on_popup_menu_id_pressed(id:int):
|
||||
match id:
|
||||
0:
|
||||
create_new_group()
|
||||
1:
|
||||
delete_selected_group()
|
||||
2:
|
||||
rename_selected_group()
|
||||
|
||||
|
||||
|
||||
func _on_button_clicked(item:TreeItem, column:int, id:int, mouse_button_index:int):
|
||||
var checked:bool = !item.is_checked(1)
|
||||
item.set_checked(1, checked)
|
||||
item.set_button(1, ButtonType.VISIBLE, bn_vis_on if checked else bn_vis_off)
|
||||
visiblity_changed.emit()
|
||||
|
||||
func is_path_visible(path:String)->bool:
|
||||
if !path_to_tree_item_map.has(path):
|
||||
return false
|
||||
|
||||
var item:TreeItem = path_to_tree_item_map[path]
|
||||
return item.is_checked(1)
|
||||
|
||||
|
||||
func get_hidden_directories()->Array[String]:
|
||||
var ret_paths:Array[String]
|
||||
|
||||
for path in path_to_tree_item_map.keys():
|
||||
var item:TreeItem = path_to_tree_item_map[path]
|
||||
if !item.is_checked(1):
|
||||
ret_paths.append(path)
|
||||
|
||||
return ret_paths
|
||||
|
||||
func dir_has_materials(dir:EditorFileSystemDirectory)->bool:
|
||||
for i in dir.get_file_count():
|
||||
var file_type:StringName = dir.get_file_type(i)
|
||||
|
||||
if file_type == "StandardMaterial3D" || file_type == "ORMMaterial3D" || file_type == "ShaderMaterial":
|
||||
return true
|
||||
|
||||
return false
|
||||
|
||||
func dir_has_materials_recursive(dir:EditorFileSystemDirectory)->bool:
|
||||
if dir_has_materials(dir):
|
||||
return true
|
||||
|
||||
for i in dir.get_subdir_count():
|
||||
var child_dir:EditorFileSystemDirectory = dir.get_subdir(i)
|
||||
if dir_has_materials_recursive(child_dir):
|
||||
return true
|
||||
|
||||
return false
|
||||
|
||||
func collapse_unused_dirs():
|
||||
if !plugin:
|
||||
return
|
||||
|
||||
var ed_iface:EditorInterface = plugin.get_editor_interface()
|
||||
var efs:EditorFileSystem = ed_iface.get_resource_filesystem()
|
||||
|
||||
var root_dir:EditorFileSystemDirectory = efs.get_filesystem()
|
||||
collapse_unused_dirs_recursive(root_dir)
|
||||
|
||||
|
||||
func collapse_unused_dirs_recursive(dir:EditorFileSystemDirectory)->bool:
|
||||
#print("path ", dir.get_path())
|
||||
if !path_to_tree_item_map.has(dir.get_path()):
|
||||
return false
|
||||
|
||||
var item:TreeItem = path_to_tree_item_map[dir.get_path()]
|
||||
#print("item ", item.get_text(0))
|
||||
var expanded:bool = dir_has_materials(dir)
|
||||
# item.collapsed = !dir_has_materials(dir)
|
||||
#
|
||||
for i in dir.get_subdir_count():
|
||||
var child_dir:EditorFileSystemDirectory = dir.get_subdir(i)
|
||||
var result:bool = collapse_unused_dirs_recursive(child_dir)
|
||||
if result:
|
||||
expanded = true
|
||||
|
||||
item.collapsed = !expanded
|
||||
|
||||
return expanded
|
||||
|
||||
func _can_drop_data(at_position:Vector2, data:Variant):
|
||||
# print("_can_drop_data %s" % data)
|
||||
return typeof(data) == TYPE_DICTIONARY and data.has("type") and data["type"] == "files"
|
||||
|
||||
|
||||
func _drop_data(at_position:Vector2, data:Variant):
|
||||
var item:TreeItem = get_item_at_position(at_position)
|
||||
if !item:
|
||||
return
|
||||
|
||||
var files = data["files"]
|
||||
#print("--drop")
|
||||
var texture_list:Array[Texture2D]
|
||||
for f in files:
|
||||
# print("Dropping %s" % f)
|
||||
var res:Resource = load(f)
|
||||
if res is Texture2D:
|
||||
#print("Dropping %s" % res.resource_path)
|
||||
|
||||
texture_list.append(res)
|
||||
|
||||
if texture_list.is_empty():
|
||||
return
|
||||
|
||||
var parent_dir_path:String = tree_item_to_path_map[item]
|
||||
|
||||
%CreateMaterialDialog.parent_dir_path = parent_dir_path
|
||||
%CreateMaterialDialog.texture_list = texture_list
|
||||
%CreateMaterialDialog.popup_centered()
|
||||
#%CreateMaterialDialog.popup_on_parent()
|
||||
|
||||
func _on_create_material_dialog_create_material(params:Dictionary):
|
||||
|
||||
#Prepare texture
|
||||
var target_texture:Texture2D
|
||||
|
||||
var tex_list:Array = params["textures"]
|
||||
if tex_list.size() == 1:
|
||||
target_texture = tex_list[0]
|
||||
elif tex_list.size() > 1:
|
||||
var anim_tex:AnimatedTexture = AnimatedTexture.new()
|
||||
anim_tex.frames = tex_list.size()
|
||||
for i in tex_list.size():
|
||||
anim_tex.set_frame_texture(i, tex_list[i])
|
||||
|
||||
target_texture = anim_tex
|
||||
|
||||
#Create material
|
||||
if params["material_type"] == "standard":
|
||||
var new_mat:StandardMaterial3D = StandardMaterial3D.new()
|
||||
new_mat.albedo_texture = target_texture
|
||||
|
||||
if params["uv_type"] == "pix_per_game_unit":
|
||||
var ppgu:int = params["pix_per_game_unit"]
|
||||
new_mat.uv1_scale = Vector3(tex_list[0].get_width() / ppgu, tex_list[0].get_height() / ppgu, 1)
|
||||
|
||||
ResourceSaver.save(new_mat, params["parent_dir"] + "/" + params["name"] + ".tres")
|
||||
|
||||
elif params["material_type"] == "shader":
|
||||
var new_mat:ShaderMaterial = ShaderMaterial.new()
|
||||
new_mat.shader = ResourceLoader.load(params["shader_res_path"], "Shader")
|
||||
|
||||
#print("tex param ", params["texture_parameter"])
|
||||
new_mat.set_shader_parameter(params["texture_parameter"], target_texture)
|
||||
|
||||
if params["uv_type"] == "pix_per_game_unit":
|
||||
var ppgu:float = params["pix_per_game_unit"]
|
||||
new_mat.set_shader_parameter(params["uv_parameter"], Vector3(tex_list[0].get_width() / ppgu, tex_list[0].get_height() / ppgu, 1))
|
||||
|
||||
ResourceSaver.save(new_mat, params["parent_dir"] + "/" + params["name"] + ".tres")
|
||||
|
||||
pass # Replace with function body.
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
[gd_scene load_steps=3 format=3 uid="uid://cchlfqbh0djdn"]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/cyclops_level_builder/docks/material_palette/material_viewer/material_groups_tree.gd" id="1_u4dlj"]
|
||||
[ext_resource type="PackedScene" uid="uid://b510d4yme5xtx" path="res://addons/cyclops_level_builder/docks/material_palette/material_viewer/create_material_dialog.tscn" id="2_adfk6"]
|
||||
|
||||
[node name="MatGroupTree" type="Tree"]
|
||||
unique_name_in_owner = true
|
||||
columns = 2
|
||||
script = ExtResource("1_u4dlj")
|
||||
|
||||
[node name="PopupMenu" type="PopupMenu" parent="."]
|
||||
unique_name_in_owner = true
|
||||
item_count = 3
|
||||
item_0/text = "New Group"
|
||||
item_0/id = 0
|
||||
item_1/text = "Delete Group"
|
||||
item_1/id = 1
|
||||
item_2/text = "Rename"
|
||||
item_2/id = 2
|
||||
|
||||
[node name="CreateMaterialDialog" parent="." instance=ExtResource("2_adfk6")]
|
||||
unique_name_in_owner = true
|
||||
visible = false
|
||||
|
||||
[connection signal="button_clicked" from="." to="." method="_on_button_clicked"]
|
||||
[connection signal="item_edited" from="." to="." method="_on_item_edited"]
|
||||
[connection signal="item_selected" from="." to="." method="_on_item_selected"]
|
||||
[connection signal="id_pressed" from="PopupMenu" to="." method="_on_popup_menu_id_pressed"]
|
||||
[connection signal="create_material" from="CreateMaterialDialog" to="." method="_on_create_material_dialog_create_material"]
|
||||
|
|
@ -0,0 +1,240 @@
|
|||
# MIT License
|
||||
#
|
||||
# Copyright (c) 2023 Mark McKay
|
||||
# https://github.com/blackears/cyclopsLevelBuilder
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in all
|
||||
# copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
@tool
|
||||
extends PanelContainer
|
||||
class_name MaterialViewer
|
||||
|
||||
#var button_group:RadioButtonGroup = RadioButtonGroup.new()
|
||||
|
||||
var builder:CyclopsLevelBuilder:
|
||||
get:
|
||||
return builder
|
||||
set(value):
|
||||
if value == builder:
|
||||
return
|
||||
|
||||
if builder:
|
||||
var ed_iface:EditorInterface = builder.get_editor_interface()
|
||||
var efs:EditorFileSystem = ed_iface.get_resource_filesystem()
|
||||
efs.filesystem_changed.disconnect(on_filesystem_changed)
|
||||
efs.resources_reimported.disconnect(on_resources_reimported)
|
||||
efs.resources_reload.disconnect(on_resources_reload)
|
||||
|
||||
builder = value
|
||||
%MatGroupTree.plugin = builder
|
||||
|
||||
if builder:
|
||||
var ed_iface:EditorInterface = builder.get_editor_interface()
|
||||
var efs:EditorFileSystem = ed_iface.get_resource_filesystem()
|
||||
efs.filesystem_changed.connect(on_filesystem_changed)
|
||||
efs.resources_reimported.connect(on_resources_reimported)
|
||||
efs.resources_reload.connect(on_resources_reload)
|
||||
|
||||
reload_materials()
|
||||
|
||||
|
||||
var material_groups:MaterialGroup
|
||||
|
||||
var selected_material_paths:Array[String]
|
||||
var material_viewer_state:MaterialViewerState = preload("res://addons/cyclops_level_builder/docks/material_palette/material_viewer/material_viewer_state_res.tres")
|
||||
|
||||
func on_filesystem_changed():
|
||||
#print("on_filesystem_changed")
|
||||
reload_materials()
|
||||
pass
|
||||
|
||||
func on_resources_reimported(resources:PackedStringArray):
|
||||
#print("on_resources_reimported ", resources)
|
||||
pass
|
||||
|
||||
func on_resources_reload(resources:PackedStringArray):
|
||||
#print("on_resources_reload ", resources)
|
||||
pass
|
||||
|
||||
func reload_materials():
|
||||
#return
|
||||
|
||||
for child in %ButtonArea.get_children():
|
||||
%ButtonArea.remove_child(child)
|
||||
child.queue_free()
|
||||
|
||||
if !builder:
|
||||
return
|
||||
|
||||
var ed_iface:EditorInterface = builder.get_editor_interface()
|
||||
var efs:EditorFileSystem = ed_iface.get_resource_filesystem()
|
||||
|
||||
var efsd:EditorFileSystemDirectory = efs.get_filesystem()
|
||||
reload_materials_recursive(efsd)
|
||||
pass
|
||||
|
||||
func reload_materials_recursive(dir:EditorFileSystemDirectory):
|
||||
var mat_name_filter:String = %lineEd_filter.text
|
||||
|
||||
if !%MatGroupTree.is_path_visible(dir.get_path()):
|
||||
return
|
||||
#var vis = %MatGroupTree.is_path_visible(dir.get_path())
|
||||
#print("reload check path ", dir.get_path(), " vis ", vis)
|
||||
#get_hidden_directories()
|
||||
|
||||
var ed_iface:EditorInterface = builder.get_editor_interface()
|
||||
var res_prev:EditorResourcePreview = ed_iface.get_resource_previewer()
|
||||
|
||||
for i in dir.get_file_count():
|
||||
# dir.get_file(i)
|
||||
var type:String = dir.get_file_type(i)
|
||||
#"StandardMaterial3D"
|
||||
if type == "StandardMaterial3D" || type == "ShaderMaterial" || type == "ORMMaterial3D":
|
||||
var path:String = dir.get_file_path(i)
|
||||
|
||||
if !mat_name_filter.is_empty() && !path.contains(mat_name_filter):
|
||||
continue
|
||||
|
||||
#print("path %s type %s" % [path, type])
|
||||
|
||||
#res_prev.queue_resource_preview(path, self, "resource_preview_callback", null)
|
||||
|
||||
var bn:MaterialButton = preload("res://addons/cyclops_level_builder/docks/material_palette/material_viewer/material_button.tscn").instantiate()
|
||||
bn.material_path = path
|
||||
bn.plugin = builder
|
||||
bn.selected = selected_material_paths.has(path)
|
||||
bn.active = !selected_material_paths.is_empty() && path == selected_material_paths[-1]
|
||||
#button_group.add_button(bn)
|
||||
bn.apply_material.connect(func(mat_bn:MaterialButton): apply_material(mat_bn))
|
||||
bn.select_material.connect(func(mat_bn:MaterialButton, type:SelectionList.Type): select_material(mat_bn, type))
|
||||
|
||||
%ButtonArea.add_child(bn)
|
||||
pass
|
||||
|
||||
for i in dir.get_subdir_count():
|
||||
reload_materials_recursive(dir.get_subdir(i))
|
||||
|
||||
func apply_material(mat_bn:MaterialButton):
|
||||
var cmd:CommandSetMaterial = CommandSetMaterial.new()
|
||||
cmd.builder = builder
|
||||
cmd.material_path = mat_bn.material_path
|
||||
|
||||
var is_obj_mode:bool = builder.mode == CyclopsLevelBuilder.Mode.OBJECT
|
||||
|
||||
var sel_blocks:Array[CyclopsBlock] = builder.get_selected_blocks()
|
||||
for block in sel_blocks:
|
||||
if is_obj_mode:
|
||||
cmd.add_target(block.get_path(), block.control_mesh.get_face_indices())
|
||||
else:
|
||||
var face_indices:PackedInt32Array = block.control_mesh.get_face_indices(true)
|
||||
if !face_indices.is_empty():
|
||||
cmd.add_target(block.get_path(), face_indices)
|
||||
|
||||
if cmd.will_change_anything():
|
||||
var undo:EditorUndoRedoManager = builder.get_undo_redo()
|
||||
cmd.add_to_undo_manager(undo)
|
||||
|
||||
|
||||
func is_active_material(path:String):
|
||||
return !selected_material_paths.is_empty() && path == selected_material_paths[-1]
|
||||
|
||||
func select_material(mat_bn:MaterialButton, sel_type:SelectionList.Type):
|
||||
match sel_type:
|
||||
SelectionList.Type.REPLACE:
|
||||
selected_material_paths = [mat_bn.material_path]
|
||||
SelectionList.Type.TOGGLE:
|
||||
var idx:int = selected_material_paths.find(mat_bn.material_path)
|
||||
if idx >= 0:
|
||||
selected_material_paths.remove_at(idx)
|
||||
else:
|
||||
selected_material_paths.append(mat_bn.material_path)
|
||||
SelectionList.Type.RANGE:
|
||||
var bn_list = %ButtonArea.get_children()
|
||||
var range_from_idx:int = -1
|
||||
var range_to_idx:int = -1
|
||||
for i in bn_list.size():
|
||||
if bn_list[i] == mat_bn:
|
||||
range_to_idx = i
|
||||
if is_active_material(bn_list[i].material_path):
|
||||
range_from_idx = i
|
||||
|
||||
for i in range(range_from_idx, range_to_idx + (1 if range_from_idx < range_to_idx else -1), 1 if range_from_idx < range_to_idx else -1):
|
||||
var path = bn_list[i].material_path
|
||||
if selected_material_paths.has(path):
|
||||
selected_material_paths.erase(path)
|
||||
selected_material_paths.append(path)
|
||||
|
||||
material_viewer_state.active_material_path = \
|
||||
"" if selected_material_paths.is_empty() else selected_material_paths[-1]
|
||||
|
||||
#print("set sel mat: ", material_viewer_state.active_material_path)
|
||||
#print("sel mat list: ", selected_material_paths)
|
||||
|
||||
for bn in %ButtonArea.get_children():
|
||||
var mat_idx:int = selected_material_paths.find(bn.material_path)
|
||||
if mat_idx >= 0:
|
||||
if mat_idx == selected_material_paths.size() - 1:
|
||||
bn.active = true
|
||||
else:
|
||||
bn.active = false
|
||||
|
||||
bn.selected = true
|
||||
|
||||
else:
|
||||
bn.active = false
|
||||
bn.selected = false
|
||||
|
||||
|
||||
|
||||
#func resource_preview_callback(path:String, preview:Texture2D, userdata:Variant):
|
||||
#pass
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready():
|
||||
#material_groups = MaterialGroup.new("All")
|
||||
#
|
||||
#reload_materials()
|
||||
|
||||
|
||||
#var root:TreeItem = %Tree.create_item()
|
||||
#var child1:TreeItem = %Tree.create_item(root)
|
||||
#var child2:TreeItem = %Tree.create_item(root)
|
||||
#var subchild1:TreeItem = %Tree.create_item(child1)
|
||||
#subchild1.set_text(0, "Subchild1")
|
||||
|
||||
pass
|
||||
|
||||
|
||||
|
||||
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||
func _process(delta):
|
||||
pass
|
||||
|
||||
|
||||
func _on_line_ed_filter_text_changed(new_text):
|
||||
reload_materials()
|
||||
|
||||
|
||||
func _on_mat_group_tree_visiblity_changed():
|
||||
reload_materials()
|
||||
|
||||
|
||||
|
||||
func _on_bn_show_unused_dirs_toggled(toggled_on):
|
||||
%MatGroupTree.show_unused_dirs = toggled_on
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
[gd_scene load_steps=3 format=3 uid="uid://denc7grw42qsu"]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/cyclops_level_builder/docks/material_palette/material_viewer/material_viewer.gd" id="1_nrjye"]
|
||||
[ext_resource type="PackedScene" uid="uid://cchlfqbh0djdn" path="res://addons/cyclops_level_builder/docks/material_palette/material_viewer/material_groups_tree.tscn" id="2_8hnut"]
|
||||
|
||||
[node name="MaterialViewer" type="PanelContainer"]
|
||||
offset_right = 523.0
|
||||
offset_bottom = 350.0
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
script = ExtResource("1_nrjye")
|
||||
|
||||
[node name="HSplitContainer" type="HSplitContainer" parent="."]
|
||||
layout_mode = 2
|
||||
split_offset = 240
|
||||
|
||||
[node name="VBoxContainer2" type="VBoxContainer" parent="HSplitContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="HSplitContainer/VBoxContainer2"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="bn_show_unused_dirs" type="Button" parent="HSplitContainer/VBoxContainer2/HBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
tooltip_text = "Show unused directories"
|
||||
toggle_mode = true
|
||||
button_pressed = true
|
||||
text = "Show unused"
|
||||
|
||||
[node name="MatGroupTree" parent="HSplitContainer/VBoxContainer2" instance=ExtResource("2_8hnut")]
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 3
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="HSplitContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="HSplitContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Label" type="Label" parent="HSplitContainer/VBoxContainer/HBoxContainer"]
|
||||
layout_mode = 2
|
||||
text = "Filter:"
|
||||
|
||||
[node name="lineEd_filter" type="LineEdit" parent="HSplitContainer/VBoxContainer/HBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
tooltip_text = "Filter materials"
|
||||
|
||||
[node name="PanelContainer" type="PanelContainer" parent="HSplitContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 3
|
||||
|
||||
[node name="ScrollContainer" type="ScrollContainer" parent="HSplitContainer/VBoxContainer/PanelContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="ButtonArea" type="HFlowContainer" parent="HSplitContainer/VBoxContainer/PanelContainer/ScrollContainer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
|
||||
[connection signal="toggled" from="HSplitContainer/VBoxContainer2/HBoxContainer/bn_show_unused_dirs" to="." method="_on_bn_show_unused_dirs_toggled"]
|
||||
[connection signal="visiblity_changed" from="HSplitContainer/VBoxContainer2/MatGroupTree" to="." method="_on_mat_group_tree_visiblity_changed"]
|
||||
[connection signal="text_changed" from="HSplitContainer/VBoxContainer/HBoxContainer/lineEd_filter" to="." method="_on_line_ed_filter_text_changed"]
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
# MIT License
|
||||
#
|
||||
# Copyright (c) 2023 Mark McKay
|
||||
# https://github.com/blackears/cyclopsLevelBuilder
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in all
|
||||
# copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
@tool
|
||||
extends Resource
|
||||
class_name MaterialViewerState
|
||||
|
||||
@export var active_material_path:String:
|
||||
set(value):
|
||||
if active_material_path != value:
|
||||
active_material_path = value
|
||||
emit_changed()
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
[gd_resource type="Resource" script_class="MaterialViewerState" load_steps=2 format=3 uid="uid://cwq6b2p7f631n"]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/cyclops_level_builder/docks/material_palette/material_viewer/material_viewer_state.gd" id="1_3sifp"]
|
||||
|
||||
[resource]
|
||||
script = ExtResource("1_3sifp")
|
||||
active_material_path = "res://content/cardboard_material.tres"
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
# MIT License
|
||||
#
|
||||
# Copyright (c) 2023 Mark McKay
|
||||
# https://github.com/blackears/cyclopsLevelBuilder
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in all
|
||||
# copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
@tool
|
||||
extends Resource
|
||||
class_name RadioButtonGroup
|
||||
|
||||
var buttons:Array
|
||||
|
||||
func select_button(button):
|
||||
for t in buttons:
|
||||
t.selected = t == button
|
||||
|
||||
func add_button(button):
|
||||
buttons.append(button)
|
||||
|
||||
func remove_button(button):
|
||||
buttons.remove_at(buttons.find(button))
|
||||
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue