391 lines
14 KiB
GDScript
391 lines
14 KiB
GDScript
@tool
|
|
extends "../utility/input_field_resource/input_field_resource.gd"
|
|
|
|
|
|
#-------------------------------------------------------------------------------
|
|
# The manager of all plant types for a given Gardener
|
|
# Handles interfacing between Greenhouse_PlantState, UI and plant placement
|
|
#-------------------------------------------------------------------------------
|
|
|
|
|
|
const Greenhouse_PlantState = preload("greenhouse_plant_state.gd")
|
|
const ui_category_greenhouse_SCN = preload("../controls/side_panel/ui_category_greenhouse.tscn")
|
|
|
|
# All the plants (plant states) we have
|
|
var greenhouse_plant_states:Array = []
|
|
# Keep a reference to selected resource to easily display it
|
|
var selected_for_edit_resource:Resource = null
|
|
|
|
var ui_category_greenhouse: Control = null
|
|
var scroll_container_plant_thumbnails_nd:Control = null
|
|
var scroll_container_properties_nd: Control = null
|
|
var panel_container_category_nd:Control = null
|
|
|
|
var grid_container_plant_thumbnails_nd:UI_IF_ThumbnailArray = null
|
|
var vbox_container_properties_nd:Control = null
|
|
var _base_control:Control = null
|
|
var _resource_previewer = null
|
|
var _file_dialog: ConfirmationDialog = null
|
|
|
|
|
|
signal prop_action_executed_on_plant_state(prop_action, final_val, plant_state)
|
|
signal prop_action_executed_on_plant_state_plant(prop_action, final_val, plant, plant_state)
|
|
signal prop_action_executed_on_LOD_variant(prop_action, final_val, LOD_variant, plant, plant_stat)
|
|
signal req_octree_reconfigure(plant, plant_state)
|
|
signal req_octree_recenter(plant, plant_state)
|
|
signal req_import_plant_data(plant_idx, file)
|
|
signal req_export_plant_data(plant_idx, file)
|
|
signal req_import_greenhouse_data(file)
|
|
signal req_export_greenhouse_data(file)
|
|
|
|
|
|
|
|
|
|
#-------------------------------------------------------------------------------
|
|
# Initialization
|
|
#-------------------------------------------------------------------------------
|
|
|
|
|
|
func _init():
|
|
super()
|
|
set_meta("class", "Greenhouse")
|
|
resource_name = "Greenhouse"
|
|
|
|
_add_res_edit_source_array("plant_types/greenhouse_plant_states", "plant_types/selected_for_edit_resource")
|
|
|
|
if Engine.is_editor_hint():
|
|
# Editor raises error everytime you run the game with F5 because of "abstract native class"
|
|
# https://github.com/godotengine/godot/issues/73525
|
|
_file_dialog = DPON_FM.ED_EditorFileDialog.new()
|
|
else:
|
|
_file_dialog = FileDialog.new()
|
|
_file_dialog.close_requested.connect(on_file_dialog_hide)
|
|
|
|
|
|
func _notification(what):
|
|
match what:
|
|
NOTIFICATION_PREDELETE:
|
|
if is_instance_valid(_file_dialog):
|
|
# Avoid memory leaks
|
|
_file_dialog.queue_free()
|
|
|
|
|
|
# The UI is created here because we need to manage it afterwards
|
|
# And I see no reason to get lost in a signal spaghetti of delegating it
|
|
func create_ui(__base_control:Control, __resource_previewer):
|
|
_base_control = __base_control
|
|
_resource_previewer = __resource_previewer
|
|
|
|
# Avoid memory leaks
|
|
if is_instance_valid(ui_category_greenhouse):
|
|
ui_category_greenhouse.queue_free()
|
|
if is_instance_valid(grid_container_plant_thumbnails_nd):
|
|
grid_container_plant_thumbnails_nd.queue_free()
|
|
if is_instance_valid(vbox_container_properties_nd):
|
|
vbox_container_properties_nd.queue_free()
|
|
|
|
ui_category_greenhouse = ui_category_greenhouse_SCN.instantiate()
|
|
scroll_container_plant_thumbnails_nd = ui_category_greenhouse.find_child('ScrollContainer_PlantThumbnails')
|
|
scroll_container_properties_nd = ui_category_greenhouse.find_child('ScrollContainer_Properties')
|
|
panel_container_category_nd = ui_category_greenhouse.find_child('Label_Category_Plants')
|
|
|
|
panel_container_category_nd.theme_type_variation = "PropertyCategory"
|
|
scroll_container_plant_thumbnails_nd.theme_type_variation = "InspectorPanelContainer"
|
|
scroll_container_properties_nd.theme_type_variation = "InspectorPanelContainer"
|
|
ui_category_greenhouse.theme_type_variation = "InspectorPanelContainer"
|
|
|
|
grid_container_plant_thumbnails_nd = create_input_field(_base_control, _resource_previewer, "plant_types/greenhouse_plant_states")
|
|
grid_container_plant_thumbnails_nd.label.visible = false
|
|
grid_container_plant_thumbnails_nd.name = "GridContainer_PlantThumbnails"
|
|
grid_container_plant_thumbnails_nd.size_flags_vertical = Control.SIZE_EXPAND_FILL
|
|
grid_container_plant_thumbnails_nd.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
|
grid_container_plant_thumbnails_nd.requested_check.connect(on_plant_state_check)
|
|
grid_container_plant_thumbnails_nd.requested_label_edit.connect(on_plant_label_edit)
|
|
|
|
vbox_container_properties_nd = create_input_field(_base_control, _resource_previewer, "plant_types/selected_for_edit_resource")
|
|
|
|
scroll_container_plant_thumbnails_nd.add_child(grid_container_plant_thumbnails_nd)
|
|
scroll_container_properties_nd.add_child(vbox_container_properties_nd)
|
|
|
|
return ui_category_greenhouse
|
|
|
|
|
|
func _create_input_field(_base_control:Control, _resource_previewer, prop:String) -> UI_InputField:
|
|
var input_field:UI_InputField = null
|
|
match prop:
|
|
"plant_types/greenhouse_plant_states":
|
|
var settings := {
|
|
"add_create_inst_button": true,
|
|
"accepted_classes": [Greenhouse_PlantState],
|
|
"element_display_size": 100 * FunLib.get_setting_safe("dreadpons_spatial_gardener/input_and_ui/greenhouse_thumbnail_scale", 1.0),
|
|
"element_interaction_flags": UI_IF_ThumbnailArray.PRESET_PLANT_STATE,
|
|
}
|
|
input_field = UI_IF_ThumbnailArray.new(greenhouse_plant_states, "Plant Types", prop, settings)
|
|
"plant_types/selected_for_edit_resource":
|
|
var settings := {
|
|
"label_visibility": false,
|
|
"tab": 0}
|
|
input_field = UI_IF_Object.new(selected_for_edit_resource, "Plant State", prop, settings)
|
|
|
|
return input_field
|
|
|
|
|
|
func add_plant_from_dict(plant_data: Dictionary, str_version: int = 1) -> int:
|
|
var new_idx = greenhouse_plant_states.size()
|
|
request_prop_action(PA_ArrayInsert.new(
|
|
"plant_types/greenhouse_plant_states",
|
|
Greenhouse_PlantState.new().ifr_from_dict(plant_data, true, str_version),
|
|
new_idx
|
|
))
|
|
return new_idx
|
|
|
|
|
|
|
|
|
|
#-------------------------------------------------------------------------------
|
|
# UI management
|
|
#-------------------------------------------------------------------------------
|
|
|
|
|
|
# Select a Greenhouse_PlantState for painting
|
|
func on_plant_state_check(index:int, state:bool):
|
|
var plant_state = greenhouse_plant_states[index]
|
|
var prop_action = PA_PropSet.new("plant/plant_brush_active", state)
|
|
plant_state.request_prop_action(prop_action)
|
|
|
|
|
|
# Edit Greenhouse_PlantState's label
|
|
func on_plant_label_edit(index:int, label_text:String):
|
|
var plant_state = greenhouse_plant_states[index]
|
|
var prop_action = PA_PropSet.new("plant/plant_label", label_text)
|
|
plant_state.request_prop_action(prop_action)
|
|
|
|
|
|
func select_plant_state_for_brush(index:int, state:bool):
|
|
if is_instance_valid(grid_container_plant_thumbnails_nd):
|
|
grid_container_plant_thumbnails_nd.set_thumb_interaction_feature_with_data(UI_ActionThumbnail_GD.InteractionFlags.CHECK, state, {"index": index})
|
|
|
|
|
|
func set_plant_state_label(index:int, label_text:String):
|
|
if is_instance_valid(grid_container_plant_thumbnails_nd):
|
|
grid_container_plant_thumbnails_nd.set_thumb_interaction_feature_with_data(UI_ActionThumbnail_GD.InteractionFlags.EDIT_LABEL, label_text, {"index": index})
|
|
|
|
|
|
func on_if_tree_entered(input_field:UI_InputField):
|
|
super.on_if_tree_entered(input_field)
|
|
|
|
if input_field.prop_name == "plant_types/greenhouse_plant_states":
|
|
for i in range(0, greenhouse_plant_states.size()):
|
|
select_plant_state_for_brush(i, greenhouse_plant_states[i].plant_brush_active)
|
|
set_plant_state_label(i, greenhouse_plant_states[i].plant_label)
|
|
|
|
|
|
func plant_count_updated(plant_index, new_count):
|
|
if is_instance_valid(grid_container_plant_thumbnails_nd) && grid_container_plant_thumbnails_nd.flex_grid.get_child_count() > plant_index:
|
|
grid_container_plant_thumbnails_nd.flex_grid.get_child(plant_index).set_counter_val(new_count)
|
|
|
|
|
|
func show_transform_import(type: String):
|
|
if _file_dialog.get_parent() != _base_control:
|
|
_base_control.add_child(_file_dialog)
|
|
_file_dialog.popup_centered_ratio(0.5)
|
|
_file_dialog.access = FileDialog.ACCESS_FILESYSTEM
|
|
_file_dialog.filters = PackedStringArray(['*.json ; JSON'])
|
|
match type:
|
|
'import':
|
|
_file_dialog.file_mode = FileDialog.FILE_MODE_OPEN_FILE
|
|
'export':
|
|
_file_dialog.file_mode = FileDialog.FILE_MODE_SAVE_FILE
|
|
|
|
|
|
func on_file_dialog_hide():
|
|
FunLib.disconnect_all(_file_dialog.file_selected)
|
|
|
|
|
|
|
|
|
|
#-------------------------------------------------------------------------------
|
|
# Signal forwarding
|
|
#-------------------------------------------------------------------------------
|
|
|
|
|
|
func on_changed_plant_state():
|
|
emit_changed()
|
|
|
|
func on_req_octree_reconfigure(plant, plant_state):
|
|
req_octree_reconfigure.emit(plant, plant_state)
|
|
|
|
func on_req_octree_recenter(plant, plant_state):
|
|
req_octree_recenter.emit(plant, plant_state)
|
|
|
|
func on_req_import_plant_data(plant, plant_state):
|
|
show_transform_import('import')
|
|
var plant_idx = greenhouse_plant_states.find(plant_state)
|
|
FunLib.disconnect_all(_file_dialog.file_selected)
|
|
_file_dialog.file_selected.connect(on_req_import_export_plant_data_file.bind(req_import_plant_data, plant_idx))
|
|
|
|
func on_req_export_plant_data(plant, plant_state):
|
|
show_transform_import('export')
|
|
var plant_idx = greenhouse_plant_states.find(plant_state)
|
|
FunLib.disconnect_all(_file_dialog.file_selected)
|
|
_file_dialog.file_selected.connect(on_req_import_export_plant_data_file.bind(req_export_plant_data, plant_idx))
|
|
|
|
func on_req_import_greenhouse_data():
|
|
show_transform_import('import')
|
|
FunLib.disconnect_all(_file_dialog.file_selected)
|
|
_file_dialog.file_selected.connect(on_req_import_export_greenhouse_data_file.bind(req_import_greenhouse_data))
|
|
|
|
func on_req_export_greenhouse_data():
|
|
show_transform_import('export')
|
|
FunLib.disconnect_all(_file_dialog.file_selected)
|
|
_file_dialog.file_selected.connect(on_req_import_export_greenhouse_data_file.bind(req_export_greenhouse_data))
|
|
|
|
func on_req_import_export_plant_data_file(file_path: String, signal_obj: Signal, plant_idx: int):
|
|
signal_obj.emit(file_path, plant_idx)
|
|
|
|
func on_req_import_export_greenhouse_data_file(file_path: String, signal_obj: Signal):
|
|
signal_obj.emit(file_path)
|
|
|
|
|
|
|
|
|
|
#-------------------------------------------------------------------------------
|
|
# Prop Actions
|
|
#-------------------------------------------------------------------------------
|
|
|
|
|
|
func on_prop_action_executed(prop_action:PropAction, final_val):
|
|
var prop_action_class = prop_action.get_meta("class")
|
|
|
|
match prop_action.prop:
|
|
"plant_types/greenhouse_plant_states":
|
|
match prop_action_class:
|
|
"PA_ArrayInsert":
|
|
select_plant_state_for_brush(prop_action.index, final_val[prop_action.index].plant_brush_active)
|
|
set_plant_state_label(prop_action.index, final_val[prop_action.index].plant_label)
|
|
|
|
|
|
|
|
func on_prop_action_executed_on_plant_state(prop_action, final_val, plant_state):
|
|
if is_instance_of(prop_action, PA_PropSet):
|
|
var plant_index = greenhouse_plant_states.find(plant_state)
|
|
match prop_action.prop:
|
|
"plant/plant_brush_active":
|
|
select_plant_state_for_brush(plant_index, final_val)
|
|
"plant/plant_label":
|
|
set_plant_state_label(plant_index, final_val)
|
|
|
|
prop_action_executed_on_plant_state.emit(prop_action, final_val, plant_state)
|
|
|
|
|
|
func on_prop_action_executed_on_plant_state_plant(prop_action, final_val, plant, plant_state):
|
|
var plant_index = greenhouse_plant_states.find(plant_state)
|
|
|
|
# Any prop action on LOD variants - update thumbnail
|
|
var update_thumbnail = prop_action.prop == "mesh/mesh_LOD_variants"
|
|
if update_thumbnail && grid_container_plant_thumbnails_nd:
|
|
grid_container_plant_thumbnails_nd._update_thumbnail(plant_state, plant_index)
|
|
|
|
prop_action_executed_on_plant_state_plant.emit(prop_action, final_val, plant, plant_state)
|
|
|
|
|
|
func on_prop_action_executed_on_LOD_variant(prop_action, final_val, LOD_variant, plant, plant_state):
|
|
prop_action_executed_on_LOD_variant.emit(prop_action, final_val, LOD_variant, plant, plant_state)
|
|
|
|
|
|
|
|
|
|
#-------------------------------------------------------------------------------
|
|
# Property export
|
|
#-------------------------------------------------------------------------------
|
|
|
|
|
|
func set_undo_redo(val):
|
|
super.set_undo_redo(val)
|
|
for plant_state in greenhouse_plant_states:
|
|
plant_state.set_undo_redo(_undo_redo)
|
|
|
|
|
|
func _get(prop):
|
|
match prop:
|
|
"plant_types/greenhouse_plant_states":
|
|
return greenhouse_plant_states
|
|
"plant_types/selected_for_edit_resource":
|
|
return selected_for_edit_resource
|
|
|
|
return null
|
|
|
|
|
|
func _modify_prop(prop:String, val):
|
|
match prop:
|
|
"plant_types/greenhouse_plant_states":
|
|
for i in range(0, val.size()):
|
|
if !is_instance_of(val[i], Greenhouse_PlantState):
|
|
val[i] = Greenhouse_PlantState.new()
|
|
|
|
FunLib.ensure_signal(val[i].changed, on_changed_plant_state)
|
|
FunLib.ensure_signal(val[i].prop_action_executed, on_prop_action_executed_on_plant_state, [val[i]])
|
|
FunLib.ensure_signal(val[i].prop_action_executed_on_plant, on_prop_action_executed_on_plant_state_plant, [val[i]])
|
|
FunLib.ensure_signal(val[i].prop_action_executed_on_LOD_variant, on_prop_action_executed_on_LOD_variant, [val[i]])
|
|
FunLib.ensure_signal(val[i].req_octree_reconfigure, on_req_octree_reconfigure, [val[i]])
|
|
FunLib.ensure_signal(val[i].req_octree_recenter, on_req_octree_recenter, [val[i]])
|
|
FunLib.ensure_signal(val[i].req_import_plant_data, on_req_import_plant_data, [val[i]])
|
|
FunLib.ensure_signal(val[i].req_export_plant_data, on_req_export_plant_data, [val[i]])
|
|
FunLib.ensure_signal(val[i].req_import_greenhouse_data, on_req_import_greenhouse_data)
|
|
FunLib.ensure_signal(val[i].req_export_greenhouse_data, on_req_export_greenhouse_data)
|
|
|
|
if val[i]._undo_redo != _undo_redo:
|
|
val[i].set_undo_redo(_undo_redo)
|
|
return val
|
|
|
|
|
|
func _set(prop, val):
|
|
var return_val = true
|
|
val = _modify_prop(prop, val)
|
|
|
|
match prop:
|
|
"plant_types/greenhouse_plant_states":
|
|
greenhouse_plant_states = val
|
|
"plant_types/selected_for_edit_resource":
|
|
selected_for_edit_resource = val
|
|
_:
|
|
return_val = false
|
|
|
|
if return_val:
|
|
emit_changed()
|
|
return return_val
|
|
|
|
|
|
func _get_prop_dictionary():
|
|
return {
|
|
"plant_types/greenhouse_plant_states":
|
|
{
|
|
"name": "plant_types/greenhouse_plant_states",
|
|
"type": TYPE_ARRAY,
|
|
"usage": PROPERTY_USAGE_DEFAULT,
|
|
"hint": PROPERTY_HINT_NONE
|
|
},
|
|
"plant_types/selected_for_edit_resource":
|
|
{
|
|
"name": "plant_types/selected_for_edit_resource",
|
|
"type": TYPE_OBJECT,
|
|
"usage": PROPERTY_USAGE_DEFAULT,
|
|
"hint": PROPERTY_HINT_NONE
|
|
},
|
|
}
|
|
|
|
|
|
func _fix_duplicate_signals(copy):
|
|
copy._modify_prop("plant_types/greenhouse_plant_states", copy.greenhouse_plant_states)
|
|
copy.selected_for_edit_resource = null
|
|
|
|
|
|
func get_prop_tooltip(prop:String) -> String:
|
|
match prop:
|
|
"plant_types/greenhouse_plant_states":
|
|
return "All the plants in this Greenhouse"
|
|
"plant_types/selected_for_edit_resource":
|
|
return "The plant currently selected for edit"
|
|
|
|
return ""
|