built more assets and started playing with foliage painting

This commit is contained in:
derek
2024-12-04 17:02:46 -06:00
parent dd960cc00e
commit 478e2822d2
359 changed files with 34172 additions and 178 deletions

View File

@@ -0,0 +1,15 @@
[gd_scene format=3 uid="uid://2fwp1t7pk0r"]
[node name="UI_Category_Brushes" type="VBoxContainer"]
offset_right = 348.0
offset_bottom = 112.0
[node name="Label_Category" type="Label" parent="."]
layout_mode = 2
text = "Brushes"
horizontal_alignment = 1
vertical_alignment = 1
[node name="TabContainer_Brushes" type="TabContainer" parent="."]
layout_mode = 2
size_flags_vertical = 3

View File

@@ -0,0 +1,37 @@
[gd_scene format=3 uid="uid://c1llamk0isnv"]
[node name="UI_Category_Greenhouse" type="VBoxContainer"]
offset_top = 120.0
offset_right = 348.0
offset_bottom = 582.0
[node name="Label_Category_Plants" type="Label" parent="."]
layout_mode = 2
text = "Plants"
horizontal_alignment = 1
vertical_alignment = 1
[node name="TabContainer" type="TabContainer" parent="."]
layout_mode = 2
size_flags_vertical = 3
tabs_visible = false
[node name="VSplitContainer" type="VSplitContainer" parent="TabContainer"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
split_offset = 150
[node name="ScrollContainer_PlantThumbnails" type="ScrollContainer" parent="TabContainer/VSplitContainer"]
layout_mode = 2
horizontal_scroll_mode = 0
[node name="VBoxContainer" type="VBoxContainer" parent="TabContainer/VSplitContainer"]
layout_mode = 2
size_flags_vertical = 3
[node name="ScrollContainer_Properties" type="ScrollContainer" parent="TabContainer/VSplitContainer/VBoxContainer"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
horizontal_scroll_mode = 0

View File

@@ -0,0 +1,51 @@
@tool
extends MarginContainer
@export var arrow_down:ImageTexture = null
@export var arrow_right:ImageTexture = null
var folded: bool = false : set = set_folded
var button_text: String = 'Section' : set = set_button_text
var nesting_level: int = 0 : set = set_nesting_level
signal folding_state_changed(new_state)
func _ready():
set_folded(folded)
set_button_text(button_text)
set_nesting_level(nesting_level)
func toggle_folded():
set_folded(!folded)
func set_folded(val):
folded = val
$VBoxContainer_Main/HBoxContainer_Offset.visible = !folded
$VBoxContainer_Main/Button_Fold.icon = arrow_right if folded else arrow_down
folding_state_changed.emit(folded)
func set_button_text(val):
button_text = val
$VBoxContainer_Main/Button_Fold.text = button_text
func add_prop_node(prop_node: Control):
$VBoxContainer_Main/HBoxContainer_Offset/VBoxContainer_Properties.add_child(prop_node)
func set_nesting_level(val):
nesting_level = val
match nesting_level:
0:
$VBoxContainer_Main/Button_Fold.theme_type_variation = "PropertySection"
1:
$VBoxContainer_Main/Button_Fold.theme_type_variation = "PropertySubsection"

View File

@@ -0,0 +1,60 @@
[gd_scene load_steps=6 format=3 uid="uid://cntl0a50ubjlr"]
[ext_resource type="Script" path="res://addons/dreadpon.spatial_gardener/controls/side_panel/ui_foldable_section.gd" id="2"]
[sub_resource type="Image" id="Image_4r0cm"]
data = {
"data": PackedByteArray(255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 70, 255, 255, 255, 76, 255, 255, 255, 9, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 9, 255, 255, 255, 76, 255, 255, 255, 69, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 76, 255, 255, 255, 99, 255, 255, 255, 82, 255, 255, 255, 9, 255, 255, 255, 9, 255, 255, 255, 82, 255, 255, 255, 99, 255, 255, 255, 76, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 9, 255, 255, 255, 82, 255, 255, 255, 99, 255, 255, 255, 82, 255, 255, 255, 82, 255, 255, 255, 99, 255, 255, 255, 82, 255, 255, 255, 8, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 9, 255, 255, 255, 82, 255, 255, 255, 99, 255, 255, 255, 99, 255, 255, 255, 82, 255, 255, 255, 8, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 9, 255, 255, 255, 76, 255, 255, 255, 76, 255, 255, 255, 8, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0),
"format": "RGBA8",
"height": 12,
"mipmaps": false,
"width": 12
}
[sub_resource type="ImageTexture" id="ImageTexture_btpaa"]
image = SubResource("Image_4r0cm")
[sub_resource type="Image" id="Image_1q5kb"]
data = {
"data": PackedByteArray(255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 70, 255, 255, 255, 76, 255, 255, 255, 9, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 76, 255, 255, 255, 99, 255, 255, 255, 82, 255, 255, 255, 9, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 9, 255, 255, 255, 82, 255, 255, 255, 99, 255, 255, 255, 82, 255, 255, 255, 9, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 9, 255, 255, 255, 82, 255, 255, 255, 99, 255, 255, 255, 76, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 9, 255, 255, 255, 82, 255, 255, 255, 99, 255, 255, 255, 76, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 9, 255, 255, 255, 82, 255, 255, 255, 99, 255, 255, 255, 82, 255, 255, 255, 8, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 76, 255, 255, 255, 99, 255, 255, 255, 82, 255, 255, 255, 8, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 69, 255, 255, 255, 76, 255, 255, 255, 8, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0),
"format": "RGBA8",
"height": 12,
"mipmaps": false,
"width": 12
}
[sub_resource type="ImageTexture" id="ImageTexture_cwp62"]
image = SubResource("Image_1q5kb")
[node name="UI_FoldableSection" type="MarginContainer"]
offset_right = 322.0
offset_bottom = 146.0
script = ExtResource("2")
arrow_down = SubResource("ImageTexture_btpaa")
arrow_right = SubResource("ImageTexture_cwp62")
[node name="VBoxContainer_Main" type="VBoxContainer" parent="."]
layout_mode = 2
[node name="Button_Fold" type="Button" parent="VBoxContainer_Main"]
layout_mode = 2
theme_type_variation = &"PropertySection"
text = "Section"
icon = SubResource("ImageTexture_btpaa")
alignment = 0
[node name="HBoxContainer_Offset" type="HBoxContainer" parent="VBoxContainer_Main"]
layout_mode = 2
size_flags_horizontal = 3
[node name="Offset" type="Control" parent="VBoxContainer_Main/HBoxContainer_Offset"]
custom_minimum_size = Vector2(4, 0)
layout_mode = 2
size_flags_vertical = 3
[node name="VBoxContainer_Properties" type="VBoxContainer" parent="VBoxContainer_Main/HBoxContainer_Offset"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
[connection signal="pressed" from="VBoxContainer_Main/Button_Fold" to="." method="toggle_folded"]

View File

@@ -0,0 +1,20 @@
[gd_scene format=3 uid="uid://blw02gc85o6ro"]
[node name="UI_Section_Brush" type="PanelContainer"]
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
offset_left = 4.0
offset_top = 31.0
offset_right = -4.0
offset_bottom = -4.0
grow_horizontal = 2
grow_vertical = 2
[node name="ScrollContainer_Properties" type="ScrollContainer" parent="."]
layout_mode = 2
size_flags_horizontal = 3
[node name="VBoxContainer_Properties" type="VBoxContainer" parent="ScrollContainer_Properties"]
layout_mode = 2
size_flags_horizontal = 3

View File

@@ -0,0 +1,149 @@
@tool
extends TabContainer
#-------------------------------------------------------------------------------
# Displays the UI for Greenhouse + its plants and Toolshed + its brushes
#-------------------------------------------------------------------------------
const FunLib = preload("../../utility/fun_lib.gd")
const FoldableSection = preload("ui_foldable_section.gd")
const UI_IF_Object = preload("../input_fields/ui_if_object.gd")
const Greenhouse = preload("../../greenhouse/greenhouse.gd")
const PropAction = preload('../../utility/input_field_resource/prop_action.gd')
const PA_PropSet = preload("../../utility/input_field_resource/pa_prop_set.gd")
const PA_ArrayInsert = preload("../../utility/input_field_resource/pa_array_insert.gd")
const PA_ArrayRemove = preload("../../utility/input_field_resource/pa_array_remove.gd")
const PA_ArraySet = preload("../../utility/input_field_resource/pa_array_set.gd")
@onready var panel_container_tools_nd = $PanelContainer
@onready var panel_container_tools_split_nd = $PanelContainer/PanelContainer_Tools_Split
@onready var label_error_nd = $MarginContainer/Label_Error
#-------------------------------------------------------------------------------
# Lifecycle
#-------------------------------------------------------------------------------
func _ready():
set_meta("class", "UI_SidePanel")
panel_container_tools_nd.theme_type_variation = "InspectorPanelContainer"
#-------------------------------------------------------------------------------
# Updating the UI
#-------------------------------------------------------------------------------
# Set Greenhouse/Toolshed UI as a child
# Can pass an index to specify child order
func set_tool_ui(control:Control, index:int):
if panel_container_tools_split_nd.get_child_count() > index:
var last_tool = panel_container_tools_split_nd.get_child(index)
panel_container_tools_split_nd.remove_child(last_tool)
last_tool.queue_free()
panel_container_tools_split_nd.add_child(control)
if panel_container_tools_split_nd.get_child_count() > index:
panel_container_tools_split_nd.move_child(control, index)
# Switch between invalid setup error and normal tool view
func set_main_control_state(state):
current_tab = 0 if state else 1
#-------------------------------------------------------------------------------
# Folding sections
#-------------------------------------------------------------------------------
# Not a fan of how brute-force it is
# TODO: this WILL NOT WORK with nested foldables or in any slightly-different configuration
# in the future, we need to associated foldables directly with their input_field_resource
# and bake that association into foldable states
# Remove states that represent deleted resources
func cleanup_folding_states(folding_states:Dictionary):
for greenhouse_id in folding_states.keys().duplicate():
# Remove not found resource paths, but keep resource names until converted to paths
if !is_res_name(greenhouse_id) && !ResourceLoader.exists(greenhouse_id):
folding_states.erase(greenhouse_id)
else:
for plant_id in folding_states[greenhouse_id].keys().duplicate():
if !is_res_name(plant_id) && !ResourceLoader.exists(plant_id):
folding_states[greenhouse_id].erase(plant_id)
# Selected a new plant for edit. Update it's folding and bind foldables
func on_greenhouse_prop_action_executed(folding_states:Dictionary, greenhouse:Greenhouse, prop_action: PropAction, final_val):
if is_instance_of(prop_action, PA_PropSet) && prop_action.prop == 'plant_types/selected_for_edit_resource':
refresh_folding_states_for_greenhouse(folding_states, greenhouse)
# Something caused a folding update (typically a gardener selected for edit)
func refresh_folding_states_for_greenhouse(folding_states:Dictionary, greenhouse:Greenhouse):
if !greenhouse.selected_for_edit_resource: return
var greenhouse_id = get_res_name_or_path(folding_states, greenhouse)
var plant_id = get_res_name_or_path(folding_states[greenhouse_id], greenhouse.selected_for_edit_resource)
if folding_states.has(greenhouse_id) && folding_states[greenhouse_id].has(plant_id):
call_deferred('set_folding_states', self, folding_states[greenhouse_id][plant_id])
call_deferred('bind_foldables', self, folding_states, greenhouse_id, plant_id)
# Restore folding states
func set_folding_states(node:Node, states: Dictionary):
if is_instance_of(node, UI_IF_Object):
var section_node = null
for section_name in node.property_sections:
section_node = node.property_sections[section_name].section
section_node.folded = states.get(section_name, false)
for child in node.get_children():
set_folding_states(child, states)
# Bind foldable ui elements to update the relevant folding states
func bind_foldables(node:Node, folding_states: Dictionary, greenhouse_id: String, plant_id: String):
if is_instance_of(node, UI_IF_Object):
var section_node = null
for section_name in node.property_sections:
section_node = node.property_sections[section_name].section
section_node.folding_state_changed.connect(on_foldable_folding_state_changed.bind(section_name, folding_states, greenhouse_id, plant_id))
on_foldable_folding_state_changed(section_node.folded, section_name, folding_states, greenhouse_id, plant_id)
for child in node.get_children():
bind_foldables(child, folding_states, greenhouse_id, plant_id)
# Foldable signal callback. Save it's state to plugin state
func on_foldable_folding_state_changed(folded:bool, section_name:String, folding_states: Dictionary, greenhouse_id: String, plant_id: String):
folding_states[greenhouse_id][plant_id][section_name] = folded
# Get resource path to use as ID. If resource hasn't been saved yet - use it's 'name' instead
# Also acts as a replacer when folding_states have resource names instead of paths, but paths became available
func get_res_name_or_path(target_dict:Dictionary, res):
var res_name = str(res)
if target_dict.has(res_name) && res.resource_path != '':
target_dict[res.resource_path] = target_dict[res_name]
target_dict.erase(res_name)
var res_id = str(res) if res.resource_path == '' else res.resource_path
if !target_dict.has(res_id):
target_dict[res_id] = {}
return res_id
# Check if giver string represents a resource name (e.g. [Resource:9000])
func is_res_name(string: String):
var result = string.begins_with('[') && string.ends_with(']')
return result

View File

@@ -0,0 +1,32 @@
[gd_scene load_steps=2 format=3 uid="uid://t2apc6cgn7ud"]
[ext_resource type="Script" path="res://addons/dreadpon.spatial_gardener/controls/side_panel/ui_side_panel.gd" id="3"]
[node name="SidePanel" type="TabContainer"]
custom_minimum_size = Vector2(300, 0)
offset_right = 450.0
offset_bottom = 600.0
size_flags_horizontal = 3
size_flags_vertical = 3
size_flags_stretch_ratio = 0.3
tabs_visible = false
script = ExtResource("3")
metadata/class = "UI_SidePanel"
[node name="PanelContainer" type="PanelContainer" parent="."]
layout_mode = 2
theme_type_variation = &"InspectorPanelContainer"
[node name="PanelContainer_Tools_Split" type="VSplitContainer" parent="PanelContainer"]
layout_mode = 2
split_offset = 200
[node name="MarginContainer" type="MarginContainer" parent="."]
visible = false
layout_mode = 2
[node name="Label_Error" type="Label" parent="MarginContainer"]
layout_mode = 2
text = "To begin, set the Gardener's Work Directory in the Inspector"
horizontal_alignment = 1
vertical_alignment = 1