initial commit
2
.gitattributes
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# Normalize EOL for all files that Git considers text files.
|
||||||
|
* text=auto eol=lf
|
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# Godot 4+ specific ignores
|
||||||
|
.godot/
|
@ -0,0 +1,46 @@
|
|||||||
|
# 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 ActionDeleteSelectedBlocks
|
||||||
|
extends CyclopsAction
|
||||||
|
|
||||||
|
|
||||||
|
func _init(plugin:CyclopsLevelBuilder, name:String = "", accellerator:Key = KEY_NONE):
|
||||||
|
super._init(plugin, "Delete Selected Blocks")
|
||||||
|
|
||||||
|
func _execute():
|
||||||
|
var blocks:Array[CyclopsConvexBlock] = plugin.get_selected_blocks()
|
||||||
|
if blocks.is_empty():
|
||||||
|
return
|
||||||
|
|
||||||
|
var cmd:CommandDeleteBlocks = CommandDeleteBlocks.new()
|
||||||
|
cmd.builder = plugin
|
||||||
|
|
||||||
|
for block in blocks:
|
||||||
|
cmd.block_paths.append(block.get_path())
|
||||||
|
|
||||||
|
|
||||||
|
var undo:EditorUndoRedoManager = plugin.get_undo_redo()
|
||||||
|
cmd.add_to_undo_manager(undo)
|
||||||
|
|
@ -0,0 +1,45 @@
|
|||||||
|
# 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 ActionDuplicateSelectedBlocks
|
||||||
|
extends CyclopsAction
|
||||||
|
|
||||||
|
|
||||||
|
func _init(plugin:CyclopsLevelBuilder, name:String = "", accellerator:Key = KEY_NONE):
|
||||||
|
super._init(plugin, "Duplicate Selected Blocks")
|
||||||
|
|
||||||
|
func _execute():
|
||||||
|
var blocks:Array[CyclopsConvexBlock] = plugin.get_selected_blocks()
|
||||||
|
if blocks.is_empty():
|
||||||
|
return
|
||||||
|
|
||||||
|
var cmd:CommandDuplicateBlocks = CommandDuplicateBlocks.new()
|
||||||
|
cmd.builder = plugin
|
||||||
|
|
||||||
|
for block in blocks:
|
||||||
|
cmd.blocks_to_duplicate.append(block.get_path())
|
||||||
|
|
||||||
|
|
||||||
|
var undo:EditorUndoRedoManager = plugin.get_undo_redo()
|
||||||
|
cmd.add_to_undo_manager(undo)
|
@ -0,0 +1,45 @@
|
|||||||
|
# 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 ActionMergeSelectedBlocks
|
||||||
|
extends CyclopsAction
|
||||||
|
|
||||||
|
|
||||||
|
func _init(plugin:CyclopsLevelBuilder, name:String = "", accellerator:Key = KEY_NONE):
|
||||||
|
super._init(plugin, "Merge Selected Blocks")
|
||||||
|
|
||||||
|
func _execute():
|
||||||
|
var blocks:Array[CyclopsConvexBlock] = plugin.get_selected_blocks()
|
||||||
|
if blocks.is_empty():
|
||||||
|
return
|
||||||
|
|
||||||
|
var cmd:CommandMergeBlocks = CommandMergeBlocks.new()
|
||||||
|
cmd.builder = plugin
|
||||||
|
|
||||||
|
for block in blocks:
|
||||||
|
cmd.block_paths.append(block.get_path())
|
||||||
|
|
||||||
|
|
||||||
|
var undo:EditorUndoRedoManager = plugin.get_undo_redo()
|
||||||
|
cmd.add_to_undo_manager(undo)
|
@ -0,0 +1,30 @@
|
|||||||
|
# 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 ActionMirrorSelectionX2
|
||||||
|
extends ActionScaleSelection
|
||||||
|
|
||||||
|
func _init(plugin:CyclopsLevelBuilder):
|
||||||
|
super._init(plugin, "Mirror Selection X")
|
||||||
|
scale = Vector3(-1, 1, 1)
|
@ -0,0 +1,30 @@
|
|||||||
|
# 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 ActionMirrorSelectionY2
|
||||||
|
extends ActionScaleSelection
|
||||||
|
|
||||||
|
func _init(plugin:CyclopsLevelBuilder):
|
||||||
|
super._init(plugin, "Mirror Selection Y")
|
||||||
|
scale = Vector3(1, -1, 1)
|
@ -0,0 +1,30 @@
|
|||||||
|
# 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 ActionMirrorSelectionZ
|
||||||
|
extends ActionScaleSelection
|
||||||
|
|
||||||
|
func _init(plugin:CyclopsLevelBuilder):
|
||||||
|
super._init(plugin, "Mirror Selection Z")
|
||||||
|
scale = Vector3(1, 1, -1)
|
@ -0,0 +1,55 @@
|
|||||||
|
# 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 ActionRotateSelection
|
||||||
|
extends CyclopsAction
|
||||||
|
|
||||||
|
var rotation_axis:Vector3 = Vector3.ONE
|
||||||
|
var rotation_angle:float
|
||||||
|
|
||||||
|
func _init(plugin:CyclopsLevelBuilder, name:String = "", accellerator:Key = KEY_NONE):
|
||||||
|
super._init(plugin, name, accellerator)
|
||||||
|
|
||||||
|
func _execute():
|
||||||
|
var blocks:Array[CyclopsConvexBlock] = plugin.get_selected_blocks()
|
||||||
|
if blocks.is_empty():
|
||||||
|
return
|
||||||
|
|
||||||
|
var pivot:Vector3 = calc_pivot_of_blocks(blocks)
|
||||||
|
|
||||||
|
var cmd:CommandTransformBlocks = CommandTransformBlocks.new()
|
||||||
|
cmd.builder = plugin
|
||||||
|
|
||||||
|
for block in blocks:
|
||||||
|
cmd.add_block(block.get_path())
|
||||||
|
|
||||||
|
var xform:Transform3D = Transform3D.IDENTITY
|
||||||
|
xform = xform.translated_local(pivot)
|
||||||
|
xform = xform.rotated_local(rotation_axis, rotation_angle)
|
||||||
|
xform = xform.translated_local(-pivot)
|
||||||
|
cmd.transform = xform
|
||||||
|
#print("cform %s" % xform)
|
||||||
|
|
||||||
|
var undo:EditorUndoRedoManager = plugin.get_undo_redo()
|
||||||
|
cmd.add_to_undo_manager(undo)
|
31
addons/cyclops_level_builder/actions/action_rotate_x_180.gd
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
# 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 ActionRotateX180
|
||||||
|
extends ActionRotateSelection
|
||||||
|
|
||||||
|
func _init(plugin:CyclopsLevelBuilder):
|
||||||
|
super._init(plugin, "Rotate 180 X")
|
||||||
|
rotation_axis = Vector3(1, 0, 0)
|
||||||
|
rotation_angle = deg_to_rad(180)
|
@ -0,0 +1,31 @@
|
|||||||
|
# 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 ActionRotateX90Ccw
|
||||||
|
extends ActionRotateSelection
|
||||||
|
|
||||||
|
func _init(plugin:CyclopsLevelBuilder):
|
||||||
|
super._init(plugin, "Rotate 90 Ccw X")
|
||||||
|
rotation_axis = Vector3(1, 0, 0)
|
||||||
|
rotation_angle = deg_to_rad(90)
|
@ -0,0 +1,31 @@
|
|||||||
|
# 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 ActionRotateX90Cw
|
||||||
|
extends ActionRotateSelection
|
||||||
|
|
||||||
|
func _init(plugin:CyclopsLevelBuilder):
|
||||||
|
super._init(plugin, "Rotate 90 Cw X")
|
||||||
|
rotation_axis = Vector3(1, 0, 0)
|
||||||
|
rotation_angle = deg_to_rad(-90)
|
31
addons/cyclops_level_builder/actions/action_rotate_y_180.gd
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
# 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 ActionRotateY180
|
||||||
|
extends ActionRotateSelection
|
||||||
|
|
||||||
|
func _init(plugin:CyclopsLevelBuilder):
|
||||||
|
super._init(plugin, "Rotate 180 Y")
|
||||||
|
rotation_axis = Vector3(0, 1, 0)
|
||||||
|
rotation_angle = deg_to_rad(180)
|
@ -0,0 +1,31 @@
|
|||||||
|
# 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 ActionRotateY90Ccw
|
||||||
|
extends ActionRotateSelection
|
||||||
|
|
||||||
|
func _init(plugin:CyclopsLevelBuilder):
|
||||||
|
super._init(plugin, "Rotate 90 Ccw Y")
|
||||||
|
rotation_axis = Vector3(0, 1, 0)
|
||||||
|
rotation_angle = deg_to_rad(90)
|
@ -0,0 +1,31 @@
|
|||||||
|
# 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 ActionRotateY90Cw
|
||||||
|
extends ActionRotateSelection
|
||||||
|
|
||||||
|
func _init(plugin:CyclopsLevelBuilder):
|
||||||
|
super._init(plugin, "Rotate 90 Cw Y")
|
||||||
|
rotation_axis = Vector3(0, 1, 0)
|
||||||
|
rotation_angle = deg_to_rad(-90)
|
31
addons/cyclops_level_builder/actions/action_rotate_z_180.gd
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
# 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 ActionRotateZ180
|
||||||
|
extends ActionRotateSelection
|
||||||
|
|
||||||
|
func _init(plugin:CyclopsLevelBuilder):
|
||||||
|
super._init(plugin, "Rotate 180 Z")
|
||||||
|
rotation_axis = Vector3(0, 0, 1)
|
||||||
|
rotation_angle = deg_to_rad(180)
|
@ -0,0 +1,31 @@
|
|||||||
|
# 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 ActionRotateZ90Ccw
|
||||||
|
extends ActionRotateSelection
|
||||||
|
|
||||||
|
func _init(plugin:CyclopsLevelBuilder):
|
||||||
|
super._init(plugin, "Rotate 90 Ccw Z")
|
||||||
|
rotation_axis = Vector3(0, 0, 1)
|
||||||
|
rotation_angle = deg_to_rad(90)
|
@ -0,0 +1,31 @@
|
|||||||
|
# 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 ActionRotateZ90Cw
|
||||||
|
extends ActionRotateSelection
|
||||||
|
|
||||||
|
func _init(plugin:CyclopsLevelBuilder):
|
||||||
|
super._init(plugin, "Rotate 90 Cw Z")
|
||||||
|
rotation_axis = Vector3(0, 0, 1)
|
||||||
|
rotation_angle = deg_to_rad(-90)
|
@ -0,0 +1,54 @@
|
|||||||
|
# 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 ActionScaleSelection
|
||||||
|
extends CyclopsAction
|
||||||
|
|
||||||
|
var scale:Vector3 = Vector3.ONE
|
||||||
|
|
||||||
|
func _init(plugin:CyclopsLevelBuilder, name:String = "", accellerator:Key = KEY_NONE):
|
||||||
|
super._init(plugin, name, accellerator)
|
||||||
|
|
||||||
|
func _execute():
|
||||||
|
var blocks:Array[CyclopsConvexBlock] = plugin.get_selected_blocks()
|
||||||
|
if blocks.is_empty():
|
||||||
|
return
|
||||||
|
|
||||||
|
var pivot:Vector3 = calc_pivot_of_blocks(blocks)
|
||||||
|
|
||||||
|
var cmd:CommandTransformBlocks = CommandTransformBlocks.new()
|
||||||
|
cmd.builder = plugin
|
||||||
|
|
||||||
|
for block in blocks:
|
||||||
|
cmd.add_block(block.get_path())
|
||||||
|
|
||||||
|
var xform:Transform3D = Transform3D.IDENTITY
|
||||||
|
xform = xform.translated_local(pivot)
|
||||||
|
xform = xform.scaled_local(scale)
|
||||||
|
xform = xform.translated_local(-pivot)
|
||||||
|
cmd.transform = xform
|
||||||
|
#print("cform %s" % xform)
|
||||||
|
|
||||||
|
var undo:EditorUndoRedoManager = plugin.get_undo_redo()
|
||||||
|
cmd.add_to_undo_manager(undo)
|
52
addons/cyclops_level_builder/actions/action_snap_to_grid.gd
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
# 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 ActionSnapToGrid
|
||||||
|
extends CyclopsAction
|
||||||
|
|
||||||
|
func _init(plugin:CyclopsLevelBuilder):
|
||||||
|
super._init(plugin, "Snap to grid")
|
||||||
|
|
||||||
|
|
||||||
|
func _execute():
|
||||||
|
var blocks:Array[CyclopsConvexBlock] = plugin.get_selected_blocks()
|
||||||
|
if blocks.is_empty():
|
||||||
|
return
|
||||||
|
|
||||||
|
var pivot:Vector3 = calc_pivot_of_blocks(blocks)
|
||||||
|
|
||||||
|
var cmd:CommandSnapToGrid = CommandSnapToGrid.new()
|
||||||
|
cmd.builder = plugin
|
||||||
|
|
||||||
|
for block in blocks:
|
||||||
|
cmd.add_block(block.get_path())
|
||||||
|
|
||||||
|
|
||||||
|
cmd.grid_size = pow(2, plugin.get_global_scene().grid_size)
|
||||||
|
#print("cform %s" % xform)
|
||||||
|
|
||||||
|
var undo:EditorUndoRedoManager = plugin.get_undo_redo()
|
||||||
|
cmd.add_to_undo_manager(undo)
|
||||||
|
|
||||||
|
|
@ -0,0 +1,33 @@
|
|||||||
|
# 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 ActionToolDuplicate
|
||||||
|
extends CyclopsAction
|
||||||
|
|
||||||
|
|
||||||
|
func _init(plugin:CyclopsLevelBuilder, name:String = "", accellerator:Key = KEY_NONE):
|
||||||
|
super._init(plugin, "Duplicate Selected Blocks")
|
||||||
|
|
||||||
|
func _execute():
|
||||||
|
plugin.switch_to_tool(ToolDuplicate.new())
|
54
addons/cyclops_level_builder/actions/cyclops_action.gd
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
# 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 CyclopsAction
|
||||||
|
extends RefCounted
|
||||||
|
|
||||||
|
var plugin:CyclopsLevelBuilder
|
||||||
|
|
||||||
|
var name:String = ""
|
||||||
|
var accellerator:Key = KEY_NONE
|
||||||
|
|
||||||
|
func _init(plugin:CyclopsLevelBuilder, name:String = "", accellerator:Key = KEY_NONE):
|
||||||
|
self.plugin = plugin
|
||||||
|
self.name= name
|
||||||
|
self.accellerator = accellerator
|
||||||
|
|
||||||
|
func _execute():
|
||||||
|
pass
|
||||||
|
|
||||||
|
func calc_pivot_of_blocks(blocks:Array[CyclopsConvexBlock])->Vector3:
|
||||||
|
# var blocks_root:CyclopsBlocks = plugin.active_node
|
||||||
|
var grid_step_size:float = pow(2, plugin.get_global_scene().grid_size)
|
||||||
|
|
||||||
|
var bounds:AABB = blocks[0].control_mesh.bounds
|
||||||
|
for idx in range(1, blocks.size()):
|
||||||
|
var block:CyclopsConvexBlock = blocks[idx]
|
||||||
|
bounds = bounds.merge(block.control_mesh.bounds)
|
||||||
|
|
||||||
|
var center:Vector3 = bounds.get_center()
|
||||||
|
var pivot:Vector3 = MathUtil.snap_to_grid(center, grid_step_size)
|
||||||
|
|
||||||
|
return pivot
|
||||||
|
|
BIN
addons/cyclops_level_builder/art/cyclops.aseprite
Normal file
142
addons/cyclops_level_builder/art/cyclops.svg
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
width="32"
|
||||||
|
height="32"
|
||||||
|
viewBox="0 0 32 32"
|
||||||
|
version="1.1"
|
||||||
|
id="svg5"
|
||||||
|
inkscape:version="1.2.2 (732a01da63, 2022-12-09)"
|
||||||
|
sodipodi:docname="cyclops.svg"
|
||||||
|
inkscape:export-filename="cyclops_closed.png"
|
||||||
|
inkscape:export-xdpi="72"
|
||||||
|
inkscape:export-ydpi="72"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview7"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#111111"
|
||||||
|
borderopacity="1"
|
||||||
|
inkscape:showpageshadow="0"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pagecheckerboard="1"
|
||||||
|
inkscape:deskcolor="#d1d1d1"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="17.25178"
|
||||||
|
inkscape:cx="9.7381256"
|
||||||
|
inkscape:cy="10.433706"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="1017"
|
||||||
|
inkscape:window-x="1912"
|
||||||
|
inkscape:window-y="-8"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="layer3" />
|
||||||
|
<defs
|
||||||
|
id="defs2" />
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1">
|
||||||
|
<path
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.15774px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="M 4.5878173,28.851656 C 4.491135,24.674634 7.1014538,22.972623 9.9105956,21.024042 L 22.716572,20.83618 c 2.050611,2.112456 5.504016,4.021079 5.44802,8.078098 z"
|
||||||
|
id="path3766"
|
||||||
|
sodipodi:nodetypes="ccccc" />
|
||||||
|
<path
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.15774px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
|
||||||
|
d="m 25.753688,15.482091 c 0.156553,-0.250483 2.403741,-2.373742 3.694635,-2.066491 1.695855,0.403637 1.446745,3.66121 0.939314,5.260157 -0.611229,1.926017 -2.613395,3.748315 -3.694635,3.444152 -0.935221,-0.263087 -1.565524,-2.03518 -1.565524,-2.03518"
|
||||||
|
id="path3843"
|
||||||
|
sodipodi:nodetypes="csssc" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1.15774px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m 26.912174,17.110235 c 0.706768,-0.73189 1.415699,-1.455116 2.285665,-1.534213"
|
||||||
|
id="path3845"
|
||||||
|
sodipodi:nodetypes="cc" />
|
||||||
|
<path
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.15774px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
|
||||||
|
d="M 6.8436682,15.170808 C 6.6871161,14.920325 4.4399274,12.797065 3.1490342,13.104316 1.453178,13.507954 1.702288,16.765527 2.2097192,18.364472 c 0.6112284,1.926018 2.6133951,3.748315 3.6946352,3.444152 0.9352213,-0.263087 1.5655234,-2.035179 1.5655234,-2.035179"
|
||||||
|
id="path3843-6"
|
||||||
|
sodipodi:nodetypes="csssc" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1.15774px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="M 5.6851813,16.798952 C 4.9784148,16.067062 4.2694824,15.343836 3.3995172,15.264739"
|
||||||
|
id="path3845-7"
|
||||||
|
sodipodi:nodetypes="cc" />
|
||||||
|
<ellipse
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.810419;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-dashoffset:0.8;stroke-opacity:1"
|
||||||
|
id="path2244"
|
||||||
|
cx="16.336857"
|
||||||
|
cy="16.477674"
|
||||||
|
rx="10.879799"
|
||||||
|
ry="8.6858559" />
|
||||||
|
<path
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.15774px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
|
||||||
|
d="m 14.12493,6.9645952 c 0,0 -2.734227,0.7311537 -2.609474,1.5698289 0.289028,1.9430589 2.615214,3.4253189 5.111866,3.4721999 2.143974,0.04026 4.930688,-0.996693 5.53415,-3.0245418 0.266502,-0.8955417 -2.641601,-1.8376556 -2.641601,-1.8376556 z"
|
||||||
|
id="path3613"
|
||||||
|
sodipodi:nodetypes="cssscc" />
|
||||||
|
<path
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.15774px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m 13.621403,8.4392124 c 0.03597,-0.143865 3.129065,-4.9993121 3.129065,-4.9993121 l 3.093099,5.107211 c 0,0 -1.036582,1.7146207 -3.200998,1.6184827 -1.986985,-0.08826 -3.021166,-1.7263816 -3.021166,-1.7263816 z"
|
||||||
|
id="path3711"
|
||||||
|
sodipodi:nodetypes="cccsc" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1.15774px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m 13.96694,23.572677 c 0,0 1.310205,-0.09653 2.582791,-0.12975 1.459112,-0.0381 2.614745,0.192371 2.614745,0.192371"
|
||||||
|
id="path3727-8"
|
||||||
|
sodipodi:nodetypes="csc" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer2"
|
||||||
|
inkscape:label="EyeClosed"
|
||||||
|
style="display:inline">
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1.15774px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m 9.3470074,17.047613 c 0,0 3.1696546,3.057312 7.1700936,3.005804 4.400975,-0.05665 6.637818,-3.005804 6.637818,-3.005804"
|
||||||
|
id="path3727"
|
||||||
|
sodipodi:nodetypes="csc" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1.15774px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m 23.280163,15.012434 c 1.484124,-0.05522 2.067074,1.04017 2.097801,2.254352"
|
||||||
|
id="path3729"
|
||||||
|
sodipodi:nodetypes="cc" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1.15774px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="M 9.5035596,14.668018 C 8.5016248,15.062299 7.6875529,15.899562 7.155275,16.89106"
|
||||||
|
id="path3731"
|
||||||
|
sodipodi:nodetypes="cc" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer3"
|
||||||
|
inkscape:label="EyeOpen"
|
||||||
|
style="display:none">
|
||||||
|
<path
|
||||||
|
style="display:inline;fill:none;stroke:#000000;stroke-width:1.15774px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m 23.389083,17.318695 c 0,0 -2.749922,3.508872 -7.150897,3.565527 -4.00044,0.0515 -6.8435886,-3.84539 -6.8435886,-3.84539 0,0 2.4413346,-3.718794 6.9539426,-3.677816 4.834349,0.0439 7.040543,3.957679 7.040543,3.957679 z"
|
||||||
|
id="path3727-0"
|
||||||
|
sodipodi:nodetypes="cscsc" />
|
||||||
|
<path
|
||||||
|
style="display:inline;fill:none;stroke:#000000;stroke-width:1.15774px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m 24.400556,15.983168 c 1.017688,0.831014 0.994271,1.833112 -0.141093,2.674146"
|
||||||
|
id="path3729-3"
|
||||||
|
sodipodi:nodetypes="cc" />
|
||||||
|
<path
|
||||||
|
style="display:inline;fill:none;stroke:#000000;stroke-width:1.15774px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m 8.3384149,15.452179 c -1.007661,0.395044 -1.231048,1.983805 0.030541,2.736122"
|
||||||
|
id="path3731-4"
|
||||||
|
sodipodi:nodetypes="cc" />
|
||||||
|
<ellipse
|
||||||
|
style="display:inline;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.914835;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-dashoffset:0.8;stroke-opacity:1"
|
||||||
|
id="path4064"
|
||||||
|
cx="16.418505"
|
||||||
|
cy="17.069185"
|
||||||
|
rx="2.3088593"
|
||||||
|
ry="2.2155721" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 7.0 KiB |
37
addons/cyclops_level_builder/art/cyclops.svg.import
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://bmbwskudf7ldr"
|
||||||
|
path="res://.godot/imported/cyclops.svg-62ab1cb5293c5a489284f34e0c642019.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://addons/cyclops_level_builder/art/cyclops.svg"
|
||||||
|
dest_files=["res://.godot/imported/cyclops.svg-62ab1cb5293c5a489284f34e0c642019.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
||||||
|
svg/scale=1.0
|
||||||
|
editor/scale_with_editor_scale=false
|
||||||
|
editor/convert_colors_with_editor_theme=false
|
BIN
addons/cyclops_level_builder/art/cyclops1.png
Normal file
After Width: | Height: | Size: 369 B |
34
addons/cyclops_level_builder/art/cyclops1.png.import
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://l4qj0lbj3ioa"
|
||||||
|
path="res://.godot/imported/cyclops1.png-6f459321d21304ca30333893d06ffb09.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://addons/cyclops_level_builder/art/cyclops1.png"
|
||||||
|
dest_files=["res://.godot/imported/cyclops1.png-6f459321d21304ca30333893d06ffb09.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
BIN
addons/cyclops_level_builder/art/cyclops2.png
Normal file
After Width: | Height: | Size: 433 B |
34
addons/cyclops_level_builder/art/cyclops2.png.import
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://oxrgrpeaamq3"
|
||||||
|
path="res://.godot/imported/cyclops2.png-510e6418526608a41b6474466da5ef6e.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://addons/cyclops_level_builder/art/cyclops2.png"
|
||||||
|
dest_files=["res://.godot/imported/cyclops2.png-510e6418526608a41b6474466da5ef6e.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
BIN
addons/cyclops_level_builder/art/cyclops_16.aseprite
Normal file
BIN
addons/cyclops_level_builder/art/cyclops_16.png
Normal file
After Width: | Height: | Size: 258 B |
34
addons/cyclops_level_builder/art/cyclops_16.png.import
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://df0a5uffpuqg3"
|
||||||
|
path="res://.godot/imported/cyclops_16.png-f07e4f06ecdf5a5bd3bf65311c5a89e7.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://addons/cyclops_level_builder/art/cyclops_16.png"
|
||||||
|
dest_files=["res://.godot/imported/cyclops_16.png-f07e4f06ecdf5a5bd3bf65311c5a89e7.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
BIN
addons/cyclops_level_builder/art/cyclops_17.png
Normal file
After Width: | Height: | Size: 272 B |
34
addons/cyclops_level_builder/art/cyclops_17.png.import
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://ynphxd22kahd"
|
||||||
|
path="res://.godot/imported/cyclops_17.png-c21222671fab466b90ffb528051b4f8e.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://addons/cyclops_level_builder/art/cyclops_17.png"
|
||||||
|
dest_files=["res://.godot/imported/cyclops_17.png-c21222671fab466b90ffb528051b4f8e.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
BIN
addons/cyclops_level_builder/art/cyclops_3.aseprite
Normal file
BIN
addons/cyclops_level_builder/art/cyclops_3.png
Normal file
After Width: | Height: | Size: 588 B |
34
addons/cyclops_level_builder/art/cyclops_3.png.import
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://d0krdms4l6ns4"
|
||||||
|
path="res://.godot/imported/cyclops_3.png-6415cec0c5295619847f207c8fb5e88e.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://addons/cyclops_level_builder/art/cyclops_3.png"
|
||||||
|
dest_files=["res://.godot/imported/cyclops_3.png-6415cec0c5295619847f207c8fb5e88e.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
BIN
addons/cyclops_level_builder/art/cyclops_4.png
Normal file
After Width: | Height: | Size: 643 B |
34
addons/cyclops_level_builder/art/cyclops_4.png.import
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://cg3yjatinkymb"
|
||||||
|
path="res://.godot/imported/cyclops_4.png-e03a17198c56b52428203cf1953feb8c.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://addons/cyclops_level_builder/art/cyclops_4.png"
|
||||||
|
dest_files=["res://.godot/imported/cyclops_4.png-e03a17198c56b52428203cf1953feb8c.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
BIN
addons/cyclops_level_builder/art/cyclops_closed.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
34
addons/cyclops_level_builder/art/cyclops_closed.png.import
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://dd8xjcq5k2kia"
|
||||||
|
path="res://.godot/imported/cyclops_closed.png-8f54cf7552f8e17ac6aa0c8d6378241b.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://addons/cyclops_level_builder/art/cyclops_closed.png"
|
||||||
|
dest_files=["res://.godot/imported/cyclops_closed.png-8f54cf7552f8e17ac6aa0c8d6378241b.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
BIN
addons/cyclops_level_builder/art/cyclops_open.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
34
addons/cyclops_level_builder/art/cyclops_open.png.import
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://dv78ucvwmycdh"
|
||||||
|
path="res://.godot/imported/cyclops_open.png-44d55f3db65056f90cc00f3559bf1cb3.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://addons/cyclops_level_builder/art/cyclops_open.png"
|
||||||
|
dest_files=["res://.godot/imported/cyclops_open.png-44d55f3db65056f90cc00f3559bf1cb3.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
BIN
addons/cyclops_level_builder/art/materialTest.blend
Normal file
48
addons/cyclops_level_builder/art/materialTest.blend.import
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="scene"
|
||||||
|
importer_version=1
|
||||||
|
type="PackedScene"
|
||||||
|
uid="uid://bp8tbh8g23hkk"
|
||||||
|
path="res://.godot/imported/materialTest.blend-aa817559d244ec647e2795b1bec725af.scn"
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://addons/cyclops_level_builder/art/materialTest.blend"
|
||||||
|
dest_files=["res://.godot/imported/materialTest.blend-aa817559d244ec647e2795b1bec725af.scn"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
nodes/root_type="Node3D"
|
||||||
|
nodes/root_name="Scene Root"
|
||||||
|
nodes/apply_root_scale=true
|
||||||
|
nodes/root_scale=1.0
|
||||||
|
meshes/ensure_tangents=true
|
||||||
|
meshes/generate_lods=true
|
||||||
|
meshes/create_shadow_meshes=true
|
||||||
|
meshes/light_baking=1
|
||||||
|
meshes/lightmap_texel_size=0.2
|
||||||
|
skins/use_named_skins=true
|
||||||
|
animation/import=true
|
||||||
|
animation/fps=30
|
||||||
|
animation/trimming=false
|
||||||
|
animation/remove_immutable_tracks=true
|
||||||
|
import_script/path=""
|
||||||
|
_subresources={}
|
||||||
|
gltf/embedded_image_handling=1
|
||||||
|
blender/nodes/visible=0
|
||||||
|
blender/nodes/punctual_lights=true
|
||||||
|
blender/nodes/cameras=true
|
||||||
|
blender/nodes/custom_properties=true
|
||||||
|
blender/nodes/modifiers=1
|
||||||
|
blender/meshes/colors=false
|
||||||
|
blender/meshes/uvs=true
|
||||||
|
blender/meshes/normals=true
|
||||||
|
blender/meshes/tangents=true
|
||||||
|
blender/meshes/skins=2
|
||||||
|
blender/meshes/export_bones_deforming_mesh_only=false
|
||||||
|
blender/materials/unpack_enabled=true
|
||||||
|
blender/materials/export_materials=1
|
||||||
|
blender/animation/limit_playback=true
|
||||||
|
blender/animation/always_sample=true
|
||||||
|
blender/animation/group_tracks=true
|
BIN
addons/cyclops_level_builder/art/materialTest.blend1
Normal file
BIN
addons/cyclops_level_builder/art/materialTest.glb
Normal file
32
addons/cyclops_level_builder/art/materialTest.glb.import
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="scene"
|
||||||
|
importer_version=1
|
||||||
|
type="PackedScene"
|
||||||
|
uid="uid://dxpve684yme21"
|
||||||
|
path="res://.godot/imported/materialTest.glb-89a5487d9d67cb795bea9d0f40563ce7.scn"
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://addons/cyclops_level_builder/art/materialTest.glb"
|
||||||
|
dest_files=["res://.godot/imported/materialTest.glb-89a5487d9d67cb795bea9d0f40563ce7.scn"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
nodes/root_type="Node3D"
|
||||||
|
nodes/root_name="Scene Root"
|
||||||
|
nodes/apply_root_scale=true
|
||||||
|
nodes/root_scale=1.0
|
||||||
|
meshes/ensure_tangents=true
|
||||||
|
meshes/generate_lods=true
|
||||||
|
meshes/create_shadow_meshes=true
|
||||||
|
meshes/light_baking=1
|
||||||
|
meshes/lightmap_texel_size=0.2
|
||||||
|
skins/use_named_skins=true
|
||||||
|
animation/import=true
|
||||||
|
animation/fps=30
|
||||||
|
animation/trimming=false
|
||||||
|
animation/remove_immutable_tracks=true
|
||||||
|
import_script/path=""
|
||||||
|
_subresources={}
|
||||||
|
gltf/embedded_image_handling=1
|
BIN
addons/cyclops_level_builder/art/textures/checkerboard.aseprite
Normal file
BIN
addons/cyclops_level_builder/art/textures/checkerboard.png
Normal file
After Width: | Height: | Size: 405 B |
@ -0,0 +1,35 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://b78mg60xhic6n"
|
||||||
|
path.s3tc="res://.godot/imported/checkerboard.png-cfbf91dbc6f1912b9574735ecca5a514.s3tc.ctex"
|
||||||
|
metadata={
|
||||||
|
"imported_formats": ["s3tc_bptc"],
|
||||||
|
"vram_texture": true
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://addons/cyclops_level_builder/art/textures/checkerboard.png"
|
||||||
|
dest_files=["res://.godot/imported/checkerboard.png-cfbf91dbc6f1912b9574735ecca5a514.s3tc.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=2
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=true
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=0
|
BIN
addons/cyclops_level_builder/art/textures/grid_cell.aseprite
Normal file
BIN
addons/cyclops_level_builder/art/textures/grid_cell.png
Normal file
After Width: | Height: | Size: 411 B |
@ -0,0 +1,35 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://dpoaquoridpp6"
|
||||||
|
path.bptc="res://.godot/imported/grid_cell.png-608181fcff7b2e489ee715ed212734c5.bptc.ctex"
|
||||||
|
metadata={
|
||||||
|
"imported_formats": ["s3tc_bptc"],
|
||||||
|
"vram_texture": true
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://addons/cyclops_level_builder/art/textures/grid_cell.png"
|
||||||
|
dest_files=["res://.godot/imported/grid_cell.png-608181fcff7b2e489ee715ed212734c5.bptc.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=2
|
||||||
|
compress/high_quality=true
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=true
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=0
|
BIN
addons/cyclops_level_builder/art/textures/grid_cell2.aseprite
Normal file
BIN
addons/cyclops_level_builder/art/textures/grid_cell2.png
Normal file
After Width: | Height: | Size: 416 B |
@ -0,0 +1,34 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://bnlqi20ay4vs1"
|
||||||
|
path="res://.godot/imported/grid_cell2.png-1f268fac69e50a444ba304e9119a8d5b.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://addons/cyclops_level_builder/art/textures/grid_cell2.png"
|
||||||
|
dest_files=["res://.godot/imported/grid_cell2.png-1f268fac69e50a444ba304e9119a8d5b.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=true
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=0
|
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
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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
|
||||||
|
|
125
addons/cyclops_level_builder/controls/numeric_line_edit.gd
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
# MIT License
|
||||||
|
#
|
||||||
|
# Copyright (c) 2023 Mark McKay
|
||||||
|
# https://github.com/blackears/cyclopsLevelBuilder
|
||||||
|
#
|
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
# of this software and associated documentation files (the "Software"), to deal
|
||||||
|
# in the Software without restriction, including without limitation the rights
|
||||||
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
# copies of the Software, and to permit persons to whom the Software is
|
||||||
|
# furnished to do so, subject to the following conditions:
|
||||||
|
#
|
||||||
|
# The above copyright notice and this permission notice shall be included in all
|
||||||
|
# copies or substantial portions of the Software.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
|
||||||
|
@tool
|
||||||
|
extends PanelContainer
|
||||||
|
class_name NumbericLineEdit
|
||||||
|
|
||||||
|
signal value_changed(value)
|
||||||
|
|
||||||
|
@export var value:float:
|
||||||
|
get:
|
||||||
|
return value
|
||||||
|
set(v):
|
||||||
|
if value == v:
|
||||||
|
return
|
||||||
|
value = v
|
||||||
|
dirty = true
|
||||||
|
|
||||||
|
@export var snap_size:float = 1
|
||||||
|
var dirty:bool = true
|
||||||
|
|
||||||
|
enum State{ IDLE, READY, DRAGGING, TEXT_EDIT }
|
||||||
|
var state:State = State.IDLE
|
||||||
|
|
||||||
|
var mouse_down_pos:Vector2
|
||||||
|
var drag_start_radius:float = 4
|
||||||
|
var value_start_drag:float
|
||||||
|
|
||||||
|
# Called when the node enters the scene tree for the first time.
|
||||||
|
func _ready():
|
||||||
|
# text = "%.4f" % value
|
||||||
|
# $HBoxContainer/LineEdit.text = "%s" % value
|
||||||
|
# $HBoxContainer/Label.text = "%s" % value
|
||||||
|
$HBoxContainer/LineEdit.visible = false
|
||||||
|
pass
|
||||||
|
|
||||||
|
func _process(delta):
|
||||||
|
if dirty:
|
||||||
|
$HBoxContainer/LineEdit.text = format_number(value)
|
||||||
|
$HBoxContainer/Label.text = format_number(value)
|
||||||
|
dirty = false
|
||||||
|
|
||||||
|
func format_number(val:float)->String:
|
||||||
|
var text:String = "%.5f" % val
|
||||||
|
var idx:int = text.findn(".")
|
||||||
|
if idx != -1:
|
||||||
|
text = text.rstrip("0")
|
||||||
|
if text.right(1) == ".":
|
||||||
|
text = text.left(-1)
|
||||||
|
return text
|
||||||
|
|
||||||
|
|
||||||
|
func _gui_input(event):
|
||||||
|
if event is InputEventMouseButton:
|
||||||
|
var e:InputEventMouseButton = event
|
||||||
|
if e.is_pressed():
|
||||||
|
if state == State.IDLE:
|
||||||
|
mouse_down_pos = e.position
|
||||||
|
state = State.READY
|
||||||
|
else:
|
||||||
|
if state == State.READY:
|
||||||
|
$HBoxContainer/LineEdit.visible = true
|
||||||
|
$HBoxContainer/Label.visible = false
|
||||||
|
state = State.TEXT_EDIT
|
||||||
|
elif state == State.DRAGGING:
|
||||||
|
state = State.IDLE
|
||||||
|
|
||||||
|
|
||||||
|
accept_event()
|
||||||
|
|
||||||
|
elif event is InputEventMouseMotion:
|
||||||
|
var e:InputEventMouseMotion = event
|
||||||
|
if state == State.READY:
|
||||||
|
if e.position.distance_to(mouse_down_pos) >= drag_start_radius:
|
||||||
|
state = State.DRAGGING
|
||||||
|
value_start_drag = value
|
||||||
|
|
||||||
|
elif state == State.DRAGGING:
|
||||||
|
var offset = e.position.x - mouse_down_pos.x
|
||||||
|
var new_value = value_start_drag + (offset * snap_size / 20.0)
|
||||||
|
#print("-new_value %s" % new_value)
|
||||||
|
new_value = ceil(new_value / snap_size) * snap_size
|
||||||
|
|
||||||
|
#print("new_value %s" % new_value)
|
||||||
|
|
||||||
|
if value != new_value:
|
||||||
|
value = new_value
|
||||||
|
value_changed.emit(value)
|
||||||
|
dirty = true
|
||||||
|
|
||||||
|
func _on_line_edit_text_submitted(new_text):
|
||||||
|
var regex = RegEx.new()
|
||||||
|
regex.compile("^[+-]?([0-9]+([.][0-9]*)?|[.][0-9]+)$")
|
||||||
|
var result:RegExMatch = regex.search(new_text)
|
||||||
|
if result:
|
||||||
|
# print("found match")
|
||||||
|
value = float(new_text)
|
||||||
|
value_changed.emit(value)
|
||||||
|
|
||||||
|
dirty = true
|
||||||
|
state = State.IDLE
|
||||||
|
$HBoxContainer/LineEdit.visible = false
|
||||||
|
$HBoxContainer/Label.visible = true
|
||||||
|
# text = "%s" % value
|
||||||
|
# print("text changed2 %s" % text)
|
26
addons/cyclops_level_builder/controls/numeric_line_edit.tscn
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
[gd_scene load_steps=2 format=3 uid="uid://diibmlqy1mpqb"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://addons/cyclops_level_builder/controls/numeric_line_edit.gd" id="1_u8bpo"]
|
||||||
|
|
||||||
|
[node name="PanelContainer" type="PanelContainer"]
|
||||||
|
offset_right = 476.0
|
||||||
|
offset_bottom = 40.0
|
||||||
|
script = ExtResource("1_u8bpo")
|
||||||
|
snap_size = 0.125
|
||||||
|
|
||||||
|
[node name="HBoxContainer" type="HBoxContainer" parent="."]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="LineEdit" type="LineEdit" parent="HBoxContainer"]
|
||||||
|
visible = false
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
text = "0"
|
||||||
|
select_all_on_focus = true
|
||||||
|
|
||||||
|
[node name="Label" type="Label" parent="HBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
text = "0"
|
||||||
|
|
||||||
|
[connection signal="text_submitted" from="HBoxContainer/LineEdit" to="." method="_on_line_edit_text_submitted"]
|
@ -0,0 +1,66 @@
|
|||||||
|
# MIT License
|
||||||
|
#
|
||||||
|
# Copyright (c) 2023 Mark McKay
|
||||||
|
# https://github.com/blackears/cyclopsLevelBuilder
|
||||||
|
#
|
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
# of this software and associated documentation files (the "Software"), to deal
|
||||||
|
# in the Software without restriction, including without limitation the rights
|
||||||
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
# copies of the Software, and to permit persons to whom the Software is
|
||||||
|
# furnished to do so, subject to the following conditions:
|
||||||
|
#
|
||||||
|
# The above copyright notice and this permission notice shall be included in all
|
||||||
|
# copies or substantial portions of the Software.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
|
||||||
|
@tool
|
||||||
|
extends CheckBox
|
||||||
|
class_name LineEditorBool
|
||||||
|
|
||||||
|
var resource:Resource:
|
||||||
|
get:
|
||||||
|
return resource
|
||||||
|
set(value):
|
||||||
|
resource = value
|
||||||
|
dirty = true
|
||||||
|
|
||||||
|
var prop_name:String:
|
||||||
|
get:
|
||||||
|
return prop_name
|
||||||
|
set(value):
|
||||||
|
prop_name = value
|
||||||
|
dirty = true
|
||||||
|
|
||||||
|
var dirty = true
|
||||||
|
|
||||||
|
func update_from_resource():
|
||||||
|
if resource:
|
||||||
|
var result = resource.get(prop_name)
|
||||||
|
if result != null:
|
||||||
|
button_pressed = result
|
||||||
|
|
||||||
|
# Called when the node enters the scene tree for the first time.
|
||||||
|
func _ready():
|
||||||
|
pass # Replace with function body.
|
||||||
|
|
||||||
|
|
||||||
|
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||||
|
func _process(delta):
|
||||||
|
if dirty:
|
||||||
|
update_from_resource()
|
||||||
|
dirty = false
|
||||||
|
|
||||||
|
|
||||||
|
func _on_toggled(button_pressed):
|
||||||
|
if resource:
|
||||||
|
print("prop_name %s" % prop_name)
|
||||||
|
print("button_pressed %s" % button_pressed)
|
||||||
|
resource.set(prop_name, button_pressed)
|
@ -0,0 +1,10 @@
|
|||||||
|
[gd_scene load_steps=2 format=3 uid="uid://dpncabeqiv1xo"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://addons/cyclops_level_builder/controls/resource_inspector/line_editor_bool.gd" id="1_sn3qq"]
|
||||||
|
|
||||||
|
[node name="CheckBox" type="CheckBox"]
|
||||||
|
offset_right = 24.0
|
||||||
|
offset_bottom = 24.0
|
||||||
|
script = ExtResource("1_sn3qq")
|
||||||
|
|
||||||
|
[connection signal="toggled" from="." to="." method="_on_toggled"]
|
@ -0,0 +1,65 @@
|
|||||||
|
# MIT License
|
||||||
|
#
|
||||||
|
# Copyright (c) 2023 Mark McKay
|
||||||
|
# https://github.com/blackears/cyclopsLevelBuilder
|
||||||
|
#
|
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
# of this software and associated documentation files (the "Software"), to deal
|
||||||
|
# in the Software without restriction, including without limitation the rights
|
||||||
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
# copies of the Software, and to permit persons to whom the Software is
|
||||||
|
# furnished to do so, subject to the following conditions:
|
||||||
|
#
|
||||||
|
# The above copyright notice and this permission notice shall be included in all
|
||||||
|
# copies or substantial portions of the Software.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
|
||||||
|
@tool
|
||||||
|
extends SpinBox
|
||||||
|
class_name LineEditorFloat
|
||||||
|
|
||||||
|
|
||||||
|
var resource:Resource:
|
||||||
|
get:
|
||||||
|
return resource
|
||||||
|
set(value):
|
||||||
|
resource = value
|
||||||
|
dirty = true
|
||||||
|
|
||||||
|
var prop_name:String:
|
||||||
|
get:
|
||||||
|
return prop_name
|
||||||
|
set(value):
|
||||||
|
prop_name = value
|
||||||
|
dirty = true
|
||||||
|
|
||||||
|
var dirty = true
|
||||||
|
|
||||||
|
func update_from_resource():
|
||||||
|
if resource:
|
||||||
|
var result = resource.get(prop_name)
|
||||||
|
if result != null:
|
||||||
|
value = result
|
||||||
|
|
||||||
|
# Called when the node enters the scene tree for the first time.
|
||||||
|
func _ready():
|
||||||
|
pass # Replace with function body.
|
||||||
|
|
||||||
|
|
||||||
|
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||||
|
func _process(delta):
|
||||||
|
if dirty:
|
||||||
|
update_from_resource()
|
||||||
|
dirty = false
|
||||||
|
|
||||||
|
|
||||||
|
func _on_value_changed(value):
|
||||||
|
if resource:
|
||||||
|
resource.set(prop_name, value)
|
@ -0,0 +1,11 @@
|
|||||||
|
[gd_scene load_steps=2 format=3 uid="uid://dg45e7tw7ttu3"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://addons/cyclops_level_builder/controls/resource_inspector/line_editor_float.gd" id="1_o1hmb"]
|
||||||
|
|
||||||
|
[node name="SpinBox" type="SpinBox"]
|
||||||
|
offset_right = 83.0625
|
||||||
|
offset_bottom = 31.0
|
||||||
|
step = 0.001
|
||||||
|
script = ExtResource("1_o1hmb")
|
||||||
|
|
||||||
|
[connection signal="value_changed" from="." to="." method="_on_value_changed"]
|
@ -0,0 +1,71 @@
|
|||||||
|
# MIT License
|
||||||
|
#
|
||||||
|
# Copyright (c) 2023 Mark McKay
|
||||||
|
# https://github.com/blackears/cyclopsLevelBuilder
|
||||||
|
#
|
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
# of this software and associated documentation files (the "Software"), to deal
|
||||||
|
# in the Software without restriction, including without limitation the rights
|
||||||
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
# copies of the Software, and to permit persons to whom the Software is
|
||||||
|
# furnished to do so, subject to the following conditions:
|
||||||
|
#
|
||||||
|
# The above copyright notice and this permission notice shall be included in all
|
||||||
|
# copies or substantial portions of the Software.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
|
||||||
|
@tool
|
||||||
|
extends SpinBox
|
||||||
|
class_name LineEditorInt
|
||||||
|
|
||||||
|
var resource:Resource:
|
||||||
|
get:
|
||||||
|
return resource
|
||||||
|
set(value):
|
||||||
|
resource = value
|
||||||
|
dirty = true
|
||||||
|
|
||||||
|
var prop_name:String:
|
||||||
|
get:
|
||||||
|
return prop_name
|
||||||
|
set(value):
|
||||||
|
prop_name = value
|
||||||
|
dirty = true
|
||||||
|
|
||||||
|
var dirty = true
|
||||||
|
|
||||||
|
func update_from_resource():
|
||||||
|
#print("update_from_resource()")
|
||||||
|
if resource:
|
||||||
|
#print("resource %s" % resource)
|
||||||
|
#print("prop_name %s" % prop_name)
|
||||||
|
var result = resource.get(prop_name)
|
||||||
|
#print("result %s" % result)
|
||||||
|
if result != null:
|
||||||
|
value = result
|
||||||
|
|
||||||
|
# Called when the node enters the scene tree for the first time.
|
||||||
|
func _ready():
|
||||||
|
pass # Replace with function body.
|
||||||
|
|
||||||
|
|
||||||
|
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||||
|
func _process(delta):
|
||||||
|
if dirty:
|
||||||
|
update_from_resource()
|
||||||
|
dirty = false
|
||||||
|
|
||||||
|
|
||||||
|
func _on_value_changed(value):
|
||||||
|
print("_on_value_changed(value)")
|
||||||
|
if resource:
|
||||||
|
print("prop_name %s" % prop_name)
|
||||||
|
print("value %s" % value)
|
||||||
|
resource.set(prop_name, value)
|
@ -0,0 +1,10 @@
|
|||||||
|
[gd_scene load_steps=2 format=3 uid="uid://dh6frljlp7oqe"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://addons/cyclops_level_builder/controls/resource_inspector/line_editor_int.gd" id="1_ryygx"]
|
||||||
|
|
||||||
|
[node name="SpinBox" type="SpinBox"]
|
||||||
|
offset_right = 83.0625
|
||||||
|
offset_bottom = 40.0
|
||||||
|
script = ExtResource("1_ryygx")
|
||||||
|
|
||||||
|
[connection signal="value_changed" from="." to="." method="_on_value_changed"]
|
@ -0,0 +1,86 @@
|
|||||||
|
# MIT License
|
||||||
|
#
|
||||||
|
# Copyright (c) 2023 Mark McKay
|
||||||
|
# https://github.com/blackears/cyclopsLevelBuilder
|
||||||
|
#
|
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
# of this software and associated documentation files (the "Software"), to deal
|
||||||
|
# in the Software without restriction, including without limitation the rights
|
||||||
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
# copies of the Software, and to permit persons to whom the Software is
|
||||||
|
# furnished to do so, subject to the following conditions:
|
||||||
|
#
|
||||||
|
# The above copyright notice and this permission notice shall be included in all
|
||||||
|
# copies or substantial portions of the Software.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
|
||||||
|
@tool
|
||||||
|
extends Control
|
||||||
|
class_name ResourceInspector
|
||||||
|
|
||||||
|
@export var target:Resource:
|
||||||
|
get:
|
||||||
|
return target
|
||||||
|
set(value):
|
||||||
|
target = value
|
||||||
|
build()
|
||||||
|
|
||||||
|
func add_label(name:String):
|
||||||
|
var label:Label = Label.new()
|
||||||
|
label.text = name
|
||||||
|
$GridContainer.add_child(label)
|
||||||
|
|
||||||
|
func build():
|
||||||
|
for child in $GridContainer.get_children():
|
||||||
|
$GridContainer.remove_child(child)
|
||||||
|
|
||||||
|
if !target:
|
||||||
|
return
|
||||||
|
|
||||||
|
for prop_dict in target.get_property_list():
|
||||||
|
var prop_name:String = prop_dict["name"]
|
||||||
|
# prop_dict["class_name"]
|
||||||
|
|
||||||
|
var type:Variant.Type = prop_dict["type"]
|
||||||
|
match type:
|
||||||
|
TYPE_BOOL:
|
||||||
|
add_label(prop_name)
|
||||||
|
|
||||||
|
var editor:LineEditorBool = preload("res://addons/cyclops_level_builder/controls/resource_inspector/line_editor_bool.tscn").instantiate()
|
||||||
|
editor.resource = target
|
||||||
|
editor.prop_name = prop_name
|
||||||
|
$GridContainer.add_child(editor)
|
||||||
|
|
||||||
|
TYPE_INT:
|
||||||
|
add_label(prop_name)
|
||||||
|
|
||||||
|
var editor:LineEditorInt = preload("res://addons/cyclops_level_builder/controls/resource_inspector/line_editor_int.tscn").instantiate()
|
||||||
|
editor.resource = target
|
||||||
|
editor.prop_name = prop_name
|
||||||
|
$GridContainer.add_child(editor)
|
||||||
|
|
||||||
|
TYPE_FLOAT:
|
||||||
|
add_label(prop_name)
|
||||||
|
|
||||||
|
var editor:LineEditorFloat = preload("res://addons/cyclops_level_builder/controls/resource_inspector/line_editor_float.tscn").instantiate()
|
||||||
|
editor.resource = target
|
||||||
|
editor.prop_name = prop_name
|
||||||
|
$GridContainer.add_child(editor)
|
||||||
|
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Called when the node enters the scene tree for the first time.
|
||||||
|
func _ready():
|
||||||
|
pass # Replace with function body.
|
||||||
|
|
||||||
|
|
||||||
|
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||||
|
func _process(delta):
|
||||||
|
pass
|
@ -0,0 +1,18 @@
|
|||||||
|
[gd_scene load_steps=2 format=3 uid="uid://c2484sv0ymy2e"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://addons/cyclops_level_builder/controls/resource_inspector/resource_inspector.gd" id="1_m3yhx"]
|
||||||
|
|
||||||
|
[node name="object_inspector" type="Control"]
|
||||||
|
layout_mode = 3
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
script = ExtResource("1_m3yhx")
|
||||||
|
|
||||||
|
[node name="GridContainer" type="GridContainer" parent="."]
|
||||||
|
layout_mode = 0
|
||||||
|
offset_right = 40.0
|
||||||
|
offset_bottom = 40.0
|
||||||
|
columns = 2
|
250
addons/cyclops_level_builder/cyclops_global_scene.gd
Normal file
@ -0,0 +1,250 @@
|
|||||||
|
# MIT License
|
||||||
|
#
|
||||||
|
# Copyright (c) 2023 Mark McKay
|
||||||
|
# https://github.com/blackears/cyclopsLevelBuilder
|
||||||
|
#
|
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
# of this software and associated documentation files (the "Software"), to deal
|
||||||
|
# in the Software without restriction, including without limitation the rights
|
||||||
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
# copies of the Software, and to permit persons to whom the Software is
|
||||||
|
# furnished to do so, subject to the following conditions:
|
||||||
|
#
|
||||||
|
# The above copyright notice and this permission notice shall be included in all
|
||||||
|
# copies or substantial portions of the Software.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
|
||||||
|
@tool
|
||||||
|
extends Node3D
|
||||||
|
class_name CyclopsGlobalScene
|
||||||
|
|
||||||
|
@export var selection_color:Color = Color(1, .5, .5, 1)
|
||||||
|
@export var default_material:Material = preload("res://addons/cyclops_level_builder/materials/grid.tres")
|
||||||
|
@export var tool_edit_active_material:Material = preload("res://addons/cyclops_level_builder/materials/tool_edit_active_material.tres")
|
||||||
|
@export var tool_edit_active_fill_material:Material = preload("res://addons/cyclops_level_builder/materials/tool_edit_active_fill_material.tres")
|
||||||
|
@export var tool_edit_selected_material:Material = preload("res://addons/cyclops_level_builder/materials/tool_edit_selected_material.tres")
|
||||||
|
@export var tool_edit_selected_fill_material:Material = preload("res://addons/cyclops_level_builder/materials/tool_edit_selected_fill_material.tres")
|
||||||
|
@export var tool_edit_unselected_material:Material = preload("res://addons/cyclops_level_builder/materials/tool_edit_unselected_material.tres")
|
||||||
|
@export var tool_object_active_material:Material = preload("res://addons/cyclops_level_builder/materials/tool_object_active_material.tres")
|
||||||
|
@export var tool_object_selected_material:Material = preload("res://addons/cyclops_level_builder/materials/tool_object_selected_material.tres")
|
||||||
|
#@export var outline_material:Material = preload("res://addons/cyclops_level_builder/materials/block_outline_material.tres")
|
||||||
|
|
||||||
|
@export var tool_material:Material = preload("res://addons/cyclops_level_builder/materials/tool_material.tres")
|
||||||
|
@export var outline_material:Material = preload("res://addons/cyclops_level_builder/materials/outline_material.tres")
|
||||||
|
#@export var tool_selected_material:Material
|
||||||
|
#@export var selected_material:Material
|
||||||
|
var tool_mesh:ImmediateMesh
|
||||||
|
#var vertex_size:float = .05
|
||||||
|
|
||||||
|
@export var grid_size:int = 0
|
||||||
|
|
||||||
|
var unit_sphere:GeometryMesh
|
||||||
|
var builder:CyclopsLevelBuilder
|
||||||
|
#
|
||||||
|
#enum DisplayMode { TEXTURED, WIRE }
|
||||||
|
#var display_mode:DisplayMode = DisplayMode.TEXTURED
|
||||||
|
|
||||||
|
# Called when the node enters the scene tree for the first time.
|
||||||
|
func _ready():
|
||||||
|
unit_sphere = MathGeometry.unit_sphere()
|
||||||
|
|
||||||
|
tool_mesh = ImmediateMesh.new()
|
||||||
|
$ToolInstance3D.mesh = tool_mesh
|
||||||
|
|
||||||
|
func draw_line(p0:Vector3, p1:Vector3, mat:Material):
|
||||||
|
|
||||||
|
# var mat:Material = tool_selected_material if selected else tool_material
|
||||||
|
|
||||||
|
tool_mesh.surface_begin(Mesh.PRIMITIVE_LINES, mat)
|
||||||
|
|
||||||
|
tool_mesh.surface_add_vertex(p0)
|
||||||
|
tool_mesh.surface_add_vertex(p1)
|
||||||
|
|
||||||
|
tool_mesh.surface_end()
|
||||||
|
|
||||||
|
func draw_loop(points:PackedVector3Array, closed:bool = true, mat:Material = null):
|
||||||
|
if points.is_empty():
|
||||||
|
return
|
||||||
|
|
||||||
|
tool_mesh.surface_begin(Mesh.PRIMITIVE_LINE_STRIP, mat)
|
||||||
|
|
||||||
|
for p in points:
|
||||||
|
tool_mesh.surface_add_vertex(p)
|
||||||
|
|
||||||
|
if closed:
|
||||||
|
tool_mesh.surface_add_vertex(points[0])
|
||||||
|
|
||||||
|
tool_mesh.surface_end()
|
||||||
|
|
||||||
|
|
||||||
|
func draw_prism(points:PackedVector3Array, extrude:Vector3, mat:Material = null):
|
||||||
|
for p in points:
|
||||||
|
draw_vertex(p)
|
||||||
|
draw_vertex(p + extrude)
|
||||||
|
|
||||||
|
#Bottom loop
|
||||||
|
tool_mesh.surface_begin(Mesh.PRIMITIVE_LINE_STRIP, mat)
|
||||||
|
|
||||||
|
for p in points:
|
||||||
|
tool_mesh.surface_add_vertex(p)
|
||||||
|
|
||||||
|
tool_mesh.surface_add_vertex(points[0])
|
||||||
|
|
||||||
|
tool_mesh.surface_end()
|
||||||
|
|
||||||
|
#Top loop
|
||||||
|
tool_mesh.surface_begin(Mesh.PRIMITIVE_LINE_STRIP, mat)
|
||||||
|
|
||||||
|
for p in points:
|
||||||
|
tool_mesh.surface_add_vertex(p + extrude)
|
||||||
|
|
||||||
|
tool_mesh.surface_add_vertex(points[0] + extrude)
|
||||||
|
|
||||||
|
tool_mesh.surface_end()
|
||||||
|
|
||||||
|
#Sides
|
||||||
|
tool_mesh.surface_begin(Mesh.PRIMITIVE_LINES, mat)
|
||||||
|
|
||||||
|
for p in points:
|
||||||
|
tool_mesh.surface_add_vertex(p)
|
||||||
|
tool_mesh.surface_add_vertex(p + extrude)
|
||||||
|
|
||||||
|
tool_mesh.surface_end()
|
||||||
|
|
||||||
|
#$ToolInstance3D.mesh = mesh
|
||||||
|
|
||||||
|
|
||||||
|
func draw_triangles(tri_points:PackedVector3Array, mat:Material = null):
|
||||||
|
tool_mesh.surface_begin(Mesh.PRIMITIVE_TRIANGLES, mat)
|
||||||
|
|
||||||
|
for p in tri_points:
|
||||||
|
tool_mesh.surface_add_vertex(p)
|
||||||
|
|
||||||
|
tool_mesh.surface_end()
|
||||||
|
|
||||||
|
func draw_rect(start:Vector3, end:Vector3, mat:Material = null):
|
||||||
|
|
||||||
|
var p0:Vector3 = start
|
||||||
|
var p2:Vector3 = end
|
||||||
|
var p1:Vector3 = Vector3(p0.x, p0.y, p2.z)
|
||||||
|
var p3:Vector3 = Vector3(p2.x, p0.y, p0.z)
|
||||||
|
|
||||||
|
draw_vertex(p0, mat)
|
||||||
|
draw_vertex(p1, mat)
|
||||||
|
draw_vertex(p2, mat)
|
||||||
|
draw_vertex(p3, mat)
|
||||||
|
|
||||||
|
tool_mesh.surface_begin(Mesh.PRIMITIVE_LINE_STRIP, mat)
|
||||||
|
|
||||||
|
tool_mesh.surface_add_vertex(p0)
|
||||||
|
tool_mesh.surface_add_vertex(p1)
|
||||||
|
tool_mesh.surface_add_vertex(p2)
|
||||||
|
tool_mesh.surface_add_vertex(p3)
|
||||||
|
tool_mesh.surface_add_vertex(p0)
|
||||||
|
|
||||||
|
tool_mesh.surface_end()
|
||||||
|
|
||||||
|
#$ToolInstance3D.mesh = tool_mesh
|
||||||
|
|
||||||
|
func clear_tool_mesh():
|
||||||
|
#tool_mesh = ImmediateMesh.new()
|
||||||
|
#$ToolInstance3D.mesh = tool_mesh
|
||||||
|
tool_mesh.clear_surfaces()
|
||||||
|
|
||||||
|
# Draws the bounding box for the points [p0, p1, p2]
|
||||||
|
func draw_cube(p0:Vector3, p1:Vector3, p2:Vector3, mat:Material = null):
|
||||||
|
# print ("draw_cube %s %s %s" % [p0, p1, p2])
|
||||||
|
|
||||||
|
var bounds:AABB = AABB(p0, Vector3.ZERO)
|
||||||
|
bounds = bounds.expand(p1)
|
||||||
|
bounds = bounds.expand(p2)
|
||||||
|
|
||||||
|
var p000:Vector3 = bounds.position
|
||||||
|
var p111:Vector3 = bounds.end
|
||||||
|
var p001:Vector3 = Vector3(p000.x, p000.y, p111.z)
|
||||||
|
var p010:Vector3 = Vector3(p000.x, p111.y, p000.z)
|
||||||
|
var p011:Vector3 = Vector3(p000.x, p111.y, p111.z)
|
||||||
|
var p100:Vector3 = Vector3(p111.x, p000.y, p000.z)
|
||||||
|
var p101:Vector3 = Vector3(p111.x, p000.y, p111.z)
|
||||||
|
var p110:Vector3 = Vector3(p111.x, p111.y, p000.z)
|
||||||
|
|
||||||
|
draw_vertex(p000, mat)
|
||||||
|
draw_vertex(p001, mat)
|
||||||
|
draw_vertex(p010, mat)
|
||||||
|
draw_vertex(p011, mat)
|
||||||
|
draw_vertex(p100, mat)
|
||||||
|
draw_vertex(p101, mat)
|
||||||
|
draw_vertex(p110, mat)
|
||||||
|
draw_vertex(p111, mat)
|
||||||
|
|
||||||
|
|
||||||
|
tool_mesh.surface_begin(Mesh.PRIMITIVE_LINES, mat)
|
||||||
|
|
||||||
|
tool_mesh.surface_add_vertex(p000)
|
||||||
|
tool_mesh.surface_add_vertex(p001)
|
||||||
|
tool_mesh.surface_add_vertex(p000)
|
||||||
|
tool_mesh.surface_add_vertex(p100)
|
||||||
|
tool_mesh.surface_add_vertex(p101)
|
||||||
|
tool_mesh.surface_add_vertex(p001)
|
||||||
|
tool_mesh.surface_add_vertex(p101)
|
||||||
|
tool_mesh.surface_add_vertex(p100)
|
||||||
|
|
||||||
|
tool_mesh.surface_add_vertex(p010)
|
||||||
|
tool_mesh.surface_add_vertex(p011)
|
||||||
|
tool_mesh.surface_add_vertex(p010)
|
||||||
|
tool_mesh.surface_add_vertex(p110)
|
||||||
|
tool_mesh.surface_add_vertex(p111)
|
||||||
|
tool_mesh.surface_add_vertex(p011)
|
||||||
|
tool_mesh.surface_add_vertex(p111)
|
||||||
|
tool_mesh.surface_add_vertex(p110)
|
||||||
|
|
||||||
|
tool_mesh.surface_add_vertex(p000)
|
||||||
|
tool_mesh.surface_add_vertex(p010)
|
||||||
|
tool_mesh.surface_add_vertex(p100)
|
||||||
|
tool_mesh.surface_add_vertex(p110)
|
||||||
|
tool_mesh.surface_add_vertex(p101)
|
||||||
|
tool_mesh.surface_add_vertex(p111)
|
||||||
|
tool_mesh.surface_add_vertex(p001)
|
||||||
|
tool_mesh.surface_add_vertex(p011)
|
||||||
|
|
||||||
|
tool_mesh.surface_end()
|
||||||
|
|
||||||
|
#$ToolInstance3D.mesh = mesh
|
||||||
|
|
||||||
|
func draw_points(points:PackedVector3Array, mat:Material = null):
|
||||||
|
for p in points:
|
||||||
|
draw_vertex(p, mat)
|
||||||
|
|
||||||
|
func draw_vertex(position:Vector3, mat:Material = null):
|
||||||
|
var xform:Transform3D = Transform3D(Basis.IDENTITY.scaled(Vector3.ONE * builder.handle_point_radius), position)
|
||||||
|
draw_sphere(xform, mat)
|
||||||
|
|
||||||
|
func draw_sphere(xform:Transform3D = Transform3D.IDENTITY, material:Material = null, segs_lat:int = 6, segs_long:int = 8):
|
||||||
|
unit_sphere.append_to_immediate_mesh(tool_mesh, material, xform)
|
||||||
|
|
||||||
|
|
||||||
|
func draw_selected_blocks(viewport_camera:Camera3D):
|
||||||
|
var global_scene:CyclopsGlobalScene = builder.get_node("/root/CyclopsAutoload")
|
||||||
|
#var mesh:ImmediateMesh = ImmediateMesh.new()
|
||||||
|
|
||||||
|
if builder.active_node is CyclopsBlocks:
|
||||||
|
var blocks_root:CyclopsBlocks = builder.active_node
|
||||||
|
for child in blocks_root.get_children():
|
||||||
|
if child is CyclopsConvexBlock:
|
||||||
|
var block:CyclopsConvexBlock = child
|
||||||
|
if block.selected:
|
||||||
|
block.append_mesh_outline(tool_mesh, viewport_camera, blocks_root.global_transform)
|
||||||
|
|
||||||
|
|
||||||
|
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||||
|
func _process(delta):
|
||||||
|
# if Engine.is_editor_hint():
|
||||||
|
# rebuild_mesh()
|
||||||
|
pass
|
17
addons/cyclops_level_builder/cyclops_global_scene.tscn
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
[gd_scene load_steps=4 format=3 uid="uid://4siqre3jhe80"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://addons/cyclops_level_builder/cyclops_global_scene.gd" id="1_nu1d3"]
|
||||||
|
|
||||||
|
[sub_resource type="PlaneMesh" id="PlaneMesh_sl0cw"]
|
||||||
|
|
||||||
|
[sub_resource type="ImmediateMesh" id="ImmediateMesh_ey6kk"]
|
||||||
|
|
||||||
|
[node name="CyclopsGlobals" type="Node3D"]
|
||||||
|
script = ExtResource("1_nu1d3")
|
||||||
|
|
||||||
|
[node name="ControlMesh" type="MeshInstance3D" parent="."]
|
||||||
|
visible = false
|
||||||
|
mesh = SubResource("PlaneMesh_sl0cw")
|
||||||
|
|
||||||
|
[node name="ToolInstance3D" type="MeshInstance3D" parent="."]
|
||||||
|
mesh = SubResource("ImmediateMesh_ey6kk")
|
225
addons/cyclops_level_builder/cyclops_level_builder.gd
Normal file
@ -0,0 +1,225 @@
|
|||||||
|
# MIT License
|
||||||
|
#
|
||||||
|
# Copyright (c) 2023 Mark McKay
|
||||||
|
# https://github.com/blackears/cyclopsLevelBuilder
|
||||||
|
#
|
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
# of this software and associated documentation files (the "Software"), to deal
|
||||||
|
# in the Software without restriction, including without limitation the rights
|
||||||
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
# copies of the Software, and to permit persons to whom the Software is
|
||||||
|
# furnished to do so, subject to the following conditions:
|
||||||
|
#
|
||||||
|
# The above copyright notice and this permission notice shall be included in all
|
||||||
|
# copies or substantial portions of the Software.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
|
||||||
|
@tool
|
||||||
|
extends EditorPlugin
|
||||||
|
class_name CyclopsLevelBuilder
|
||||||
|
|
||||||
|
signal active_node_changed
|
||||||
|
signal selection_changed
|
||||||
|
|
||||||
|
const AUTOLOAD_NAME = "CyclopsAutoload"
|
||||||
|
|
||||||
|
var material_dock:Control
|
||||||
|
var uv_editor_dock:Control
|
||||||
|
var tool_properties_dock:Control
|
||||||
|
#var sticky_toolbar:StickyToolbar
|
||||||
|
var editor_toolbar:EditorToolbar
|
||||||
|
var activated:bool = false
|
||||||
|
|
||||||
|
|
||||||
|
var block_create_distance:float = 20
|
||||||
|
var tool:CyclopsTool = null
|
||||||
|
var lock_uvs:bool = false
|
||||||
|
var tool_overlay_extrude:float = .01
|
||||||
|
|
||||||
|
var tool_uv_transform:Transform2D
|
||||||
|
var tool_material_path:String
|
||||||
|
|
||||||
|
var handle_point_radius:float = .05
|
||||||
|
var handle_screen_radius:float = 4
|
||||||
|
|
||||||
|
var drag_start_radius:float = 4
|
||||||
|
|
||||||
|
enum Mode { OBJECT, EDIT }
|
||||||
|
var mode:Mode = Mode.OBJECT
|
||||||
|
enum EditMode { VERTEX, EDGE, FACE }
|
||||||
|
var edit_mode:EditMode = EditMode.VERTEX
|
||||||
|
|
||||||
|
var display_mode:DisplayMode.Type = DisplayMode.Type.TEXTURED
|
||||||
|
|
||||||
|
#var _active_node:GeometryBrush
|
||||||
|
var active_node:CyclopsBlocks:
|
||||||
|
get:
|
||||||
|
return active_node
|
||||||
|
set(value):
|
||||||
|
if active_node != value:
|
||||||
|
active_node = value
|
||||||
|
active_node_changed.emit()
|
||||||
|
|
||||||
|
func get_selected_blocks()->Array[CyclopsConvexBlock]:
|
||||||
|
var result:Array[CyclopsConvexBlock]
|
||||||
|
|
||||||
|
if active_node:
|
||||||
|
for child in active_node.get_children():
|
||||||
|
if child is CyclopsConvexBlock:
|
||||||
|
var block:CyclopsConvexBlock = child
|
||||||
|
if child.selected:
|
||||||
|
result.append(child)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
func _get_plugin_name()->String:
|
||||||
|
return "CyclopsLevelBuilder"
|
||||||
|
|
||||||
|
func _get_plugin_icon()->Texture2D:
|
||||||
|
return preload("res://addons/cyclops_level_builder/art/cyclops.svg")
|
||||||
|
|
||||||
|
func _enter_tree():
|
||||||
|
add_custom_type("CyclopsBlocks", "Node3D", preload("nodes/cyclops_blocks.gd"), preload("nodes/cyclops_blocks_icon.png"))
|
||||||
|
add_custom_type("CyclopsConvexBlock", "Node", preload("nodes/cyclops_convex_block.gd"), preload("nodes/cyclops_blocks_icon.png"))
|
||||||
|
add_custom_type("CyclopsConvexBlockBody", "Node", preload("nodes/cyclops_convex_block_body.gd"), preload("nodes/cyclops_blocks_icon.png"))
|
||||||
|
|
||||||
|
add_autoload_singleton(AUTOLOAD_NAME, "res://addons/cyclops_level_builder/cyclops_global_scene.tscn")
|
||||||
|
|
||||||
|
material_dock = preload("res://addons/cyclops_level_builder/docks/material_palette/material_palette_viewport.tscn").instantiate()
|
||||||
|
material_dock.builder = self
|
||||||
|
|
||||||
|
uv_editor_dock = preload("res://addons/cyclops_level_builder/docks/uv_editor/uv_editor_viewport.tscn").instantiate()
|
||||||
|
uv_editor_dock.builder = self
|
||||||
|
|
||||||
|
tool_properties_dock = preload("res://addons/cyclops_level_builder/docks/tool_properties/tool_properties_dock.tscn").instantiate()
|
||||||
|
tool_properties_dock.builder = self
|
||||||
|
|
||||||
|
editor_toolbar = preload("menu/editor_toolbar.tscn").instantiate()
|
||||||
|
editor_toolbar.editor_plugin = self
|
||||||
|
|
||||||
|
# sticky_toolbar = preload("menu/sticky_toolbar.tscn").instantiate()
|
||||||
|
# sticky_toolbar.plugin = self
|
||||||
|
# add_control_to_container(EditorPlugin.CONTAINER_SPATIAL_EDITOR_MENU, sticky_toolbar)
|
||||||
|
|
||||||
|
var editor:EditorInterface = get_editor_interface()
|
||||||
|
var selection:EditorSelection = editor.get_selection()
|
||||||
|
selection.selection_changed.connect(on_selection_changed)
|
||||||
|
|
||||||
|
update_activation()
|
||||||
|
|
||||||
|
|
||||||
|
#Wait until everything is loaded
|
||||||
|
await get_tree().process_frame
|
||||||
|
var global_scene:CyclopsGlobalScene = get_node("/root/CyclopsAutoload")
|
||||||
|
global_scene.builder = self
|
||||||
|
|
||||||
|
switch_to_tool(ToolBlock.new())
|
||||||
|
|
||||||
|
func find_blocks_root(node:Node)->CyclopsBlocks:
|
||||||
|
if node is CyclopsBlocks:
|
||||||
|
return node
|
||||||
|
if node is CyclopsConvexBlock:
|
||||||
|
return find_blocks_root(node.get_parent())
|
||||||
|
return null
|
||||||
|
|
||||||
|
func update_activation():
|
||||||
|
var editor:EditorInterface = get_editor_interface()
|
||||||
|
var selection:EditorSelection = editor.get_selection()
|
||||||
|
var nodes:Array[Node] = selection.get_selected_nodes()
|
||||||
|
if !nodes.is_empty():
|
||||||
|
var node:Node = nodes[0]
|
||||||
|
|
||||||
|
var blocks_root:CyclopsBlocks = find_blocks_root(node)
|
||||||
|
|
||||||
|
if blocks_root:
|
||||||
|
active_node = blocks_root
|
||||||
|
if !activated:
|
||||||
|
add_control_to_container(EditorPlugin.CONTAINER_SPATIAL_EDITOR_MENU, editor_toolbar)
|
||||||
|
add_control_to_dock(DOCK_SLOT_RIGHT_BL, material_dock)
|
||||||
|
add_control_to_dock(DOCK_SLOT_RIGHT_BL, uv_editor_dock)
|
||||||
|
add_control_to_dock(DOCK_SLOT_RIGHT_BL, tool_properties_dock)
|
||||||
|
activated = true
|
||||||
|
else:
|
||||||
|
if activated:
|
||||||
|
remove_control_from_container(EditorPlugin.CONTAINER_SPATIAL_EDITOR_MENU, editor_toolbar)
|
||||||
|
remove_control_from_docks(material_dock)
|
||||||
|
remove_control_from_docks(uv_editor_dock)
|
||||||
|
remove_control_from_docks(tool_properties_dock)
|
||||||
|
activated = false
|
||||||
|
else:
|
||||||
|
active_node = null
|
||||||
|
|
||||||
|
func on_selection_changed():
|
||||||
|
update_activation()
|
||||||
|
|
||||||
|
func _exit_tree():
|
||||||
|
# Clean-up of the plugin goes here.
|
||||||
|
remove_autoload_singleton(AUTOLOAD_NAME)
|
||||||
|
|
||||||
|
remove_custom_type("CyclopsBlocks")
|
||||||
|
remove_custom_type("CyclopsConvexBlock")
|
||||||
|
remove_custom_type("CyclopsConvexBlockBody")
|
||||||
|
|
||||||
|
# remove_control_from_container(EditorPlugin.CONTAINER_SPATIAL_EDITOR_MENU, sticky_toolbar)
|
||||||
|
|
||||||
|
if activated:
|
||||||
|
remove_control_from_docks(material_dock)
|
||||||
|
remove_control_from_docks(uv_editor_dock)
|
||||||
|
remove_control_from_docks(tool_properties_dock)
|
||||||
|
remove_control_from_container(EditorPlugin.CONTAINER_SPATIAL_EDITOR_MENU, editor_toolbar)
|
||||||
|
|
||||||
|
material_dock.queue_free()
|
||||||
|
uv_editor_dock.queue_free()
|
||||||
|
tool_properties_dock.queue_free()
|
||||||
|
editor_toolbar.queue_free()
|
||||||
|
|
||||||
|
func _handles(object:Object):
|
||||||
|
return object is CyclopsBlocks or object is CyclopsConvexBlock
|
||||||
|
|
||||||
|
func _forward_3d_draw_over_viewport(viewport_control:Control):
|
||||||
|
#Draw on top of viweport here
|
||||||
|
pass
|
||||||
|
|
||||||
|
func _forward_3d_gui_input(viewport_camera:Camera3D, event:InputEvent):
|
||||||
|
#print("plugin: " + event.as_text())
|
||||||
|
|
||||||
|
if tool:
|
||||||
|
var result:bool = tool._gui_input(viewport_camera, event)
|
||||||
|
tool._draw_tool(viewport_camera)
|
||||||
|
return EditorPlugin.AFTER_GUI_INPUT_STOP if result else EditorPlugin.AFTER_GUI_INPUT_PASS
|
||||||
|
|
||||||
|
return EditorPlugin.AFTER_GUI_INPUT_PASS
|
||||||
|
|
||||||
|
func _get_state()->Dictionary:
|
||||||
|
var state:Dictionary = {}
|
||||||
|
material_dock.save_state(state)
|
||||||
|
uv_editor_dock.save_state(state)
|
||||||
|
tool_properties_dock.save_state(state)
|
||||||
|
return state
|
||||||
|
|
||||||
|
func _set_state(state):
|
||||||
|
material_dock.load_state(state)
|
||||||
|
uv_editor_dock.load_state(state)
|
||||||
|
tool_properties_dock.load_state(state)
|
||||||
|
|
||||||
|
func switch_to_tool(_tool:CyclopsTool):
|
||||||
|
if tool:
|
||||||
|
tool._deactivate()
|
||||||
|
|
||||||
|
tool = _tool
|
||||||
|
|
||||||
|
if tool:
|
||||||
|
tool._activate(self)
|
||||||
|
var control:Control = tool._get_tool_properties_editor()
|
||||||
|
tool_properties_dock.set_editor(control)
|
||||||
|
|
||||||
|
func get_global_scene()->CyclopsGlobalScene:
|
||||||
|
var scene:CyclopsGlobalScene = get_node("/root/CyclopsAutoload")
|
||||||
|
return scene
|
54
addons/cyclops_level_builder/doc/Text
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
import bpy
|
||||||
|
import mathutils
|
||||||
|
|
||||||
|
def draw_plane(hessian):
|
||||||
|
# Extract the plane coefficients from the Hessian form
|
||||||
|
a, b, c, d = hessian
|
||||||
|
|
||||||
|
# Calculate the normal vector of the plane
|
||||||
|
normal = mathutils.Vector((a, b, c))
|
||||||
|
|
||||||
|
# Calculate the point at the center of the plane
|
||||||
|
point = normal * d
|
||||||
|
|
||||||
|
# Calculate a vector perpendicular to the normal
|
||||||
|
if abs(normal.z) < 1e-6:
|
||||||
|
tangent = mathutils.Vector((0, 0, 1))
|
||||||
|
else:
|
||||||
|
tangent = mathutils.Vector((0, 1, -normal.y/normal.z)).normalized()
|
||||||
|
|
||||||
|
binorm = tangent.cross(normal)
|
||||||
|
|
||||||
|
# Create a new mesh object for the point, dot, and line
|
||||||
|
mesh = bpy.data.meshes.new(name="Plane Center and Normal")
|
||||||
|
obj = bpy.data.objects.new(name="Plane Object", object_data=mesh)
|
||||||
|
|
||||||
|
# Create the vertices for the point, dot, and line
|
||||||
|
vertices = [
|
||||||
|
point + tangent * 0.1,
|
||||||
|
point,
|
||||||
|
point + normal,
|
||||||
|
point + binorm * 0.1,
|
||||||
|
]
|
||||||
|
|
||||||
|
# Create the edges for the line
|
||||||
|
edges = [
|
||||||
|
(0, 1), # Edge from point to start of line
|
||||||
|
(1, 2) , # Edge for the line
|
||||||
|
(1, 3)
|
||||||
|
]
|
||||||
|
|
||||||
|
# Create the mesh data for the point, dot, and line
|
||||||
|
mesh.from_pydata(vertices, edges, [])
|
||||||
|
|
||||||
|
# Add the object to the scene
|
||||||
|
bpy.context.scene.collection.objects.link(obj)
|
||||||
|
|
||||||
|
planes = [(-0.96225, 0.192449, 0.192451, -4.04145), (-0.404079, 0.888975, 0.21551, -3.85222), (-0.703526, -0.502519, -0.502519, -2.31159), (-0.123091, -0.86164, 0.492366, -2.33874), (-0.211079, -0.492518, 0.844317, -3.02547), (0.442326, 0.147442, 0.884652, -2.50651), (0.928279, -0.206284, 0.309426, -1.13456), (0.973329, -0.162221, 0.162222, -1.29777), (0.117041, 0.702247, -0.702247, -3.04307), (-9.6656e-08, 1.35319e-07, -1, -2)]
|
||||||
|
#planes = [(0, 0, -1, -12), (0, 1, 0, 9)]
|
||||||
|
|
||||||
|
for p in planes:
|
||||||
|
draw_plane(p)
|
||||||
|
|
||||||
|
#draw_plane((0, 1, 0, 11))
|
||||||
|
|
34
addons/cyclops_level_builder/doc/create_plane_objects.py
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import bpy
|
||||||
|
import mathutils
|
||||||
|
|
||||||
|
def create_plane_on_plane(p0):
|
||||||
|
# Extract the normal and distance from the Hessian form of the plane
|
||||||
|
normal = mathutils.Vector(p0[:3])
|
||||||
|
distance = p0[3]
|
||||||
|
|
||||||
|
# Calculate the center of the plane
|
||||||
|
center = normal * distance
|
||||||
|
|
||||||
|
# Create a new plane object
|
||||||
|
bpy.ops.mesh.primitive_plane_add()
|
||||||
|
obj0 = bpy.context.active_object
|
||||||
|
|
||||||
|
# Set the plane's origin to the center of the plane
|
||||||
|
obj0.location = center
|
||||||
|
|
||||||
|
# Calculate the rotation needed to align the z-axis with the plane normal
|
||||||
|
z_axis = mathutils.Vector((0, 0, 1))
|
||||||
|
angle = normal.angle(z_axis, 0)
|
||||||
|
axis = z_axis.cross(normal)
|
||||||
|
euler = mathutils.Matrix.Rotation(angle, 4, axis).to_euler()
|
||||||
|
obj0.rotation_euler = euler
|
||||||
|
|
||||||
|
|
||||||
|
return obj0
|
||||||
|
|
||||||
|
|
||||||
|
planes = [(0.274721, 9.82474e-08, -0.961524, -8.10427), (-1, -3.57626e-07, -2.38418e-07, -2), (0.904534, 0.301512, 0.301512, -1.50755), (0, 1, 0, 3), (5.08628e-06, -1, -2.75509e-06, -7.00003), (0.727606, -0.485071, -0.485072, -8.48875), (0.465341, -0.426562, -0.775566, -9.03536), (-0.369799, -0.0924517, 0.924501, 1.75654), (3.19872e-07, -0.447214, 0.894427, -0.447216), (-0.957704, -0.239427, 0.159618, -2.15484)]
|
||||||
|
for p in planes:
|
||||||
|
create_plane_on_plane(p)
|
||||||
|
|
||||||
|
#create_plane_on_plane((0.274721, 9.82474e-08, -0.961524, -8.10427))
|
35
addons/cyclops_level_builder/doc/draw_plane.py
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import bpy
|
||||||
|
import mathutils
|
||||||
|
|
||||||
|
def draw_plane(hessian):
|
||||||
|
# Extract the plane coefficients from the Hessian form
|
||||||
|
a, b, c, d = hessian
|
||||||
|
|
||||||
|
# Calculate the normal vector of the plane
|
||||||
|
normal = mathutils.Vector((a, b, c)).normalized()
|
||||||
|
|
||||||
|
# Calculate the point at the center of the plane
|
||||||
|
point = normal * d
|
||||||
|
|
||||||
|
# Create a new mesh object for the point and line
|
||||||
|
mesh = bpy.data.meshes.new(name="Plane Center and Normal")
|
||||||
|
obj = bpy.data.objects.new(name="Plane Object", object_data=mesh)
|
||||||
|
|
||||||
|
# Create the vertices for the point and line
|
||||||
|
vertices = [
|
||||||
|
point,
|
||||||
|
point + normal
|
||||||
|
]
|
||||||
|
|
||||||
|
# Create the edges for the line
|
||||||
|
edges = [
|
||||||
|
(0, 1)
|
||||||
|
]
|
||||||
|
|
||||||
|
# Create the mesh data for the point and line
|
||||||
|
mesh.from_pydata(vertices, edges, [])
|
||||||
|
|
||||||
|
# Add the object to the scene
|
||||||
|
bpy.context.scene.collection.objects.link(obj)
|
||||||
|
|
||||||
|
draw_plane((0, 1, 0, 11))
|
19
addons/cyclops_level_builder/doc/draw_points_in_blender.py
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import bpy
|
||||||
|
import bmesh
|
||||||
|
|
||||||
|
# Define the list of points for the polygon
|
||||||
|
points = [(0,0,0), (1,0,0), (1,1,0), (0,1,0)]
|
||||||
|
|
||||||
|
# Create a new mesh and add a new object to the scene
|
||||||
|
mesh = bpy.data.meshes.new("Polygon")
|
||||||
|
obj = bpy.data.objects.new("Polygon", mesh)
|
||||||
|
bpy.context.collection.objects.link(obj)
|
||||||
|
|
||||||
|
# Create a new bmesh and add vertices to it
|
||||||
|
bm = bmesh.new()
|
||||||
|
for point in points:
|
||||||
|
bm.verts.new(point)
|
||||||
|
|
||||||
|
# Add the vertices to the mesh
|
||||||
|
bm.to_mesh(mesh)
|
||||||
|
bm.free()
|
36
addons/cyclops_level_builder/doc/make_polygons.py
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import bpy
|
||||||
|
import bmesh
|
||||||
|
|
||||||
|
# Define the list of faces, where each sublist represents a face
|
||||||
|
#faces = [
|
||||||
|
# [(0,0,0), (1,0,0), (1,1,0), (0,1,0)],
|
||||||
|
# [(1,0,0), (2,0,0), (2,1,0), (1,1,0)]
|
||||||
|
#]
|
||||||
|
faces = [
|
||||||
|
[(-2.999999, 6, -0.999997), (-2.999999, 9.999996, -0.999997), (-2.999999, 9.999996, 2.999999), (-2.999999, 6, 2.999999)],
|
||||||
|
[(-2.999999, 9.999996, -0.999997), (-2.999999, 6, -0.999997), (0.999997, 6, -0.999997), (0.999997, 9.999996, -0.999997)],
|
||||||
|
[(-2.999999, 6, -0.999997), (-2.999999, 6, 2.999999), (-0.999997, 6, 5), (2.999998, 6, 1.000004), (0.999997, 6, -0.999997)],
|
||||||
|
[(-2.999999, 9.999996, -0.999997), (0.999997, 9.999996, -0.999997), (1.999999, 9.999996, 0.000005), (-1.999997, 9.999996, 4), (-2.999999, 9.999996, 2.999999)],
|
||||||
|
[(-0.999997, 6, 5), (-2.999999, 6, 2.999999), (-2.999999, 9.999996, 2.999999), (-1.999997, 9.999996, 4), (-0.999997, 7.999996, 5)],
|
||||||
|
[(0.999997, 9.999996, -0.999997), (0.999997, 6, -0.999997), (2.999999, 6, 1.000004), (2.999999, 7.999996, 1.000004), (1.999998, 9.999996, 0.000004)],
|
||||||
|
[(-1.999997, 9.999996, 4), (1.999999, 9.999996, 0.000005), (2.999998, 7.999997, 1.000004), (-0.999997, 7.999997, 5)]
|
||||||
|
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
# Create a new mesh and add a new object to the scene
|
||||||
|
mesh = bpy.data.meshes.new("Polygon")
|
||||||
|
obj = bpy.data.objects.new("Polygon", mesh)
|
||||||
|
bpy.context.collection.objects.link(obj)
|
||||||
|
|
||||||
|
# Create a new bmesh and add vertices and faces to it
|
||||||
|
bm = bmesh.new()
|
||||||
|
for face_verts in faces:
|
||||||
|
# Add vertices for the face
|
||||||
|
verts = [bm.verts.new(v) for v in face_verts]
|
||||||
|
# Add a new face between the vertices
|
||||||
|
bm.faces.new(verts)
|
||||||
|
|
||||||
|
# Update the mesh and free the bmesh
|
||||||
|
bm.to_mesh(mesh)
|
||||||
|
bm.free()
|
@ -0,0 +1,56 @@
|
|||||||
|
# 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 CommandMaterialDockAddMaterials
|
||||||
|
extends CyclopsCommand
|
||||||
|
|
||||||
|
#Public
|
||||||
|
var res_path_list:Array[String]
|
||||||
|
|
||||||
|
#Private
|
||||||
|
var old_res_path_list:Array[String]
|
||||||
|
|
||||||
|
|
||||||
|
func _init():
|
||||||
|
command_name = "Add materials"
|
||||||
|
|
||||||
|
func do_it():
|
||||||
|
# print("Add Materials do_it")
|
||||||
|
var mat_dock:MaterialPaletteViewport = builder.material_dock
|
||||||
|
old_res_path_list = mat_dock.material_list.duplicate()
|
||||||
|
|
||||||
|
# print("old mat list %s" % str(old_res_path_list))
|
||||||
|
|
||||||
|
var new_list:Array[String] = old_res_path_list.duplicate()
|
||||||
|
for mat in res_path_list:
|
||||||
|
if !new_list.has(mat):
|
||||||
|
new_list.append(mat)
|
||||||
|
|
||||||
|
# print("new mat list %s" % str(new_list))
|
||||||
|
|
||||||
|
mat_dock.set_materials(new_list)
|
||||||
|
|
||||||
|
func undo_it():
|
||||||
|
var mat_dock:MaterialPaletteViewport = builder.material_dock
|
||||||
|
mat_dock.set_materials(old_res_path_list)
|
@ -0,0 +1,52 @@
|
|||||||
|
# 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 CommandMaterialDockRemoveMaterials
|
||||||
|
extends CyclopsCommand
|
||||||
|
|
||||||
|
#Public
|
||||||
|
var res_path_list:Array[String]
|
||||||
|
|
||||||
|
#Private
|
||||||
|
var old_res_path_list:Array[String]
|
||||||
|
|
||||||
|
|
||||||
|
func _init():
|
||||||
|
command_name = "Remove materials"
|
||||||
|
|
||||||
|
func do_it():
|
||||||
|
# print("Remove Materials do_it")
|
||||||
|
|
||||||
|
var mat_dock:MaterialPaletteViewport = builder.material_dock
|
||||||
|
old_res_path_list = mat_dock.material_list.duplicate()
|
||||||
|
|
||||||
|
var new_list:Array[String] = old_res_path_list.duplicate()
|
||||||
|
for mat in res_path_list:
|
||||||
|
var idx:int = new_list.find(mat)
|
||||||
|
new_list.remove_at(idx)
|
||||||
|
mat_dock.set_materials(new_list)
|
||||||
|
|
||||||
|
func undo_it():
|
||||||
|
var mat_dock:MaterialPaletteViewport = builder.material_dock
|
||||||
|
mat_dock.set_materials(old_res_path_list)
|