1033 lines
40 KiB
GDScript
1033 lines
40 KiB
GDScript
@tool
|
|
extends "../utility/input_field_resource/input_field_resource.gd"
|
|
|
|
|
|
#-------------------------------------------------------------------------------
|
|
# All the data needed to generate a plant, it's transform
|
|
# And a containing octree
|
|
#-------------------------------------------------------------------------------
|
|
|
|
|
|
var Globals = preload("../utility/globals.gd")
|
|
const Greenhouse_LODVariant = preload("greenhouse_LOD_variant.gd")
|
|
|
|
|
|
enum ScalingType {UNIFORM, FREE, LOCK_XY, LOCK_ZY, LOCK_XZ}
|
|
enum DirectionVectorType {UNUSED, WORLD_X, WORLD_Y, WORLD_Z, NORMAL, CUSTOM}
|
|
|
|
|
|
|
|
|
|
# Different LODs for a plant starting from the most detailed
|
|
var mesh_LOD_variants:Array = []
|
|
# Keep a reference to selected resource to easily display it
|
|
var selected_for_edit_resource:Resource = null
|
|
# Distance after which the final LOD is shown
|
|
var mesh_LOD_max_distance:float = 10.0
|
|
# Distance after which the mesh is hidden
|
|
var mesh_LOD_kill_distance:float = -1.0
|
|
|
|
# How many members fit into an octree node before it's subdivided
|
|
var mesh_LOD_max_capacity:int = 75
|
|
# Minimum size of an octree node. Will not subdivide after this treshold
|
|
# Chunks of minimum size might contain members beyond the capacity limit
|
|
var mesh_LOD_min_size:float = 1.0
|
|
# A dummy variable to show a dialog for recreating an octree
|
|
var octree_reconfigure_button:bool = false
|
|
# A dummy variable to recenter an octree
|
|
var octree_recenter_button:bool = false
|
|
|
|
# How many members spawn in a 2D square of PLANT_DENSITY_UNITS aligned to a brush
|
|
# These members will then be projected onto a surface
|
|
var density_per_units:float = 100.0
|
|
|
|
# How we constraint the scale (uniform scale, unrestricted or to specific 3D plane)
|
|
var scale_scaling_type:int = ScalingType.UNIFORM
|
|
# A range of scale to randomize into
|
|
var scale_range:Array = [Vector3(1,1,1), Vector3(1,1,1)]
|
|
|
|
# How we choose the primary up vector
|
|
var up_vector_primary_type:int = DirectionVectorType.WORLD_Y
|
|
# Custom value for primary up vector if enabled
|
|
var up_vector_primary:Vector3 = Vector3()
|
|
# How we choose the secondary up vector
|
|
var up_vector_secondary_type:int = DirectionVectorType.WORLD_Y
|
|
# Custom value for secondary up vector if enabled
|
|
var up_vector_secondary:Vector3 = Vector3()
|
|
# Weight for blending between two up vectors
|
|
var up_vector_blending:float = 0.0
|
|
|
|
# How we choose the primary forward vector
|
|
var fwd_vector_primary_type:int = DirectionVectorType.UNUSED
|
|
# Custom value for primary forward vector if enabled
|
|
var fwd_vector_primary:Vector3 = Vector3()
|
|
# How we choose the secondary forward vector
|
|
var fwd_vector_secondary_type:int = DirectionVectorType.UNUSED
|
|
# Custom value for secondary forward vector if enabled
|
|
var fwd_vector_secondary:Vector3 = Vector3()
|
|
# Weight for blending between two forward vectors
|
|
var fwd_vector_blending:float = 0.0
|
|
|
|
# A range of vertical scale to randomize into (local to plant y axis)
|
|
var offset_y_range:Array = [0.0, 0.0]
|
|
# A random horizontal jitter applied when placing each instance
|
|
# A fraction of a cell, that plant is placed in (i.e. is in range (0.0, 1.0)
|
|
var offset_jitter_fraction:float = 0.6
|
|
|
|
# Random rotation in y axis (will be between (-val, val))
|
|
var rotation_random_y:float = 180.0
|
|
# Random rotation in x axis (will be between (-val, val))
|
|
var rotation_random_x:float = 0.0
|
|
# Random rotation in z axis (will be between (-val, val))
|
|
var rotation_random_z:float = 0.0
|
|
|
|
# Limits placement onto a sloped surface
|
|
# "Sloped" in relation to the chosen primary up vector
|
|
var slope_allowed_range:Array = [0.0, 180.0]
|
|
|
|
# A dummy variable to export plant data
|
|
var import_export_import_plant_data_button:bool = false
|
|
# A dummy variable to import plant data
|
|
var import_export_export_plant_data_button:bool = false
|
|
# A dummy variable to export greenhouse data
|
|
var import_export_import_greenhouse_data_button:bool = false
|
|
# A dummy variable to import greenhouse data
|
|
var import_export_export_greenhouse_data_button:bool = false
|
|
|
|
|
|
var total_instances_in_gardener:int = 0
|
|
var select_container = null
|
|
var settings_container = null
|
|
|
|
|
|
signal prop_action_executed_on_LOD_variant(prop_action, final_val, LOD_variant)
|
|
signal req_octree_reconfigure
|
|
signal req_octree_recenter
|
|
signal req_import_plant_data
|
|
signal req_export_plant_data
|
|
signal req_import_greenhouse_data
|
|
signal req_export_greenhouse_data
|
|
|
|
|
|
|
|
|
|
#-------------------------------------------------------------------------------
|
|
# Initialization
|
|
#-------------------------------------------------------------------------------
|
|
|
|
|
|
func _init():
|
|
input_field_blacklist = ["mesh/mesh_LOD_max_capacity", "mesh/mesh_LOD_min_size"]
|
|
|
|
super()
|
|
set_meta("class", "Greenhouse_Plant")
|
|
resource_name = "Greenhouse_Plant"
|
|
|
|
_add_prop_dependency("mesh/mesh_LOD_kill_distance", ["mesh/mesh_LOD_max_distance"])
|
|
_add_prop_dependency("scale/scale_range", ["scale/scale_scaling_type"])
|
|
_add_res_edit_source_array("mesh/mesh_LOD_variants", "mesh/selected_for_edit_resource")
|
|
|
|
|
|
func _create_input_field(_base_control:Control, _resource_previewer, prop:String) -> UI_InputField:
|
|
var input_field:UI_InputField = null
|
|
match prop:
|
|
"mesh/mesh_LOD_variants":
|
|
var accepted_classes := [Greenhouse_LODVariant, PackedScene, Mesh]
|
|
var settings := {
|
|
"add_create_inst_button": true,
|
|
"accepted_classes": accepted_classes,
|
|
"element_display_size": 75 * FunLib.get_setting_safe("dreadpons_spatial_gardener/input_and_ui/greenhouse_thumbnail_scale", 1.0),
|
|
"element_interaction_flags": UI_IF_ThumbnailArray.PRESET_LOD_VARIANT,
|
|
}
|
|
input_field = UI_IF_ThumbnailArray.new(mesh_LOD_variants, "LOD Variants", prop, settings)
|
|
"mesh/selected_for_edit_resource":
|
|
var settings := {
|
|
"label_visibility": false,
|
|
"tab": 1
|
|
}
|
|
input_field = UI_IF_Object.new(selected_for_edit_resource, "LOD Variant", prop, settings)
|
|
"mesh/mesh_LOD_max_distance":
|
|
var max_value = FunLib.get_setting_safe("dreadpons_spatial_gardener/input_and_ui/plant_max_distance_slider_max_value", 1000.0)
|
|
var settings := {"min": 0.0, "max": max_value, "step": 0.01, "allow_greater": true, "allow_lesser": false,}
|
|
input_field = UI_IF_RealSlider.new(mesh_LOD_max_distance, "LOD Max Distance", prop, settings)
|
|
"mesh/mesh_LOD_kill_distance":
|
|
var max_value = FunLib.get_setting_safe("dreadpons_spatial_gardener/input_and_ui/plant_kill_distance_slider_max_value", 2000.0)
|
|
var settings := {"min": -1.0, "max": max_value, "step": 0.01, "allow_greater": true, "allow_lesser": false,}
|
|
input_field = UI_IF_RealSlider.new(mesh_LOD_kill_distance, "LOD Kill Distance", prop, settings)
|
|
#======================================================
|
|
"mesh/mesh_LOD_max_capacity":
|
|
input_field = UI_IF_IntLineEdit.new(mesh_LOD_max_capacity, "Max chunk capacity", prop)
|
|
"mesh/mesh_LOD_min_size":
|
|
var max_value = FunLib.get_setting_safe("dreadpons_spatial_gardener/input_and_ui/octree_min_node_size_slider_max_value", 500.0)
|
|
var settings := {"min": 0.0, "max": max_value, "step": 0.01, "allow_greater": true, "allow_lesser": false,}
|
|
input_field = UI_IF_RealSlider.new(mesh_LOD_min_size, "Min node size", prop, settings)
|
|
"octree/octree_reconfigure_button":
|
|
var bound_input_fields:Array = create_input_fields(
|
|
_base_control, _resource_previewer, ["mesh/mesh_LOD_max_capacity", "mesh/mesh_LOD_min_size"]).values()
|
|
var settings := {
|
|
"button_text": "Configure Octree",
|
|
"bound_input_fields": bound_input_fields
|
|
}
|
|
input_field = UI_IF_ApplyChanges.new(octree_reconfigure_button, "Octree Configuration", prop, settings)
|
|
input_field.applied_changes.connect(on_dialog_if_applied_changes.bind(input_field))
|
|
input_field.canceled_changes.connect(on_dialog_if_canceled_changes.bind(input_field))
|
|
"octree/octree_recenter_button":
|
|
var settings := {"button_text": "Recenter Octree"}
|
|
input_field = UI_IF_Button.new(octree_recenter_button, "Octree Centring", prop, settings)
|
|
input_field.pressed.connect(on_if_button.bind(input_field))
|
|
#======================================================
|
|
"density/density_per_units":
|
|
var max_value = FunLib.get_setting_safe("dreadpons_spatial_gardener/input_and_ui/plant_density_slider_max_value", 2000.0)
|
|
var settings := {"min": 0.0, "max": max_value, "step": 0.01, "allow_greater": true, "allow_lesser": false,}
|
|
var field_name = "Plants Per %d Unit" % [Globals.PLANT_DENSITY_UNITS]
|
|
if Globals.PLANT_DENSITY_UNITS != 1:
|
|
field_name += "s"
|
|
input_field = UI_IF_RealSlider.new(density_per_units, field_name, prop, settings)
|
|
#======================================================
|
|
"scale/scale_scaling_type":
|
|
var settings := {"enum_list": FunLib.capitalize_string_array(ScalingType.keys())}
|
|
input_field = UI_IF_Enum.new(scale_scaling_type, "Scaling Type", prop, settings)
|
|
"scale/scale_range":
|
|
var settings := {
|
|
"is_range": true,
|
|
"value_count": 3,
|
|
"representation_type": UI_IF_MultiRange.RepresentationType.VECTOR,
|
|
}
|
|
input_field = UI_IF_MultiRange.new(scale_range, "Random Scale Range", prop, settings)
|
|
#======================================================
|
|
"up_vector/up_vector_primary_type":
|
|
var settings := {"enum_list": FunLib.capitalize_string_array(DirectionVectorType.keys())}
|
|
input_field = UI_IF_Enum.new(up_vector_primary_type, "Primary Up-Vector", prop, settings)
|
|
"up_vector/up_vector_primary":
|
|
var settings := {
|
|
"is_range": false,
|
|
"value_count": 3,
|
|
"representation_type": UI_IF_MultiRange.RepresentationType.VECTOR,
|
|
}
|
|
input_field = UI_IF_MultiRange.new(up_vector_primary, "Up-Vector Primary", prop, settings)
|
|
"up_vector/up_vector_secondary_type":
|
|
var settings := {"enum_list": FunLib.capitalize_string_array(DirectionVectorType.keys())}
|
|
input_field = UI_IF_Enum.new(up_vector_secondary_type, "Secondary Up-Vector", prop, settings)
|
|
"up_vector/up_vector_secondary":
|
|
var settings := {
|
|
"is_range": false,
|
|
"value_count": 3,
|
|
"representation_type": UI_IF_MultiRange.RepresentationType.VECTOR,
|
|
}
|
|
input_field = UI_IF_MultiRange.new(up_vector_secondary, "Up-Vector Secondary", prop, settings)
|
|
"up_vector/up_vector_blending":
|
|
var settings := {"min": 0.0, "max": 1.0, "step": 0.01, "allow_greater": false, "allow_lesser": false,}
|
|
input_field = UI_IF_RealSlider.new(up_vector_blending, "Up-Vector Blending", prop, settings)
|
|
#======================================================
|
|
"fwd_vector/fwd_vector_primary_type":
|
|
var settings := {"enum_list": FunLib.capitalize_string_array(DirectionVectorType.keys())}
|
|
input_field = UI_IF_Enum.new(fwd_vector_primary_type, "Primary Forward-Vector", prop, settings)
|
|
"fwd_vector/fwd_vector_primary":
|
|
var settings := {
|
|
"is_range": false,
|
|
"value_count": 3,
|
|
"representation_type": UI_IF_MultiRange.RepresentationType.VECTOR,
|
|
}
|
|
input_field = UI_IF_MultiRange.new(fwd_vector_primary, "Forward-Vector Primary", prop, settings)
|
|
"fwd_vector/fwd_vector_secondary_type":
|
|
var settings := {"enum_list": FunLib.capitalize_string_array(DirectionVectorType.keys())}
|
|
input_field = UI_IF_Enum.new(fwd_vector_secondary_type, "Secondary Forward-Vector", prop, settings)
|
|
"fwd_vector/fwd_vector_secondary":
|
|
var settings := {
|
|
"is_range": false,
|
|
"value_count": 3,
|
|
"representation_type": UI_IF_MultiRange.RepresentationType.VECTOR,
|
|
}
|
|
input_field = UI_IF_MultiRange.new(fwd_vector_secondary, "Forward-Vector Secondary", prop, settings)
|
|
"fwd_vector/fwd_vector_blending":
|
|
var settings := {"min": 0.0, "max": 1.0, "step": 0.01, "allow_greater": false, "allow_lesser": false,}
|
|
input_field = UI_IF_RealSlider.new(fwd_vector_blending, "Forward-Vector Blending", prop, settings)
|
|
#======================================================
|
|
"offset/offset_y_range":
|
|
var settings := {
|
|
"is_range": true,
|
|
"value_count": 1,
|
|
"representation_type": UI_IF_MultiRange.RepresentationType.VALUE,
|
|
}
|
|
input_field = UI_IF_MultiRange.new(offset_y_range, "Random Offset Range Y", prop, settings)
|
|
"offset/offset_jitter_fraction":
|
|
var settings := {"min": 0.0, "max": 1.0, "step": 0.01, "allow_greater": false, "allow_lesser": false,}
|
|
input_field = UI_IF_RealSlider.new(offset_jitter_fraction, "Offset Jitter Fraction", prop, settings)
|
|
#======================================================
|
|
"rotation/rotation_random_y":
|
|
var settings := {"min": 0.0, "max": 180.0, "step": 0.01, "allow_greater": false, "allow_lesser": false,}
|
|
input_field = UI_IF_RealSlider.new(rotation_random_y, "Random Rotation Y", prop, settings)
|
|
"rotation/rotation_random_x":
|
|
var settings := {"min": 0.0, "max": 180.0, "step": 0.01, "allow_greater": false, "allow_lesser": false,}
|
|
input_field = UI_IF_RealSlider.new(rotation_random_x, "Random Rotation X", prop, settings)
|
|
"rotation/rotation_random_z":
|
|
var settings := {"min": 0.0, "max": 180.0, "step": 0.01, "allow_greater": false, "allow_lesser": false,}
|
|
input_field = UI_IF_RealSlider.new(rotation_random_x, "Random Rotation Z", prop, settings)
|
|
#======================================================
|
|
"slope/slope_allowed_range":
|
|
var settings := {
|
|
"is_range": true,
|
|
"value_count": 1,
|
|
"representation_type": UI_IF_MultiRange.RepresentationType.VALUE,
|
|
}
|
|
input_field = UI_IF_MultiRange.new(slope_allowed_range, "Allowed Slope Range", prop, settings)
|
|
#======================================================
|
|
"import_export/import_plant_data_button":
|
|
var settings := {"button_text": "Import"}
|
|
input_field = UI_IF_Button.new(import_export_import_plant_data_button, "Import Plant Data", prop, settings)
|
|
input_field.pressed.connect(on_if_button.bind(input_field))
|
|
"import_export/export_plant_data_button":
|
|
var settings := {"button_text": "Export"}
|
|
input_field = UI_IF_Button.new(import_export_export_plant_data_button, "Export Plant Data", prop, settings)
|
|
input_field.pressed.connect(on_if_button.bind(input_field))
|
|
"import_export/import_greenhouse_data_button":
|
|
var settings := {"button_text": "Import"}
|
|
input_field = UI_IF_Button.new(import_export_import_greenhouse_data_button, "Import Greenhouse Data", prop, settings)
|
|
input_field.pressed.connect(on_if_button.bind(input_field))
|
|
"import_export/export_greenhouse_data_button":
|
|
var settings := {"button_text": "Export"}
|
|
input_field = UI_IF_Button.new(import_export_export_greenhouse_data_button, "Export Greenhouse Data", prop, settings)
|
|
input_field.pressed.connect(on_if_button.bind(input_field))
|
|
|
|
return input_field
|
|
|
|
|
|
|
|
|
|
#-------------------------------------------------------------------------------
|
|
# Signal forwarding
|
|
#-------------------------------------------------------------------------------
|
|
|
|
|
|
func on_changed_LOD_variant():
|
|
emit_changed()
|
|
|
|
|
|
func reconfigure_octree():
|
|
req_octree_reconfigure.emit()
|
|
|
|
|
|
|
|
|
|
#-------------------------------------------------------------------------------
|
|
# Prop actions
|
|
#-------------------------------------------------------------------------------
|
|
|
|
|
|
# A prop action was executed on one of the LOD variants
|
|
# If a mesh was changed - update thumbnail
|
|
# If a spawned spatial was changed - spawn or deelte them
|
|
func on_prop_action_executed_on_LOD_variant(prop_action, final_val, LOD_variant):
|
|
var index = mesh_LOD_variants.find(LOD_variant)
|
|
var update_thumbnail = prop_action.prop == "mesh"
|
|
|
|
if update_thumbnail:
|
|
prop_action_executed.emit(PA_ArraySet.new("mesh/mesh_LOD_variants", LOD_variant, index), mesh_LOD_variants)
|
|
prop_action_executed_on_LOD_variant.emit(prop_action, final_val, LOD_variant)
|
|
|
|
|
|
|
|
|
|
#-------------------------------------------------------------------------------
|
|
# UI management
|
|
#-------------------------------------------------------------------------------
|
|
|
|
|
|
# Handle changes applied by input field dialog
|
|
func on_dialog_if_applied_changes(initial_values:Array, final_values:Array, input_field:UI_InputField):
|
|
match input_field.prop_name:
|
|
"octree/octree_reconfigure_button":
|
|
UndoRedoInterface.create_action(_undo_redo, "Reconfigure Octree", 0, false, self)
|
|
UndoRedoInterface.add_do_method(_undo_redo, input_field.set_values.bind(final_values))
|
|
UndoRedoInterface.add_do_method(_undo_redo, self.reconfigure_octree)
|
|
UndoRedoInterface.add_undo_method(_undo_redo, input_field.set_values.bind(initial_values))
|
|
UndoRedoInterface.add_undo_method(_undo_redo, self.reconfigure_octree)
|
|
UndoRedoInterface.commit_action(_undo_redo, true)
|
|
|
|
|
|
# Handle changes canceled by input field dialog
|
|
func on_dialog_if_canceled_changes(input_field:UI_InputField):
|
|
pass
|
|
|
|
|
|
# Handle an input field button press
|
|
func on_if_button(input_field:UI_InputField):
|
|
match input_field.prop_name:
|
|
"octree/octree_recenter_button":
|
|
req_octree_recenter.emit()
|
|
"import_export/import_plant_data_button":
|
|
req_import_plant_data.emit()
|
|
"import_export/export_plant_data_button":
|
|
req_export_plant_data.emit()
|
|
"import_export/import_greenhouse_data_button":
|
|
req_import_greenhouse_data.emit()
|
|
"import_export/export_greenhouse_data_button":
|
|
req_export_greenhouse_data.emit()
|
|
|
|
|
|
|
|
|
|
#-------------------------------------------------------------------------------
|
|
# Property management
|
|
#-------------------------------------------------------------------------------
|
|
|
|
|
|
func _modify_prop(prop:String, val):
|
|
match prop:
|
|
"mesh/mesh_LOD_variants":
|
|
# TODO retain Greenhouse_LODVariant if it already exists when drag-and-dropping a .mesh or a .tscn resource
|
|
for i in range(0, val.size()):
|
|
if !is_instance_of(val[i], Greenhouse_LODVariant):
|
|
val[i] = Greenhouse_LODVariant.new()
|
|
|
|
FunLib.ensure_signal(val[i].changed, on_changed_LOD_variant)
|
|
FunLib.ensure_signal(val[i].prop_action_executed, on_prop_action_executed_on_LOD_variant, [val[i]])
|
|
|
|
if val[i]._undo_redo != _undo_redo:
|
|
val[i].set_undo_redo(_undo_redo)
|
|
"scale/scale_range":
|
|
val = val.duplicate()
|
|
match scale_scaling_type:
|
|
ScalingType.UNIFORM:
|
|
val[0].y = val[0].x
|
|
val[0].z = val[0].x
|
|
val[1].y = val[1].x
|
|
val[1].z = val[1].x
|
|
ScalingType.LOCK_XY:
|
|
val[0].y = val[0].x
|
|
val[1].y = val[1].x
|
|
ScalingType.LOCK_XZ:
|
|
val[0].z = val[0].x
|
|
val[1].z = val[1].x
|
|
ScalingType.LOCK_ZY:
|
|
val[0].z = val[0].y
|
|
val[1].z = val[1].y
|
|
"mesh/mesh_LOD_kill_distance":
|
|
if val < mesh_LOD_max_distance && val >= 0:
|
|
val = mesh_LOD_max_distance
|
|
# "mesh/mesh_LOD_max_distance":
|
|
# if mesh_LOD_kill_distance < val:
|
|
# mesh_LOD_kill_distance = val
|
|
"slope/slope_allowed_range":
|
|
for i in range(0, val.size()):
|
|
var element = val[i]
|
|
if element < 0.0:
|
|
val[i] = 0.0
|
|
elif element > 180.0:
|
|
val[i] = 180.0
|
|
return val
|
|
|
|
|
|
# A special override just for the plants
|
|
# To allow drag-and-dropping .mesh and .tscn instead of editing a resource
|
|
func request_prop_action(prop_action:PropAction):
|
|
match prop_action.prop:
|
|
"mesh/mesh_LOD_variants":
|
|
if is_instance_of(prop_action, PA_ArraySet):
|
|
|
|
var new_prop_action = null
|
|
if is_instance_of(prop_action.val, PackedScene):
|
|
new_prop_action = PA_PropSet.new("spawned_spatial", prop_action.val)
|
|
elif is_instance_of(prop_action.val, Mesh):
|
|
new_prop_action = PA_PropSet.new("mesh", prop_action.val)
|
|
# else:
|
|
# for mesh_class in Globals.MESH_CLASSES:
|
|
# if FunLib.obj_is_class_string(prop_action.val, mesh_class):
|
|
# new_prop_action = PA_PropSet.new("mesh", prop_action.val)
|
|
# break
|
|
|
|
if new_prop_action != null:
|
|
mesh_LOD_variants[prop_action.index].request_prop_action(new_prop_action)
|
|
return
|
|
|
|
on_prop_action_requested(prop_action)
|
|
|
|
|
|
|
|
|
|
#-------------------------------------------------------------------------------
|
|
# Property export
|
|
#-------------------------------------------------------------------------------
|
|
|
|
|
|
func set_undo_redo(val):
|
|
super.set_undo_redo(val)
|
|
for LOD_variant in mesh_LOD_variants:
|
|
LOD_variant.set_undo_redo(_undo_redo)
|
|
|
|
|
|
func _set(prop, val):
|
|
var return_val = true
|
|
val = _modify_prop(prop, val)
|
|
|
|
match prop:
|
|
"mesh/mesh_LOD_variants":
|
|
mesh_LOD_variants = val
|
|
"mesh/selected_for_edit_resource":
|
|
selected_for_edit_resource = val
|
|
"mesh/mesh_LOD_max_distance":
|
|
mesh_LOD_max_distance = val
|
|
"mesh/mesh_LOD_kill_distance":
|
|
mesh_LOD_kill_distance = val
|
|
"mesh/mesh_LOD_max_capacity":
|
|
mesh_LOD_max_capacity = val
|
|
"mesh/mesh_LOD_min_size":
|
|
mesh_LOD_min_size = val
|
|
"octree/octree_reconfigure_button":
|
|
octree_reconfigure_button = val
|
|
"octree/octree_recenter_button":
|
|
octree_recenter_button = val
|
|
|
|
"density/density_per_units":
|
|
density_per_units = val
|
|
|
|
"scale/scale_scaling_type":
|
|
scale_scaling_type = val
|
|
_emit_property_list_changed_notify()
|
|
"scale/scale_range":
|
|
scale_range = val
|
|
|
|
"up_vector/up_vector_primary_type":
|
|
up_vector_primary_type = val
|
|
_emit_property_list_changed_notify()
|
|
"up_vector/up_vector_primary":
|
|
up_vector_primary = val
|
|
"up_vector/up_vector_secondary_type":
|
|
up_vector_secondary_type = val
|
|
_emit_property_list_changed_notify()
|
|
"up_vector/up_vector_secondary":
|
|
up_vector_secondary = val
|
|
"up_vector/up_vector_blending":
|
|
up_vector_blending = val
|
|
|
|
"fwd_vector/fwd_vector_primary_type":
|
|
fwd_vector_primary_type = val
|
|
_emit_property_list_changed_notify()
|
|
"fwd_vector/fwd_vector_primary":
|
|
fwd_vector_primary = val
|
|
"fwd_vector/fwd_vector_secondary_type":
|
|
fwd_vector_secondary_type = val
|
|
_emit_property_list_changed_notify()
|
|
"fwd_vector/fwd_vector_secondary":
|
|
fwd_vector_secondary = val
|
|
"fwd_vector/fwd_vector_blending":
|
|
fwd_vector_blending = val
|
|
|
|
"offset/offset_y_range":
|
|
offset_y_range = val
|
|
"offset/offset_jitter_fraction":
|
|
offset_jitter_fraction = val
|
|
|
|
"rotation/rotation_random_y":
|
|
rotation_random_y = val
|
|
"rotation/rotation_random_x":
|
|
rotation_random_x = val
|
|
"rotation/rotation_random_z":
|
|
rotation_random_z = val
|
|
|
|
"slope/slope_allowed_range":
|
|
slope_allowed_range = val
|
|
|
|
"import_export/import_plant_data_button":
|
|
import_export_import_plant_data_button = val
|
|
"import_export/export_plant_data_button":
|
|
import_export_export_plant_data_button = val
|
|
"import_export/import_greenhouse_data_button":
|
|
import_export_import_greenhouse_data_button = val
|
|
"import_export/export_greenhouse_data_button":
|
|
import_export_export_greenhouse_data_button = val
|
|
_:
|
|
return_val = false
|
|
|
|
if return_val:
|
|
emit_changed()
|
|
return return_val
|
|
|
|
|
|
func _get(property):
|
|
match property:
|
|
"mesh/mesh_LOD_variants":
|
|
return mesh_LOD_variants
|
|
"mesh/selected_for_edit_resource":
|
|
return selected_for_edit_resource
|
|
"mesh/mesh_LOD_max_distance":
|
|
return mesh_LOD_max_distance
|
|
"mesh/mesh_LOD_kill_distance":
|
|
return mesh_LOD_kill_distance
|
|
"mesh/mesh_LOD_max_capacity":
|
|
return mesh_LOD_max_capacity
|
|
"mesh/mesh_LOD_min_size":
|
|
return mesh_LOD_min_size
|
|
"octree/octree_reconfigure_button":
|
|
return octree_reconfigure_button
|
|
"octree/octree_recenter_button":
|
|
return octree_recenter_button
|
|
|
|
"density/density_per_units":
|
|
return density_per_units
|
|
|
|
"scale/scale_scaling_type":
|
|
return scale_scaling_type
|
|
"scale/scale_range":
|
|
return scale_range
|
|
|
|
"up_vector/up_vector_primary_type":
|
|
return up_vector_primary_type
|
|
"up_vector/up_vector_primary":
|
|
return up_vector_primary
|
|
"up_vector/up_vector_secondary_type":
|
|
return up_vector_secondary_type
|
|
"up_vector/up_vector_secondary":
|
|
return up_vector_secondary
|
|
"up_vector/up_vector_blending":
|
|
return up_vector_blending
|
|
|
|
"fwd_vector/fwd_vector_primary_type":
|
|
return fwd_vector_primary_type
|
|
"fwd_vector/fwd_vector_primary":
|
|
return fwd_vector_primary
|
|
"fwd_vector/fwd_vector_secondary_type":
|
|
return fwd_vector_secondary_type
|
|
"fwd_vector/fwd_vector_secondary":
|
|
return fwd_vector_secondary
|
|
"fwd_vector/fwd_vector_blending":
|
|
return fwd_vector_blending
|
|
|
|
"offset/offset_y_range":
|
|
return offset_y_range
|
|
"offset/offset_jitter_fraction":
|
|
return offset_jitter_fraction
|
|
|
|
"rotation/rotation_random_y":
|
|
return rotation_random_y
|
|
"rotation/rotation_random_x":
|
|
return rotation_random_x
|
|
"rotation/rotation_random_z":
|
|
return rotation_random_z
|
|
|
|
"slope/slope_allowed_range":
|
|
return slope_allowed_range
|
|
|
|
"import_export/import_plant_data_button":
|
|
return import_export_import_plant_data_button
|
|
"import_export/export_plant_data_button":
|
|
return import_export_export_plant_data_button
|
|
"import_export/import_greenhouse_data_button":
|
|
return import_export_import_greenhouse_data_button
|
|
"import_export/export_greenhouse_data_button":
|
|
return import_export_export_greenhouse_data_button
|
|
|
|
return null
|
|
|
|
|
|
func _filter_prop_dictionary(prop_dict: Dictionary) -> Dictionary:
|
|
var props_to_hide := []
|
|
|
|
if up_vector_primary_type != DirectionVectorType.CUSTOM:
|
|
props_to_hide.append("up_vector/up_vector_primary")
|
|
if up_vector_secondary_type != DirectionVectorType.CUSTOM:
|
|
props_to_hide.append("up_vector/up_vector_secondary")
|
|
if fwd_vector_primary_type != DirectionVectorType.CUSTOM:
|
|
props_to_hide.append("fwd_vector/fwd_vector_primary")
|
|
if fwd_vector_secondary_type != DirectionVectorType.CUSTOM:
|
|
props_to_hide.append("fwd_vector/fwd_vector_secondary")
|
|
|
|
if up_vector_primary_type == up_vector_secondary_type && up_vector_primary_type != DirectionVectorType.CUSTOM:
|
|
props_to_hide.append("up_vector/up_vector_blending")
|
|
if fwd_vector_primary_type == fwd_vector_secondary_type && fwd_vector_primary_type != DirectionVectorType.CUSTOM:
|
|
props_to_hide.append("fwd_vector/fwd_vector_blending")
|
|
|
|
for prop in props_to_hide:
|
|
prop_dict[prop].usage = PROPERTY_USAGE_NO_EDITOR
|
|
|
|
return prop_dict
|
|
|
|
|
|
func _get_prop_dictionary():
|
|
return {
|
|
"mesh/mesh_LOD_variants":
|
|
{
|
|
"name": "mesh/mesh_LOD_variants",
|
|
"type": TYPE_ARRAY,
|
|
"usage": PROPERTY_USAGE_DEFAULT,
|
|
"hint": PROPERTY_HINT_NONE
|
|
},
|
|
"mesh/selected_for_edit_resource":
|
|
{
|
|
"name": "mesh/selected_for_edit_resource",
|
|
"type": TYPE_OBJECT,
|
|
"usage": PROPERTY_USAGE_DEFAULT,
|
|
"hint": PROPERTY_HINT_NONE
|
|
},
|
|
"mesh/mesh_LOD_max_distance":
|
|
{
|
|
"name": "mesh/mesh_LOD_max_distance",
|
|
"type": TYPE_FLOAT,
|
|
"usage": PROPERTY_USAGE_DEFAULT,
|
|
"hint": PROPERTY_HINT_NONE
|
|
},
|
|
"mesh/mesh_LOD_kill_distance":
|
|
{
|
|
"name": "mesh/mesh_LOD_kill_distance",
|
|
"type": TYPE_FLOAT,
|
|
"usage": PROPERTY_USAGE_DEFAULT,
|
|
"hint": PROPERTY_HINT_NONE
|
|
},
|
|
"mesh/mesh_LOD_max_capacity":
|
|
{
|
|
"name": "mesh/mesh_LOD_max_capacity",
|
|
"type": TYPE_INT,
|
|
"usage": PROPERTY_USAGE_DEFAULT,
|
|
"hint": PROPERTY_HINT_NONE
|
|
},
|
|
"mesh/mesh_LOD_min_size":
|
|
{
|
|
"name": "mesh/mesh_LOD_min_size",
|
|
"type": TYPE_FLOAT,
|
|
"usage": PROPERTY_USAGE_DEFAULT,
|
|
"hint": PROPERTY_HINT_NONE
|
|
},
|
|
"octree/octree_reconfigure_button":
|
|
{
|
|
"name": "octree/octree_reconfigure_button",
|
|
"type": TYPE_BOOL,
|
|
"usage": PROPERTY_USAGE_DEFAULT,
|
|
"hint": PROPERTY_HINT_NONE
|
|
},
|
|
"octree/octree_recenter_button":
|
|
{
|
|
"name": "octree/octree_recenter_button",
|
|
"type": TYPE_BOOL,
|
|
"usage": PROPERTY_USAGE_DEFAULT,
|
|
"hint": PROPERTY_HINT_NONE
|
|
},
|
|
#======================================================
|
|
"density/density_per_units":
|
|
{
|
|
"name": "density/density_per_units",
|
|
"type": TYPE_FLOAT,
|
|
"usage": PROPERTY_USAGE_DEFAULT,
|
|
"hint": PROPERTY_HINT_NONE
|
|
},
|
|
#======================================================
|
|
"scale/scale_scaling_type":
|
|
{
|
|
"name": "scale/scale_scaling_type",
|
|
"type": TYPE_INT,
|
|
"usage": PROPERTY_USAGE_DEFAULT,
|
|
"hint": PROPERTY_HINT_ENUM,
|
|
"hint_string": "Uniform,Free,Lock XY,Lock ZY,Lock XZ"
|
|
},
|
|
"scale/scale_range":
|
|
{
|
|
"name": "scale/scale_range",
|
|
"type": TYPE_ARRAY,
|
|
"usage": PROPERTY_USAGE_DEFAULT,
|
|
"hint": PROPERTY_HINT_NONE
|
|
},
|
|
#======================================================
|
|
"up_vector/up_vector_primary_type":
|
|
{
|
|
"name": "up_vector/up_vector_primary_type",
|
|
"type": TYPE_INT,
|
|
"usage": PROPERTY_USAGE_DEFAULT,
|
|
"hint": PROPERTY_HINT_ENUM,
|
|
"hint_string": "Unused,World X,World Y,World Z,Normal,Custom"
|
|
},
|
|
"up_vector/up_vector_primary":
|
|
{
|
|
"name": "up_vector/up_vector_primary",
|
|
"type": TYPE_VECTOR3,
|
|
"usage": PROPERTY_USAGE_DEFAULT,
|
|
"hint": PROPERTY_HINT_NONE
|
|
},
|
|
"up_vector/up_vector_secondary_type":
|
|
{
|
|
"name": "up_vector/up_vector_secondary_type",
|
|
"type": TYPE_INT,
|
|
"usage": PROPERTY_USAGE_DEFAULT,
|
|
"hint": PROPERTY_HINT_ENUM,
|
|
"hint_string": "Unused,World X,World Y,World Z,Normal,Custom"
|
|
},
|
|
"up_vector/up_vector_secondary":
|
|
{
|
|
"name": "up_vector/up_vector_secondary",
|
|
"type": TYPE_VECTOR3,
|
|
"usage": PROPERTY_USAGE_DEFAULT,
|
|
"hint": PROPERTY_HINT_NONE
|
|
},
|
|
"up_vector/up_vector_blending":
|
|
{
|
|
"name": "up_vector/up_vector_blending",
|
|
"type": TYPE_FLOAT,
|
|
"usage": PROPERTY_USAGE_DEFAULT,
|
|
"hint": PROPERTY_HINT_RANGE,
|
|
"hint_string": "0.0,1.0"
|
|
},
|
|
#======================================================
|
|
"fwd_vector/fwd_vector_primary_type":
|
|
{
|
|
"name": "fwd_vector/fwd_vector_primary_type",
|
|
"type": TYPE_INT,
|
|
"usage": PROPERTY_USAGE_DEFAULT,
|
|
"hint": PROPERTY_HINT_ENUM,
|
|
"hint_string": "Unused,World X,World Y,World Z,Normal,Custom"
|
|
},
|
|
"fwd_vector/fwd_vector_primary":
|
|
{
|
|
"name": "fwd_vector/fwd_vector_primary",
|
|
"type": TYPE_VECTOR3,
|
|
"usage": PROPERTY_USAGE_DEFAULT,
|
|
"hint": PROPERTY_HINT_NONE
|
|
},
|
|
"fwd_vector/fwd_vector_secondary_type":
|
|
{
|
|
"name": "fwd_vector/fwd_vector_secondary_type",
|
|
"type": TYPE_INT,
|
|
"usage": PROPERTY_USAGE_DEFAULT,
|
|
"hint": PROPERTY_HINT_ENUM,
|
|
"hint_string": "Unused,World X,World Y,World Z,Normal,Custom"
|
|
},
|
|
"fwd_vector/fwd_vector_secondary":
|
|
{
|
|
"name": "fwd_vector/fwd_vector_secondary",
|
|
"type": TYPE_VECTOR3,
|
|
"usage": PROPERTY_USAGE_DEFAULT,
|
|
"hint": PROPERTY_HINT_NONE
|
|
},
|
|
"fwd_vector/fwd_vector_blending":
|
|
{
|
|
"name": "fwd_vector/fwd_vector_blending",
|
|
"type": TYPE_FLOAT,
|
|
"usage": PROPERTY_USAGE_DEFAULT,
|
|
"hint": PROPERTY_HINT_RANGE,
|
|
"hint_string": "0.0,1.0"
|
|
},
|
|
#======================================================
|
|
"offset/offset_y_range":
|
|
{
|
|
"name": "offset/offset_y_range",
|
|
"type": TYPE_ARRAY,
|
|
"usage": PROPERTY_USAGE_DEFAULT,
|
|
"hint": PROPERTY_HINT_NONE
|
|
},
|
|
"offset/offset_jitter_fraction":
|
|
{
|
|
"name": "offset/offset_jitter_fraction",
|
|
"type": TYPE_FLOAT,
|
|
"usage": PROPERTY_USAGE_DEFAULT,
|
|
"hint": PROPERTY_HINT_NONE
|
|
},
|
|
#======================================================
|
|
"rotation/rotation_random_y":
|
|
{
|
|
"name": "rotation/rotation_random_y",
|
|
"type": TYPE_FLOAT,
|
|
"usage": PROPERTY_USAGE_DEFAULT,
|
|
"hint": PROPERTY_HINT_RANGE,
|
|
"hint_string": "0.0,180.0"
|
|
},
|
|
"rotation/rotation_random_x":
|
|
{
|
|
"name": "rotation/rotation_random_x",
|
|
"type": TYPE_FLOAT,
|
|
"usage": PROPERTY_USAGE_DEFAULT,
|
|
"hint": PROPERTY_HINT_RANGE,
|
|
"hint_string": "0.0,180.0"
|
|
},
|
|
"rotation/rotation_random_z":
|
|
{
|
|
"name": "rotation/rotation_random_z",
|
|
"type": TYPE_FLOAT,
|
|
"usage": PROPERTY_USAGE_DEFAULT,
|
|
"hint": PROPERTY_HINT_RANGE,
|
|
"hint_string": "0.0,180.0"
|
|
},
|
|
#======================================================
|
|
"slope/slope_allowed_range":
|
|
{
|
|
"name": "slope/slope_allowed_range",
|
|
"type": TYPE_ARRAY,
|
|
"usage": PROPERTY_USAGE_DEFAULT,
|
|
"hint": PROPERTY_HINT_NONE
|
|
},
|
|
#======================================================
|
|
"import_export/import_plant_data_button":
|
|
{
|
|
"name": "import_export/import_plant_data_button",
|
|
"type": TYPE_BOOL,
|
|
"usage": PROPERTY_USAGE_DEFAULT,
|
|
"hint": PROPERTY_HINT_NONE
|
|
},
|
|
"import_export/export_plant_data_button":
|
|
{
|
|
"name": "import_export/export_plant_data_button",
|
|
"type": TYPE_BOOL,
|
|
"usage": PROPERTY_USAGE_DEFAULT,
|
|
"hint": PROPERTY_HINT_NONE
|
|
},
|
|
"import_export/import_greenhouse_data_button":
|
|
{
|
|
"name": "import_export/import_greenhouse_data_button",
|
|
"type": TYPE_BOOL,
|
|
"usage": PROPERTY_USAGE_DEFAULT,
|
|
"hint": PROPERTY_HINT_NONE
|
|
},
|
|
"import_export/export_greenhouse_data_button":
|
|
{
|
|
"name": "import_export/export_greenhouse_data_button",
|
|
"type": TYPE_BOOL,
|
|
"usage": PROPERTY_USAGE_DEFAULT,
|
|
"hint": PROPERTY_HINT_NONE
|
|
},
|
|
}
|
|
|
|
|
|
func _fix_duplicate_signals(copy):
|
|
copy._modify_prop("mesh/mesh_LOD_variants", copy.mesh_LOD_variants)
|
|
copy.selected_for_edit_resource = null
|
|
|
|
|
|
func get_prop_tooltip(prop:String) -> String:
|
|
match prop:
|
|
"mesh/mesh_LOD_variants":
|
|
return "The array of Level Of Detail resources that's used to swap meshes depending on distance to the camera\n" \
|
|
+ "This allows to have high-detailed meshes when the player is close, but low-detailed when they're far way\n" \
|
|
+ "This technique is used to optimize performance\n" \
|
|
+ "\n" \
|
|
+ "This property supports drag-and-drop of Greenhouse_LODVariant resources\n" \
|
|
+ "As well as .mesh and .tscn resources. In this case, Greenhouse_LODVariant will be created automatically"
|
|
"mesh/selected_for_edit_resource":
|
|
return "The plant currently selected for editing"
|
|
"mesh/mesh_LOD_max_distance":
|
|
return "The distance after which the lowest-detailed LOD (last one in the array) is chosen\n" \
|
|
+ "LODs in-between are spread evenly across this distance\n"
|
|
"mesh/mesh_LOD_kill_distance":
|
|
return "The distance after which the mesh and it's Spawned Node3D are removed entirely\n" \
|
|
+ "Used to save perfomance by rejecting small objects like grass or rocks at big distances\n" \
|
|
+ "A default value of '-1' disables this behavior (the object will be active forever)"
|
|
"mesh/mesh_LOD_max_capacity":
|
|
return "The soft limit of how many instances can an octree node contain before it is subdivided\n" \
|
|
+ "This can be bypassed by the node minimum size"
|
|
"mesh/mesh_LOD_min_size":
|
|
return "The hard limit of how small an octree node can get\n" \
|
|
+ "If both capacity and size limits are approached, only the size will be honored\n" \
|
|
+ "I.e. octree nodes will contain more instances than their capacity allows"
|
|
"octree/octree_reconfigure_button":
|
|
return "The button to reconfigure octree nodes' capacity and minimum size"
|
|
"octree/octree_recenter_button":
|
|
return "The button to recenter the entire octree according to the space it's instances occupy\n" \
|
|
+ "This operation is recommended once you finished painting your plants\n" \
|
|
+ "As it optimizes both the performance (slightly) and the LOD switching behavior (more importantly)"
|
|
|
|
"density/density_per_units":
|
|
return "How many plants will be placed in a square of %dx%d units\n" % [Globals.PLANT_DENSITY_UNITS, Globals.PLANT_DENSITY_UNITS] \
|
|
+ "This is an approximate amount and it should not be taken as an absolute\n"
|
|
|
|
"scale/scale_scaling_type":
|
|
return "Defines the rules for scaling randomization\n" \
|
|
+ "By default it scales uniformly, meaning all axes will have the same value\n" \
|
|
+ "You can remove the lock entirely and allow each axis to have it's own randomized value (typically results in wonky-looking meshes)\n" \
|
|
+ "Or you can lock one of the planes\n" \
|
|
+ "e.g. XZ-lock with make horizontal scaling uniform (plants won't appear twisted), but allow varying vertical scaling"
|
|
"scale/scale_range":
|
|
return "The range in which scaling is randomized. Honors the scaling type\n" \
|
|
+ "When any scaling lock is active (including Uniform), only the first variable can be edited, the rest will update automatically"
|
|
|
|
"up_vector/up_vector_primary_type":
|
|
return "Defines the source for the up vector used to orient our plant\n" \
|
|
+ "Can use world-based vectors, normals of the surface or a custom vector in world-space"
|
|
"up_vector/up_vector_primary":
|
|
return "The custom value to be used as primary up vector"
|
|
"up_vector/up_vector_secondary_type":
|
|
return "Defines the source for second vector to be used in blending/interpolation\n" \
|
|
+ "Can use world-based vectors, normals of the surface or a custom vector in world-space"
|
|
"up_vector/up_vector_secondary":
|
|
return "The custom value to be used as secondary up vector"
|
|
"up_vector/up_vector_blending":
|
|
return "How much we blend between our vectors\n" \
|
|
+ "0.0 - use primary, 0.5 - use in-between the two, 1.0 - use secondary and so on\n" \
|
|
+ "Is used to specify the main orientation for our plant and then a small inclination towards something\n" \
|
|
+ "E.g. a tree that grows upward, but is slightly tilted with it's surface"
|
|
|
|
"fwd_vector/fwd_vector_primary_type":
|
|
return "Defines the source for the forward vector used to orient our plant\n" \
|
|
+ "Can use world-based vectors, normals of the surface or a custom vector in world-space"
|
|
"fwd_vector/fwd_vector_primary":
|
|
return "The custom value to be used as primary forward vector"
|
|
"fwd_vector/fwd_vector_secondary_type":
|
|
return "Defines the source for second vector to be used in blending/interpolation\n" \
|
|
+ "Can use world-based vectors, normals of the surface or a custom vector in world-space"
|
|
"fwd_vector/fwd_vector_secondary":
|
|
return "The custom value to be used as secondary forward vector"
|
|
"fwd_vector/fwd_vector_blending":
|
|
return "How much we blend between our vectors\n" \
|
|
+ "0.0 - use primary, 0.5 - use in-between the two, 1.0 - use secondary and so on\n" \
|
|
+ "Is used to specify the main orientation for our plant and then a small inclination towards something\n" \
|
|
+ "E.g. a signpost that points forward in world space, but is slightly tilted to it's target"
|
|
|
|
"offset/offset_y_range":
|
|
return "The range of random vertical offset in local space\n" \
|
|
+ "Used to hide things like roots below the surface"
|
|
"offset/offset_jitter_fraction":
|
|
return "The random 'cell offset' for each instance\n" \
|
|
+ "All instances are placed on a virtual grid, and with a jitter of 0.0 will appear placed using a ruler\n" \
|
|
+ "Jitter specifies how far in local space of each cell can an instance be offset\n" \
|
|
+ "E.g. 0.0 - instance in the center, 0.5 - instance can be halfway to the cell's border, 1.0 - instance can appear on the border\n" \
|
|
+ "The values of 0.0 and 1.0 should generally be avoided"
|
|
|
|
"rotation/rotation_random_y":
|
|
return "The range of random rotation on Y axis (Yaw)\n" \
|
|
+ "E.g. 45 means it can be rotated to a random angle between 45 degress clokwise and counter clockwise"
|
|
"rotation/rotation_random_x":
|
|
return "The range of random rotation on X axis (Pitch)\n" \
|
|
+ "E.g. 45 means it can be rotated to a random angle between 45 degress clokwise and counter clockwise"
|
|
"rotation/rotation_random_z":
|
|
return "The range of random rotation on Z axis (Roll)\n" \
|
|
+ "E.g. 45 means it can be rotated to a random angle between 45 degress clokwise and counter clockwise"
|
|
|
|
"slope/slope_allowed_range":
|
|
return "The range of slopes (in degrees) where our plant can be placed\n" \
|
|
+ "Can be used to avoid placing plants on steep slopes or vertical walls\n" \
|
|
+ "\n" \
|
|
+ "NOTE: slope is calculated in relation to the Primary Up Vector\n" \
|
|
+ "If you wish to align your plant to Surface Normal and use the slope\n" \
|
|
+ "Set Primary Up Vector to World Y, secondary to Normal and just blend all the way to the secondary vector (blend = 1.0)"
|
|
|
|
"import_export/import_plant_data_button":
|
|
return "The button to import plant settings and transforms\n" \
|
|
+ "For the current plant inside a current Gardener\n" \
|
|
+ "Instances are ADDED to the existing ones; to replace you'll need to manually erase the old instances first\n" \
|
|
+ "\n" \
|
|
+ "NOTE: import recreates your octree nodes anew and they won't be the same\n" \
|
|
+ "(but they were killed already by an export operation to begin with)\n" \
|
|
+ "Most of the time this can be ignored since you likely Rebuild/Recenter your octrees on a regular basis anyway"
|
|
"import_export/export_plant_data_button":
|
|
return "The button to export plant settings and transforms\n" \
|
|
+ "Of current plant inside a current Gardener\n" \
|
|
+ "To import them to a different scene\n" \
|
|
+ "Or when switching between plugin versions (whenever necessary)\n" \
|
|
+ "\n" \
|
|
+ "NOTE: export kills whatever octree nodes you have\n" \
|
|
+ "(and import recreates them anew but they won't be the same)\n" \
|
|
+ "Most of the time this can be ignored since you likely Rebuild/Recenter your octrees on a regular basis anyway"
|
|
"import_export/import_greenhouse_data_button":
|
|
return "The button to import all greenhouse plant settings and transforms\n" \
|
|
+ "Inside a current Gardener\n" \
|
|
+ "Instances are ADDED to the existing ones; to replace you'll need to manually erase the old instances first\n" \
|
|
+ "\n" \
|
|
+ "NOTE: import recreates your octree nodes anew and they won't be the same\n" \
|
|
+ "(but they were killed already by an export operation to begin with)\n" \
|
|
+ "Most of the time this can be ignored since you likely Rebuild/Recenter your octrees on a regular basis anyway"
|
|
"import_export/export_greenhouse_data_button":
|
|
return "The button to export all greenhouse plant settings and transforms\n" \
|
|
+ "Inside a current Gardener\n" \
|
|
+ "To import them to a different scene\n" \
|
|
+ "Or when switching between plugin versions (whenever necessary)\n" \
|
|
+ "\n" \
|
|
+ "NOTE: export kills whatever octree nodes you have\n" \
|
|
+ "(and import recreates them anew but they won't be the same)\n" \
|
|
+ "Most of the time this can be ignored since you likely Rebuild/Recenter your octrees on a regular basis anyway"
|
|
|
|
return ""
|