initial commit
This commit is contained in:
69
addons/cyclops_level_builder/commands/cmd_add_block.gd
Normal file
69
addons/cyclops_level_builder/commands/cmd_add_block.gd
Normal file
@ -0,0 +1,69 @@
|
||||
# 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
|
||||
class_name CommandAddBlock2
|
||||
extends CyclopsCommand
|
||||
|
||||
#Public data to set before activating command
|
||||
var blocks_root_path:NodePath
|
||||
var block_name:String
|
||||
var bounds:AABB
|
||||
var material_path:String
|
||||
var uv_transform:Transform2D = Transform2D.IDENTITY
|
||||
|
||||
#Private data
|
||||
var block_path:NodePath
|
||||
|
||||
func _init():
|
||||
command_name = "Add block"
|
||||
|
||||
func do_it():
|
||||
var block:CyclopsConvexBlock = preload("../nodes/cyclops_convex_block.gd").new()
|
||||
|
||||
var blocks_root:CyclopsBlocks = builder.get_node(blocks_root_path)
|
||||
blocks_root.add_child(block)
|
||||
block.owner = builder.get_editor_interface().get_edited_scene_root()
|
||||
block.name = block_name
|
||||
|
||||
var material_id:int = -1
|
||||
if ResourceLoader.exists(material_path):
|
||||
var mat = load(material_path)
|
||||
if mat is Material:
|
||||
material_id = 0
|
||||
block.materials.append(mat)
|
||||
|
||||
|
||||
var mesh:ConvexVolume = ConvexVolume.new()
|
||||
mesh.init_block(bounds, uv_transform, material_id)
|
||||
|
||||
block.block_data = mesh.to_convex_block_data()
|
||||
block_path = block.get_path()
|
||||
|
||||
# print("AddBlockCommand do_it() %s %s" % [block_inst_id, bounds])
|
||||
|
||||
func undo_it():
|
||||
var block:CyclopsConvexBlock = builder.get_node(block_path)
|
||||
block.queue_free()
|
||||
|
||||
# print("AddBlockCommand undo_it()")
|
102
addons/cyclops_level_builder/commands/cmd_add_cylinder.gd
Normal file
102
addons/cyclops_level_builder/commands/cmd_add_cylinder.gd
Normal file
@ -0,0 +1,102 @@
|
||||
# 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
|
||||
class_name CommandAddCylinder
|
||||
extends CyclopsCommand
|
||||
|
||||
#Public data to set before activating command
|
||||
var blocks_root_path:NodePath
|
||||
#var block_name:String
|
||||
var block_name_prefix:String = "Block_"
|
||||
var origin:Vector3
|
||||
var axis_normal:Vector3
|
||||
var height:float
|
||||
var radius_inner:float
|
||||
var radius_outer:float
|
||||
var segments:int
|
||||
var tube:bool = false
|
||||
|
||||
var material_path:String
|
||||
var uv_transform:Transform2D = Transform2D.IDENTITY
|
||||
|
||||
#Private data
|
||||
var block_paths:Array[NodePath]
|
||||
|
||||
func _init():
|
||||
command_name = "Add cylinder"
|
||||
|
||||
func create_block(blocks_root:CyclopsBlocks, mat:Material)->CyclopsConvexBlock:
|
||||
var block:CyclopsConvexBlock = preload("../nodes/cyclops_convex_block.gd").new()
|
||||
blocks_root.add_child(block)
|
||||
block.owner = builder.get_editor_interface().get_edited_scene_root()
|
||||
block.name = GeneralUtil.find_unique_name(builder.active_node, block_name_prefix)
|
||||
|
||||
if mat:
|
||||
block.materials.append(mat)
|
||||
|
||||
return block
|
||||
|
||||
|
||||
func do_it():
|
||||
var blocks_root:CyclopsBlocks = builder.get_node(blocks_root_path)
|
||||
|
||||
var material:Material
|
||||
var material_id:int = -1
|
||||
if ResourceLoader.exists(material_path):
|
||||
var mat = load(material_path)
|
||||
if mat is Material:
|
||||
material_id = 0
|
||||
material = mat
|
||||
|
||||
if tube:
|
||||
var bounding_points_inner:PackedVector3Array = MathUtil.create_circle_points(origin, axis_normal, radius_inner, segments)
|
||||
var bounding_points_outer:PackedVector3Array = MathUtil.create_circle_points(origin, axis_normal, radius_outer, segments)
|
||||
|
||||
for p_idx0 in bounding_points_inner.size():
|
||||
var p_idx1:int = wrap(p_idx0 + 1, 0, bounding_points_inner.size())
|
||||
|
||||
var block:CyclopsConvexBlock = create_block(blocks_root, material)
|
||||
|
||||
var mesh:ConvexVolume = ConvexVolume.new()
|
||||
var base_points:PackedVector3Array = [bounding_points_inner[p_idx0], bounding_points_inner[p_idx1], bounding_points_outer[p_idx1], bounding_points_outer[p_idx0]]
|
||||
|
||||
mesh.init_prism(base_points, axis_normal * height, uv_transform, material_id)
|
||||
|
||||
block.block_data = mesh.to_convex_block_data()
|
||||
block_paths.append(block.get_path())
|
||||
|
||||
else:
|
||||
var block:CyclopsConvexBlock = create_block(blocks_root, material)
|
||||
|
||||
var bounding_points:PackedVector3Array = MathUtil.create_circle_points(origin, axis_normal, radius_outer, segments)
|
||||
var mesh:ConvexVolume = ConvexVolume.new()
|
||||
mesh.init_prism(bounding_points, axis_normal * height, uv_transform, material_id)
|
||||
|
||||
block.block_data = mesh.to_convex_block_data()
|
||||
block_paths.append(block.get_path())
|
||||
|
||||
func undo_it():
|
||||
for path in block_paths:
|
||||
var block:CyclopsConvexBlock = builder.get_node(path)
|
||||
block.queue_free()
|
69
addons/cyclops_level_builder/commands/cmd_add_prism.gd
Normal file
69
addons/cyclops_level_builder/commands/cmd_add_prism.gd
Normal file
@ -0,0 +1,69 @@
|
||||
# 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
|
||||
class_name CommandAddPrism
|
||||
extends CyclopsCommand
|
||||
|
||||
var blocks_root_path:NodePath
|
||||
var block_name:String
|
||||
var base_polygon:PackedVector3Array
|
||||
var extrude:Vector3
|
||||
var uv_transform:Transform2D
|
||||
var material_path:String
|
||||
|
||||
#Private
|
||||
var block_path:NodePath
|
||||
|
||||
func _init():
|
||||
command_name = "Add prism"
|
||||
|
||||
func do_it():
|
||||
var block:CyclopsConvexBlock = preload("../nodes/cyclops_convex_block.gd").new()
|
||||
|
||||
var blocks_root:CyclopsBlocks = builder.get_node(blocks_root_path)
|
||||
blocks_root.add_child(block)
|
||||
block.owner = builder.get_editor_interface().get_edited_scene_root()
|
||||
# block.owner = block_owner
|
||||
block.name = block_name
|
||||
|
||||
var material_id:int = -1
|
||||
if ResourceLoader.exists(material_path):
|
||||
var mat = load(material_path)
|
||||
if mat is Material:
|
||||
material_id = 0
|
||||
block.materials.append(mat)
|
||||
|
||||
var mesh:ConvexVolume = ConvexVolume.new()
|
||||
mesh.init_prism(base_polygon, extrude, uv_transform, material_id)
|
||||
|
||||
block.block_data = mesh.to_convex_block_data()
|
||||
block_path = block.get_path()
|
||||
|
||||
# print("AddBlockCommand do_it() %s %s" % [block_inst_id, bounds])
|
||||
|
||||
func undo_it():
|
||||
var block:CyclopsConvexBlock = builder.get_node(block_path)
|
||||
block.queue_free()
|
||||
|
||||
# print("AddBlockCommand undo_it()")
|
150
addons/cyclops_level_builder/commands/cmd_add_stairs.gd
Normal file
150
addons/cyclops_level_builder/commands/cmd_add_stairs.gd
Normal file
@ -0,0 +1,150 @@
|
||||
# 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
|
||||
class_name CommandAddStairs
|
||||
extends CyclopsCommand
|
||||
|
||||
#var blocks_root_inst_id:int
|
||||
var blocks_root_path:NodePath
|
||||
var block_name_prefix:String
|
||||
var floor_normal:Vector3
|
||||
var drag_origin:Vector3
|
||||
var base_drag_cur:Vector3
|
||||
var block_drag_cur:Vector3
|
||||
var step_height:float = .25
|
||||
var step_depth:float = .5
|
||||
var direction:int = 0
|
||||
|
||||
var uv_transform:Transform2D
|
||||
var material_path:String
|
||||
|
||||
#Private data
|
||||
var block_paths:Array[NodePath]
|
||||
|
||||
func _init():
|
||||
command_name = "Add stairs"
|
||||
|
||||
func create_block(blocks_root:CyclopsBlocks, mat:Material)->CyclopsConvexBlock:
|
||||
var block:CyclopsConvexBlock = preload("../nodes/cyclops_convex_block.gd").new()
|
||||
blocks_root.add_child(block)
|
||||
block.owner = builder.get_editor_interface().get_edited_scene_root()
|
||||
block.name = GeneralUtil.find_unique_name(builder.active_node, block_name_prefix)
|
||||
|
||||
if mat:
|
||||
block.materials.append(mat)
|
||||
|
||||
return block
|
||||
|
||||
|
||||
func do_it():
|
||||
var blocks_root:CyclopsBlocks = builder.get_node(blocks_root_path)
|
||||
|
||||
var material:Material
|
||||
var material_id:int = -1
|
||||
if ResourceLoader.exists(material_path):
|
||||
var mat = load(material_path)
|
||||
if mat is Material:
|
||||
material_id = 0
|
||||
material = mat
|
||||
|
||||
var tan_bi:Array[Vector3] = MathUtil.get_axis_aligned_tangent_and_binormal(floor_normal)
|
||||
var u_normal:Vector3 = tan_bi[0]
|
||||
var v_normal:Vector3 = tan_bi[1]
|
||||
|
||||
#Rotate ccw by 90 degree increments
|
||||
match direction:
|
||||
1:
|
||||
var tmp:Vector3 = u_normal
|
||||
u_normal = -v_normal
|
||||
v_normal = tmp
|
||||
2:
|
||||
u_normal = -u_normal
|
||||
v_normal = -v_normal
|
||||
3:
|
||||
var tmp:Vector3 = -u_normal
|
||||
u_normal = v_normal
|
||||
v_normal = tmp
|
||||
|
||||
var u_span:Vector3 = (base_drag_cur - drag_origin).project(u_normal)
|
||||
var v_span:Vector3 = (base_drag_cur - drag_origin).project(v_normal)
|
||||
|
||||
var stairs_origin:Vector3 = drag_origin
|
||||
if u_span.dot(u_normal) < 0:
|
||||
stairs_origin += u_span
|
||||
u_span = -u_span
|
||||
if v_span.dot(v_normal) < 0:
|
||||
stairs_origin += v_span
|
||||
v_span = -v_span
|
||||
|
||||
#Stairs should ascend along v axis
|
||||
var height_offset = block_drag_cur - base_drag_cur
|
||||
if height_offset.dot(floor_normal) < 0:
|
||||
return
|
||||
var num_steps:int = min(v_span.length() / step_depth, height_offset.length() / step_height)
|
||||
|
||||
var max_height:float = floor(height_offset.length() / step_height) * step_height
|
||||
|
||||
var step_span:Vector3 = v_normal * step_depth
|
||||
for i in num_steps:
|
||||
var base_points:PackedVector3Array = [stairs_origin + step_span * i, \
|
||||
stairs_origin + u_span + step_span * i, \
|
||||
stairs_origin + u_span + step_span * (i + 1), \
|
||||
stairs_origin + step_span * (i + 1)]
|
||||
|
||||
var mesh:ConvexVolume = ConvexVolume.new()
|
||||
mesh.init_prism(base_points, \
|
||||
floor_normal * (max_height - step_height * i), \
|
||||
uv_transform, material_id)
|
||||
|
||||
var block:CyclopsConvexBlock = create_block(blocks_root, material)
|
||||
|
||||
block.block_data = mesh.to_convex_block_data()
|
||||
block_paths.append(block.get_path())
|
||||
|
||||
# global_scene.draw_prism(base_points, \
|
||||
# floor_normal * (max_height - step_height * i), \
|
||||
# global_scene.tool_material)
|
||||
|
||||
|
||||
# var bounding_points_inner:PackedVector3Array = MathUtil.create_circle_points(origin, axis_normal, radius_inner, segments)
|
||||
# var bounding_points_outer:PackedVector3Array = MathUtil.create_circle_points(origin, axis_normal, radius_outer, segments)
|
||||
#
|
||||
# for p_idx0 in bounding_points_inner.size():
|
||||
# var p_idx1:int = wrap(p_idx0 + 1, 0, bounding_points_inner.size())
|
||||
#
|
||||
# var block:CyclopsConvexBlock = create_block(blocks_root, material)
|
||||
#
|
||||
# var mesh:ConvexVolume = ConvexVolume.new()
|
||||
# var base_points:PackedVector3Array = [bounding_points_inner[p_idx0], bounding_points_inner[p_idx1], bounding_points_outer[p_idx1], bounding_points_outer[p_idx0]]
|
||||
#
|
||||
# mesh.init_prism(base_points, axis_normal * height, uv_transform, material_id)
|
||||
#
|
||||
# block.block_data = mesh.to_convex_block_data()
|
||||
# block_paths.append(block.get_path())
|
||||
|
||||
|
||||
func undo_it():
|
||||
for path in block_paths:
|
||||
var block:CyclopsConvexBlock = builder.get_node(path)
|
||||
block.queue_free()
|
73
addons/cyclops_level_builder/commands/cmd_add_vertices.gd
Normal file
73
addons/cyclops_level_builder/commands/cmd_add_vertices.gd
Normal file
@ -0,0 +1,73 @@
|
||||
# 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
|
||||
class_name CommandAddVertices
|
||||
extends CyclopsCommand
|
||||
|
||||
|
||||
#Public
|
||||
var points_to_add:PackedVector3Array
|
||||
var block_path:NodePath
|
||||
|
||||
#Private
|
||||
var tracked_block_data:ConvexBlockData
|
||||
var selected_points:PackedVector3Array
|
||||
|
||||
|
||||
func _init():
|
||||
command_name = "Add vertices"
|
||||
|
||||
func do_it():
|
||||
var block:CyclopsConvexBlock = builder.get_node(block_path)
|
||||
|
||||
if !tracked_block_data:
|
||||
var tracked_vol:ConvexVolume = block.control_mesh
|
||||
tracked_block_data = tracked_vol.to_convex_block_data()
|
||||
|
||||
for v in tracked_vol.vertices:
|
||||
if v.selected:
|
||||
selected_points.append(v.point)
|
||||
|
||||
var vol:ConvexVolume = ConvexVolume.new()
|
||||
vol.init_from_convex_block_data(tracked_block_data)
|
||||
|
||||
var point_list:PackedVector3Array = vol.get_points()
|
||||
point_list.append_array(points_to_add)
|
||||
|
||||
var new_vol:ConvexVolume = ConvexVolume.new()
|
||||
new_vol.init_from_points(point_list)
|
||||
new_vol.copy_face_attributes(vol)
|
||||
|
||||
|
||||
for v_idx in new_vol.vertices.size():
|
||||
var v:ConvexVolume.VertexInfo = new_vol.vertices[v_idx]
|
||||
if selected_points.has(v.point):
|
||||
v.selected = true
|
||||
|
||||
block.block_data = new_vol.to_convex_block_data()
|
||||
|
||||
|
||||
func undo_it():
|
||||
var block:CyclopsConvexBlock = builder.get_node(block_path)
|
||||
block.block_data = tracked_block_data
|
102
addons/cyclops_level_builder/commands/cmd_clip_block.gd
Normal file
102
addons/cyclops_level_builder/commands/cmd_clip_block.gd
Normal file
@ -0,0 +1,102 @@
|
||||
# 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
|
||||
class_name CommandClipBlock
|
||||
extends CyclopsCommand
|
||||
|
||||
#Public data to set before activating command
|
||||
var blocks_root_path:NodePath
|
||||
var block_path:NodePath
|
||||
var cut_plane:Plane
|
||||
var uv_transform:Transform2D = Transform2D.IDENTITY
|
||||
var material_path:String = ""
|
||||
|
||||
#Private
|
||||
var block_sibling_name:String
|
||||
var old_block_data:ConvexBlockData
|
||||
var old_mat_list:Array[Material]
|
||||
var block_sibling_path:NodePath
|
||||
|
||||
func _init():
|
||||
command_name = "Clip block"
|
||||
|
||||
func get_material_index(mat_list:Array[Material], path:String)->int:
|
||||
if path.is_empty():
|
||||
return -1
|
||||
for i in mat_list.size():
|
||||
var mat:Material = mat_list[i]
|
||||
if mat != null && mat.resource_path == path:
|
||||
return i
|
||||
return -1
|
||||
|
||||
func do_it():
|
||||
var blocks_root:CyclopsBlocks = builder.get_node(blocks_root_path)
|
||||
var block:CyclopsConvexBlock = builder.get_node(block_path)
|
||||
|
||||
old_block_data = block.block_data.duplicate()
|
||||
old_mat_list = block.materials.duplicate()
|
||||
|
||||
var new_mat_list0:Array[Material] = old_mat_list.duplicate()
|
||||
|
||||
var cut_mat_idx = get_material_index(old_mat_list, material_path)
|
||||
if cut_mat_idx == -1:
|
||||
var mat = load(material_path)
|
||||
if mat is Material:
|
||||
cut_mat_idx = new_mat_list0.size()
|
||||
new_mat_list0.append(mat)
|
||||
|
||||
|
||||
var new_mat_list1:Array[Material] = new_mat_list0.duplicate()
|
||||
|
||||
var cut_plane_reverse:Plane = Plane(-cut_plane.normal, cut_plane.get_center())
|
||||
|
||||
var vol0:ConvexVolume = block.control_mesh.cut_with_plane(cut_plane, uv_transform, cut_mat_idx)
|
||||
var vol1:ConvexVolume = block.control_mesh.cut_with_plane(MathUtil.flip_plane(cut_plane), uv_transform, cut_mat_idx)
|
||||
|
||||
#Set data of existing block
|
||||
block.block_data = vol0.to_convex_block_data()
|
||||
block.materials = new_mat_list0
|
||||
|
||||
#Create second block
|
||||
var block_sibling:CyclopsConvexBlock = preload("../nodes/cyclops_convex_block.gd").new()
|
||||
|
||||
blocks_root.add_child(block_sibling)
|
||||
block_sibling.owner = builder.get_editor_interface().get_edited_scene_root()
|
||||
block_sibling.name = block_sibling_name
|
||||
block_sibling.selected = block.selected
|
||||
block_sibling_path = block_sibling.get_path()
|
||||
|
||||
block_sibling.block_data = vol1.to_convex_block_data()
|
||||
block_sibling.materials = new_mat_list1
|
||||
|
||||
|
||||
func undo_it():
|
||||
var block:CyclopsConvexBlock = builder.get_node(block_path)
|
||||
block.block_data = old_block_data
|
||||
block.materials = old_mat_list.duplicate()
|
||||
|
||||
var block_sibling:CyclopsConvexBlock = builder.get_node(block_sibling_path)
|
||||
block_sibling.queue_free()
|
||||
|
||||
|
93
addons/cyclops_level_builder/commands/cmd_delete_blocks.gd
Normal file
93
addons/cyclops_level_builder/commands/cmd_delete_blocks.gd
Normal file
@ -0,0 +1,93 @@
|
||||
# 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
|
||||
class_name CommandDeleteBlocks
|
||||
extends CyclopsCommand
|
||||
|
||||
class TrackedBlock extends RefCounted:
|
||||
var path:NodePath
|
||||
var path_parent:NodePath
|
||||
var data:ConvexBlockData
|
||||
var materials:Array[Material]
|
||||
var selected:bool
|
||||
var name:String
|
||||
|
||||
func _init(block:CyclopsConvexBlock):
|
||||
path = block.get_path()
|
||||
path_parent = block.get_parent().get_path()
|
||||
name = block.name
|
||||
data = block.block_data.duplicate()
|
||||
selected = block.selected
|
||||
materials = block.materials
|
||||
|
||||
#Public
|
||||
var block_paths:Array[NodePath]
|
||||
|
||||
#Private
|
||||
var tracked_blocks:Array[TrackedBlock]
|
||||
|
||||
func _init():
|
||||
command_name = "Delete blocks"
|
||||
|
||||
func will_change_anything():
|
||||
if !block_paths.is_empty():
|
||||
return true
|
||||
|
||||
return false
|
||||
|
||||
|
||||
func do_it():
|
||||
#print("Delete do_it")
|
||||
|
||||
if tracked_blocks.is_empty():
|
||||
var points:PackedVector3Array
|
||||
|
||||
for path in block_paths:
|
||||
var block:CyclopsConvexBlock = builder.get_node(path)
|
||||
var tracker:TrackedBlock = TrackedBlock.new(block)
|
||||
tracked_blocks.append(tracker)
|
||||
|
||||
#Delete source blocks
|
||||
for block_path in block_paths:
|
||||
var del_block:CyclopsConvexBlock = builder.get_node(block_path)
|
||||
del_block.queue_free()
|
||||
|
||||
|
||||
func undo_it():
|
||||
#print("Delete undo_it")
|
||||
for tracked in tracked_blocks:
|
||||
var parent = builder.get_node(tracked.path_parent)
|
||||
|
||||
var block:CyclopsConvexBlock = preload("../nodes/cyclops_convex_block.gd").new()
|
||||
block.block_data = tracked.data
|
||||
block.materials = tracked.materials
|
||||
block.name = tracked.name
|
||||
block.selected = tracked.selected
|
||||
|
||||
parent.add_child(block)
|
||||
block.owner = builder.get_editor_interface().get_edited_scene_root()
|
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,87 @@
|
||||
# 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
|
||||
class_name CommandDuplicateBlocks
|
||||
extends CyclopsCommand
|
||||
|
||||
#Public
|
||||
var blocks_root_path:NodePath
|
||||
var blocks_to_duplicate:Array[NodePath]
|
||||
var move_offset:Vector3
|
||||
var lock_uvs:bool
|
||||
|
||||
#Private
|
||||
class BlockInfo extends RefCounted:
|
||||
var new_block:CyclopsConvexBlock
|
||||
var source_data:ConvexBlockData
|
||||
#var materials:Array[Material]
|
||||
|
||||
func _init(new_block:CyclopsConvexBlock, source_data:ConvexBlockData):
|
||||
self.new_block = new_block
|
||||
self.source_data = source_data
|
||||
|
||||
var added_blocks:Array[BlockInfo]
|
||||
|
||||
func will_change_anything():
|
||||
return !added_blocks.is_empty()
|
||||
|
||||
func do_it():
|
||||
if added_blocks.is_empty():
|
||||
#Create new blocks
|
||||
for block_path in blocks_to_duplicate:
|
||||
var new_block:CyclopsConvexBlock = preload("../nodes/cyclops_convex_block.gd").new()
|
||||
|
||||
var source_block:CyclopsConvexBlock = builder.get_node(block_path)
|
||||
|
||||
var blocks_root:CyclopsBlocks = builder.get_node(blocks_root_path)
|
||||
new_block.name = GeneralUtil.find_unique_name(blocks_root, source_block.name)
|
||||
blocks_root.add_child(new_block)
|
||||
new_block.owner = builder.get_editor_interface().get_edited_scene_root()
|
||||
|
||||
var info:BlockInfo = BlockInfo.new(new_block, source_block.block_data)
|
||||
new_block.materials = source_block.materials
|
||||
new_block.selected = true
|
||||
|
||||
added_blocks.append(info)
|
||||
|
||||
for path in blocks_to_duplicate:
|
||||
var block:CyclopsConvexBlock = builder.get_node(path)
|
||||
block.selected = false
|
||||
|
||||
for info in added_blocks:
|
||||
var vol:ConvexVolume = ConvexVolume.new()
|
||||
vol.init_from_convex_block_data(info.source_data)
|
||||
vol.translate(move_offset, lock_uvs)
|
||||
info.new_block.block_data = vol.to_convex_block_data()
|
||||
|
||||
|
||||
func undo_it():
|
||||
for block in added_blocks:
|
||||
block.new_block.queue_free()
|
||||
added_blocks = []
|
||||
|
||||
for path in blocks_to_duplicate:
|
||||
var block:CyclopsConvexBlock = builder.get_node(path)
|
||||
block.selected = true
|
||||
|
149
addons/cyclops_level_builder/commands/cmd_merge_blocks.gd
Normal file
149
addons/cyclops_level_builder/commands/cmd_merge_blocks.gd
Normal file
@ -0,0 +1,149 @@
|
||||
# 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
|
||||
class_name CommandMergeBlocks
|
||||
extends CyclopsCommand
|
||||
|
||||
class TrackedBlock extends RefCounted:
|
||||
var path:NodePath
|
||||
var path_parent:NodePath
|
||||
var data:ConvexBlockData
|
||||
var materials:Array[Material]
|
||||
var selected:bool
|
||||
var name:String
|
||||
|
||||
func _init(block:CyclopsConvexBlock):
|
||||
path = block.get_path()
|
||||
path_parent = block.get_parent().get_path()
|
||||
name = block.name
|
||||
data = block.block_data.duplicate()
|
||||
selected = block.selected
|
||||
materials = block.materials
|
||||
|
||||
#Public
|
||||
var block_paths:Array[NodePath]
|
||||
var block_name_prefix:String = "Block_"
|
||||
|
||||
#Private
|
||||
var tracked_blocks:Array[TrackedBlock]
|
||||
var merged_block_data:ConvexBlockData
|
||||
var merged_mat_list:Array[Material]
|
||||
var merged_block_path:NodePath
|
||||
|
||||
func _init():
|
||||
command_name = "Merge blocks"
|
||||
|
||||
func get_best_face(centroid:Vector3, ref_list:Array[NodePath])->Array:
|
||||
var best_face:ConvexVolume.FaceInfo
|
||||
var best_dist:float = INF
|
||||
var best_block:CyclopsConvexBlock
|
||||
|
||||
for block_path in ref_list:
|
||||
var block:CyclopsConvexBlock = builder.get_node(block_path)
|
||||
var vol:ConvexVolume = block.control_mesh
|
||||
for f in vol.faces:
|
||||
var face_center:Vector3 = f.get_centroid()
|
||||
var offset:float = centroid.distance_squared_to(face_center)
|
||||
if offset < best_dist:
|
||||
best_dist = offset
|
||||
best_face = f
|
||||
best_block = block
|
||||
|
||||
if best_face.material_id == -1:
|
||||
return [best_face, null]
|
||||
return [best_face, best_block.materials[best_face.material_id]]
|
||||
|
||||
func copy_face_attributes(target:ConvexVolume, ref_list:Array[NodePath])->Array[Material]:
|
||||
var mat_list:Array[Material]
|
||||
|
||||
for f in target.faces:
|
||||
var centroid:Vector3 = f.get_centroid()
|
||||
var res:Array = get_best_face(centroid, ref_list)
|
||||
var ref_face:ConvexVolume.FaceInfo = res[0]
|
||||
var material:Material = res[1]
|
||||
|
||||
var mat_idx:int = -1
|
||||
if material != null:
|
||||
mat_idx = mat_list.find(material)
|
||||
if mat_idx == -1:
|
||||
mat_idx = mat_list.size()
|
||||
mat_list.append(material)
|
||||
|
||||
f.material_id = mat_idx
|
||||
f.uv_transform = ref_face.uv_transform
|
||||
f.selected = ref_face.selected
|
||||
|
||||
return mat_list
|
||||
|
||||
func do_it():
|
||||
if tracked_blocks.is_empty():
|
||||
var points:PackedVector3Array
|
||||
|
||||
for path in block_paths:
|
||||
var block:CyclopsConvexBlock = builder.get_node(path)
|
||||
var tracker:TrackedBlock = TrackedBlock.new(block)
|
||||
tracked_blocks.append(tracker)
|
||||
|
||||
points.append_array(block.control_mesh.get_points())
|
||||
|
||||
var merged_vol:ConvexVolume = ConvexVolume.new()
|
||||
merged_vol.init_from_points(points)
|
||||
merged_mat_list = copy_face_attributes(merged_vol, block_paths)
|
||||
merged_block_data = merged_vol.to_convex_block_data()
|
||||
|
||||
|
||||
#Delete source blocks
|
||||
for block_path in block_paths:
|
||||
var del_block:CyclopsConvexBlock = builder.get_node(block_path)
|
||||
del_block.queue_free()
|
||||
|
||||
#Create block
|
||||
var block:CyclopsConvexBlock = preload("../nodes/cyclops_convex_block.gd").new()
|
||||
var parent:Node = builder.get_node(tracked_blocks[0].path_parent)
|
||||
parent.add_child(block)
|
||||
block.owner = builder.get_editor_interface().get_edited_scene_root()
|
||||
block.name = GeneralUtil.find_unique_name(parent, block_name_prefix)
|
||||
block.block_data = merged_block_data
|
||||
block.materials = merged_mat_list
|
||||
#block.materials
|
||||
|
||||
merged_block_path = block.get_path()
|
||||
|
||||
func undo_it():
|
||||
# var blocks_root:CyclopsBlocks = builder.get_node(blocks_root_path)
|
||||
var merged_block:CyclopsConvexBlock = builder.get_node(merged_block_path)
|
||||
merged_block.queue_free()
|
||||
|
||||
# for i in blocks_to_merge.size():
|
||||
for tracked in tracked_blocks:
|
||||
var parent = builder.get_node(tracked.path_parent)
|
||||
|
||||
var block:CyclopsConvexBlock = preload("../nodes/cyclops_convex_block.gd").new()
|
||||
block.block_data = tracked.data
|
||||
block.materials = tracked.materials
|
||||
block.name = tracked.name
|
||||
block.selected = tracked.selected
|
||||
|
||||
parent.add_child(block)
|
||||
block.owner = builder.get_editor_interface().get_edited_scene_root()
|
64
addons/cyclops_level_builder/commands/cmd_move_blocks.gd
Normal file
64
addons/cyclops_level_builder/commands/cmd_move_blocks.gd
Normal file
@ -0,0 +1,64 @@
|
||||
# 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
|
||||
class_name CommandMoveBlocks
|
||||
extends CyclopsCommand
|
||||
|
||||
#Public data to set before activating command
|
||||
var move_offset:Vector3
|
||||
var lock_uvs:bool = false
|
||||
|
||||
#Private
|
||||
var blocks_to_move:Array[NodePath]
|
||||
var tracked_block_data:Array[ConvexBlockData]
|
||||
|
||||
func _init():
|
||||
command_name = "Move blocks"
|
||||
|
||||
#Add blocks to be moved here
|
||||
func add_block(block_path:NodePath):
|
||||
blocks_to_move.append(block_path)
|
||||
|
||||
var block:CyclopsConvexBlock = builder.get_node(block_path)
|
||||
#tracked_blocks.append(block)
|
||||
tracked_block_data.append(block.block_data.duplicate())
|
||||
|
||||
#Moves all blocks from the start position by this amount
|
||||
func move_to(offset:Vector3):
|
||||
for i in blocks_to_move.size():
|
||||
var block:CyclopsConvexBlock = builder.get_node(blocks_to_move[i])
|
||||
|
||||
var ctl_mesh:ConvexVolume = ConvexVolume.new()
|
||||
ctl_mesh.init_from_convex_block_data(tracked_block_data[i])
|
||||
ctl_mesh.translate(offset, lock_uvs)
|
||||
var result_data:ConvexBlockData = ctl_mesh.to_convex_block_data()
|
||||
block.block_data = result_data
|
||||
#tracked_blocks[block_idx].block_data = result_data
|
||||
|
||||
func do_it():
|
||||
move_to(move_offset)
|
||||
|
||||
func undo_it():
|
||||
move_to(Vector3.ZERO)
|
||||
|
132
addons/cyclops_level_builder/commands/cmd_move_edges.gd
Normal file
132
addons/cyclops_level_builder/commands/cmd_move_edges.gd
Normal file
@ -0,0 +1,132 @@
|
||||
# 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
|
||||
class_name CommandMoveEdges
|
||||
extends CyclopsCommand
|
||||
|
||||
|
||||
class BlockEdgeChanges extends RefCounted:
|
||||
var block_path:NodePath
|
||||
var edge_indices:Array[int] = []
|
||||
var tracked_block_data:ConvexBlockData
|
||||
|
||||
#Public
|
||||
var move_offset:Vector3 = Vector3.ZERO
|
||||
|
||||
#Private
|
||||
var block_map:Dictionary = {}
|
||||
|
||||
func add_edge(block_path:NodePath, index:int):
|
||||
add_edges(block_path, [index])
|
||||
|
||||
func add_edges(block_path:NodePath, indices:Array[int]):
|
||||
var changes:BlockEdgeChanges
|
||||
if block_map.has(block_path):
|
||||
changes = block_map[block_path]
|
||||
else:
|
||||
changes = BlockEdgeChanges.new()
|
||||
changes.block_path = block_path
|
||||
var block:CyclopsConvexBlock = builder.get_node(block_path)
|
||||
changes.tracked_block_data = block.block_data
|
||||
block_map[block_path] = changes
|
||||
|
||||
for index in indices:
|
||||
if !changes.edge_indices.has(index):
|
||||
changes.edge_indices.append(index)
|
||||
|
||||
func _init():
|
||||
command_name = "Move edges"
|
||||
|
||||
|
||||
func do_it():
|
||||
# print("cmd move edges- DO IT")
|
||||
|
||||
for block_path in block_map.keys():
|
||||
|
||||
# print("%s" % block_path)
|
||||
|
||||
var block:CyclopsConvexBlock = builder.get_node(block_path)
|
||||
var rec:BlockEdgeChanges = block_map[block_path]
|
||||
|
||||
# print("rec %s" % rec)
|
||||
|
||||
var vol:ConvexVolume = ConvexVolume.new()
|
||||
vol.init_from_convex_block_data(rec.tracked_block_data)
|
||||
|
||||
# print("init done")
|
||||
|
||||
#var moved_vert_indices:PackedInt32Array
|
||||
var new_points:PackedVector3Array
|
||||
var new_sel_centroids:PackedVector3Array
|
||||
var moved_indices:Array[int] = []
|
||||
for edge_index in rec.edge_indices:
|
||||
var e:ConvexVolume.EdgeInfo = vol.edges[edge_index]
|
||||
var v0:ConvexVolume.VertexInfo = vol.vertices[e.start_index]
|
||||
var v1:ConvexVolume.VertexInfo = vol.vertices[e.end_index]
|
||||
if e.selected:
|
||||
new_sel_centroids.append((v0.point + v1.point) / 2 + move_offset)
|
||||
|
||||
if !moved_indices.has(e.start_index):
|
||||
new_points.append(v0.point + move_offset)
|
||||
moved_indices.append(e.start_index)
|
||||
if !moved_indices.has(e.end_index):
|
||||
new_points.append(v1.point + move_offset)
|
||||
moved_indices.append(e.end_index)
|
||||
else:
|
||||
if !moved_indices.has(e.start_index):
|
||||
new_points.append(v0.point + move_offset)
|
||||
moved_indices.append(e.start_index)
|
||||
if !moved_indices.has(e.end_index):
|
||||
new_points.append(v1.point + move_offset)
|
||||
moved_indices.append(e.end_index)
|
||||
|
||||
for v_idx in vol.vertices.size():
|
||||
if !moved_indices.has(v_idx):
|
||||
new_points.append(vol.vertices[v_idx].point)
|
||||
#print("new points_ %s" % new_points)
|
||||
|
||||
var new_vol:ConvexVolume = ConvexVolume.new()
|
||||
new_vol.init_from_points(new_points)
|
||||
|
||||
new_vol.copy_face_attributes(vol)
|
||||
|
||||
#print("new init done")
|
||||
|
||||
#Copy selection data
|
||||
for e_idx in new_vol.edges.size():
|
||||
var e_new:ConvexVolume.EdgeInfo = new_vol.edges[e_idx]
|
||||
var centroid:Vector3 = (new_vol.vertices[e_new.start_index].point + new_vol.vertices[e_new.end_index].point) / 2
|
||||
# print ("vol point %s " % v1.point)
|
||||
if new_sel_centroids.has(centroid):
|
||||
# print("set sel")
|
||||
e_new.selected = true
|
||||
|
||||
block.block_data = new_vol.to_convex_block_data()
|
||||
|
||||
|
||||
func undo_it():
|
||||
for block_path in block_map.keys():
|
||||
var rec:BlockEdgeChanges = block_map[block_path]
|
||||
var block:CyclopsConvexBlock = builder.get_node(block_path)
|
||||
block.block_data = rec.tracked_block_data
|
104
addons/cyclops_level_builder/commands/cmd_move_face_planar.gd
Normal file
104
addons/cyclops_level_builder/commands/cmd_move_face_planar.gd
Normal file
@ -0,0 +1,104 @@
|
||||
# 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
|
||||
class_name CommandMoveFacePlanar
|
||||
extends CyclopsCommand
|
||||
|
||||
#Public data to set before activating command
|
||||
var blocks_root_path:NodePath
|
||||
var block_path:NodePath
|
||||
var move_dir_normal:Vector3
|
||||
var move_amount:float
|
||||
var face_id:int
|
||||
var lock_uvs:bool = false
|
||||
|
||||
|
||||
#Private
|
||||
var block_name:String
|
||||
var block_selected:bool
|
||||
var tracked_block_data:ConvexBlockData
|
||||
|
||||
var deleted:bool = false
|
||||
|
||||
|
||||
func _init():
|
||||
command_name = "Move face planar"
|
||||
|
||||
func move_to(offset:Vector3, intermediate:bool):
|
||||
# print("move_to off %s faceid %s amount %s movedir %s" % [offset, face_id, move_amount, move_dir_normal])
|
||||
if !tracked_block_data:
|
||||
var block:CyclopsConvexBlock = builder.get_node(block_path)
|
||||
|
||||
block_name = block.name
|
||||
block_selected = block.selected
|
||||
tracked_block_data = block.block_data
|
||||
|
||||
var ctl_mesh:ConvexVolume = ConvexVolume.new()
|
||||
ctl_mesh.init_from_convex_block_data(tracked_block_data)
|
||||
var new_mesh:ConvexVolume = ctl_mesh.translate_face_plane(face_id, offset, lock_uvs)
|
||||
|
||||
#print("offset %s" % offset)
|
||||
#print("ctl_mesh %s" % ctl_mesh.get_points())
|
||||
|
||||
|
||||
var block:CyclopsConvexBlock = builder.get_node(block_path)
|
||||
|
||||
if new_mesh == null || new_mesh.is_empty():
|
||||
#print("new_mesh EMPTY")
|
||||
block.block_data = null
|
||||
if !intermediate:
|
||||
block.queue_free()
|
||||
deleted = true
|
||||
return
|
||||
|
||||
#ctl_mesh.remove_unused_planes()
|
||||
#print("new_mesh %s" % new_mesh.get_points())
|
||||
|
||||
var result_data:ConvexBlockData = new_mesh.to_convex_block_data()
|
||||
# var result_data:ConvexBlockData = ctl_mesh.to_convex_block_data()
|
||||
block.block_data = result_data
|
||||
|
||||
|
||||
func do_it_intermediate():
|
||||
move_to(move_dir_normal * move_amount, true)
|
||||
|
||||
func do_it():
|
||||
move_to(move_dir_normal * move_amount, false)
|
||||
|
||||
func undo_it():
|
||||
if deleted:
|
||||
var block:CyclopsConvexBlock = preload("../nodes/cyclops_convex_block.gd").new()
|
||||
|
||||
var blocks_root:CyclopsBlocks = builder.get_node(blocks_root_path)
|
||||
blocks_root.add_child(block)
|
||||
block.owner = builder.get_editor_interface().get_edited_scene_root()
|
||||
block.block_data = tracked_block_data
|
||||
block.name = block_name
|
||||
block.selected = block_selected
|
||||
|
||||
deleted = false
|
||||
return
|
||||
|
||||
move_to(Vector3.ZERO, false)
|
||||
|
131
addons/cyclops_level_builder/commands/cmd_move_faces.gd
Normal file
131
addons/cyclops_level_builder/commands/cmd_move_faces.gd
Normal file
@ -0,0 +1,131 @@
|
||||
# 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
|
||||
class_name CommandMoveFaces
|
||||
extends CyclopsCommand
|
||||
|
||||
class BlockFaceChanges extends RefCounted:
|
||||
var block_path:NodePath
|
||||
var face_indices:Array[int] = []
|
||||
var tracked_block_data:ConvexBlockData
|
||||
|
||||
#Public
|
||||
var move_offset:Vector3 = Vector3.ZERO
|
||||
|
||||
#Private
|
||||
var block_map:Dictionary = {}
|
||||
|
||||
|
||||
func add_face(block_path:NodePath, index:int):
|
||||
# print("Adding face %s %s" % [block_path, index])
|
||||
add_faces(block_path, [index])
|
||||
|
||||
func add_faces(block_path:NodePath, indices:Array[int]):
|
||||
var changes:BlockFaceChanges
|
||||
if block_map.has(block_path):
|
||||
changes = block_map[block_path]
|
||||
else:
|
||||
changes = BlockFaceChanges.new()
|
||||
changes.block_path = block_path
|
||||
var block:CyclopsConvexBlock = builder.get_node(block_path)
|
||||
changes.tracked_block_data = block.block_data
|
||||
block_map[block_path] = changes
|
||||
|
||||
for index in indices:
|
||||
if !changes.face_indices.has(index):
|
||||
changes.face_indices.append(index)
|
||||
|
||||
|
||||
func _init():
|
||||
command_name = "Move faces"
|
||||
|
||||
|
||||
|
||||
func do_it():
|
||||
# print("cmd move edges- DO IT")
|
||||
|
||||
for block_path in block_map.keys():
|
||||
|
||||
# print("%s" % block_path)
|
||||
|
||||
var block:CyclopsConvexBlock = builder.get_node(block_path)
|
||||
var rec:BlockFaceChanges = block_map[block_path]
|
||||
|
||||
# print("rec %s" % rec)
|
||||
|
||||
var vol:ConvexVolume = ConvexVolume.new()
|
||||
vol.init_from_convex_block_data(rec.tracked_block_data)
|
||||
|
||||
# print("init done")
|
||||
|
||||
#var moved_vert_indices:PackedInt32Array
|
||||
var new_points:PackedVector3Array
|
||||
var new_sel_centroids:PackedVector3Array
|
||||
var moved_vert_indices:Array[int] = []
|
||||
for face_index in rec.face_indices:
|
||||
var f:ConvexVolume.FaceInfo = vol.faces[face_index]
|
||||
var centroid:Vector3 = f.get_centroid()
|
||||
# var v0:ConvexVolume.VertexInfo = vol.vertices[e.start_index]
|
||||
# var v1:ConvexVolume.VertexInfo = vol.vertices[e.end_index]
|
||||
if f.selected:
|
||||
new_sel_centroids.append(centroid + move_offset)
|
||||
|
||||
for v_idx in f.vertex_indices:
|
||||
if !moved_vert_indices.has(v_idx):
|
||||
new_points.append(vol.vertices[v_idx].point + move_offset)
|
||||
moved_vert_indices.append(v_idx)
|
||||
else:
|
||||
for v_idx in f.vertex_indices:
|
||||
if !moved_vert_indices.has(v_idx):
|
||||
new_points.append(vol.vertices[v_idx].point + move_offset)
|
||||
moved_vert_indices.append(v_idx)
|
||||
|
||||
for v_idx in vol.vertices.size():
|
||||
if !moved_vert_indices.has(v_idx):
|
||||
new_points.append(vol.vertices[v_idx].point)
|
||||
#print("new points_ %s" % new_points)
|
||||
|
||||
var new_vol:ConvexVolume = ConvexVolume.new()
|
||||
new_vol.init_from_points(new_points)
|
||||
|
||||
new_vol.copy_face_attributes(vol)
|
||||
#print("new init done")
|
||||
|
||||
#Copy selection data
|
||||
for f_idx in new_vol.faces.size():
|
||||
var f_new:ConvexVolume.FaceInfo = new_vol.faces[f_idx]
|
||||
var centroid:Vector3 = f_new.get_centroid()
|
||||
# print ("vol point %s " % v1.point)
|
||||
if new_sel_centroids.has(centroid):
|
||||
# print("set sel")
|
||||
f_new.selected = true
|
||||
|
||||
block.block_data = new_vol.to_convex_block_data()
|
||||
|
||||
|
||||
func undo_it():
|
||||
for block_path in block_map.keys():
|
||||
var rec:BlockFaceChanges = block_map[block_path]
|
||||
var block:CyclopsConvexBlock = builder.get_node(block_path)
|
||||
block.block_data = rec.tracked_block_data
|
105
addons/cyclops_level_builder/commands/cmd_move_vertices.gd
Normal file
105
addons/cyclops_level_builder/commands/cmd_move_vertices.gd
Normal file
@ -0,0 +1,105 @@
|
||||
# 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
|
||||
class_name CommandMoveVertices
|
||||
extends CyclopsCommand
|
||||
|
||||
class BlockVertexChanges extends RefCounted:
|
||||
var block_path:NodePath
|
||||
var vertex_indices:Array[int] = []
|
||||
var tracked_block_data:ConvexBlockData
|
||||
|
||||
#Public
|
||||
var move_offset:Vector3 = Vector3.ZERO
|
||||
|
||||
#Private
|
||||
var block_map:Dictionary = {}
|
||||
|
||||
|
||||
func add_vertex(block_path:NodePath, index:int):
|
||||
add_vertices(block_path, [index])
|
||||
|
||||
func add_vertices(block_path:NodePath, indices:Array[int]):
|
||||
# print("adding vertex %s %s" % [block_path, indices])
|
||||
var changes:BlockVertexChanges
|
||||
if block_map.has(block_path):
|
||||
changes = block_map[block_path]
|
||||
else:
|
||||
changes = BlockVertexChanges.new()
|
||||
changes.block_path = block_path
|
||||
var block:CyclopsConvexBlock = builder.get_node(block_path)
|
||||
changes.tracked_block_data = block.block_data
|
||||
block_map[block_path] = changes
|
||||
|
||||
for index in indices:
|
||||
if !changes.vertex_indices.has(index):
|
||||
changes.vertex_indices.append(index)
|
||||
|
||||
func _init():
|
||||
command_name = "Move vertices"
|
||||
|
||||
func do_it():
|
||||
# print("move verts do_it")
|
||||
for block_path in block_map.keys():
|
||||
|
||||
var block:CyclopsConvexBlock = builder.get_node(block_path)
|
||||
var rec:BlockVertexChanges = block_map[block_path]
|
||||
|
||||
var vol:ConvexVolume = ConvexVolume.new()
|
||||
vol.init_from_convex_block_data(rec.tracked_block_data)
|
||||
|
||||
# print("rec.vertex_indices %s" % rec.vertex_indices)
|
||||
# print("move_offset %s" % move_offset)
|
||||
var selected_points:PackedVector3Array
|
||||
var new_points:PackedVector3Array
|
||||
for v_idx in vol.vertices.size():
|
||||
if rec.vertex_indices.has(v_idx):
|
||||
var p:Vector3 = vol.vertices[v_idx].point + move_offset
|
||||
new_points.append(p)
|
||||
selected_points.append(p)
|
||||
else:
|
||||
new_points.append(vol.vertices[v_idx].point)
|
||||
|
||||
|
||||
var new_vol:ConvexVolume = ConvexVolume.new()
|
||||
new_vol.init_from_points(new_points)
|
||||
|
||||
new_vol.copy_face_attributes(vol)
|
||||
|
||||
for v_idx in new_vol.vertices.size():
|
||||
var v:ConvexVolume.VertexInfo = new_vol.vertices[v_idx]
|
||||
# print ("vol point %s " % v.point)
|
||||
if selected_points.has(v.point):
|
||||
# print("set sel")
|
||||
v.selected = true
|
||||
|
||||
block.block_data = new_vol.to_convex_block_data()
|
||||
|
||||
|
||||
func undo_it():
|
||||
# print("move verts undo_it")
|
||||
for block_path in block_map.keys():
|
||||
var rec:BlockVertexChanges = block_map[block_path]
|
||||
var block:CyclopsConvexBlock = builder.get_node(block_path)
|
||||
block.block_data = rec.tracked_block_data
|
135
addons/cyclops_level_builder/commands/cmd_select_blocks.gd
Normal file
135
addons/cyclops_level_builder/commands/cmd_select_blocks.gd
Normal file
@ -0,0 +1,135 @@
|
||||
# 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
|
||||
class_name CommandSelectBlocks
|
||||
extends CyclopsCommand
|
||||
|
||||
#Public
|
||||
var selection_type:Selection.Type = Selection.Type.REPLACE
|
||||
|
||||
var block_paths:Array[NodePath]
|
||||
|
||||
#Private
|
||||
var tracked_selected_blocks:Array[NodePath]
|
||||
var tracked_active_blocks:Array[NodePath]
|
||||
|
||||
|
||||
func _init():
|
||||
command_name = "Select blocks"
|
||||
|
||||
func will_change_anything()->bool:
|
||||
|
||||
var active_path:NodePath
|
||||
if !block_paths.is_empty():
|
||||
active_path = block_paths[0]
|
||||
|
||||
for child in builder.active_node.get_children():
|
||||
if child is CyclopsConvexBlock:
|
||||
var block:CyclopsConvexBlock = child
|
||||
var path:NodePath = block.get_path()
|
||||
|
||||
match selection_type:
|
||||
Selection.Type.REPLACE:
|
||||
if block.selected != block_paths.has(path):
|
||||
return true
|
||||
|
||||
if block.active != (path == active_path):
|
||||
return true
|
||||
|
||||
Selection.Type.ADD:
|
||||
if block_paths.has(path):
|
||||
if !block.selected:
|
||||
return true
|
||||
if block.active != (path == active_path):
|
||||
return true
|
||||
|
||||
Selection.Type.SUBTRACT:
|
||||
if block_paths.has(path):
|
||||
if block.selected:
|
||||
return true
|
||||
|
||||
Selection.Type.TOGGLE:
|
||||
if !block_paths.is_empty():
|
||||
return true
|
||||
|
||||
return false
|
||||
|
||||
|
||||
func do_it():
|
||||
# print("sel verts do_it")
|
||||
|
||||
#Cache state
|
||||
tracked_selected_blocks.clear()
|
||||
tracked_active_blocks.clear()
|
||||
|
||||
for child in builder.active_node.get_children():
|
||||
if child is CyclopsConvexBlock:
|
||||
var block:CyclopsConvexBlock = child
|
||||
if block.selected:
|
||||
tracked_selected_blocks.append(block.get_path())
|
||||
if block.active:
|
||||
tracked_active_blocks.append(block.get_path())
|
||||
|
||||
#Do selection
|
||||
var active_path:NodePath
|
||||
if !block_paths.is_empty():
|
||||
active_path = block_paths[0]
|
||||
|
||||
for child in builder.active_node.get_children():
|
||||
if child is CyclopsConvexBlock:
|
||||
var block:CyclopsConvexBlock = child
|
||||
var path:NodePath = block.get_path()
|
||||
|
||||
match selection_type:
|
||||
Selection.Type.REPLACE:
|
||||
block.selected = block_paths.has(path)
|
||||
block.active = path == active_path
|
||||
Selection.Type.ADD:
|
||||
if block_paths.has(path):
|
||||
block.selected = true
|
||||
block.active = path == active_path
|
||||
Selection.Type.SUBTRACT:
|
||||
if block_paths.has(path):
|
||||
block.selected = false
|
||||
block.active = false
|
||||
Selection.Type.TOGGLE:
|
||||
block.active = path == active_path
|
||||
if block_paths.has(path):
|
||||
block.selected = !block.selected
|
||||
if !block.selected:
|
||||
block.active = false
|
||||
|
||||
builder.selection_changed.emit()
|
||||
|
||||
func undo_it():
|
||||
|
||||
for child in builder.active_node.get_children():
|
||||
if child is CyclopsConvexBlock:
|
||||
var block:CyclopsConvexBlock = child
|
||||
var path:NodePath = block.get_path()
|
||||
|
||||
block.selected = tracked_selected_blocks.has(path)
|
||||
block.active = tracked_active_blocks.has(path)
|
||||
|
||||
builder.selection_changed.emit()
|
189
addons/cyclops_level_builder/commands/cmd_select_edges.gd
Normal file
189
addons/cyclops_level_builder/commands/cmd_select_edges.gd
Normal file
@ -0,0 +1,189 @@
|
||||
# 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
|
||||
class_name CommandSelectEdges
|
||||
extends CyclopsCommand
|
||||
|
||||
class BlockEdgeChanges extends RefCounted:
|
||||
var block_path:NodePath
|
||||
var edge_indices:Array[int] = []
|
||||
var tracked_block_data:ConvexBlockData
|
||||
|
||||
#Public
|
||||
var selection_type:Selection.Type = Selection.Type.REPLACE
|
||||
|
||||
#Private
|
||||
var block_map:Dictionary = {}
|
||||
|
||||
|
||||
func add_edge(block_path:NodePath, index:int):
|
||||
add_edges(block_path, [index])
|
||||
|
||||
func add_edges(block_path:NodePath, indices:Array[int]):
|
||||
var changes:BlockEdgeChanges
|
||||
if block_map.has(block_path):
|
||||
changes = block_map[block_path]
|
||||
else:
|
||||
changes = BlockEdgeChanges.new()
|
||||
changes.block_path = block_path
|
||||
var block:CyclopsConvexBlock = builder.get_node(block_path)
|
||||
changes.tracked_block_data = block.block_data
|
||||
block_map[block_path] = changes
|
||||
|
||||
for index in indices:
|
||||
if !changes.edge_indices.has(index):
|
||||
changes.edge_indices.append(index)
|
||||
|
||||
|
||||
func _init():
|
||||
command_name = "Select edges"
|
||||
|
||||
func will_change_anything()->bool:
|
||||
for block_path in block_map.keys():
|
||||
#print("path %s" % node_path)
|
||||
|
||||
var rec:BlockEdgeChanges = block_map[block_path]
|
||||
var block:CyclopsConvexBlock = builder.get_node(block_path)
|
||||
|
||||
var vol:ConvexVolume = ConvexVolume.new()
|
||||
vol.init_from_convex_block_data(rec.tracked_block_data)
|
||||
|
||||
if !rec.edge_indices.is_empty():
|
||||
if vol.active_edge != rec.edge_indices[0]:
|
||||
return true
|
||||
|
||||
match selection_type:
|
||||
Selection.Type.REPLACE:
|
||||
for e_idx in vol.edges.size():
|
||||
var e:ConvexVolume.EdgeInfo = vol.edges[e_idx]
|
||||
if e.selected != rec.edge_indices.has(e_idx):
|
||||
#print("will change SREP")
|
||||
return true
|
||||
Selection.Type.ADD:
|
||||
for e_idx in rec.edge_indices:
|
||||
var e:ConvexVolume.EdgeInfo = vol.edges[e_idx]
|
||||
if rec.edge_indices.has(e_idx):
|
||||
if !e.selected:
|
||||
#print("will change ADD")
|
||||
return true
|
||||
Selection.Type.SUBTRACT:
|
||||
for e_idx in rec.edge_indices:
|
||||
var e:ConvexVolume.EdgeInfo = vol.edges[e_idx]
|
||||
if rec.edge_indices.has(e_idx):
|
||||
if e.selected:
|
||||
#print("will change SUB")
|
||||
return true
|
||||
Selection.Type.TOGGLE:
|
||||
#print("will change TOG")
|
||||
return true
|
||||
|
||||
return false
|
||||
|
||||
func do_it():
|
||||
# print("sel edges do_it")
|
||||
|
||||
for block_path in block_map.keys():
|
||||
# print("path %s" % block_path)
|
||||
|
||||
var rec:BlockEdgeChanges = block_map[block_path]
|
||||
var block:CyclopsConvexBlock = builder.get_node(block_path)
|
||||
|
||||
var vol:ConvexVolume = ConvexVolume.new()
|
||||
vol.init_from_convex_block_data(rec.tracked_block_data)
|
||||
|
||||
if !rec.edge_indices.is_empty():
|
||||
var active_index:int = rec.edge_indices[0]
|
||||
match selection_type:
|
||||
Selection.Type.REPLACE:
|
||||
vol.active_edge = active_index
|
||||
Selection.Type.ADD:
|
||||
vol.active_edge = active_index
|
||||
Selection.Type.SUBTRACT:
|
||||
if rec.edge_indices.has(vol.active_edge):
|
||||
vol.active_edge = -1
|
||||
Selection.Type.TOGGLE:
|
||||
if rec.edge_indices.has(vol.active_edge):
|
||||
vol.active_edge = -1
|
||||
elif !vol.edges[active_index].selected:
|
||||
vol.active_edge = active_index
|
||||
|
||||
match selection_type:
|
||||
Selection.Type.REPLACE:
|
||||
for e_idx in vol.edges.size():
|
||||
var e:ConvexVolume.EdgeInfo = vol.edges[e_idx]
|
||||
e.selected = rec.edge_indices.has(e_idx)
|
||||
|
||||
Selection.Type.ADD:
|
||||
for e_idx in vol.edges.size():
|
||||
var e:ConvexVolume.EdgeInfo = vol.edges[e_idx]
|
||||
if rec.edge_indices.has(e_idx):
|
||||
e.selected = true
|
||||
|
||||
Selection.Type.SUBTRACT:
|
||||
for e_idx in vol.edges.size():
|
||||
var e:ConvexVolume.EdgeInfo = vol.edges[e_idx]
|
||||
if rec.edge_indices.has(e_idx):
|
||||
e.selected = false
|
||||
|
||||
Selection.Type.TOGGLE:
|
||||
for e_idx in vol.edges.size():
|
||||
var e:ConvexVolume.EdgeInfo = vol.edges[e_idx]
|
||||
if rec.edge_indices.has(e_idx):
|
||||
#print("flipping %s" % e.selected)
|
||||
e.selected = !e.selected
|
||||
|
||||
if vol.active_edge != -1:
|
||||
if vol.active_edge >= vol.edges.size() || !vol.edges[vol.active_edge].selected:
|
||||
vol.active_edge = -1
|
||||
|
||||
#Synchronize vertex & face selection
|
||||
#print("synchronizing verts")
|
||||
# var selected_verts:Array[int] = []
|
||||
# for e in vol.edges:
|
||||
# if e.selected:
|
||||
# for v_idx in [e.start_index, e.end_index]:
|
||||
# if !selected_verts.has(v_idx):
|
||||
# #print("selecting vert %s" % v_idx)
|
||||
# selected_verts.append(v_idx)
|
||||
# for v_idx in vol.vertices.size():
|
||||
# vol.vertices[v_idx].selected = selected_verts.has(v_idx)
|
||||
# vol.update_edge_and_face_selection_from_vertices()
|
||||
|
||||
block.block_data = vol.to_convex_block_data()
|
||||
|
||||
builder.selection_changed.emit()
|
||||
|
||||
func undo_it():
|
||||
# print("sel verts undo_it")
|
||||
#print("sel vert undo_it()")
|
||||
for block_path in block_map.keys():
|
||||
var rec:BlockEdgeChanges = block_map[block_path]
|
||||
var block:CyclopsConvexBlock = builder.get_node(block_path)
|
||||
block.block_data = rec.tracked_block_data
|
||||
|
||||
builder.selection_changed.emit()
|
||||
|
||||
|
||||
|
||||
|
180
addons/cyclops_level_builder/commands/cmd_select_faces.gd
Normal file
180
addons/cyclops_level_builder/commands/cmd_select_faces.gd
Normal file
@ -0,0 +1,180 @@
|
||||
# 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
|
||||
class_name CommandSelectFaces
|
||||
extends CyclopsCommand
|
||||
|
||||
class BlockFaceChanges extends RefCounted:
|
||||
var block_path:NodePath
|
||||
var face_indices:Array[int] = []
|
||||
var tracked_block_data:ConvexBlockData
|
||||
|
||||
#Public
|
||||
var selection_type:Selection.Type = Selection.Type.REPLACE
|
||||
|
||||
#Private
|
||||
var block_map:Dictionary = {}
|
||||
|
||||
func add_face(block_path:NodePath, index:int):
|
||||
add_faces(block_path, [index])
|
||||
|
||||
func add_faces(block_path:NodePath, indices:Array[int]):
|
||||
var changes:BlockFaceChanges
|
||||
if block_map.has(block_path):
|
||||
changes = block_map[block_path]
|
||||
else:
|
||||
changes = BlockFaceChanges.new()
|
||||
changes.block_path = block_path
|
||||
var block:CyclopsConvexBlock = builder.get_node(block_path)
|
||||
changes.tracked_block_data = block.block_data
|
||||
block_map[block_path] = changes
|
||||
|
||||
for index in indices:
|
||||
if !changes.face_indices.has(index):
|
||||
changes.face_indices.append(index)
|
||||
|
||||
|
||||
func _init():
|
||||
command_name = "Select faces"
|
||||
|
||||
func will_change_anything()->bool:
|
||||
for block_path in block_map.keys():
|
||||
#print("path %s" % node_path)
|
||||
|
||||
var rec:BlockFaceChanges = block_map[block_path]
|
||||
var block:CyclopsConvexBlock = builder.get_node(block_path)
|
||||
|
||||
var vol:ConvexVolume = ConvexVolume.new()
|
||||
vol.init_from_convex_block_data(rec.tracked_block_data)
|
||||
|
||||
# var active_idx:int = -1
|
||||
if !rec.face_indices.is_empty():
|
||||
if vol.active_face != rec.face_indices[0]:
|
||||
return true
|
||||
|
||||
match selection_type:
|
||||
Selection.Type.REPLACE:
|
||||
for f_idx in vol.faces.size():
|
||||
var f:ConvexVolume.FaceInfo = vol.faces[f_idx]
|
||||
if f.selected != rec.face_indices.has(f_idx):
|
||||
return true
|
||||
Selection.Type.ADD:
|
||||
for f_idx in vol.faces.size():
|
||||
var f:ConvexVolume.FaceInfo = vol.faces[f_idx]
|
||||
if rec.face_indices.has(f_idx):
|
||||
if !f.selected:
|
||||
return true
|
||||
Selection.Type.SUBTRACT:
|
||||
for f_idx in vol.faces.size():
|
||||
var f:ConvexVolume.FaceInfo = vol.faces[f_idx]
|
||||
if rec.face_indices.has(f_idx):
|
||||
if f.selected:
|
||||
return true
|
||||
Selection.Type.TOGGLE:
|
||||
return true
|
||||
|
||||
return false
|
||||
|
||||
func do_it():
|
||||
#print("sel verts do_it")
|
||||
#print("sel vert do_it()")
|
||||
for block_path in block_map.keys():
|
||||
# print("path %s" % block_path)
|
||||
|
||||
var rec:BlockFaceChanges = block_map[block_path]
|
||||
var block:CyclopsConvexBlock = builder.get_node(block_path)
|
||||
|
||||
var vol:ConvexVolume = ConvexVolume.new()
|
||||
vol.init_from_convex_block_data(rec.tracked_block_data)
|
||||
if !rec.face_indices.is_empty():
|
||||
var active_index:int = rec.face_indices[0]
|
||||
match selection_type:
|
||||
Selection.Type.REPLACE:
|
||||
vol.active_face = active_index
|
||||
Selection.Type.ADD:
|
||||
vol.active_face = active_index
|
||||
Selection.Type.SUBTRACT:
|
||||
if rec.face_indices.has(vol.active_face):
|
||||
vol.active_face = -1
|
||||
Selection.Type.TOGGLE:
|
||||
if rec.face_indices.has(vol.active_face):
|
||||
vol.active_face = -1
|
||||
elif !vol.faces[active_index].selected:
|
||||
vol.active_face = active_index
|
||||
|
||||
|
||||
# print("face active index %s" % active_idx)
|
||||
|
||||
match selection_type:
|
||||
Selection.Type.REPLACE:
|
||||
for f_idx in vol.faces.size():
|
||||
var f:ConvexVolume.FaceInfo = vol.faces[f_idx]
|
||||
f.selected = rec.face_indices.has(f_idx)
|
||||
|
||||
Selection.Type.ADD:
|
||||
for f_idx in vol.faces.size():
|
||||
var f:ConvexVolume.FaceInfo = vol.faces[f_idx]
|
||||
if rec.face_indices.has(f_idx):
|
||||
f.selected = true
|
||||
|
||||
Selection.Type.SUBTRACT:
|
||||
for f_idx in vol.faces.size():
|
||||
var f:ConvexVolume.FaceInfo = vol.faces[f_idx]
|
||||
if rec.face_indices.has(f_idx):
|
||||
f.selected = false
|
||||
|
||||
Selection.Type.TOGGLE:
|
||||
for f_idx in vol.faces.size():
|
||||
var f:ConvexVolume.FaceInfo = vol.faces[f_idx]
|
||||
if rec.face_indices.has(f_idx):
|
||||
f.selected = !f.selected
|
||||
|
||||
if vol.active_face != -1:
|
||||
if vol.active_face >= vol.faces.size() || !vol.faces[vol.active_face].selected:
|
||||
vol.active_face = -1
|
||||
|
||||
|
||||
#Synchronize edge & vertex selection
|
||||
# var selected_verts:Array[int] = []
|
||||
# for f in vol.faces:
|
||||
# if f.selected:
|
||||
# for v_idx in f.vertex_indices:
|
||||
# if !selected_verts.has(v_idx):
|
||||
# selected_verts.append(v_idx)
|
||||
# for v_idx in vol.vertices.size():
|
||||
# vol.vertices[v_idx].selected = selected_verts.has(v_idx)
|
||||
# vol.update_edge_and_face_selection_from_vertices()
|
||||
|
||||
block.block_data = vol.to_convex_block_data()
|
||||
builder.selection_changed.emit()
|
||||
|
||||
func undo_it():
|
||||
# print("undo_it() select faces")
|
||||
for block_path in block_map.keys():
|
||||
var rec:BlockFaceChanges = block_map[block_path]
|
||||
var block:CyclopsConvexBlock = builder.get_node(block_path)
|
||||
block.block_data = rec.tracked_block_data
|
||||
|
||||
builder.selection_changed.emit()
|
||||
|
167
addons/cyclops_level_builder/commands/cmd_select_vertices.gd
Normal file
167
addons/cyclops_level_builder/commands/cmd_select_vertices.gd
Normal file
@ -0,0 +1,167 @@
|
||||
# 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
|
||||
class_name CommandSelectVertices
|
||||
extends CyclopsCommand
|
||||
|
||||
class BlockVertexChanges extends RefCounted:
|
||||
var block_path:NodePath
|
||||
var vertex_indices:Array[int] = []
|
||||
var tracked_block_data:ConvexBlockData
|
||||
|
||||
#Public
|
||||
var selection_type:Selection.Type = Selection.Type.REPLACE
|
||||
|
||||
#Private
|
||||
var block_map:Dictionary = {}
|
||||
|
||||
|
||||
|
||||
|
||||
func add_vertex(block_path:NodePath, index:int):
|
||||
add_vertices(block_path, [index])
|
||||
|
||||
func add_vertices(block_path:NodePath, indices:Array[int]):
|
||||
var changes:BlockVertexChanges
|
||||
if block_map.has(block_path):
|
||||
changes = block_map[block_path]
|
||||
else:
|
||||
changes = BlockVertexChanges.new()
|
||||
changes.block_path = block_path
|
||||
var block:CyclopsConvexBlock = builder.get_node(block_path)
|
||||
changes.tracked_block_data = block.block_data
|
||||
block_map[block_path] = changes
|
||||
|
||||
for index in indices:
|
||||
if !changes.vertex_indices.has(index):
|
||||
changes.vertex_indices.append(index)
|
||||
|
||||
|
||||
func _init():
|
||||
command_name = "Select vertices"
|
||||
|
||||
|
||||
func will_change_anything()->bool:
|
||||
for block_path in block_map.keys():
|
||||
#print("path %s" % node_path)
|
||||
|
||||
var rec:BlockVertexChanges = block_map[block_path]
|
||||
var block:CyclopsConvexBlock = builder.get_node(block_path)
|
||||
|
||||
var vol:ConvexVolume = ConvexVolume.new()
|
||||
vol.init_from_convex_block_data(rec.tracked_block_data)
|
||||
|
||||
if !rec.vertex_indices.is_empty():
|
||||
if vol.active_vertex != rec.vertex_indices[0]:
|
||||
return true
|
||||
|
||||
match selection_type:
|
||||
Selection.Type.REPLACE:
|
||||
for v_idx in vol.vertices.size():
|
||||
var v:ConvexVolume.VertexInfo = vol.vertices[v_idx]
|
||||
if v.selected != rec.vertex_indices.has(v_idx):
|
||||
return true
|
||||
Selection.Type.ADD:
|
||||
for v_idx in rec.vertex_indices:
|
||||
var v:ConvexVolume.VertexInfo = vol.vertices[v_idx]
|
||||
if rec.vertex_indices.has(v_idx):
|
||||
if !v.selected:
|
||||
return true
|
||||
Selection.Type.SUBTRACT:
|
||||
for v_idx in rec.vertex_indices:
|
||||
var v:ConvexVolume.VertexInfo = vol.vertices[v_idx]
|
||||
if rec.vertex_indices.has(v_idx):
|
||||
if v.selected:
|
||||
return true
|
||||
Selection.Type.TOGGLE:
|
||||
return true
|
||||
|
||||
return false
|
||||
|
||||
|
||||
func do_it():
|
||||
# print("sel verts do_it")
|
||||
for block_path in block_map.keys():
|
||||
#print("path %s" % node_path)
|
||||
|
||||
var rec:BlockVertexChanges = block_map[block_path]
|
||||
var block:CyclopsConvexBlock = builder.get_node(block_path)
|
||||
|
||||
var vol:ConvexVolume = ConvexVolume.new()
|
||||
vol.init_from_convex_block_data(rec.tracked_block_data)
|
||||
|
||||
if !rec.vertex_indices.is_empty():
|
||||
var active_index:int = rec.vertex_indices[0]
|
||||
match selection_type:
|
||||
Selection.Type.REPLACE:
|
||||
vol.active_vertex = active_index
|
||||
Selection.Type.ADD:
|
||||
vol.active_vertex = active_index
|
||||
Selection.Type.SUBTRACT:
|
||||
if rec.vertex_indices.has(vol.active_vertex):
|
||||
vol.active_vertex = -1
|
||||
Selection.Type.TOGGLE:
|
||||
if rec.vertex_indices.has(vol.active_vertex):
|
||||
vol.active_vertex = -1
|
||||
elif !vol.vertices[active_index].selected:
|
||||
vol.active_vertex = active_index
|
||||
|
||||
match selection_type:
|
||||
Selection.Type.REPLACE:
|
||||
for v_idx in vol.vertices.size():
|
||||
var v:ConvexVolume.VertexInfo = vol.vertices[v_idx]
|
||||
v.selected = rec.vertex_indices.has(v_idx)
|
||||
|
||||
Selection.Type.ADD:
|
||||
for v_idx in vol.vertices.size():
|
||||
var v:ConvexVolume.VertexInfo = vol.vertices[v_idx]
|
||||
if rec.vertex_indices.has(v_idx):
|
||||
v.selected = true
|
||||
|
||||
Selection.Type.SUBTRACT:
|
||||
for v_idx in vol.vertices.size():
|
||||
var v:ConvexVolume.VertexInfo = vol.vertices[v_idx]
|
||||
if rec.vertex_indices.has(v_idx):
|
||||
v.selected = false
|
||||
|
||||
Selection.Type.TOGGLE:
|
||||
for v_idx in vol.vertices.size():
|
||||
var v:ConvexVolume.VertexInfo = vol.vertices[v_idx]
|
||||
if rec.vertex_indices.has(v_idx):
|
||||
v.selected = !v.selected
|
||||
|
||||
vol.update_edge_and_face_selection_from_vertices()
|
||||
block.block_data = vol.to_convex_block_data()
|
||||
|
||||
builder.selection_changed.emit()
|
||||
|
||||
func undo_it():
|
||||
# print("sel verts undo_it")
|
||||
#print("sel vert undo_it()")
|
||||
for block_path in block_map.keys():
|
||||
var rec:BlockVertexChanges = block_map[block_path]
|
||||
var block:CyclopsConvexBlock = builder.get_node(block_path)
|
||||
block.block_data = rec.tracked_block_data
|
||||
|
||||
builder.selection_changed.emit()
|
153
addons/cyclops_level_builder/commands/cmd_set_material.gd
Normal file
153
addons/cyclops_level_builder/commands/cmd_set_material.gd
Normal file
@ -0,0 +1,153 @@
|
||||
# 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
|
||||
class_name CommandSetMaterial
|
||||
extends CyclopsCommand
|
||||
|
||||
class Target extends RefCounted:
|
||||
var block_path:NodePath
|
||||
var face_indices:PackedInt32Array
|
||||
|
||||
class BlockCache extends RefCounted:
|
||||
var path:NodePath
|
||||
var data:ConvexBlockData
|
||||
var materials:Array[Material]
|
||||
|
||||
#Public
|
||||
var material_path:String
|
||||
|
||||
#Private
|
||||
var target_list:Array[Target] = []
|
||||
|
||||
var cache_list:Array[BlockCache] = []
|
||||
|
||||
func add_target(block_path:NodePath, face_indices:PackedInt32Array):
|
||||
# print("add target %s %s" % [block_path.get_name(block_path.get_name_count() - 1), face_indices])
|
||||
var target:Target = Target.new()
|
||||
target.block_path = block_path
|
||||
target.face_indices = face_indices
|
||||
|
||||
target_list.append(target)
|
||||
|
||||
func make_cache():
|
||||
cache_list = []
|
||||
|
||||
for t in target_list:
|
||||
var cache:BlockCache = BlockCache.new()
|
||||
var block:CyclopsConvexBlock = builder.get_node(t.block_path)
|
||||
|
||||
cache.path = block.get_path()
|
||||
cache.data = block.block_data
|
||||
cache.materials = block.materials.duplicate()
|
||||
|
||||
cache_list.append(cache)
|
||||
|
||||
func will_change_anything()->bool:
|
||||
for t in target_list:
|
||||
if !t.face_indices.is_empty():
|
||||
return true
|
||||
return false
|
||||
|
||||
func _init():
|
||||
command_name = "Set material"
|
||||
|
||||
func do_it():
|
||||
make_cache()
|
||||
|
||||
# print("cmd set material %s" % material_path)
|
||||
for t in target_list:
|
||||
var block:CyclopsConvexBlock = builder.get_node(t.block_path)
|
||||
|
||||
var data:ConvexBlockData = block.block_data
|
||||
var vol:ConvexVolume = ConvexVolume.new()
|
||||
vol.init_from_convex_block_data(data)
|
||||
|
||||
var mat_list:Array[Material] = block.materials.duplicate()
|
||||
# print("start mat list")
|
||||
# for m in mat_list:
|
||||
# print("cur mat %s" % "?" if m == null else m.resource_path)
|
||||
|
||||
var target_material:Material
|
||||
for m in mat_list:
|
||||
if m.resource_path == material_path:
|
||||
target_material = m
|
||||
break
|
||||
if !target_material:
|
||||
target_material = load(material_path)
|
||||
mat_list.append(target_material)
|
||||
|
||||
# print("target mat list")
|
||||
# for m in mat_list:
|
||||
# print("mat %s" % "?" if m == null else m.resource_path)
|
||||
|
||||
var remap_face_idx_to_mat:Array[Material] = []
|
||||
|
||||
var ctl_mesh:ConvexVolume = ConvexVolume.new()
|
||||
ctl_mesh.init_from_convex_block_data(block.control_mesh.to_convex_block_data())
|
||||
|
||||
for f_idx in ctl_mesh.faces.size():
|
||||
var f:ConvexVolume.FaceInfo = ctl_mesh.faces[f_idx]
|
||||
|
||||
if t.face_indices.has(f_idx):
|
||||
remap_face_idx_to_mat.append(target_material)
|
||||
elif f.material_id >= 0 && f.material_id < block.materials.size():
|
||||
remap_face_idx_to_mat.append(block.materials[f.material_id])
|
||||
else:
|
||||
remap_face_idx_to_mat.append(null)
|
||||
|
||||
# print("remap faceidx to mat")
|
||||
# for m in remap_face_idx_to_mat:
|
||||
# print("mat %s" % "?" if m == null else m.resource_path)
|
||||
|
||||
#Reduce material list, discarding unused materials
|
||||
var mat_list_reduced:Array[Material]
|
||||
for m in remap_face_idx_to_mat:
|
||||
if m != null && !mat_list_reduced.has(m):
|
||||
mat_list_reduced.append(m)
|
||||
|
||||
# print("mat_list_reduced")
|
||||
# for m in mat_list_reduced:
|
||||
# print("mat %s" % "?" if m == null else m.resource_path)
|
||||
|
||||
#Set new face materials using new material ids
|
||||
for f_idx in remap_face_idx_to_mat.size():
|
||||
#print("face_idx %s" % f_idx)
|
||||
var face:ConvexVolume.FaceInfo = ctl_mesh.faces[f_idx]
|
||||
var mat = remap_face_idx_to_mat[f_idx]
|
||||
#print("mat %s" % "?" if mat == null else mat.resource_path)
|
||||
#print("has %s" % mat_list_reduced.has(mat))
|
||||
#print("find %s" % mat_list_reduced.find(mat))
|
||||
|
||||
face.material_id = -1 if mat == null else mat_list_reduced.find(mat)
|
||||
#print("face.material_id %s" % face.material_id)
|
||||
|
||||
block.materials = mat_list_reduced
|
||||
block.block_data = ctl_mesh.to_convex_block_data()
|
||||
|
||||
func undo_it():
|
||||
for cache in cache_list:
|
||||
var block:CyclopsConvexBlock = builder.get_node(cache.path)
|
||||
block.materials = cache.materials.duplicate()
|
||||
block.block_data = cache.data
|
||||
|
110
addons/cyclops_level_builder/commands/cmd_set_uv_transform.gd
Normal file
110
addons/cyclops_level_builder/commands/cmd_set_uv_transform.gd
Normal file
@ -0,0 +1,110 @@
|
||||
# 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
|
||||
class_name CommandSetUvTransform
|
||||
extends CyclopsCommand
|
||||
|
||||
|
||||
class BlockFaceChanges extends RefCounted:
|
||||
var block_path:NodePath
|
||||
var face_indices:Array[int] = []
|
||||
var tracked_block_data:ConvexBlockData
|
||||
|
||||
var uv_transform:Transform2D = Transform2D.IDENTITY
|
||||
|
||||
#Private
|
||||
var block_map:Dictionary = {}
|
||||
|
||||
func add_face(block_path:NodePath, index:int):
|
||||
add_faces(block_path, [index])
|
||||
|
||||
func add_faces(block_path:NodePath, indices:Array[int]):
|
||||
var changes:BlockFaceChanges
|
||||
if block_map.has(block_path):
|
||||
changes = block_map[block_path]
|
||||
else:
|
||||
changes = BlockFaceChanges.new()
|
||||
changes.block_path = block_path
|
||||
var block:CyclopsConvexBlock = builder.get_node(block_path)
|
||||
changes.tracked_block_data = block.block_data
|
||||
block_map[block_path] = changes
|
||||
|
||||
for index in indices:
|
||||
if !changes.face_indices.has(index):
|
||||
changes.face_indices.append(index)
|
||||
|
||||
|
||||
func _init():
|
||||
command_name = "Set Uv Transform"
|
||||
|
||||
func will_change_anything()->bool:
|
||||
for block_path in block_map.keys():
|
||||
|
||||
var rec:BlockFaceChanges = block_map[block_path]
|
||||
var block:CyclopsConvexBlock = builder.get_node(block_path)
|
||||
|
||||
# print("face active index %s" % active_idx)
|
||||
var vol:ConvexVolume = ConvexVolume.new()
|
||||
vol.init_from_convex_block_data(rec.tracked_block_data)
|
||||
|
||||
for f_idx in vol.faces.size():
|
||||
if rec.face_indices.has(f_idx):
|
||||
var f:ConvexVolume.FaceInfo = vol.faces[f_idx]
|
||||
if f.uv_transform != uv_transform:
|
||||
return true
|
||||
|
||||
return false
|
||||
|
||||
|
||||
func do_it():
|
||||
#print("sel verts do_it")
|
||||
#print("sel vert do_it()")
|
||||
for block_path in block_map.keys():
|
||||
# print("path %s" % block_path)
|
||||
|
||||
var rec:BlockFaceChanges = block_map[block_path]
|
||||
var block:CyclopsConvexBlock = builder.get_node(block_path)
|
||||
|
||||
# print("face active index %s" % active_idx)
|
||||
var vol:ConvexVolume = ConvexVolume.new()
|
||||
vol.init_from_convex_block_data(rec.tracked_block_data)
|
||||
|
||||
for f_idx in vol.faces.size():
|
||||
if rec.face_indices.has(f_idx):
|
||||
var f:ConvexVolume.FaceInfo = vol.faces[f_idx]
|
||||
f.uv_transform = uv_transform
|
||||
|
||||
block.block_data = vol.to_convex_block_data()
|
||||
builder.selection_changed.emit()
|
||||
|
||||
|
||||
func undo_it():
|
||||
# print("undo_it() select faces")
|
||||
for block_path in block_map.keys():
|
||||
var rec:BlockFaceChanges = block_map[block_path]
|
||||
var block:CyclopsConvexBlock = builder.get_node(block_path)
|
||||
block.block_data = rec.tracked_block_data
|
||||
|
||||
builder.selection_changed.emit()
|
||||
|
82
addons/cyclops_level_builder/commands/cmd_snap_to_grid.gd
Normal file
82
addons/cyclops_level_builder/commands/cmd_snap_to_grid.gd
Normal file
@ -0,0 +1,82 @@
|
||||
# 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
|
||||
class_name CommandSnapToGrid
|
||||
extends CyclopsCommand
|
||||
|
||||
class TrackedInfo extends RefCounted:
|
||||
var data:ConvexBlockData
|
||||
|
||||
var grid_size:float
|
||||
|
||||
#Private
|
||||
var blocks_to_move:Array[NodePath]
|
||||
var tracked_block_data:Array[TrackedInfo]
|
||||
|
||||
|
||||
func _init():
|
||||
command_name = "Snap to grid"
|
||||
|
||||
|
||||
#Add blocks to be moved here
|
||||
func add_block(block_path:NodePath):
|
||||
blocks_to_move.append(block_path)
|
||||
|
||||
var block:CyclopsConvexBlock = builder.get_node(block_path)
|
||||
#tracked_blocks.append(block)
|
||||
var info:TrackedInfo = TrackedInfo.new()
|
||||
info.data = block.block_data.duplicate()
|
||||
# info.materials = block.materials
|
||||
tracked_block_data.append(info)
|
||||
|
||||
|
||||
func do_it():
|
||||
for i in blocks_to_move.size():
|
||||
var block:CyclopsConvexBlock = builder.get_node(blocks_to_move[i])
|
||||
|
||||
var vol:ConvexVolume = ConvexVolume.new()
|
||||
vol.init_from_convex_block_data(tracked_block_data[i].data)
|
||||
|
||||
var points_new:PackedVector3Array
|
||||
for v_idx in vol.vertices.size():
|
||||
var v:ConvexVolume.VertexInfo = vol.vertices[v_idx]
|
||||
var p_snap:Vector3 = MathUtil.snap_to_grid(v.point, grid_size)
|
||||
points_new.append(p_snap)
|
||||
|
||||
var new_vol:ConvexVolume = ConvexVolume.new()
|
||||
new_vol.init_from_points(points_new)
|
||||
|
||||
|
||||
new_vol.copy_face_attributes(vol)
|
||||
|
||||
block.block_data = new_vol.to_convex_block_data()
|
||||
|
||||
func undo_it():
|
||||
for i in blocks_to_move.size():
|
||||
var block:CyclopsConvexBlock = builder.get_node(blocks_to_move[i])
|
||||
|
||||
block.block_data = tracked_block_data[i].data
|
||||
|
||||
|
||||
|
@ -0,0 +1,76 @@
|
||||
# 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
|
||||
class_name CommandTransformBlocks
|
||||
extends CyclopsCommand
|
||||
|
||||
class TrackedInfo extends RefCounted:
|
||||
var data:ConvexBlockData
|
||||
# var materials:Array[Material]
|
||||
|
||||
var transform:Transform3D
|
||||
var lock_uvs:bool = false
|
||||
|
||||
#Private
|
||||
var blocks_to_move:Array[NodePath]
|
||||
var tracked_block_data:Array[TrackedInfo]
|
||||
|
||||
func _init():
|
||||
command_name = "Transform blocks"
|
||||
|
||||
#Add blocks to be moved here
|
||||
func add_block(block_path:NodePath):
|
||||
blocks_to_move.append(block_path)
|
||||
|
||||
var block:CyclopsConvexBlock = builder.get_node(block_path)
|
||||
#tracked_blocks.append(block)
|
||||
var info:TrackedInfo = TrackedInfo.new()
|
||||
info.data = block.block_data.duplicate()
|
||||
# info.materials = block.materials
|
||||
tracked_block_data.append(info)
|
||||
|
||||
#Moves all blocks from the start position by this amount
|
||||
func apply_transform(xform:Transform3D):
|
||||
for i in blocks_to_move.size():
|
||||
var block:CyclopsConvexBlock = builder.get_node(blocks_to_move[i])
|
||||
|
||||
var ctl_mesh:ConvexVolume = ConvexVolume.new()
|
||||
ctl_mesh.init_from_convex_block_data(tracked_block_data[i].data)
|
||||
ctl_mesh.transform(xform, lock_uvs)
|
||||
var result_data:ConvexBlockData = ctl_mesh.to_convex_block_data()
|
||||
block.block_data = result_data
|
||||
# block.materials = tracked_block_data[i].materials
|
||||
#tracked_blocks[block_idx].block_data = result_data
|
||||
|
||||
func do_it():
|
||||
# if blocks_to_move.is_empty():
|
||||
# var blocks:Array[CyclopsConvexBlock] = builder.get_selected_blocks()
|
||||
# for block in blocks:
|
||||
# add_block(block.get_path())
|
||||
|
||||
apply_transform(transform)
|
||||
|
||||
func undo_it():
|
||||
apply_transform(Transform3D.IDENTITY)
|
||||
|
43
addons/cyclops_level_builder/commands/cyclops_command.gd
Normal file
43
addons/cyclops_level_builder/commands/cyclops_command.gd
Normal file
@ -0,0 +1,43 @@
|
||||
# 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
|
||||
class_name CyclopsCommand
|
||||
extends RefCounted
|
||||
|
||||
var command_name:String = ""
|
||||
var builder:CyclopsLevelBuilder
|
||||
|
||||
func add_to_undo_manager(undo_manager:EditorUndoRedoManager):
|
||||
undo_manager.create_action(command_name, UndoRedo.MERGE_DISABLE)
|
||||
undo_manager.add_do_method(self, "do_it")
|
||||
undo_manager.add_undo_method(self, "undo_it")
|
||||
|
||||
undo_manager.commit_action()
|
||||
|
||||
func do_it()->void:
|
||||
pass
|
||||
|
||||
func undo_it()->void:
|
||||
pass
|
||||
|
Reference in New Issue
Block a user