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,778 @@
@tool
extends Node3D
#-------------------------------------------------------------------------------
# Manages the lifecycles and connection of all components:
# Greenhouse plants, Toolshed brushes, Painter controller
# And the Arborist plant placement manager
#
# A lot of these connections go through the Gardener
# Because some signal receivers need additional data the signal senders don't know about
# E.g. painter doesn't know about plant states, but arborist needs them to apply painting changes
#-------------------------------------------------------------------------------
const FunLib = preload("../utility/fun_lib.gd")
const Logger = preload("../utility/logger.gd")
const Defaults = preload("../utility/defaults.gd")
const Greenhouse = preload("../greenhouse/greenhouse.gd")
const Toolshed = preload("../toolshed/toolshed.gd")
const Painter = preload("painter.gd")
const Arborist = preload("../arborist/arborist.gd")
const DebugViewer = preload("debug_viewer.gd")
const UI_SidePanel_SCN = preload("../controls/side_panel/ui_side_panel.tscn")
const UI_SidePanel = preload("../controls/side_panel/ui_side_panel.gd")
const Globals = preload("../utility/globals.gd")
const DataImportExport = preload("data_import_export.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_PropEdit = preload("../utility/input_field_resource/pa_prop_edit.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")
var plugin_version: String = ""
var storage_version: int = 0
#export
var refresh_octree_shared_LOD_variants:bool = false : set = set_refresh_octree_shared_LOD_variants
# file_management
var garden_work_directory:String : set = set_garden_work_directory
# gardening
var gardening_collision_mask := pow(2, 0) : set = set_gardening_collision_mask
var initialized_for_edit:bool = false : set = set_initialized_for_edit
var is_edited: bool = false
var toolshed:Toolshed = null
var greenhouse:Greenhouse = null
var painter:Painter = null
var arborist:Arborist = null
var debug_viewer:DebugViewer = null
var _resource_previewer = null
var _base_control:Control = null
var _undo_redo = null
var _side_panel:UI_SidePanel = null
var ui_category_brushes:Control = null
var ui_category_plants:Control = null
var painting_node:Node3D = null
var logger = null
var forward_input_events:bool = true
signal changed_initialized_for_edit(state)
signal greenhouse_prop_action_executed(prop_action, final_val)
#-------------------------------------------------------------------------------
# Lifecycle
#-------------------------------------------------------------------------------
func _init():
set_meta("class", "Gardener")
# Update plugin/storage versions that might have been stored inside a .tscn file for this Gardener
# In case it was created in an older version of this plugin
func update_plugin_ver():
plugin_version = get_plugin_ver()
storage_version = get_storage_ver()
static func get_plugin_ver():
return '1.3.3'
static func get_storage_ver():
return 3
func _ready():
update_plugin_ver()
logger = Logger.get_for(self, name)
# Without editor we only care about an Arborist
# But it is already self-sufficient, so no need to initialize it
if !Engine.is_editor_hint(): return
if has_node('painting'):
painting_node = get_node('painting')
else:
painting_node = Node3D.new()
painting_node.name = "painting"
add_child(painting_node)
if has_node('debug_viewer'):
debug_viewer = get_node('debug_viewer')
else:
debug_viewer = DebugViewer.new()
debug_viewer.name = "debug_viewer"
add_child(debug_viewer)
init_painter()
painter.set_brush_collision_mask(gardening_collision_mask)
reload_resources()
init_arborist()
set_gardening_collision_mask(gardening_collision_mask)
func _enter_tree():
pass
func _exit_tree():
if !Engine.is_editor_hint(): return
_apply_changes()
stop_editing()
func _process(delta):
if painter:
painter.update(delta)
func _apply_changes():
if !Engine.is_editor_hint(): return
if !FunLib.is_dir_valid(garden_work_directory): return
save_toolshed()
save_greenhouse()
toolshed.set_undo_redo(_undo_redo)
greenhouse.set_undo_redo(_undo_redo)
func add_child(node:Node, legible_unique_name:bool = false, internal:InternalMode = 0):
super.add_child(node, legible_unique_name)
update_configuration_warnings()
#-------------------------------------------------------------------------------
# Input
#-------------------------------------------------------------------------------
func forwarded_input(camera, event):
if !forward_input_events: return false
var handled = painter.forwarded_input(camera, event)
if !handled:
handled = toolshed.forwarded_input(camera, event)
if !handled:
handled = arborist._unhandled_input(event)
return handled
# A hack to propagate editor camera
# Should be called by plugin.gd
func propagate_camera(camera:Camera3D):
if arborist:
arborist.active_camera_override = camera
#-------------------------------------------------------------------------------
# Initialization
#-------------------------------------------------------------------------------
# This is supposed to address a problem decribed in "start_gardener_edit()" of "plugin.gd"
# Instead of recalculating everything, we hope it's enough to just restore the member references
func restore_references():
logger = Logger.get_for(self, name)
if !Engine.is_editor_hint(): return
if has_node('painting'):
painting_node = get_node('painting')
if has_node('debug_viewer'):
debug_viewer = get_node('debug_viewer')
init_painter()
painter.set_brush_collision_mask(gardening_collision_mask)
reload_resources()
if has_node("Arborist") && is_instance_of(get_node("Arborist"), Arborist):
arborist = get_node("Arborist")
set_gardening_collision_mask(gardening_collision_mask)
# Initialize a Painter
# Assumed to be the first manager to initialize
func init_painter():
FunLib.free_children(painting_node)
painter = Painter.new(painting_node)
painter.stroke_updated.connect(on_painter_stroke_updated)
painter.changed_active_brush_prop.connect(on_changed_active_brush_prop)
painter.stroke_started.connect(on_painter_stroke_started)
painter.stroke_finished.connect(on_painter_stroke_finished)
# Initialize the Arborist and connect it to other objects
# Won't be called without editor, as Arborist is already self-sufficient
func init_arborist():
# A fancy way of saying
# "Make sure there is a correct node with a correct name"
if has_node("Arborist") && is_instance_of(get_node("Arborist"), Arborist):
arborist = get_node("Arborist")
logger.info("Found existing Arborist")
else:
if has_node("Arborist"):
var old_arborist = get_node("Arborist")
old_arborist.owner = null
remove_child(old_arborist)
old_arborist.queue_free()
logger.info("Removed invalid Arborist")
arborist = Arborist.new()
arborist.name = "Arborist"
add_child(arborist)
logger.info("Added new Arborist")
if greenhouse:
pair_arborist_greenhouse()
pair_debug_viewer_arborist()
pair_debug_viewer_greenhouse()
# Initialize a Greenhouse and a Toolshed
# Rebuild UI if needed
func reload_resources():
var last_toolshed = toolshed
var last_greenhouse = greenhouse
var created_new_toolshed := false
var created_new_greenhouse := false
if !FunLib.is_dir_valid(garden_work_directory):
logger.warn("Skipped loading Toolshed and Greenhouse, please specify a working directory for this Gardener (%s)" % [str(self)])
else:
toolshed = FunLib.load_res(garden_work_directory, "toolshed.tres", false)
greenhouse = FunLib.load_res(garden_work_directory, "greenhouse.tres", false)
if !toolshed:
logger.warn("Unable to load Toolshed, created a new one")
toolshed = Defaults.DEFAULT_TOOLSHED()
created_new_toolshed = true
if !greenhouse:
logger.warn("Unable to load Greenhouse, created a new one")
greenhouse = Greenhouse.new()
created_new_greenhouse = true
toolshed.set_undo_redo(_undo_redo)
greenhouse.set_undo_redo(_undo_redo)
if last_toolshed:
last_toolshed.prop_action_executed.disconnect(on_toolshed_prop_action_executed)
last_toolshed.prop_action_executed_on_brush.disconnect(on_toolshed_prop_action_executed_on_brush)
FunLib.ensure_signal(toolshed.prop_action_executed, on_toolshed_prop_action_executed)
FunLib.ensure_signal(toolshed.prop_action_executed_on_brush, on_toolshed_prop_action_executed_on_brush)
if last_greenhouse:
last_greenhouse.prop_action_executed.disconnect(on_greenhouse_prop_action_executed)
last_greenhouse.prop_action_executed_on_plant_state.disconnect(on_greenhouse_prop_action_executed_on_plant_state)
last_greenhouse.prop_action_executed_on_plant_state_plant.disconnect(on_greenhouse_prop_action_executed_on_plant_state_plant)
last_greenhouse.prop_action_executed_on_LOD_variant.disconnect(on_greenhouse_prop_action_executed_on_LOD_variant)
last_greenhouse.req_octree_reconfigure.disconnect(on_greenhouse_req_octree_reconfigure)
last_greenhouse.req_octree_recenter.disconnect(on_greenhouse_req_octree_recenter)
last_greenhouse.req_import_plant_data.disconnect(on_greenhouse_req_import_plant_data)
last_greenhouse.req_export_plant_data.disconnect(on_greenhouse_req_export_plant_data)
last_greenhouse.req_import_greenhouse_data.disconnect(on_greenhouse_req_import_greenhouse_data)
last_greenhouse.req_export_greenhouse_data.disconnect(on_greenhouse_req_export_greenhouse_data)
FunLib.ensure_signal(greenhouse.prop_action_executed, on_greenhouse_prop_action_executed)
FunLib.ensure_signal(greenhouse.prop_action_executed_on_plant_state, on_greenhouse_prop_action_executed_on_plant_state)
FunLib.ensure_signal(greenhouse.prop_action_executed_on_plant_state_plant, on_greenhouse_prop_action_executed_on_plant_state_plant)
FunLib.ensure_signal(greenhouse.prop_action_executed_on_LOD_variant, on_greenhouse_prop_action_executed_on_LOD_variant)
FunLib.ensure_signal(greenhouse.req_octree_reconfigure, on_greenhouse_req_octree_reconfigure)
FunLib.ensure_signal(greenhouse.req_octree_recenter, on_greenhouse_req_octree_recenter)
FunLib.ensure_signal(greenhouse.req_import_plant_data, on_greenhouse_req_import_plant_data)
FunLib.ensure_signal(greenhouse.req_export_plant_data, on_greenhouse_req_export_plant_data)
FunLib.ensure_signal(greenhouse.req_import_greenhouse_data, on_greenhouse_req_import_greenhouse_data)
FunLib.ensure_signal(greenhouse.req_export_greenhouse_data, on_greenhouse_req_export_greenhouse_data)
if arborist:
pair_arborist_greenhouse()
if toolshed && toolshed != last_toolshed && _side_panel:
ui_category_brushes = toolshed.create_ui(_base_control, _resource_previewer)
_side_panel.set_tool_ui(ui_category_brushes, 0)
if greenhouse && greenhouse != last_greenhouse && _side_panel:
ui_category_plants = greenhouse.create_ui(_base_control, _resource_previewer)
_side_panel.set_tool_ui(ui_category_plants, 1)
if arborist:
for i in range(0, arborist.octree_managers.size()):
arborist.emit_member_count(i)
if created_new_toolshed:
save_toolshed()
if created_new_greenhouse:
save_greenhouse()
# It's possible we load a different Greenhouse while an Arborist is already initialized
# So collapse that into a function
func pair_arborist_greenhouse():
if !arborist || !greenhouse:
if !arborist: logger.warn("Arborist->Greenhouse: Arborist is not initialized!")
if !greenhouse: logger.warn("Arborist->Greenhouse: Greenhouse is not initialized!")
return
# We could duplicate an array, but that's additional overhead so we assume Arborist won't change it
arborist.setup(greenhouse.greenhouse_plant_states)
if !arborist.member_count_updated.is_connected(greenhouse.plant_count_updated):
arborist.member_count_updated.connect(greenhouse.plant_count_updated)
func pair_debug_viewer_greenhouse():
if !debug_viewer || !greenhouse:
if !debug_viewer: logger.warn("DebugViewer->Greenhouse: DebugViewer is not initialized!")
if !greenhouse: logger.warn("DebugViewer->Greenhouse: Greenhouse is not initialized!")
return
debug_viewer.set_prop_edit_selected_plant(greenhouse.greenhouse_plant_states.find(greenhouse.selected_for_edit_resource))
reinit_debug_draw_brush_active()
func pair_debug_viewer_arborist():
if !debug_viewer || !arborist:
if !debug_viewer: logger.warn("DebugViewer->Arborist: DebugViewer is not initialized!")
if !arborist: logger.warn("DebugViewer->Arborist: Arborist is not initialized!")
return
if !arborist.req_debug_redraw.is_connected(debug_viewer.request_debug_redraw):
arborist.req_debug_redraw.connect(debug_viewer.request_debug_redraw)
#-------------------------------------------------------------------------------
# Start/stop editing lifecycle
#-------------------------------------------------------------------------------
# Start editing (painting) a scene
func start_editing(__base_control:Control, __resource_previewer, __undoRedo, __side_panel:UI_SidePanel):
_base_control = __base_control
_resource_previewer = __resource_previewer
_undo_redo = __undoRedo
_side_panel = __side_panel
changed_initialized_for_edit.connect(_side_panel.set_main_control_state)
ui_category_brushes = toolshed.create_ui(_base_control, _resource_previewer)
ui_category_plants = greenhouse.create_ui(_base_control, _resource_previewer)
_side_panel.set_tool_ui(ui_category_brushes, 0)
_side_panel.set_tool_ui(ui_category_plants, 1)
toolshed.set_undo_redo(_undo_redo)
greenhouse.set_undo_redo(_undo_redo)
arborist._undo_redo = _undo_redo
# # Making sure we and UI are on the same page (setting property values and checkboxes/tabs)
painter_update_to_active_brush(toolshed.active_brush)
_side_panel.set_main_control_state(initialized_for_edit)
painter.start_editing()
for i in range(0, arborist.octree_managers.size()):
arborist.emit_member_count(i)
# Make sure LOD_Variants in a shared Octree array are up-to-date
set_refresh_octree_shared_LOD_variants(true)
is_edited = true
# Stop editing (painting) a scene
func stop_editing():
if is_instance_valid(_side_panel):
changed_initialized_for_edit.disconnect(_side_panel.set_main_control_state)
_side_panel = null
if is_instance_valid(painter):
painter.stop_editing()
is_edited = false
# We can properly start editing only when a workDirectory is set
func validate_initialized_for_edit():
var work_directory_valid = FunLib.is_dir_valid(garden_work_directory)
# Originally there were two conditions to fulfill, not just the workDirectory
# Keeping this in case it will be needed in the future
var _initialized_for_edit = work_directory_valid
if initialized_for_edit != _initialized_for_edit:
set_initialized_for_edit(_initialized_for_edit)
# Pass a request for updating a debug view menu
func up_to_date_debug_view_menu(debug_view_menu:MenuButton):
assert(debug_viewer)
debug_viewer.up_to_date_debug_view_menu(debug_view_menu)
debug_viewer.request_debug_redraw(arborist.octree_managers)
# Pass a request for checking a debug view menu flag
func debug_view_flag_checked(debug_view_menu:MenuButton, flag:int):
assert(debug_viewer)
debug_viewer.flag_checked(debug_view_menu, flag)
debug_viewer.request_debug_redraw(arborist.octree_managers)
#-------------------------------------------------------------------------------
# Handle changes in owned properties
#-------------------------------------------------------------------------------
func set_gardening_collision_mask(val):
gardening_collision_mask = val
if painter:
painter.set_brush_collision_mask(gardening_collision_mask)
if arborist:
arborist.set_gardening_collision_mask(gardening_collision_mask)
func set_garden_work_directory(val):
if !val.is_empty() && !val.ends_with("/"):
val += "/"
var changed = garden_work_directory != val
garden_work_directory = val
if !Engine.is_editor_hint(): return
# If we changed a directory, reload everything that resides there
if changed:
if is_inside_tree():
reload_resources()
validate_initialized_for_edit()
func set_initialized_for_edit(val):
initialized_for_edit = val
changed_initialized_for_edit.emit(initialized_for_edit)
#-------------------------------------------------------------------------------
# Handle communication with the Greenhouse
#-------------------------------------------------------------------------------
# When Greenhouse properties are changed
func on_greenhouse_prop_action_executed(prop_action:PropAction, final_val):
if is_instance_of(prop_action, PA_ArrayInsert):
arborist.on_plant_added(final_val[prop_action.index], prop_action.index)
reinit_debug_draw_brush_active()
elif is_instance_of(prop_action, PA_ArrayRemove):
arborist.on_plant_removed(prop_action.val, prop_action.index)
reinit_debug_draw_brush_active()
elif is_instance_of(prop_action, PA_PropSet) && prop_action.prop == "plant_types/selected_for_edit_resource":
debug_viewer.set_prop_edit_selected_plant(greenhouse.greenhouse_plant_states.find(final_val))
debug_viewer.request_debug_redraw(arborist.octree_managers)
greenhouse_prop_action_executed.emit(prop_action, final_val)
# When Greenhouse_PlantState properties are changed
func on_greenhouse_prop_action_executed_on_plant_state(prop_action:PropAction, final_val, plant_state):
var plant_index = greenhouse.greenhouse_plant_states.find(plant_state)
match prop_action.prop:
"plant/plant_brush_active":
if is_instance_of(prop_action, PA_PropSet) || is_instance_of(prop_action, PA_PropEdit):
debug_viewer.set_brush_active_plant(plant_state.plant_brush_active, plant_index)
debug_viewer.request_debug_redraw(arborist.octree_managers)
# When Greenhouse_Plant properties are changed
func on_greenhouse_prop_action_executed_on_plant_state_plant(prop_action:PropAction, final_val, plant, plant_state):
var plant_index = greenhouse.greenhouse_plant_states.find(plant_state)
match prop_action.prop:
"mesh/mesh_LOD_variants":
if is_instance_of(prop_action, PA_ArrayInsert):
var mesh_index = prop_action.index
arborist.on_LOD_variant_added(plant_index, mesh_index, final_val[mesh_index])
elif is_instance_of(prop_action, PA_ArrayRemove):
var mesh_index = prop_action.index
arborist.on_LOD_variant_removed(plant_index, mesh_index)
elif is_instance_of(prop_action, PA_ArraySet):
var mesh_index = prop_action.index
arborist.on_LOD_variant_set(plant_index, mesh_index, final_val[mesh_index])
"mesh/mesh_LOD_max_distance":
if is_instance_of(prop_action, PA_PropSet) || is_instance_of(prop_action, PA_PropEdit):
arborist.update_plant_LOD_max_distance(plant_index, final_val)
"mesh/mesh_LOD_kill_distance":
if is_instance_of(prop_action, PA_PropSet) || is_instance_of(prop_action, PA_PropEdit):
arborist.update_plant_LOD_kill_distance(plant_index, final_val)
# When Greenhouse_LODVariant properties are changed
func on_greenhouse_prop_action_executed_on_LOD_variant(prop_action:PropAction, final_val, LOD_variant, plant, plant_state):
var plant_index = greenhouse.greenhouse_plant_states.find(plant_state)
var mesh_index = plant.mesh_LOD_variants.find(LOD_variant)
match prop_action.prop:
"spawned_spatial":
if is_instance_of(prop_action, PA_PropSet) || is_instance_of(prop_action, PA_PropEdit):
arborist.on_LOD_variant_prop_changed_spawned_spatial(plant_index, mesh_index, final_val)
"cast_shadow":
if is_instance_of(prop_action, PA_PropSet) || is_instance_of(prop_action, PA_PropEdit):
arborist.set_LODs_to_active_index(plant_index)
# A request to reconfigure an octree
func on_greenhouse_req_octree_reconfigure(plant, plant_state):
if !is_edited: return
var plant_index = greenhouse.greenhouse_plant_states.find(plant_state)
arborist.reconfigure_octree(plant_state, plant_index)
# A request to recenter an octree
func on_greenhouse_req_octree_recenter(plant, plant_state):
if !is_edited: return
var plant_index = greenhouse.greenhouse_plant_states.find(plant_state)
arborist.recenter_octree(plant_state, plant_index)
# Update brush active indexes for DebugViewer
func reinit_debug_draw_brush_active():
debug_viewer.reset_brush_active_plants()
for plant_index in range(0, greenhouse.greenhouse_plant_states.size()):
var plant_state = greenhouse.greenhouse_plant_states[plant_index]
debug_viewer.set_brush_active_plant(plant_state.plant_brush_active, plant_index)
debug_viewer.request_debug_redraw(arborist.octree_managers)
#-------------------------------------------------------------------------------
# Importing/exporting data
#-------------------------------------------------------------------------------
# A request to import plant data
func on_greenhouse_req_import_plant_data(file_path: String, plant_idx: int):
if !is_edited: return
var import_export = DataImportExport.new(arborist, greenhouse)
import_export.import_plant_data(file_path, plant_idx)
# A request to export plant data
func on_greenhouse_req_export_plant_data(file_path: String, plant_idx: int):
if !is_edited: return
var import_export = DataImportExport.new(arborist, greenhouse)
import_export.export_plant_data(file_path, plant_idx)
# A request to import entire greenhouse data
func on_greenhouse_req_import_greenhouse_data(file_path: String):
if !is_edited: return
var import_export = DataImportExport.new(arborist, greenhouse)
import_export.import_greenhouse_data(file_path)
# A request to export entire greenhouse data
func on_greenhouse_req_export_greenhouse_data(file_path: String):
if !is_edited: return
var import_export = DataImportExport.new(arborist, greenhouse)
import_export.export_greenhouse_data(file_path)
#-------------------------------------------------------------------------------
# Painter stroke lifecycle
#-------------------------------------------------------------------------------
func on_painter_stroke_started(brush_data:Dictionary):
var active_brush = toolshed.active_brush
arborist.on_stroke_started(active_brush, greenhouse.greenhouse_plant_states)
func on_painter_stroke_finished(brush_data:Dictionary):
arborist.on_stroke_finished()
func on_painter_stroke_updated(brush_data:Dictionary):
arborist.on_stroke_updated(brush_data)
#-------------------------------------------------------------------------------
# Painter - Toolshed relations
#-------------------------------------------------------------------------------
# Changed active brush from Toolshed. Update the painter
func on_toolshed_prop_action_executed(prop_action:PropAction, final_val):
assert(painter)
if prop_action.prop != "brush/active_brush": return
if !(is_instance_of(prop_action, PA_PropSet)) && !(is_instance_of(prop_action, PA_PropEdit)): return
if final_val != toolshed.active_brush:
logger.error("Passed final_val is not equal to toolshed.active_brush!")
return
painter_update_to_active_brush(final_val)
func painter_update_to_active_brush(active_brush):
assert(active_brush)
painter.queue_call_when_camera('update_all_props_to_active_brush', [active_brush])
#-------------------------------------------------------------------------------
# Quick edit for brush properties
#-------------------------------------------------------------------------------
# Property change instigated by Painter
func on_changed_active_brush_prop(prop: String, val, final:bool):
var prop_action: PropAction = null
if final:
prop_action = PA_PropSet.new(prop, val)
else:
prop_action = PA_PropEdit.new(prop, val)
if prop_action:
toolshed.active_brush.request_prop_action(prop_action)
# Propagate active_brush property changes to Painter
func on_toolshed_prop_action_executed_on_brush(prop_action:PropAction, final_val, brush):
assert(painter)
if !(is_instance_of(prop_action, PA_PropSet)) && !(is_instance_of(prop_action, PA_PropEdit)): return
if brush != toolshed.active_brush: return
match prop_action.prop:
"shape/shape_volume_size":
painter.set_active_brush_size(final_val)
"shape/shape_projection_size":
painter.set_active_brush_size(final_val)
"behavior/behavior_strength":
painter.set_active_brush_strength(final_val)
"behavior/behavior_overlap_mode":
painter_update_to_active_brush(brush)
#-------------------------------------------------------------------------------
# Saving, loading and file management
#-------------------------------------------------------------------------------
func save_toolshed():
if FunLib.is_dir_valid(garden_work_directory):
FunLib.save_res(toolshed, garden_work_directory, "toolshed.tres")
func save_greenhouse():
if FunLib.is_dir_valid(garden_work_directory):
FunLib.save_res(greenhouse, garden_work_directory, "greenhouse.tres")
#-------------------------------------------------------------------------------
# Property export
#-------------------------------------------------------------------------------
# Writing this by hand THRICE for each property is honestly tiring
# Built-in Godot reflection would go a long way
func _get(property):
match property:
"file_management/garden_work_directory":
return garden_work_directory
"gardening/gardening_collision_mask":
return gardening_collision_mask
"plugin_version":
return
"storage_version":
return storage_version
func _set(property, val):
var return_val = true
match property:
"file_management/garden_work_directory":
set_garden_work_directory(val)
"gardening/gardening_collision_mask":
set_gardening_collision_mask(val)
_:
return_val = false
return return_val
func _get_property_list():
return [
{
"name": "file_management/garden_work_directory",
"type": TYPE_STRING,
"usage": PROPERTY_USAGE_DEFAULT,
"hint": PROPERTY_HINT_DIR
},
{
"name": "gardening/gardening_collision_mask",
"type": TYPE_INT,
"usage": PROPERTY_USAGE_DEFAULT,
"hint": PROPERTY_HINT_LAYERS_3D_PHYSICS
},
{
"name": "plugin_version",
"type": TYPE_STRING,
"usage": PROPERTY_USAGE_NO_EDITOR,
},
{
"name": "storage_version",
"type": TYPE_STRING,
"usage": PROPERTY_USAGE_NO_EDITOR,
},
]
# Warning to be displayed in editor SceneTree
func _get_configuration_warnings():
var arborist_check = get_node("Arborist")
if arborist_check && is_instance_of(arborist_check, Arborist):
return ""
else:
return "Gardener is missing a valid Arborist child\nSince it should be created automatically, try reloading a scene or recreating a Gardener"
func set_refresh_octree_shared_LOD_variants(val):
refresh_octree_shared_LOD_variants = false
if val && arborist && greenhouse:
for i in range(0, greenhouse.greenhouse_plant_states.size()):
arborist.refresh_octree_shared_LOD_variants(i, greenhouse.greenhouse_plant_states[i].plant.mesh_LOD_variants)