initial commit

This commit is contained in:
Lera Elvoé 2023-05-24 00:27:34 +03:00
commit 11ee2c7949
Signed by: yagich
SSH Key Fingerprint: SHA256:6xjGb6uA7lAVcULa7byPEN//rQ0wPoG+UzYVMfZnbvc
174 changed files with 13452 additions and 0 deletions

2
.gitattributes vendored Normal file
View File

@ -0,0 +1,2 @@
# Normalize EOL for all files that Git considers text files.
* text=auto eol=lf

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
# Godot 4+ specific ignores
.godot/

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View 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)

View 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 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)

View 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 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)

View 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)

View 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 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)

View 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 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)

View 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)

View 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 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)

View 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 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)

View 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 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)

View 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)

View File

@ -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())

View 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

Binary file not shown.

View 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

View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 369 B

View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 433 B

View 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

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 258 B

View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 272 B

View 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

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 588 B

View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 643 B

View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View 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

Binary file not shown.

View 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

Binary file not shown.

Binary file not shown.

View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 405 B

View File

@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 411 B

View File

@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 416 B

View File

@ -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

View 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()")

View 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()

View 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()")

View 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()

View 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

View 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()

View 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()

View File

@ -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

View 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()

View 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)

View 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

View 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)

View 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

View 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

View 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()

View 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()

View 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()

View 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()

View 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

View 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()

View 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

View File

@ -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)

View 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

View 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)

View 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"]

View File

@ -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)

View File

@ -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"]

View File

@ -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)

View File

@ -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"]

View File

@ -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)

View File

@ -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"]

View File

@ -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

View File

@ -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

View 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

View 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")

View 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

View 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))

View 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))

View 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))

View 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()

View 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()

View File

@ -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)

View 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 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)

Some files were not shown because too many files have changed in this diff Show More