Adds missing data

This commit is contained in:
Michel 2025-02-03 19:17:20 +01:00
parent e6391d9fdd
commit 53cdcc3433
620 changed files with 47293 additions and 151 deletions

View file

@ -0,0 +1,461 @@
# MIT License
#
# Copyright (c) 2023 Mark McKay
# https://github.com/blackears/cyclopsLevelBuilder
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
@tool
extends EditorPlugin
class_name CyclopsLevelBuilder
signal active_node_changed
signal selection_changed
signal snapping_tool_changed
const AUTOLOAD_NAME = "CyclopsAutoload"
const CYCLOPS_HUD_NAME = "CyclopsGlobalHud"
var config:CyclopsConfig = preload("res://addons/cyclops_level_builder/data/configuration.tres")
var logger:CyclopsLogger = CyclopsLogger.new()
var material_dock:MaterialPaletteViewport
var convex_face_editor_dock:ConvexFaceEdtiorViewport
var tool_properties_dock:ToolPropertiesDock
var snapping_properties_dock:SnappingPropertiesDock
var cyclops_console_dock:CyclopsConsole
var main_toolbar:MainToolbar
var editor_toolbar:EditorToolbar
var upgrade_cyclops_blocks_toolbar:UpgradeCyclopsBlocksToolbar
var activated:bool = false
var always_on:bool = false:
get:
return always_on
set(value):
always_on = value
#print("always_on %s" % always_on)
update_activation()
var block_create_distance:float = 10
var tool:CyclopsTool = null
var snapping_system:CyclopsSnappingSystem = null
var lock_uvs:bool = false
var tool_overlay_extrude:float = .01
var tool_uv_transform:Transform2D
var tool_material_path:String
var handle_screen_radius:float = 6
var drag_start_radius:float = 6
enum Mode { OBJECT, EDIT }
var mode:Mode = Mode.OBJECT
enum EditMode { VERTEX, EDGE, FACE }
var edit_mode:CyclopsLevelBuilder.EditMode = CyclopsLevelBuilder.EditMode.VERTEX
var display_mode:DisplayMode.Type = DisplayMode.Type.MATERIAL
var cached_viewport_camera:Camera3D
var editor_cache:Dictionary
var editor_cache_file:String = "user://cyclops_editor_cache.json"
func get_snapping_manager()->SnappingManager:
var mgr:SnappingManager = SnappingManager.new()
mgr.snap_enabled = CyclopsAutoload.settings.get_property(CyclopsGlobalScene.SNAPPING_ENABLED)
mgr.snap_tool = snapping_system
return mgr
func _get_plugin_name()->String:
return "CyclopsLevelBuilder"
func _get_plugin_icon()->Texture2D:
return preload("res://addons/cyclops_level_builder/art/cyclops.svg")
func _enter_tree():
if FileAccess.file_exists(editor_cache_file):
#print(">> _enter_tree")
var text:String = FileAccess.get_file_as_string(editor_cache_file)
#print("load text:", text)
editor_cache = JSON.parse_string(text)
add_custom_type("CyclopsScene", "Node3D", preload("nodes/cyclops_scene.gd"), preload("nodes/cyclops_blocks_icon.png"))
add_custom_type("CyclopsBlock", "Node3D", preload("nodes/cyclops_block.gd"), preload("nodes/cyclops_blocks_icon.png"))
add_custom_type("CyclopsBlocks", "Node3D", preload("nodes/cyclops_blocks.gd"), preload("nodes/cyclops_blocks_icon.png"))
add_custom_type("CyclopsConvexBlock", "Node", preload("nodes/cyclops_convex_block.gd"), preload("nodes/cyclops_blocks_icon.png"))
add_custom_type("CyclopsConvexBlockBody", "Node", preload("nodes/cyclops_convex_block_body.gd"), preload("nodes/cyclops_blocks_icon.png"))
add_autoload_singleton(AUTOLOAD_NAME, "res://addons/cyclops_level_builder/cyclops_global_scene.tscn")
#add_autoload_singleton(CYCLOPS_HUD_NAME, "res://addons/cyclops_level_builder/cyclops_global_hud.tscn")
material_dock = preload("res://addons/cyclops_level_builder/docks/material_palette/material_palette_viewport.tscn").instantiate()
material_dock.builder = self
convex_face_editor_dock = preload("res://addons/cyclops_level_builder/docks/convex_face_editor/convex_face_editor_viewport.tscn").instantiate()
convex_face_editor_dock.builder = self
tool_properties_dock = preload("res://addons/cyclops_level_builder/docks/tool_properties/tool_properties_dock.tscn").instantiate()
tool_properties_dock.builder = self
snapping_properties_dock = preload("res://addons/cyclops_level_builder/docks/snapping_properties/snapping_properties_dock.tscn").instantiate()
snapping_properties_dock.builder = self
cyclops_console_dock = preload("res://addons/cyclops_level_builder/docks/cyclops_console/cyclops_console.tscn").instantiate()
cyclops_console_dock.editor_plugin = self
main_toolbar = preload("menu/main_toolbar.tscn").instantiate()
main_toolbar.editor_plugin = self
editor_toolbar = preload("menu/editor_toolbar.tscn").instantiate()
editor_toolbar.editor_plugin = self
upgrade_cyclops_blocks_toolbar = preload("res://addons/cyclops_level_builder/menu/upgrade_cyclops_blocks_toolbar.tscn").instantiate()
upgrade_cyclops_blocks_toolbar.editor_plugin = self
add_control_to_bottom_panel(cyclops_console_dock, "Cyclops")
add_control_to_container(EditorPlugin.CONTAINER_SPATIAL_EDITOR_MENU, main_toolbar)
var editor:EditorInterface = get_editor_interface()
var selection:EditorSelection = editor.get_selection()
selection.selection_changed.connect(on_selection_changed)
update_activation()
#Wait until everything is loaded
await get_tree().process_frame
var global_scene:CyclopsGlobalScene = get_node("/root/CyclopsAutoload")
global_scene.builder = self
switch_to_snapping_system(SnappingSystemGrid.new())
switch_to_tool(ToolBlock.new())
func _exit_tree():
var file:FileAccess = FileAccess.open(editor_cache_file, FileAccess.WRITE)
#var text:String = JSON.stringify(editor_cache, " ")
#print("saving cache:", text)
file.store_string(JSON.stringify(editor_cache, " "))
file.close()
# Clean-up of the plugin goes here.
remove_autoload_singleton(AUTOLOAD_NAME)
#remove_autoload_singleton(CYCLOPS_HUD_NAME)
remove_custom_type("CyclopsScene")
remove_custom_type("CyclopsBlock")
remove_custom_type("CyclopsBlocks")
remove_custom_type("CyclopsConvexBlock")
remove_custom_type("CyclopsConvexBlockBody")
remove_control_from_bottom_panel(cyclops_console_dock)
remove_control_from_container(EditorPlugin.CONTAINER_SPATIAL_EDITOR_MENU, main_toolbar)
if activated:
remove_control_from_docks(material_dock)
remove_control_from_docks(convex_face_editor_dock)
remove_control_from_docks(tool_properties_dock)
remove_control_from_docks(snapping_properties_dock)
remove_control_from_docks(cyclops_console_dock)
remove_control_from_container(EditorPlugin.CONTAINER_SPATIAL_EDITOR_MENU, editor_toolbar)
if upgrade_cyclops_blocks_toolbar.activated:
remove_control_from_container(EditorPlugin.CONTAINER_SPATIAL_EDITOR_MENU, upgrade_cyclops_blocks_toolbar)
material_dock.queue_free()
convex_face_editor_dock.queue_free()
tool_properties_dock.queue_free()
snapping_properties_dock.queue_free()
cyclops_console_dock.queue_free()
main_toolbar.queue_free()
editor_toolbar.queue_free()
upgrade_cyclops_blocks_toolbar.queue_free()
func log(message:String, level:CyclopsLogger.LogLevel = CyclopsLogger.LogLevel.ERROR):
logger.log(message, level)
func get_blocks()->Array[CyclopsBlock]:
return get_blocks_recursive(get_editor_interface().get_edited_scene_root())
func get_blocks_recursive(node:Node)->Array[CyclopsBlock]:
var result:Array[CyclopsBlock]
if node is CyclopsBlock:
result.append(node)
for child in node.get_children():
result.append_array(get_blocks_recursive(child))
return result
func is_selected(node:Node)->bool:
var selection:EditorSelection = get_editor_interface().get_selection()
for n in selection.get_selected_nodes():
if n == node:
return true
return false
func is_active_block(block:CyclopsBlock)->bool:
var selection:EditorSelection = get_editor_interface().get_selection()
var nodes:Array[Node] = selection.get_selected_nodes()
return !nodes.is_empty() && nodes.back() == block
func get_active_block()->CyclopsBlock:
var selection:EditorSelection = get_editor_interface().get_selection()
var nodes:Array[Node] = selection.get_selected_nodes()
var back:Node = nodes.back()
if back is CyclopsBlock:
return back
return null
#Blocks listed in order of selection with last block being the most recent (ie, active) one
func get_selected_blocks()->Array[CyclopsBlock]:
var result:Array[CyclopsBlock]
var selection:EditorSelection = get_editor_interface().get_selection()
for node in selection.get_selected_nodes():
if node is CyclopsBlock:
result.append(node)
return result
func get_block_add_parent()->Node:
var selection:EditorSelection = get_editor_interface().get_selection()
var nodes:Array = selection.get_selected_nodes()
if nodes.is_empty():
return get_editor_interface().get_edited_scene_root()
if nodes[0] is CyclopsBlock:
#print("getting parent of ", nodes[0].name)
return nodes[0].get_parent()
return nodes[0]
func update_activation():
var editor:EditorInterface = get_editor_interface()
var selection:EditorSelection = editor.get_selection()
var nodes:Array[Node] = selection.get_selected_nodes()
#Node list ordered in order of selection with most recently sdelected at end
var node:Node = null
if !nodes.is_empty():
node = nodes[0]
if node is CyclopsBlock || always_on:
#print("updarting activation")
if !activated:
add_control_to_container(EditorPlugin.CONTAINER_SPATIAL_EDITOR_MENU, editor_toolbar)
add_control_to_bottom_panel(material_dock, "Materials")
add_control_to_dock(DOCK_SLOT_RIGHT_BL, convex_face_editor_dock)
add_control_to_dock(DOCK_SLOT_RIGHT_BL, tool_properties_dock)
add_control_to_dock(DOCK_SLOT_RIGHT_BL, snapping_properties_dock)
activated = true
else:
if activated:
remove_control_from_container(EditorPlugin.CONTAINER_SPATIAL_EDITOR_MENU, editor_toolbar)
remove_control_from_bottom_panel(material_dock)
remove_control_from_docks(convex_face_editor_dock)
remove_control_from_docks(tool_properties_dock)
remove_control_from_docks(snapping_properties_dock)
activated = false
if node is CyclopsBlocks:
if !upgrade_cyclops_blocks_toolbar.activated:
add_control_to_container(EditorPlugin.CONTAINER_SPATIAL_EDITOR_MENU, upgrade_cyclops_blocks_toolbar)
upgrade_cyclops_blocks_toolbar.activated = true
else:
if upgrade_cyclops_blocks_toolbar.activated:
remove_control_from_container(EditorPlugin.CONTAINER_SPATIAL_EDITOR_MENU, upgrade_cyclops_blocks_toolbar)
upgrade_cyclops_blocks_toolbar.activated = false
func on_selection_changed():
update_activation()
if cached_viewport_camera:
tool._draw_tool(cached_viewport_camera)
func _handles(object:Object):
# return object is CyclopsBlocks or object is CyclopsConvexBlock
return object is CyclopsBlock or object is CyclopsBlocks or always_on
func _forward_3d_draw_over_viewport(viewport_control:Control):
var global_scene:CyclopsGlobalScene = get_global_scene()
global_scene.draw_over_viewport(viewport_control)
#Draw on top of viweport here
func _forward_3d_gui_input(viewport_camera:Camera3D, event:InputEvent):
#print("plugin: " + event.as_text())
cached_viewport_camera = viewport_camera
if tool:
var result:bool = tool._gui_input(viewport_camera, event)
tool._draw_tool(viewport_camera)
return EditorPlugin.AFTER_GUI_INPUT_STOP if result else EditorPlugin.AFTER_GUI_INPUT_PASS
return EditorPlugin.AFTER_GUI_INPUT_PASS
func _get_state()->Dictionary:
var state:Dictionary = {}
#print("ed cache ", str(editor_cache))
#state["editor_cache"] = editor_cache.duplicate()
material_dock.save_state(state)
convex_face_editor_dock.save_state(state)
tool_properties_dock.save_state(state)
snapping_properties_dock.save_state(state)
cyclops_console_dock.save_state(state)
return state
func _set_state(state):
#print("ed set_state ", str(state))
#editor_cache = state.get("editor_cache", {}).duplicate()
material_dock.load_state(state)
convex_face_editor_dock.load_state(state)
tool_properties_dock.load_state(state)
snapping_properties_dock.load_state(state)
cyclops_console_dock.load_state(state)
func get_tool_cache(tool_id:String):
if !editor_cache.has("tool"):
return {}
if !editor_cache.tool.has(tool_id):
return {}
return editor_cache.tool[tool_id]
func set_tool_cache(tool_id:String, cache:Dictionary):
if !editor_cache.has("tool"):
editor_cache["tool"] = {}
editor_cache.tool[tool_id] = cache
func get_snapping_cache(tool_id:String):
if !editor_cache.has("snapping"):
return {}
if !editor_cache.snapping.has(tool_id):
return {}
return editor_cache.snapping[tool_id]
func set_snapping_cache(tool_id:String, cache:Dictionary):
if !editor_cache.has("snapping"):
editor_cache["snapping"] = {}
editor_cache.snapping[tool_id] = cache
func switch_to_tool(_tool:CyclopsTool):
#print(">> switch to tool")
if tool:
tool._deactivate()
tool = _tool
if tool:
tool._activate(self)
var control:Control = tool._get_tool_properties_editor()
tool_properties_dock.set_editor(control)
func switch_to_snapping_system(_snapping_system:CyclopsSnappingSystem):
if snapping_system:
snapping_system._deactivate()
snapping_system = _snapping_system
if snapping_system:
snapping_system._activate(self)
var control:Control = snapping_system._get_properties_editor()
snapping_properties_dock.set_editor(control)
snapping_tool_changed.emit()
func get_global_scene()->CyclopsGlobalScene:
var scene:CyclopsGlobalScene = get_node("/root/CyclopsAutoload")
return scene
func intersect_ray_closest(origin:Vector3, dir:Vector3)->IntersectResults:
var best_result:IntersectResults
var blocks:Array[CyclopsBlock] = get_blocks()
for block in blocks:
if !block.is_visible_in_tree():
continue
var result:IntersectResults = block.intersect_ray_closest(origin, dir)
# print("isect %s %s" % [node.name, result])
if result:
if !best_result or result.distance_squared < best_result.distance_squared:
# print("setting best result %s" % node.name)
best_result = result
# print("best_result %s" % ray_best_result)
# print("returning best result %s" % ray_best_result)
return best_result
func intersect_ray_closest_selected_only(origin:Vector3, dir:Vector3)->IntersectResults:
var best_result:IntersectResults
var blocks:Array[CyclopsBlock] = get_selected_blocks()
for block in blocks:
var result:IntersectResults = block.intersect_ray_closest(origin, dir)
if result:
if !best_result or result.distance_squared < best_result.distance_squared:
best_result = result
return best_result
func intersect_frustum_all(frustum:Array[Plane])->Array[CyclopsBlock]:
var result:Array[CyclopsBlock] = []
var blocks:Array[CyclopsBlock] = get_blocks()
for block in blocks:
var xform:Transform3D = block.global_transform.affine_inverse()
var frustum_local:Array[Plane]
for p in frustum:
frustum_local.append(xform * p)
#print("intersect_frustum_all block %s" % block.get_path())
var vol:ConvexVolume = block.control_mesh
# if !vol:
# print("nil vol %s" % block.get_path())
if vol && vol.intersects_frustum(frustum_local):
result.append(block)
return result