Compare commits

..

No commits in common. "2a6038025887dc2066446471e2f325b35edc22eb" and "9fccf9891748e7ad355349c3e7d1b91533d98a5a" have entirely different histories.

146 changed files with 11 additions and 12256 deletions

View File

@ -1,261 +0,0 @@
{
"connections": [
{
"from": "colorize",
"from_port": 0,
"to": "Material",
"to_port": 0
},
{
"from": "skewed_uneven_bricks_2",
"from_port": 0,
"to": "make_tileable_square",
"to_port": 0
},
{
"from": "make_tileable_square",
"from_port": 0,
"to": "colorize",
"to_port": 0
},
{
"from": "fbm3",
"from_port": 0,
"to": "make_tileable_square_2",
"to_port": 0
},
{
"from": "make_tileable_square_2",
"from_port": 0,
"to": "math",
"to_port": 1
},
{
"from": "colorize",
"from_port": 0,
"to": "colorize_2",
"to_port": 0
},
{
"from": "colorize_2",
"from_port": 0,
"to": "math",
"to_port": 0
},
{
"from": "math",
"from_port": 0,
"to": "invert",
"to_port": 0
},
{
"from": "invert",
"from_port": 0,
"to": "Material",
"to_port": 2
}
],
"label": "Graph",
"longdesc": "",
"name": "_Node_799",
"node_position": {
"x": 0.0,
"y": 0.0
},
"nodes": [
{
"export_last_target": "Godot/Godot 4 Standard",
"export_paths": {
"Blender": "D:/Programms/Development/Game-Engines/Godot/Godot 4/Projects/MagicNStuff/asset_src/models/electrics/hologram_projector_glass",
"Godot/Godot 4 Standard": "D:/Programms/Development/Game-Engines/Godot/Godot 4/Projects/MagicNStuff/source/src/gameplay/props/electrics/hologram_projector/model/glass"
},
"name": "Material",
"node_position": {
"x": 1158.208984375,
"y": -289.662231445312
},
"parameters": {
"albedo_color": {
"a": 1.0,
"b": 1.0,
"g": 1.0,
"r": 1.0,
"type": "Color"
},
"ao": 1.0,
"depth_scale": 0.5,
"emission_energy": 1.0,
"flags_transparent": false,
"metallic": 1.0,
"normal": 1.0,
"roughness": 0.7,
"size": 8.0,
"sss": 1.0
},
"seed_int": 0,
"type": "material"
},
{
"name": "skewed_uneven_bricks_2",
"node_position": {
"x": -397.5,
"y": -289.0
},
"parameters": {
"bevel": 0.0,
"columns": 6.0,
"corner": 0.3,
"mortar": 0.04,
"randomness": 0.0,
"round": 0.06,
"rows": 6.0
},
"seed_int": 0,
"type": "skewed_uneven_bricks"
},
{
"name": "colorize",
"node_position": {
"x": 230.500015258789,
"y": -271.399993896484
},
"parameters": {
"gradient": {
"interpolation": 1,
"points": [
{
"a": 1.0,
"b": 0.30078125,
"g": 0.30078125,
"pos": 0.0505725190839695,
"r": 0.30078125
},
{
"a": 1.0,
"b": 0.06640625,
"g": 0.06640625,
"pos": 0.445610687022901,
"r": 0.06640625
}
],
"type": "Gradient"
}
},
"seed_int": 0,
"type": "colorize"
},
{
"name": "fbm3",
"node_position": {
"x": 68.6030349731445,
"y": -5.20602083206177
},
"parameters": {
"folds": 0.0,
"iterations": 5.0,
"noise": 1.0,
"offset": 0.0,
"persistence": 0.5,
"scale_x": 16.0,
"scale_y": 13.0
},
"seed_int": 0,
"type": "fbm3"
},
{
"name": "make_tileable_square",
"node_position": {
"x": -94.5,
"y": -234.0
},
"parameters": {
"fw": 0.2
},
"seed_int": 0,
"type": "make_tileable_square"
},
{
"name": "math",
"node_position": {
"x": 639.997985839844,
"y": -80.1040115356445
},
"parameters": {
"clamp": false,
"default_in1": 0.0,
"default_in2": 0.0,
"op": 3.0
},
"seed_int": 0,
"type": "math"
},
{
"name": "make_tileable_square_2",
"node_position": {
"x": 361.857055664062,
"y": 11.725022315979
},
"parameters": {
"fw": 0.47
},
"seed_int": 0,
"type": "make_tileable_square"
},
{
"name": "colorize_2",
"node_position": {
"x": 367.584899902344,
"y": -176.591888427734
},
"parameters": {
"gradient": {
"interpolation": 0,
"points": [
{
"a": 1.0,
"b": 0.48046875,
"g": 0.48046875,
"pos": 0,
"r": 0.48046875
},
{
"a": 1.0,
"b": 0.48046875,
"g": 0.48046875,
"pos": 0.173070560815243,
"r": 0.48046875
},
{
"a": 1.0,
"b": 0.13671875,
"g": 0.13671875,
"pos": 0.173090560815243,
"r": 0.13671875
}
],
"type": "Gradient"
}
},
"seed_int": 0,
"type": "colorize"
},
{
"name": "invert",
"node_position": {
"x": 925.055053710938,
"y": -112.261871337891
},
"parameters": {
},
"seed_int": 0,
"type": "invert"
}
],
"parameters": {
},
"seed_int": 0,
"shortdesc": "",
"type": "graph"
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -1,235 +0,0 @@
{
"connections": [
{
"from": "skewed_uneven_bricks_2",
"from_port": 0,
"to": "make_tileable_square",
"to_port": 0
},
{
"from": "make_tileable_square",
"from_port": 0,
"to": "colorize",
"to_port": 0
},
{
"from": "colorize",
"from_port": 0,
"to": "greyscale",
"to_port": 0
},
{
"from": "greyscale",
"from_port": 0,
"to": "colorize_2",
"to_port": 0
},
{
"from": "colorize_2",
"from_port": 0,
"to": "Material",
"to_port": 0
},
{
"from": "colorize_2",
"from_port": 0,
"to": "colorize_3",
"to_port": 0
},
{
"from": "colorize_3",
"from_port": 0,
"to": "Material",
"to_port": 3
}
],
"label": "Graph",
"longdesc": "",
"name": "_Node_799",
"node_position": {
"x": 0.0,
"y": 0.0
},
"nodes": [
{
"export_last_target": "Godot/Godot 4 Standard",
"export_paths": {
"Blender": "D:/Programms/Development/Game-Engines/Godot/Godot 4/Projects/MagicNStuff/asset_src/models/electrics/hologram_projector_glass",
"Godot/Godot 4 Standard": "D:/Programms/Development/Game-Engines/Godot/Godot 4/Projects/MagicNStuff/source/src/gameplay/props/electrics/hologram_projector/model/glass_active"
},
"name": "Material",
"node_position": {
"x": 1588.208984375,
"y": -315.662231445312
},
"parameters": {
"albedo_color": {
"a": 1.0,
"b": 1.0,
"g": 1.0,
"r": 1.0,
"type": "Color"
},
"ao": 1.0,
"depth_scale": 0.5,
"emission_energy": 1.0,
"flags_transparent": false,
"metallic": 1.0,
"normal": 1.0,
"roughness": 0.7,
"size": 8.0,
"sss": 1.0
},
"seed_int": 0,
"type": "material"
},
{
"name": "skewed_uneven_bricks_2",
"node_position": {
"x": -397.5,
"y": -289.0
},
"parameters": {
"bevel": 0.0,
"columns": 6.0,
"corner": 0.3,
"mortar": 0.04,
"randomness": 0.0,
"round": 0.06,
"rows": 6.0
},
"seed_int": 0,
"type": "skewed_uneven_bricks"
},
{
"name": "colorize",
"node_position": {
"x": 230.500015258789,
"y": -271.399993896484
},
"parameters": {
"gradient": {
"interpolation": 1,
"points": [
{
"a": 1.0,
"b": 0.30078125,
"g": 0.30078125,
"pos": 0.0505725190839695,
"r": 0.30078125
},
{
"a": 1.0,
"b": 0.06640625,
"g": 0.06640625,
"pos": 0.445610687022901,
"r": 0.06640625
}
],
"type": "Gradient"
}
},
"seed_int": 0,
"type": "colorize"
},
{
"name": "make_tileable_square",
"node_position": {
"x": -94.5,
"y": -234.0
},
"parameters": {
"fw": 0.2
},
"seed_int": 0,
"type": "make_tileable_square"
},
{
"name": "greyscale",
"node_position": {
"x": 787.90380859375,
"y": -288.896728515625
},
"parameters": {
"mode": 2.0
},
"seed_int": 0,
"type": "greyscale"
},
{
"name": "colorize_2",
"node_position": {
"x": 1020.0,
"y": -320.0
},
"parameters": {
"gradient": {
"interpolation": 1,
"points": [
{
"a": 1.0,
"b": 1.0,
"g": 0.765625,
"pos": 0.0,
"r": 0.375
},
{
"a": 1.0,
"b": 0.0,
"g": 0.0,
"pos": 1.0,
"r": 0.0
}
],
"type": "Gradient"
}
},
"seed_int": 0,
"type": "colorize"
},
{
"name": "colorize_3",
"node_position": {
"x": 1206.23718261719,
"y": -251.841186523438
},
"parameters": {
"gradient": {
"interpolation": 0,
"points": [
{
"a": 1.0,
"b": 0.0,
"g": 0.0,
"pos": 0,
"r": 0.0
},
{
"a": 1.0,
"b": 0.0,
"g": 0.0,
"pos": 0.611631221374046,
"r": 0.0
},
{
"a": 1.0,
"b": 1.0,
"g": 0.765625,
"pos": 0.611651221374046,
"r": 0.375
}
],
"type": "Gradient"
}
},
"seed_int": 0,
"type": "colorize"
}
],
"parameters": {
},
"seed_int": 0,
"shortdesc": "",
"type": "graph"
}

View File

@ -1,24 +0,0 @@
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
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 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.
For more information, please refer to <https://unlicense.org>

View File

@ -1,52 +0,0 @@
# Stairs Character 3D
A simple class based on Godot's default CharacterBody3D with very simple stair stepping ability.
Just call "move_and_stair_step()" instead of "move_and_slide()".
Only tested with cylinder colliders. Works best with "0.01" collider margin.
There are a couple signals you can connect to:
- on_stair_step (any step, up or down)
- on_stair_step_down
- on_stair_step_up
Example usage:
```gdscript
extends StairsCharacter3D
const SPEED = 5.0
const JUMP_VELOCITY = 4.5
# Get the gravity from the project settings to be synced with RigidBody nodes.
var gravity: float = ProjectSettings.get_setting("physics/3d/default_gravity")
func _physics_process(delta: float) -> void:
# Add the gravity.
if not is_on_floor():
velocity.y -= gravity * delta
# Handle jump.
if Input.is_action_just_pressed("ui_accept") and is_on_floor():
velocity.y = JUMP_VELOCITY
# Get the input direction and handle the movement/deceleration.
# As good practice, you should replace UI actions with custom gameplay actions.
var input_dir := Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")
var direction := (transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized()
if direction:
velocity.x = direction.x * SPEED
velocity.z = direction.z * SPEED
else:
velocity.x = move_toward(velocity.x, 0, SPEED)
velocity.z = move_toward(velocity.z, 0, SPEED)
# call move_and_stair_step instead of default move_and_slide
move_and_stair_step()
```
# Note
This plugin is basically just [Andricraft's GDScript Stairs Character](https://github.com/Andicraft/stairs-character) translated into C++.
I made it as a learning exercise for GDExtension.

View File

@ -1,22 +0,0 @@
[configuration]
entry_symbol = "gdextension_init"
compatibility_minimum = 4.3
[libraries]
linux.debug.x86_64 = "bin/libStairsCharacter.linux.debug.x86_64.so"
linux.release.x86_64 = "bin/libStairsCharacter.linux.release.x86_64.so"
linux.debug.arm64 = "bin/libStairsCharacter.linux.debug.arm64.so"
linux.release.arm64 = "bin/libStairsCharacter.linux.release.arm64.so"
linux.debug.rv64 = "bin/libStairsCharacter.linux.debug.rv64.so"
linux.release.rv64 = "bin/libStairsCharacter.linux.release.rv64.so"
windows.debug.x86_64 = "bin/libStairsCharacter.windows.debug.x86_64.dll"
windows.release.x86_64 = "bin/libStairsCharacter.windows.release.x86_64.dll"
macos.debug = "bin/libStairsCharacter.macos.debug.framework"
macos.release = "bin/libStairsCharacter.macos.release.framework"
android.debug.arm64 = "bin/libStairsCharacter.android.debug.arm64.so"
android.release.arm64 = "bin/libStairsCharacter.android.release.arm64.so"
[icons]
StairsCharacter3D = "stairs_character.svg"

View File

@ -1 +0,0 @@
uid://tkege8xp3mnb

View File

@ -1 +0,0 @@
<svg height="32" width="32" version="1.1" id="_x32_" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 512 512" xml:space="preserve"><style type="text/css">.st0{fill:#cd5c5c;}</style><g stroke-opacity="1" fill-opacity="1"><path class="st0" d="M315.664 0 193.969 32.069v98.468l-86.38 20.729v98.477l-86.381 20.73v117.37L196.337 512l6.388-1.532 288.068-71.995V124.166L315.664 0zM188.487 470.942 50.17 372.883v-68.175l138.317 98.799V470.942zM201.627 386.197 66.192 289.462l58.411-14.02 135.436 96.746L201.627 386.197zM274.868 356.078l-138.317-98.799v-71.778l138.317 98.8V356.078zM288.008 266.992l-135.436-96.746 58.402-14.01 135.446 96.754L288.008 266.992zM361.248 236.881l-138.317-98.8V66.296l138.317 98.808V236.881zM374.388 147.803 238.943 51.057l70.699-19.833 136.193 96.572L374.388 147.803z" fill="black" opacity="1" fill-opacity="1"/></g></svg>

Before

Width:  |  Height:  |  Size: 886 B

View File

@ -1,43 +0,0 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://f8rpbcuiicd7"
path="res://.godot/imported/stairs_character.svg-a9660f3f5b9588e29c90e9a9aaadbbda.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/StairsCharacter/stairs_character.svg"
dest_files=["res://.godot/imported/stairs_character.svg-a9660f3f5b9588e29c90e9a9aaadbbda.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
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/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
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

View File

@ -1,17 +0,0 @@
@tool
extends HBoxContainer
var colour : Color
var title : String:
set = set_title
var index : int
@onready var colour_picker := $TODOColourPickerButton
func _ready() -> void:
$TODOColourPickerButton.color = colour
$Label.text = title
func set_title(value: String) -> void:
title = value
$Label.text = value

View File

@ -1 +0,0 @@
uid://dd033y6smf6jh

View File

@ -1,44 +0,0 @@
@tool
extends Control
signal tree_built # used for debugging
const Todo := preload("res://addons/Todo_Manager/todo_class.gd")
const TodoItem := preload("res://addons/Todo_Manager/todoItem_class.gd")
var _sort_alphabetical := true
@onready var tree := $Panel/Tree as Tree
func build_tree(todo_item : TodoItem, patterns : Array, cased_patterns : Array[String]) -> void:
tree.clear()
var root := tree.create_item()
root.set_text(0, "Scripts")
var script := tree.create_item(root)
script.set_text(0, todo_item.get_short_path() + " -------")
script.set_metadata(0, todo_item)
for todo in todo_item.todos:
var item := tree.create_item(script)
var content_header : String = todo.content
if "\n" in todo.content:
content_header = content_header.split("\n")[0] + "..."
item.set_text(0, "(%0) - %1".format([todo.line_number, content_header], "%_"))
item.set_tooltip_text(0, todo.content)
item.set_metadata(0, todo)
for i in range(0, len(cased_patterns)):
if cased_patterns[i] == todo.pattern:
item.set_custom_color(0, patterns[i][1])
emit_signal("tree_built")
func sort_alphabetical(a, b) -> bool:
if a.script_path > b.script_path:
return true
else:
return false
func sort_backwards(a, b) -> bool:
if a.script_path < b.script_path:
return true
else:
return false

View File

@ -1 +0,0 @@
uid://dp4hevwsquax6

View File

@ -1,336 +0,0 @@
@tool
extends Control
#signal tree_built # used for debugging
enum { CASE_INSENSITIVE, CASE_SENSITIVE }
const Project := preload("res://addons/Todo_Manager/Project.gd")
const Current := preload("res://addons/Todo_Manager/Current.gd")
const Todo := preload("res://addons/Todo_Manager/todo_class.gd")
const TodoItem := preload("res://addons/Todo_Manager/todoItem_class.gd")
const ColourPicker := preload("res://addons/Todo_Manager/UI/ColourPicker.tscn")
const PatternEdit := preload("res://addons/Todo_Manager/PatternEdit.gd")
const PatternEditScene := preload("res://addons/Todo_Manager/UI/PatternEdit.tscn")
const ToggleButton := preload("res://addons/Todo_Manager/UI/ToggleButton.tscn")
# Pattern array format - [regex, colour, case_sensitivity, enabled]
const DEFAULT_PATTERNS := [["\\bTODO\\b", Color("96f1ad"), CASE_INSENSITIVE, true], ["\\bHACK\\b", Color("d5bc70"), CASE_INSENSITIVE, true], ["\\bFIXME\\b", Color("d57070"), CASE_INSENSITIVE, true]]
const DEFAULT_SCRIPT_COLOUR := Color("ccced3")
const DEFAULT_SCRIPT_NAME := false
const DEFAULT_SORT := true
var plugin : EditorPlugin
var todo_items : Array
var script_colour := Color("ccced3")
var ignore_paths : Array[String] = []
var full_path := false
var auto_refresh := true
var builtin_enabled := false
var _sort_alphabetical := true
var patterns := [["\\bTODO\\b", Color("96f1ad"), CASE_INSENSITIVE, true], ["\\bHACK\\b", Color("d5bc70"), CASE_INSENSITIVE, true], ["\\bFIXME\\b", Color("d57070"), CASE_INSENSITIVE, true]]
@onready var tabs := $VBoxContainer/TabContainer as TabContainer
@onready var project := $VBoxContainer/TabContainer/Project as Project
@onready var current := $VBoxContainer/TabContainer/Current as Current
@onready var project_tree := $VBoxContainer/TabContainer/Project/Panel/Tree as Tree
@onready var project_toggles_container := $VBoxContainer/TabContainer/Project/TogglesScrollContainer/VBoxContainer as VBoxContainer
@onready var current_tree := $VBoxContainer/TabContainer/Current/Panel/Tree as Tree
@onready var current_toggles_container := $VBoxContainer/TabContainer/Current/TogglesScrollContainer/VBoxContainer as VBoxContainer
@onready var settings_panel := $VBoxContainer/TabContainer/Settings as Panel
@onready var colours_container := $VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/HBoxContainer3/Colours as VBoxContainer
@onready var pattern_container := $VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/HBoxContainer4/Patterns as VBoxContainer
@onready var ignore_textbox := $VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/VBoxContainer/HBoxContainer2/Scripts/IgnorePaths/TextEdit as LineEdit
@onready var auto_refresh_button := $VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/HBoxContainer5/Patterns/RefreshCheckButton as CheckButton
func _ready() -> void:
load_config()
populate_settings()
func build_tree() -> void:
if tabs:
add_toggle_buttons()
var filtered_patterns = patterns.filter(func (p): return p[3] == true)
match tabs.current_tab:
0:
project.build_tree(todo_items, ignore_paths, filtered_patterns, plugin.cased_patterns, _sort_alphabetical, full_path)
create_config_file()
1:
current.build_tree(get_active_script(), filtered_patterns, plugin.cased_patterns)
create_config_file()
2:
pass
_:
pass
func get_active_script() -> TodoItem:
var current_script : Script = plugin.get_editor_interface().get_script_editor().get_current_script()
if current_script:
var script_path = current_script.resource_path
for todo_item in todo_items:
if todo_item.script_path == script_path:
return todo_item
# nothing found
var todo_item := TodoItem.new(script_path, [])
return todo_item
else:
# not a script
var todo_item := TodoItem.new("res://Documentation", [])
return todo_item
func go_to_script(script_path: String, line_number : int = 0) -> void:
if plugin.get_editor_interface().get_editor_settings().get_setting("text_editor/external/use_external_editor"):
var exec_path = plugin.get_editor_interface().get_editor_settings().get_setting("text_editor/external/exec_path")
var args := get_exec_flags(exec_path, script_path, line_number)
OS.execute(exec_path, args)
else:
var script := load(script_path)
plugin.get_editor_interface().edit_resource(script)
plugin.get_editor_interface().get_script_editor().goto_line(line_number - 1)
func get_exec_flags(editor_path : String, script_path : String, line_number : int) -> PackedStringArray:
var args : PackedStringArray
var script_global_path = ProjectSettings.globalize_path(script_path)
if editor_path.ends_with("code.cmd") or editor_path.ends_with("code"): ## VS Code
args.append(ProjectSettings.globalize_path("res://"))
args.append("--goto")
args.append(script_global_path + ":" + str(line_number))
elif editor_path.ends_with("rider64.exe") or editor_path.ends_with("rider"): ## Rider
args.append("--line")
args.append(str(line_number))
args.append(script_global_path)
else: ## Atom / Sublime
args.append(script_global_path + ":" + str(line_number))
return args
func sort_alphabetical(a, b) -> bool:
if a.script_path > b.script_path:
return true
else:
return false
func sort_backwards(a, b) -> bool:
if a.script_path < b.script_path:
return true
else:
return false
func populate_settings() -> void:
for i in patterns.size():
## Create Colour Pickers
var colour_picker: Node = ColourPicker.instantiate()
colour_picker.colour = patterns[i][1]
colour_picker.title = patterns[i][0]
colour_picker.index = i
colours_container.add_child(colour_picker)
colour_picker.colour_picker.color_changed.connect(change_colour.bind(i))
## Create Patterns
var pattern_edit: PatternEdit = PatternEditScene.instantiate()
pattern_edit.text = patterns[i][0]
pattern_edit.index = i
pattern_container.add_child(pattern_edit)
pattern_edit.line_edit.text_changed.connect(change_pattern.bind(i,
colour_picker))
pattern_edit.remove_button.pressed.connect(remove_pattern.bind(i,
pattern_edit, colour_picker))
pattern_edit.case_checkbox.button_pressed = patterns[i][2]
pattern_edit.case_checkbox.toggled.connect(case_sensitive_pattern.bind(i))
var pattern_button := $VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/HBoxContainer4/Patterns/AddPatternButton
$VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/HBoxContainer4/Patterns.move_child(pattern_button, 0)
# path filtering
var ignore_paths_field := ignore_textbox
if not ignore_paths_field.is_connected("text_changed", _on_ignore_paths_changed):
ignore_paths_field.connect("text_changed", _on_ignore_paths_changed)
var ignore_paths_text := ""
for path in ignore_paths:
ignore_paths_text += path + ", "
ignore_paths_text = ignore_paths_text.trim_suffix(", ")
ignore_paths_field.text = ignore_paths_text
auto_refresh_button.button_pressed = auto_refresh
func rebuild_settings() -> void:
for node in colours_container.get_children():
node.queue_free()
for node in pattern_container.get_children():
if node is Button:
continue
node.queue_free()
populate_settings()
func add_toggle_buttons() -> void:
for toggle in project_toggles_container.get_children():
toggle.queue_free()
for toggle in current_toggles_container.get_children():
toggle.queue_free()
for pattern in patterns:
var toggle : Button = ToggleButton.instantiate()
toggle.text = pattern[0].replace('\\b', '')
toggle.button_pressed = pattern[3]
toggle.connect("toggled", toggle_pattern_enabled.bind(pattern))
if tabs.current_tab == 0:
project_toggles_container.add_child(toggle)
elif tabs.current_tab == 1:
current_toggles_container.add_child(toggle)
#### CONFIG FILE ####
func create_config_file() -> void:
var config = ConfigFile.new()
config.set_value("scripts", "full_path", full_path)
config.set_value("scripts", "sort_alphabetical", _sort_alphabetical)
config.set_value("scripts", "script_colour", script_colour)
config.set_value("scripts", "ignore_paths", ignore_paths)
config.set_value("patterns", "patterns", patterns)
config.set_value("config", "auto_refresh", auto_refresh)
config.set_value("config", "builtin_enabled", builtin_enabled)
var err = config.save("res://addons/Todo_Manager/todo.cfg")
func load_config() -> void:
var config := ConfigFile.new()
if config.load("res://addons/Todo_Manager/todo.cfg") == OK:
full_path = config.get_value("scripts", "full_path", DEFAULT_SCRIPT_NAME)
_sort_alphabetical = config.get_value("scripts", "sort_alphabetical", DEFAULT_SORT)
script_colour = config.get_value("scripts", "script_colour", DEFAULT_SCRIPT_COLOUR)
ignore_paths = config.get_value("scripts", "ignore_paths", [] as Array[String])
patterns = config.get_value("patterns", "patterns", DEFAULT_PATTERNS)
fix_missing_values(patterns)
auto_refresh = config.get_value("config", "auto_refresh", true)
builtin_enabled = config.get_value("config", "builtin_enabled", false)
else:
create_config_file()
func fix_missing_values(patterns: Array) -> void:
for pattern in patterns:
if pattern.size() == 2:
pattern.append(CASE_INSENSITIVE)
if pattern.size() == 3:
pattern.append(true)
#### Events ####
func _on_SettingsButton_toggled(button_pressed: bool) -> void:
settings_panel.visible = button_pressed
if button_pressed == false:
create_config_file()
# plugin.find_tokens_from_path(plugin.script_cache)
if auto_refresh:
plugin.rescan_files(true)
func _on_Tree_item_activated() -> void:
var item : TreeItem
match tabs.current_tab:
0:
item = project_tree.get_selected()
1:
item = current_tree.get_selected()
if item.get_metadata(0) is Todo:
var todo : Todo = item.get_metadata(0)
call_deferred("go_to_script", todo.script_path, todo.line_number)
else:
var todo_item = item.get_metadata(0)
call_deferred("go_to_script", todo_item.script_path)
func _on_FullPathCheckBox_toggled(button_pressed: bool) -> void:
full_path = button_pressed
func _on_ScriptColourPickerButton_color_changed(color: Color) -> void:
script_colour = color
func _on_RescanButton_pressed() -> void:
plugin.rescan_files(true)
func change_colour(colour: Color, index: int) -> void:
patterns[index][1] = colour
func change_pattern(value: String, index: int, this_colour: Node) -> void:
patterns[index][0] = value
this_colour.title = value
plugin.rescan_files(true)
func remove_pattern(index: int, this: Node, this_colour: Node) -> void:
patterns.remove_at(index)
this.queue_free()
this_colour.queue_free()
plugin.rescan_files(true)
func toggle_pattern_enabled(active: bool, pattern: Array) -> void:
pattern[3] = active
plugin.rescan_files(true)
func case_sensitive_pattern(active: bool, index: int) -> void:
if active:
patterns[index][2] = CASE_SENSITIVE
else:
patterns[index][2] = CASE_INSENSITIVE
plugin.rescan_files(true)
func _on_DefaultButton_pressed() -> void:
patterns = DEFAULT_PATTERNS.duplicate(true)
_sort_alphabetical = DEFAULT_SORT
script_colour = DEFAULT_SCRIPT_COLOUR
full_path = DEFAULT_SCRIPT_NAME
rebuild_settings()
plugin.rescan_files(true)
func _on_AlphSortCheckBox_toggled(button_pressed: bool) -> void:
_sort_alphabetical = button_pressed
plugin.rescan_files(true)
func _on_AddPatternButton_pressed() -> void:
patterns.append(["\\bplaceholder\\b", Color.WHITE, CASE_INSENSITIVE, true])
rebuild_settings()
func _on_RefreshCheckButton_toggled(button_pressed: bool) -> void:
auto_refresh = button_pressed
func _on_Timer_timeout() -> void:
plugin.refresh_lock = false
func _on_ignore_paths_changed(new_text: String) -> void:
var text = ignore_textbox.text
var split: Array = text.split(',')
ignore_paths.clear()
for elem in split:
if elem == " " || elem == "":
continue
ignore_paths.push_front(elem.lstrip(' ').rstrip(' '))
# validate so no empty string slips through (all paths ignored)
var i := 0
for path in ignore_paths:
if (path == "" || path == " "):
ignore_paths.remove_at(i)
i += 1
plugin.rescan_files(true)
func _on_TabContainer_tab_changed(tab: int) -> void:
build_tree()
func _on_BuiltInCheckButton_toggled(button_pressed: bool) -> void:
builtin_enabled = button_pressed
plugin.rescan_files(true)

View File

@ -1 +0,0 @@
uid://csgl0vtsudgxh

View File

@ -1,21 +0,0 @@
@tool
extends HBoxContainer
var text : String : set = set_text
var disabled : bool
var index : int
@onready var line_edit := $LineEdit as LineEdit
@onready var remove_button := $RemoveButton as Button
@onready var case_checkbox := %CaseSensativeCheckbox as CheckBox
func _ready() -> void:
line_edit.text = text
remove_button.disabled = disabled
func set_text(value: String) -> void:
text = value
if line_edit:
line_edit.text = value

View File

@ -1 +0,0 @@
uid://betg01sk02eyy

View File

@ -1,73 +0,0 @@
@tool
extends Control
signal tree_built # used for debugging
const Todo := preload("res://addons/Todo_Manager/todo_class.gd")
var _sort_alphabetical := true
var _full_path := false
@onready var tree := $Panel/Tree as Tree
func build_tree(todo_items : Array, ignore_paths : Array, patterns : Array, cased_patterns: Array[String], sort_alphabetical : bool, full_path : bool) -> void:
_full_path = full_path
tree.clear()
if sort_alphabetical:
todo_items.sort_custom(Callable(self, "sort_alphabetical"))
else:
todo_items.sort_custom(Callable(self, "sort_backwards"))
var root := tree.create_item()
root.set_text(0, "Scripts")
for todo_item in todo_items:
var ignore := false
for ignore_path in ignore_paths:
var script_path : String = todo_item.script_path
if script_path.begins_with(ignore_path) or script_path.begins_with("res://" + ignore_path) or script_path.begins_with("res:///" + ignore_path):
ignore = true
break
if ignore:
continue
var script := tree.create_item(root)
if full_path:
script.set_text(0, todo_item.script_path + " -------")
else:
script.set_text(0, todo_item.get_short_path() + " -------")
script.set_metadata(0, todo_item)
for todo in todo_item.todos:
var item := tree.create_item(script)
var content_header : String = todo.content
if "\n" in todo.content:
content_header = content_header.split("\n")[0] + "..."
item.set_text(0, "(%0) - %1".format([todo.line_number, content_header], "%_"))
item.set_tooltip_text(0, todo.content)
item.set_metadata(0, todo)
for i in range(0, len(cased_patterns)):
if cased_patterns[i] == todo.pattern:
item.set_custom_color(0, patterns[i][1])
emit_signal("tree_built")
func sort_alphabetical(a, b) -> bool:
if _full_path:
if a.script_path < b.script_path:
return true
else:
return false
else:
if a.get_short_path() < b.get_short_path():
return true
else:
return false
func sort_backwards(a, b) -> bool:
if _full_path:
if a.script_path > b.script_path:
return true
else:
return false
else:
if a.get_short_path() > b.get_short_path():
return true
else:
return false

View File

@ -1 +0,0 @@
uid://bnyawhvwojm5g

View File

@ -1,4 +0,0 @@
class_name Test extends RefCounted
var a: String
var b: bool

View File

@ -1 +0,0 @@
uid://den1uk6816qrb

View File

@ -1,17 +0,0 @@
[gd_scene load_steps=2 format=3 uid="uid://bie1xn8v1kd66"]
[ext_resource type="Script" uid="uid://dd033y6smf6jh" path="res://addons/Todo_Manager/ColourPicker.gd" id="1"]
[node name="TODOColour" type="HBoxContainer"]
offset_right = 105.0
offset_bottom = 31.0
script = ExtResource("1")
metadata/_edit_use_custom_anchors = false
[node name="Label" type="Label" parent="."]
layout_mode = 2
[node name="TODOColourPickerButton" type="ColorPickerButton" parent="."]
custom_minimum_size = Vector2(40, 0)
layout_mode = 2
size_flags_horizontal = 10

View File

@ -1,365 +0,0 @@
[gd_scene load_steps=6 format=3 uid="uid://b6k0dtftankcx"]
[ext_resource type="Script" uid="uid://csgl0vtsudgxh" path="res://addons/Todo_Manager/Dock.gd" id="1"]
[ext_resource type="Script" uid="uid://bnyawhvwojm5g" path="res://addons/Todo_Manager/Project.gd" id="2"]
[ext_resource type="Script" uid="uid://dp4hevwsquax6" path="res://addons/Todo_Manager/Current.gd" id="3"]
[sub_resource type="ButtonGroup" id="ButtonGroup_kqxcu"]
[sub_resource type="ButtonGroup" id="ButtonGroup_kltg3"]
[node name="Dock" type="Control"]
custom_minimum_size = Vector2(0, 200)
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
size_flags_vertical = 3
script = ExtResource("1")
[node name="VBoxContainer" type="VBoxContainer" parent="."]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
offset_top = 4.0
grow_horizontal = 2
grow_vertical = 2
metadata/_edit_layout_mode = 1
[node name="Header" type="HBoxContainer" parent="VBoxContainer"]
visible = false
layout_mode = 2
[node name="HeaderLeft" type="HBoxContainer" parent="VBoxContainer/Header"]
layout_mode = 2
size_flags_horizontal = 3
[node name="Title" type="Label" parent="VBoxContainer/Header/HeaderLeft"]
layout_mode = 2
text = "Todo Dock:"
[node name="HeaderRight" type="HBoxContainer" parent="VBoxContainer/Header"]
layout_mode = 2
size_flags_horizontal = 3
alignment = 2
[node name="SettingsButton" type="Button" parent="VBoxContainer/Header/HeaderRight"]
visible = false
layout_mode = 2
toggle_mode = true
text = "Settings"
[node name="TabContainer" type="TabContainer" parent="VBoxContainer"]
layout_mode = 2
size_flags_vertical = 3
current_tab = 0
[node name="Project" type="Control" parent="VBoxContainer/TabContainer"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
script = ExtResource("2")
metadata/_tab_index = 0
[node name="Panel" type="Panel" parent="VBoxContainer/TabContainer/Project"]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
offset_right = -106.0
grow_horizontal = 2
grow_vertical = 2
[node name="Tree" type="Tree" parent="VBoxContainer/TabContainer/Project/Panel"]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
hide_root = true
[node name="TogglesScrollContainer" type="ScrollContainer" parent="VBoxContainer/TabContainer/Project"]
layout_mode = 1
anchors_preset = 11
anchor_left = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
offset_left = -102.0
grow_horizontal = 0
grow_vertical = 2
[node name="VBoxContainer" type="VBoxContainer" parent="VBoxContainer/TabContainer/Project/TogglesScrollContainer"]
layout_mode = 2
size_flags_horizontal = 3
theme_override_constants/separation = 6
[node name="Current" type="Control" parent="VBoxContainer/TabContainer"]
visible = false
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
script = ExtResource("3")
metadata/_tab_index = 1
[node name="Panel" type="Panel" parent="VBoxContainer/TabContainer/Current"]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
offset_right = -106.0
[node name="Tree" type="Tree" parent="VBoxContainer/TabContainer/Current/Panel"]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
hide_folding = true
hide_root = true
[node name="TogglesScrollContainer" type="ScrollContainer" parent="VBoxContainer/TabContainer/Current"]
layout_mode = 1
anchors_preset = 11
anchor_left = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
offset_left = -102.0
grow_horizontal = 0
grow_vertical = 2
[node name="VBoxContainer" type="VBoxContainer" parent="VBoxContainer/TabContainer/Current/TogglesScrollContainer"]
layout_mode = 2
size_flags_horizontal = 3
theme_override_constants/separation = 6
[node name="Settings" type="Panel" parent="VBoxContainer/TabContainer"]
visible = false
layout_mode = 2
metadata/_tab_index = 2
[node name="ScrollContainer" type="ScrollContainer" parent="VBoxContainer/TabContainer/Settings"]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="MarginContainer" type="MarginContainer" parent="VBoxContainer/TabContainer/Settings/ScrollContainer"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
[node name="VBoxContainer" type="VBoxContainer" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
[node name="Scripts" type="HBoxContainer" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer"]
layout_mode = 2
[node name="Label" type="Label" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/Scripts"]
layout_mode = 2
text = "Scripts:"
[node name="HSeparator" type="HSeparator" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/Scripts"]
layout_mode = 2
size_flags_horizontal = 3
[node name="VBoxContainer" type="VBoxContainer" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer"]
layout_mode = 2
size_flags_horizontal = 5
[node name="HBoxContainer2" type="HBoxContainer" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/VBoxContainer"]
layout_mode = 2
[node name="VSeparator" type="VSeparator" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/VBoxContainer/HBoxContainer2"]
layout_mode = 2
[node name="Scripts" type="VBoxContainer" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/VBoxContainer/HBoxContainer2"]
layout_mode = 2
[node name="ScriptName" type="HBoxContainer" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/VBoxContainer/HBoxContainer2/Scripts"]
layout_mode = 2
[node name="Label" type="Label" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/VBoxContainer/HBoxContainer2/Scripts/ScriptName"]
layout_mode = 2
text = "Script Name:"
[node name="FullPathCheckBox" type="CheckBox" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/VBoxContainer/HBoxContainer2/Scripts/ScriptName"]
layout_mode = 2
button_group = SubResource("ButtonGroup_kqxcu")
text = "Full path"
[node name="ShortNameCheckBox" type="CheckBox" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/VBoxContainer/HBoxContainer2/Scripts/ScriptName"]
layout_mode = 2
button_pressed = true
button_group = SubResource("ButtonGroup_kqxcu")
text = "Short name"
[node name="ScriptSort" type="HBoxContainer" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/VBoxContainer/HBoxContainer2/Scripts"]
layout_mode = 2
[node name="Label" type="Label" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/VBoxContainer/HBoxContainer2/Scripts/ScriptSort"]
layout_mode = 2
text = "Sort Order:"
[node name="AlphSortCheckBox" type="CheckBox" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/VBoxContainer/HBoxContainer2/Scripts/ScriptSort"]
layout_mode = 2
button_pressed = true
button_group = SubResource("ButtonGroup_kltg3")
text = "Alphabetical"
[node name="RAlphSortCheckBox" type="CheckBox" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/VBoxContainer/HBoxContainer2/Scripts/ScriptSort"]
layout_mode = 2
button_group = SubResource("ButtonGroup_kltg3")
text = "Reverse Alphabetical"
[node name="ScriptColour" type="HBoxContainer" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/VBoxContainer/HBoxContainer2/Scripts"]
layout_mode = 2
[node name="Label" type="Label" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/VBoxContainer/HBoxContainer2/Scripts/ScriptColour"]
layout_mode = 2
text = "Script Colour:"
[node name="ScriptColourPickerButton" type="ColorPickerButton" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/VBoxContainer/HBoxContainer2/Scripts/ScriptColour"]
custom_minimum_size = Vector2(40, 0)
layout_mode = 2
color = Color(0.8, 0.807843, 0.827451, 1)
[node name="IgnorePaths" type="HBoxContainer" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/VBoxContainer/HBoxContainer2/Scripts"]
layout_mode = 2
[node name="Label" type="Label" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/VBoxContainer/HBoxContainer2/Scripts/IgnorePaths"]
layout_mode = 2
text = "Ignore Paths:"
[node name="TextEdit" type="LineEdit" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/VBoxContainer/HBoxContainer2/Scripts/IgnorePaths"]
custom_minimum_size = Vector2(100, 0)
layout_mode = 2
expand_to_text_length = true
[node name="Label3" type="Label" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/VBoxContainer/HBoxContainer2/Scripts/IgnorePaths"]
layout_mode = 2
text = "(Separated by commas)"
[node name="TODOColours" type="HBoxContainer" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer"]
layout_mode = 2
[node name="Label" type="Label" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/TODOColours"]
layout_mode = 2
text = "TODO Colours:"
[node name="HSeparator" type="HSeparator" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/TODOColours"]
layout_mode = 2
size_flags_horizontal = 3
[node name="HBoxContainer3" type="HBoxContainer" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer"]
layout_mode = 2
[node name="VSeparator" type="VSeparator" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/HBoxContainer3"]
layout_mode = 2
[node name="Colours" type="VBoxContainer" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/HBoxContainer3"]
layout_mode = 2
[node name="Patterns" type="HBoxContainer" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer"]
layout_mode = 2
[node name="Label" type="Label" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/Patterns"]
layout_mode = 2
text = "Patterns:"
[node name="HSeparator" type="HSeparator" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/Patterns"]
layout_mode = 2
size_flags_horizontal = 3
[node name="HBoxContainer4" type="HBoxContainer" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer"]
layout_mode = 2
[node name="VSeparator" type="VSeparator" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/HBoxContainer4"]
layout_mode = 2
[node name="Patterns" type="VBoxContainer" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/HBoxContainer4"]
layout_mode = 2
size_flags_horizontal = 3
[node name="AddPatternButton" type="Button" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/HBoxContainer4/Patterns"]
layout_mode = 2
size_flags_horizontal = 0
text = "Add"
[node name="Config" type="HBoxContainer" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer"]
layout_mode = 2
[node name="Label" type="Label" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/Config"]
layout_mode = 2
text = "Config:"
[node name="HSeparator" type="HSeparator" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/Config"]
layout_mode = 2
size_flags_horizontal = 3
[node name="HBoxContainer5" type="HBoxContainer" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer"]
layout_mode = 2
[node name="VSeparator" type="VSeparator" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/HBoxContainer5"]
layout_mode = 2
[node name="Patterns" type="VBoxContainer" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/HBoxContainer5"]
layout_mode = 2
[node name="RefreshCheckButton" type="CheckButton" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/HBoxContainer5/Patterns"]
layout_mode = 2
size_flags_horizontal = 0
button_pressed = true
text = "Auto Refresh"
[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/HBoxContainer5/Patterns"]
layout_mode = 2
[node name="BuiltInCheckButton" type="CheckButton" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/HBoxContainer5/Patterns/HBoxContainer"]
layout_mode = 2
text = "Scan Built-in Scripts"
[node name="Label" type="Label" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/HBoxContainer5/Patterns/HBoxContainer"]
layout_mode = 2
[node name="DefaultButton" type="Button" parent="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/HBoxContainer5/Patterns"]
layout_mode = 2
size_flags_horizontal = 0
text = "Reset to default"
[node name="Timer" type="Timer" parent="."]
one_shot = true
[node name="RescanButton" type="Button" parent="."]
layout_mode = 1
anchors_preset = 1
anchor_left = 1.0
anchor_right = 1.0
offset_left = -102.0
offset_top = 3.0
offset_bottom = 34.0
grow_horizontal = 0
text = "Rescan Files"
flat = true
[connection signal="toggled" from="VBoxContainer/Header/HeaderRight/SettingsButton" to="." method="_on_SettingsButton_toggled"]
[connection signal="tab_changed" from="VBoxContainer/TabContainer" to="." method="_on_TabContainer_tab_changed"]
[connection signal="item_activated" from="VBoxContainer/TabContainer/Project/Panel/Tree" to="." method="_on_Tree_item_activated"]
[connection signal="item_activated" from="VBoxContainer/TabContainer/Current/Panel/Tree" to="." method="_on_Tree_item_activated"]
[connection signal="toggled" from="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/VBoxContainer/HBoxContainer2/Scripts/ScriptName/FullPathCheckBox" to="." method="_on_FullPathCheckBox_toggled"]
[connection signal="toggled" from="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/VBoxContainer/HBoxContainer2/Scripts/ScriptSort/AlphSortCheckBox" to="." method="_on_AlphSortCheckBox_toggled"]
[connection signal="color_changed" from="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/VBoxContainer/HBoxContainer2/Scripts/ScriptColour/ScriptColourPickerButton" to="." method="_on_ScriptColourPickerButton_color_changed"]
[connection signal="pressed" from="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/HBoxContainer4/Patterns/AddPatternButton" to="." method="_on_AddPatternButton_pressed"]
[connection signal="toggled" from="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/HBoxContainer5/Patterns/RefreshCheckButton" to="." method="_on_RefreshCheckButton_toggled"]
[connection signal="toggled" from="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/HBoxContainer5/Patterns/HBoxContainer/BuiltInCheckButton" to="." method="_on_BuiltInCheckButton_toggled"]
[connection signal="pressed" from="VBoxContainer/TabContainer/Settings/ScrollContainer/MarginContainer/VBoxContainer/HBoxContainer5/Patterns/DefaultButton" to="." method="_on_DefaultButton_pressed"]
[connection signal="timeout" from="Timer" to="." method="_on_Timer_timeout"]
[connection signal="pressed" from="RescanButton" to="." method="_on_RescanButton_pressed"]

View File

@ -1,21 +0,0 @@
[gd_resource type="Theme" load_steps=4 format=3 uid="uid://cignxcqjqfst0"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_0amm0"]
bg_color = Color(1, 1, 1, 0.0784314)
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_juds7"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_elllf"]
bg_color = Color(0.12549, 0.156863, 0.192157, 1)
border_width_bottom = 2
border_color = Color(0.439216, 0.729412, 0.980392, 1)
corner_radius_top_left = 4
corner_radius_top_right = 4
corner_radius_bottom_right = 4
corner_radius_bottom_left = 4
[resource]
Button/colors/font_pressed_color = Color(0.439216, 0.729412, 0.980392, 1)
Button/styles/hover = SubResource("StyleBoxFlat_0amm0")
Button/styles/normal = SubResource("StyleBoxEmpty_juds7")
Button/styles/pressed = SubResource("StyleBoxFlat_elllf")

View File

@ -1,26 +0,0 @@
[gd_scene load_steps=2 format=3 uid="uid://bx11sel2q5wli"]
[ext_resource type="Script" uid="uid://betg01sk02eyy" path="res://addons/Todo_Manager/PatternEdit.gd" id="1_mujq6"]
[node name="Pattern" type="HBoxContainer"]
script = ExtResource("1_mujq6")
[node name="LineEdit" type="LineEdit" parent="."]
layout_mode = 2
size_flags_horizontal = 0
expand_to_text_length = true
[node name="RemoveButton" type="Button" parent="."]
layout_mode = 2
text = "-"
[node name="MarginContainer" type="MarginContainer" parent="."]
custom_minimum_size = Vector2(20, 0)
layout_mode = 2
size_flags_horizontal = 0
[node name="CaseSensativeCheckbox" type="CheckBox" parent="."]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 0
text = "Case Sensitive"

View File

@ -1,29 +0,0 @@
[gd_scene load_steps=5 format=3 uid="uid://bq0tjjng7hdvt"]
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_5887s"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_rtgj1"]
bg_color = Color(1, 1, 1, 0.0705882)
corner_radius_top_left = 4
corner_radius_top_right = 4
corner_radius_bottom_right = 4
corner_radius_bottom_left = 4
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_5887s"]
bg_color = Color(0.12549, 0.156863, 0.192157, 1)
border_width_bottom = 2
border_color = Color(0.439216, 0.729412, 0.980392, 1)
corner_radius_top_left = 4
corner_radius_top_right = 4
corner_radius_bottom_right = 4
corner_radius_bottom_left = 4
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_f41nr"]
[node name="Button" type="Button"]
theme_override_styles/focus = SubResource("StyleBoxEmpty_5887s")
theme_override_styles/hover = SubResource("StyleBoxFlat_rtgj1")
theme_override_styles/pressed = SubResource("StyleBoxFlat_5887s")
theme_override_styles/normal = SubResource("StyleBoxEmpty_f41nr")
toggle_mode = true
text = "TODO"

View File

@ -1,7 +0,0 @@
extends Node
# TODO: this is a TODO
# HACK: this is a HACK
# FIXME: this is a FIXME
# TODO this works too
#Hack any format will do

View File

@ -1 +0,0 @@
uid://dotx67t7w7hhk

Binary file not shown.

Before

Width:  |  Height:  |  Size: 111 KiB

View File

@ -1,40 +0,0 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://c7v1fdudy4quq"
path="res://.godot/imported/Instruct1.png-698c6faa3ef3ac4960807faa3e028bd6.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/Todo_Manager/doc/images/Instruct1.png"
dest_files=["res://.godot/imported/Instruct1.png-698c6faa3ef3ac4960807faa3e028bd6.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
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/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
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.

Before

Width:  |  Height:  |  Size: 12 KiB

View File

@ -1,40 +0,0 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://b80nmr6b06t21"
path="res://.godot/imported/Instruct2.png-4e8664e49d00a397bbd539f7dee976ff.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/Todo_Manager/doc/images/Instruct2.png"
dest_files=["res://.godot/imported/Instruct2.png-4e8664e49d00a397bbd539f7dee976ff.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
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/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
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.

Before

Width:  |  Height:  |  Size: 57 KiB

View File

@ -1,40 +0,0 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bmpb4ldb5xhm2"
path="res://.godot/imported/Instruct3.png-3cc62ed99bf29d90b803cb8eb40881e9.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/Todo_Manager/doc/images/Instruct3.png"
dest_files=["res://.godot/imported/Instruct3.png-3cc62ed99bf29d90b803cb8eb40881e9.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
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/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
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.

Before

Width:  |  Height:  |  Size: 20 KiB

View File

@ -1,40 +0,0 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dtsgcaefwbblx"
path="res://.godot/imported/Instruct4.png-bf5aa1cffc066175cecf9281b0774809.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/Todo_Manager/doc/images/Instruct4.png"
dest_files=["res://.godot/imported/Instruct4.png-bf5aa1cffc066175cecf9281b0774809.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
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/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
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.

Before

Width:  |  Height:  |  Size: 48 KiB

View File

@ -1,40 +0,0 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bq57uhyrdewef"
path="res://.godot/imported/Instruct5.png-001538ed8b5682dcf232de08035aab38.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/Todo_Manager/doc/images/Instruct5.png"
dest_files=["res://.godot/imported/Instruct5.png-001538ed8b5682dcf232de08035aab38.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
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/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
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.

Before

Width:  |  Height:  |  Size: 23 KiB

View File

@ -1,40 +0,0 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cnjwqakk07q5g"
path="res://.godot/imported/TODO_Manager_Logo.png-e07d7ec75201c66b732ef87ec1bece15.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/Todo_Manager/doc/images/TODO_Manager_Logo.png"
dest_files=["res://.godot/imported/TODO_Manager_Logo.png-e07d7ec75201c66b732ef87ec1bece15.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
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/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
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.

Before

Width:  |  Height:  |  Size: 243 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

View File

@ -1,40 +0,0 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dm4238rk6sken"
path="res://.godot/imported/example1.png-6386c332ca46e1e62ea061b956a901cd.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/Todo_Manager/doc/images/example1.png"
dest_files=["res://.godot/imported/example1.png-6386c332ca46e1e62ea061b956a901cd.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
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/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
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.

Before

Width:  |  Height:  |  Size: 30 KiB

View File

@ -1,40 +0,0 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://b4gc0l6pibggy"
path="res://.godot/imported/example2.png-2e3a8f9cd1e178daf22b83dc0513f37a.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/Todo_Manager/doc/images/example2.png"
dest_files=["res://.godot/imported/example2.png-2e3a8f9cd1e178daf22b83dc0513f37a.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
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/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
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

View File

@ -1,7 +0,0 @@
[plugin]
name="Todo Manager"
description="Dock for managing TODO messages and other notes in your code."
author="Peter de Vroom"
version="2.5.0"
script="plugin.gd"

View File

@ -1,295 +0,0 @@
@tool
extends EditorPlugin
const DockScene := preload("res://addons/Todo_Manager/UI/Dock.tscn")
const Dock := preload("res://addons/Todo_Manager/Dock.gd")
const Todo := preload("res://addons/Todo_Manager/todo_class.gd")
const TodoItem := preload("res://addons/Todo_Manager/todoItem_class.gd")
var _dockUI : Dock
class TodoCacheValue:
var todos: Array
var last_modified_time: int
func _init(todos: Array, last_modified_time: int):
self.todos = todos
self.last_modified_time = last_modified_time
var todo_cache : Dictionary # { key: script_path, value: TodoCacheValue }
var remove_queue : Array
var combined_pattern : String
var cased_patterns : Array[String]
var refresh_lock := false # makes sure _on_filesystem_changed only triggers once
func _enter_tree() -> void:
_dockUI = DockScene.instantiate() as Control
add_control_to_bottom_panel(_dockUI, "TODO")
get_editor_interface().get_resource_filesystem().connect("filesystem_changed",
_on_filesystem_changed)
get_editor_interface().get_file_system_dock().connect("file_removed", queue_remove)
get_editor_interface().get_script_editor().connect("editor_script_changed",
_on_active_script_changed)
_dockUI.plugin = self
var filtered_patterns = _dockUI.patterns.filter(func (p): return p[3] == true)
if filtered_patterns.size() > 0:
combined_pattern = combine_patterns(filtered_patterns)
find_tokens_from_path(find_scripts())
_dockUI.build_tree()
func _exit_tree() -> void:
_dockUI.create_config_file()
remove_control_from_bottom_panel(_dockUI)
_dockUI.free()
func queue_remove(file: String):
for i in _dockUI.todo_items.size() - 1:
if _dockUI.todo_items[i].script_path == file:
_dockUI.todo_items.remove_at(i)
func find_tokens_from_path(scripts: Array[String]) -> void:
for script_path in scripts:
var file := FileAccess.open(script_path, FileAccess.READ)
var contents := file.get_as_text()
if script_path.ends_with(".tscn"):
handle_built_in_scripts(contents, script_path)
else:
find_tokens(contents, script_path)
func handle_built_in_scripts(contents: String, resource_path: String):
var s := contents.split("sub_resource type=\"GDScript\"")
if s.size() <= 1:
return
for i in range(1, s.size()):
var script_components := s[i].split("script/source")
var script_name = script_components[0].substr(5, 14)
find_tokens(script_components[1], resource_path + "::" + script_name)
func find_tokens(text: String, script_path: String) -> void:
var cached_todos = get_cached_todos(script_path)
if cached_todos.size() != 0:
# var i := 0
# for todo_item in _dockUI.todo_items:
# if todo_item.script_path == script_path:
# _dockUI.todo_items.remove_at(i)
# i += 1
var todo_item := TodoItem.new(script_path, cached_todos)
_dockUI.todo_items.append(todo_item)
else:
var regex = RegEx.new()
# if regex.compile("#\\s*\\bTODO\\b.*|#\\s*\\bHACK\\b.*") == OK:
if regex.compile(combined_pattern) == OK:
var result : Array[RegExMatch] = regex.search_all(text)
if result.is_empty():
for i in _dockUI.todo_items.size():
if _dockUI.todo_items[i].script_path == script_path:
_dockUI.todo_items.remove_at(i)
return # No tokens found
var match_found : bool
var i := 0
for todo_item in _dockUI.todo_items:
if todo_item.script_path == script_path:
match_found = true
var updated_todo_item := update_todo_item(todo_item, result, text, script_path)
_dockUI.todo_items.remove_at(i)
_dockUI.todo_items.insert(i, updated_todo_item)
break
i += 1
if !match_found:
_dockUI.todo_items.append(create_todo_item(result, text, script_path))
func create_todo_item(regex_results: Array[RegExMatch], text: String, script_path: String) -> TodoItem:
var todo_item = TodoItem.new(script_path, [])
todo_item.script_path = script_path
var last_line_number := 0
var lines := text.split("\n")
for r in regex_results:
var new_todo : Todo = create_todo(r.get_string(), script_path)
new_todo.line_number = get_line_number(r.get_string(), text, last_line_number)
# GD Multiline comment
var trailing_line := new_todo.line_number
var should_break = false
while trailing_line < lines.size() and lines[trailing_line].dedent().begins_with("#"):
for other_r in regex_results:
if lines[trailing_line] in other_r.get_string():
should_break = true
break
if should_break:
break
new_todo.content += "\n" + lines[trailing_line]
trailing_line += 1
last_line_number = new_todo.line_number
todo_item.todos.append(new_todo)
cache_todos(todo_item.todos, script_path)
return todo_item
func update_todo_item(todo_item: TodoItem, regex_results: Array[RegExMatch], text: String, script_path: String) -> TodoItem:
todo_item.todos.clear()
var lines := text.split("\n")
for r in regex_results:
var new_todo : Todo = create_todo(r.get_string(), script_path)
new_todo.line_number = get_line_number(r.get_string(), text)
# GD Multiline comment
var trailing_line := new_todo.line_number
var should_break = false
while trailing_line < lines.size() and lines[trailing_line].dedent().begins_with("#"):
for other_r in regex_results:
if lines[trailing_line] in other_r.get_string():
should_break = true
break
if should_break:
break
new_todo.content += "\n" + lines[trailing_line]
trailing_line += 1
todo_item.todos.append(new_todo)
return todo_item
func get_line_number(what: String, from: String, start := 0) -> int:
what = what.split('\n')[0] # Match first line of multiline C# comments
var temp_array := from.split('\n')
var lines := Array(temp_array)
var line_number# = lines.find(what) + 1
for i in range(start, lines.size()):
if what in lines[i]:
line_number = i + 1 # +1 to account of 0-based array vs 1-based line numbers
break
else:
line_number = 0 # This is an error
return line_number
func _on_filesystem_changed() -> void:
if !refresh_lock:
if _dockUI.auto_refresh:
refresh_lock = true
_dockUI.get_node("Timer").start()
rescan_files(false)
func find_scripts() -> Array[String]:
var scripts : Array[String]
var directory_queue : Array[String]
var dir := DirAccess.open("res://")
if dir.get_open_error() == OK:
get_dir_contents(dir, scripts, directory_queue)
else:
printerr("TODO_Manager: There was an error during find_scripts()")
while not directory_queue.is_empty():
if dir.change_dir(directory_queue[0]) == OK:
get_dir_contents(dir, scripts, directory_queue)
else:
printerr("TODO_Manager: There was an error at: " + directory_queue[0])
directory_queue.pop_front()
return scripts
func cache_todos(todos: Array, script_path: String) -> void:
var last_modified_time = FileAccess.get_modified_time(script_path)
todo_cache[script_path] = TodoCacheValue.new(todos, last_modified_time)
func get_cached_todos(script_path: String) -> Array:
if todo_cache.has(script_path) and !script_path.contains("tscn::"):
var cached_value: TodoCacheValue = todo_cache[script_path]
if cached_value.last_modified_time == FileAccess.get_modified_time(script_path):
return cached_value.todos
return []
func get_dir_contents(dir: DirAccess, scripts: Array[String], directory_queue: Array[String]) -> void:
dir.include_navigational = false
dir.include_hidden = false
if dir_has_gdignore(dir):
return
dir.list_dir_begin()
var file_name : String = dir.get_next()
while file_name != "":
if dir.current_is_dir():
if file_name.begins_with('.'): # Skip folders which should never have scripts
pass
else:
directory_queue.append(dir.get_current_dir().path_join(file_name))
else:
if file_name.ends_with(".gd") or file_name.ends_with(".cs") \
or file_name.ends_with(".c") or file_name.ends_with(".cpp") or file_name.ends_with(".h") \
or ((file_name.ends_with(".tscn") and _dockUI.builtin_enabled)):
scripts.append(dir.get_current_dir().path_join(file_name))
file_name = dir.get_next()
dir.list_dir_end()
func dir_has_gdignore(dir: DirAccess) -> bool:
var files = dir.get_files()
return files.has(".gdignore")
func rescan_files(clear_cache: bool) -> void:
_dockUI.todo_items.clear()
if clear_cache:
todo_cache.clear()
var filtered_patterns = _dockUI.patterns.filter(func (p): return p[3] == true)
if filtered_patterns.size() > 0:
combined_pattern = combine_patterns(filtered_patterns)
find_tokens_from_path(find_scripts())
_dockUI.build_tree()
func combine_patterns(patterns: Array) -> String:
# Case Sensitivity
cased_patterns = []
for pattern in patterns:
if pattern[2] == _dockUI.CASE_INSENSITIVE:
cased_patterns.append(pattern[0].insert(0, "((?i)") + ")")
else:
cased_patterns.append("(" + pattern[0] + ")")
var pattern_string := "((\\/\\*)|(#|\\/\\/))\\s*("
for i in range(patterns.size()):
if i == 0:
pattern_string += cased_patterns[i]
else:
pattern_string += "|" + cased_patterns[i]
pattern_string += ")(?(2)[\\s\\S]*?\\*\\/|.*)"
return pattern_string
func create_todo(todo_string: String, script_path: String) -> Todo:
var todo := Todo.new()
var regex = RegEx.new()
for pattern in cased_patterns:
if regex.compile(pattern) == OK:
var result : RegExMatch = regex.search(todo_string)
if result:
todo.pattern = pattern
todo.title = result.strings[0]
else:
continue
else:
printerr("Error compiling " + pattern)
todo.content = todo_string
todo.script_path = script_path
return todo
func _on_active_script_changed(script) -> void:
if _dockUI:
if _dockUI.tabs.current_tab == 1:
_dockUI.build_tree()

View File

@ -1 +0,0 @@
uid://cgmj81roq24r8

View File

@ -1,15 +0,0 @@
[scripts]
full_path=false
sort_alphabetical=true
script_colour=Color(0.8, 0.80784315, 0.827451, 1)
ignore_paths=Array[String](["res://addons/"])
[patterns]
patterns=[["\\bTODO\\b", Color(0.5882353, 0.94509804, 0.6784314, 1), 0, true], ["\\bHACK\\b", Color(0.8352941, 0.7372549, 0.4392157, 1), 0, true], ["\\bFIXME\\b", Color(0.8352941, 0.4392157, 0.4392157, 1), 0, true]]
[config]
auto_refresh=true
builtin_enabled=false

View File

@ -1,18 +0,0 @@
@tool
extends RefCounted
var script_path : String
var todos : Array
func _init(script_path: String, todos: Array):
self.script_path = script_path
self.todos = todos
func get_short_path() -> String:
var temp_array := script_path.rsplit('/', false, 1)
var short_path : String
if not temp_array.size() > 1:
short_path = "(!)" + temp_array[0]
else:
short_path = temp_array[1]
return short_path

View File

@ -1 +0,0 @@
uid://yao1gny5ka0a

View File

@ -1,8 +0,0 @@
@tool
extends RefCounted
var pattern : String
var title : String
var content : String
var script_path : String
var line_number : int

View File

@ -1 +0,0 @@
uid://cvxelosp5shwf

View File

@ -1,44 +0,0 @@
@tool
class_name Cursor3D
extends Marker3D
## The size of the 3D Cursor within your scene
@export var size_scale: float = 1.0
@export_group("Label Settings")
## This setting decides whether the label with the text '3D Cursor' should
## be displayed
@export var show_label: bool = true
## This setting decides whether the label should scale with the selected size
## of the 3D Cursor.
@export var scale_affect_label: bool = false
# The standard scale of the 3D Cursor. This size is chosen because of the
# size of the .png used for the cursor. Please don't touch (private var)
var _scale: float = 0.25
## The sprite of the 3D Cursor
@onready var sprite_3d: Sprite3D = $Sprite3D
## The label of the 3D Cursor
@onready var label_3d: Label3D = $Sprite3D/Label3D
func _process(delta: float) -> void:
if not Engine.is_editor_hint():
hide()
# No manual user input allowed on rotation and scale;
# Reset any user input to 0 or 1 respectively
rotation = Vector3.ZERO
scale = Vector3.ONE
# Show the label if desired
label_3d.visible = show_label
# Set the scale of the 3D Cursor
sprite_3d.scale = Vector3(_scale * size_scale, _scale * size_scale, _scale * size_scale)
if scale_affect_label:
label_3d.scale = Vector3.ONE * 4
else:
var label_scale = 1 / (_scale * size_scale)
label_3d.scale = Vector3(label_scale, label_scale, label_scale)

View File

@ -1 +0,0 @@
uid://dt04kfvdc21nb

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

View File

@ -1,41 +0,0 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cdqg3y11tiold"
path.s3tc="res://.godot/imported/3d_cursor.png-3f509e9f2ec38702e6618d6c6cc63f4d.s3tc.ctex"
metadata={
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
[deps]
source_file="res://addons/godot_3d_cursor/3d_cursor.png"
dest_files=["res://.godot/imported/3d_cursor.png-3f509e9f2ec38702e6618d6c6cc63f4d.s3tc.ctex"]
[params]
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
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/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
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

@ -1,19 +0,0 @@
[gd_scene load_steps=3 format=3 uid="uid://dfpatff4d5okj"]
[ext_resource type="Texture2D" uid="uid://brmxsn2cjdqw4" path="res://addons/godot_3d_cursor/3d_cursor.png" id="2_mnq4l"]
[ext_resource type="Script" uid="uid://dt04kfvdc21nb" path="res://addons/godot_3d_cursor/3d_cursor.gd" id="2_stis0"]
[node name="3DCursor" type="Marker3D"]
script = ExtResource("2_stis0")
[node name="Sprite3D" type="Sprite3D" parent="."]
transform = Transform3D(0.25, 0, 0, 0, 0.25, 0, 0, 0, 0.25, 0, 0, 0)
billboard = 1
no_depth_test = true
texture = ExtResource("2_mnq4l")
[node name="Label3D" type="Label3D" parent="Sprite3D"]
transform = Transform3D(4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 2.4, 0)
billboard = 1
no_depth_test = true
text = "3D Cursor"

View File

@ -1,228 +0,0 @@
@tool
class_name PieMenu
extends Control
## Emitted when the "3D Cursor to Origin" command is invoked through the [PieMenu]
signal cursor_to_origin_pressed
## Emitted when the "3D Cursor to Selected Object(s)" command is invoked through the [PieMenu]
signal cursor_to_selected_objects_pressed
## Emitted when the "Selected Object to 3D Cursor" command is invoked through the [PieMenu]
signal selected_object_to_cursor_pressed
## Emitted when the "Remove 3D Cursor from Scene" command is invoked through the [PieMenu]
signal remove_cursor_from_scene_pressed
## Emitted when the "Toggle 3D Cursor" command is invoked through the [PieMenu]
signal toggle_cursor_pressed
## The dimmed color for the selection indicator that is used if no button is hovered
const _dimmed_selection_indicator_color: Color = Color("8c8c8cFF")
## The value at which the buttons start to animate/slide if the menu is shown
var slide_start: int = 0
## The position the buttons animate/slide to
var slide_end: int = 100
## The radius of the menu. The buttons are aligned around an invisible circle
## and this is the corresponding radius.
var menu_radius: int = slide_start
## The buttons that are "loaded"
var buttons: Array[Button] = []
var _hovered_button: Button
var _show_menu_echo: bool = false
@onready var selection_indicator: Sprite2D = $SelectionIndicator
@onready var toggle_3d_cursor: Button = $Toggle3DCursor
func _process(delta: float) -> void:
#var viewport_height: int = get_viewport().size.y
#var viewport_width: int = get_viewport().size.x
# If the menu is shown animate the buttons
if visible:
menu_radius = lerp(menu_radius, slide_end, 20 * delta)
# Reset the button positions when the menu is hidden
if not visible:
menu_radius = slide_start
_show_menu_echo = true
_align_buttons()
# Load all children from the pie menu
var children = get_children()
# Get all the children that are buttons if there are no new button return
if children.filter(_is_button) == buttons:
return
# If there are new buttons repopulate the buttons list and display them
buttons.clear()
for button: Button in children.filter(_is_button):
buttons.append(button)
_align_buttons()
func _input(event: InputEvent) -> void:
if not is_visible_in_tree():
return
# If the [PieMenu] is opened the selection indicator will rotate according
# to the mouse position. If the user hovers over a button the indicator
# will change its color to white and a more dimmed color otherwise
if event is InputEventMouseMotion:
# Calculate the angle of the mouse position to the x axis
var rot: float = rad_to_deg(get_local_mouse_position().angle_to(Vector2.RIGHT)) - 45
# Apply the rotation to the indicator
selection_indicator.rotation_degrees = -rot
# If the key used to open the [PieMenu] is held down while selecting hovering
# over a button the user can invoke the buttons action by releasing the
# key (s). This does not work if the key was released prior to hovering
# over a button. This functionality is similar to the one in Blender
if not event is InputEventKey:
return
if not event.keycode == KEY_S:
return
if event.is_released() and _hovered_button == null:
_show_menu_echo = false
return
if _show_menu_echo and event.is_released():
_hovered_button.pressed.emit()
## This method should be used in conjuncton with a [Array.filter] method.
## It checks whether a node inherits from Button
func _is_button(child: Node) -> bool:
return child is Button
## This method aligns the available buttons in a circular menu by using
## some [sin] and [cos] magic
func _align_buttons() -> void:
var button_count: int = len(buttons)
for i in range(button_count):
var button: Button = buttons[i]
var theta: float = (i / float(button_count)) * TAU
var x: float = (menu_radius * cos(theta))
var y: float = (menu_radius * sin(theta)) - button.size.y / 2.0
x = x - button.size.x if x < 0 else x
button.position = Vector2(x, y)
## Connected to the corresponding UI button this method acts as a repeater
## by emitting the corresponding signal classes can listen to via a [PieMenu]
## instance
func _on_3d_cursor_to_origin_pressed() -> void:
hide()
cursor_to_origin_pressed.emit()
## Executes when the "3D Cursor to Origin" button is hovered
func _on_3d_cursor_to_origin_mouse_entered() -> void:
_hovered_button = $"3DCursorToOrigin"
_on_mouse_entered_button()
## Executes when the "3D Cursor to Origin" button is no longer hovered
func _on_3d_cursor_to_origin_mouse_exited() -> void:
_hovered_button = null
_on_mouse_exited_button()
## Connected to the corresponding UI button this method acts as a repeater
## by emitting the corresponding signal classes can listen to via a [PieMenu]
## instance
func _on_3d_cursor_to_selected_objects_pressed() -> void:
hide()
cursor_to_selected_objects_pressed.emit()
## Executes when the "3D Cursor to Selected Object(s)" button is hovered
func _on_3d_cursor_to_selected_objects_mouse_entered() -> void:
_hovered_button = $"3DCursorToSelectedObjects"
_on_mouse_entered_button()
## Executes when the "3D Cursor to Selected Object(s)" button is no longer hovered
func _on_3d_cursor_to_selected_objects_mouse_exited() -> void:
_hovered_button = null
_on_mouse_exited_button()
## Connected to the corresponding UI button this method acts as a repeater
## by emitting the corresponding signal classes can listen to via a [PieMenu]
## instance
func _on_selected_object_to_3d_cursor_pressed() -> void:
hide()
selected_object_to_cursor_pressed.emit()
## Executes when the "Selected Object to 3D Cursor" button is hovered
func _on_selected_object_to_3d_cursor_mouse_entered() -> void:
_hovered_button = $SelectedObjectTo3DCursor
_on_mouse_entered_button()
## Executes when the "Selected Object to 3D Cursor" button is no longer hovered
func _on_selected_object_to_3d_cursor_mouse_exited() -> void:
_hovered_button = null
_on_mouse_exited_button()
## Connected to the corresponding UI button this method acts as a repeater
## by emitting the corresponding signal classes can listen to via a [PieMenu]
## instance
func _on_remove_3d_cursor_from_scene_pressed() -> void:
hide()
remove_cursor_from_scene_pressed.emit()
## Executes when the "Remove 3D Cursor" button is hovered
func _on_remove_3d_cursor_from_scene_mouse_entered() -> void:
_hovered_button = $Remove3DCursorFromScene
_on_mouse_entered_button()
## Executes when the "Remove 3D Cursor" button is no longer hovered
func _on_remove_3d_cursor_from_scene_mouse_exited() -> void:
_hovered_button = null
_on_mouse_exited_button()
## Connected to the corresponding UI button this method acts as a repeater
## by emitting the corresponding signal classes can listen to via a [PieMenu]
## instance
func _on_toggle_3d_cursor_pressed() -> void:
hide()
toggle_cursor_pressed.emit()
## Executes when the "Disable/Enable 3D Cursor" button is hovered
func _on_toggle_3d_cursor_mouse_entered() -> void:
_hovered_button = toggle_3d_cursor
_on_mouse_entered_button()
## Executes when the "Disable/Enable 3D Cursor" button is hovered
func _on_toggle_3d_cursor_mouse_exited() -> void:
_hovered_button = null
_on_mouse_exited_button()
## This method is executed by every button of the [PieMenu]. It brightens
## the color of the selection indicator when a button is hovered.
func _on_mouse_entered_button() -> void:
selection_indicator.modulate = Color.WHITE
## This method is executed by every button of the [PieMenu]. It dims the color
## of the selection indicator when a button is no longer hovered
func _on_mouse_exited_button() -> void:
selection_indicator.modulate = _dimmed_selection_indicator_color
## This method is a little helper that is used to prevent some quirky behaviour
## with the consumption of events. It checks whether the user clicked on a
## button rather than the space around it
func hit_any_button() -> bool:
var mouse_position: Vector2 = get_global_mouse_position()
for button in buttons:
if button.get_global_rect().has_point(mouse_position):
return true
return false
func change_toggle_label(visible: bool) -> void:
toggle_3d_cursor.text = ("Disable" if visible else "Enable") + " 3D Cursor"

View File

@ -1 +0,0 @@
uid://dul31m8bwxlxm

View File

@ -1,119 +0,0 @@
[gd_scene load_steps=5 format=3 uid="uid://igrlue2n5478"]
[ext_resource type="Script" uid="uid://dul31m8bwxlxm" path="res://addons/godot_3d_cursor/pie_menu.gd" id="1_a7cko"]
[ext_resource type="Texture2D" uid="uid://bhift5k0v2tga" path="res://addons/godot_3d_cursor/selection_ring.png" id="2_k5qvu"]
[ext_resource type="Texture2D" uid="uid://bngw0w7d1nrgv" path="res://addons/godot_3d_cursor/selection_indicator.png" id="3_euipm"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_s5fna"]
bg_color = Color(0.145098, 0.145098, 0.145098, 0.258824)
corner_radius_top_left = 20
corner_radius_top_right = 20
corner_radius_bottom_right = 20
corner_radius_bottom_left = 20
[node name="PieMenu" type="Control"]
layout_mode = 3
anchors_preset = 8
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
grow_horizontal = 2
grow_vertical = 2
size_flags_horizontal = 4
size_flags_vertical = 4
script = ExtResource("1_a7cko")
[node name="Panel" type="Panel" parent="."]
layout_mode = 1
anchors_preset = 8
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
offset_left = -347.5
offset_top = -145.0
offset_right = 379.5
offset_bottom = 145.0
grow_horizontal = 2
grow_vertical = 2
theme_override_styles/panel = SubResource("StyleBoxFlat_s5fna")
[node name="3DCursorToSelectedObjects" type="Button" parent="."]
layout_mode = 0
offset_left = 100.0
offset_top = -15.5
offset_right = 347.0
offset_bottom = 15.5
mouse_default_cursor_shape = 2
text = "3D Cursor to Selected Object(s)"
[node name="Remove3DCursorFromScene" type="Button" parent="."]
layout_mode = 0
offset_left = 30.9017
offset_top = 79.6054
offset_right = 273.902
offset_bottom = 110.606
mouse_default_cursor_shape = 2
text = "Remove 3D Cursor from Scene"
[node name="SelectedObjectTo3DCursor" type="Button" parent="."]
layout_mode = 0
offset_left = -309.902
offset_top = 43.2785
offset_right = -80.9017
offset_bottom = 74.2785
mouse_default_cursor_shape = 2
text = "Selected Object to 3D Cursor"
[node name="3DCursorToOrigin" type="Button" parent="."]
layout_mode = 1
anchors_preset = 8
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
offset_left = -237.902
offset_top = -74.2785
offset_right = -80.9017
offset_bottom = -43.2785
grow_horizontal = 2
grow_vertical = 2
size_flags_horizontal = 0
mouse_default_cursor_shape = 2
text = "3D Cursor to Origin"
[node name="Toggle3DCursor" type="Button" parent="."]
layout_mode = 0
offset_left = 30.9017
offset_top = -110.606
offset_right = 176.902
offset_bottom = -79.6055
mouse_default_cursor_shape = 2
text = "Disable 3D Cursor"
[node name="SelectionRing" type="Sprite2D" parent="."]
modulate = Color(0.148438, 0.148438, 0.148438, 1)
scale = Vector2(0.2, 0.2)
texture = ExtResource("2_k5qvu")
[node name="SelectionIndicator" type="Sprite2D" parent="."]
modulate = Color(0.550781, 0.550781, 0.550781, 1)
scale = Vector2(0.2, 0.2)
texture = ExtResource("3_euipm")
[connection signal="mouse_entered" from="3DCursorToSelectedObjects" to="." method="_on_3d_cursor_to_selected_objects_mouse_entered"]
[connection signal="mouse_exited" from="3DCursorToSelectedObjects" to="." method="_on_3d_cursor_to_selected_objects_mouse_exited"]
[connection signal="pressed" from="3DCursorToSelectedObjects" to="." method="_on_3d_cursor_to_selected_objects_pressed"]
[connection signal="mouse_entered" from="Remove3DCursorFromScene" to="." method="_on_remove_3d_cursor_from_scene_mouse_entered"]
[connection signal="mouse_exited" from="Remove3DCursorFromScene" to="." method="_on_remove_3d_cursor_from_scene_mouse_exited"]
[connection signal="pressed" from="Remove3DCursorFromScene" to="." method="_on_remove_3d_cursor_from_scene_pressed"]
[connection signal="mouse_entered" from="SelectedObjectTo3DCursor" to="." method="_on_selected_object_to_3d_cursor_mouse_entered"]
[connection signal="mouse_exited" from="SelectedObjectTo3DCursor" to="." method="_on_selected_object_to_3d_cursor_mouse_exited"]
[connection signal="pressed" from="SelectedObjectTo3DCursor" to="." method="_on_selected_object_to_3d_cursor_pressed"]
[connection signal="mouse_entered" from="3DCursorToOrigin" to="." method="_on_3d_cursor_to_origin_mouse_entered"]
[connection signal="mouse_exited" from="3DCursorToOrigin" to="." method="_on_3d_cursor_to_origin_mouse_exited"]
[connection signal="pressed" from="3DCursorToOrigin" to="." method="_on_3d_cursor_to_origin_pressed"]
[connection signal="mouse_entered" from="Toggle3DCursor" to="." method="_on_toggle_3d_cursor_mouse_entered"]
[connection signal="mouse_exited" from="Toggle3DCursor" to="." method="_on_toggle_3d_cursor_mouse_exited"]
[connection signal="pressed" from="Toggle3DCursor" to="." method="_on_toggle_3d_cursor_pressed"]

View File

@ -1,7 +0,0 @@
[plugin]
name="Godot 3D Cursor"
description="This plugin for the Godot Engine implements a 3D cursor, offering functionality similar to Blenders 3D cursor.\n\nNote: Due to certain engine limitations, you must switch to a tab other than 3D (e.g., 2D, Script, or AssetLib) and back to 3D once after enabling this plugin, and also upon engine startup, to activate the plugin correctly.\n\nUsage: You can set the 3D cursor's position by using Shift + Right Click.\n\nVersion 1.2: The Pie Menu / Undo-Redo Update\n\nIn this update, Ive added a Pie Menu, similar to Blenders, which can be invoked with Shift + S. This menu displays commands found in the Command Palette (Ctrl + Shift + P) and offers faster access to desired functionality.\n\nAnother major feature in this version is the Undo-Redo functionality. This should be straightforward, except for the Remove 3D Cursor from Scene command, which is intentionally not undoable, as it frees the cursor object itself."
author="Marco"
version="1.3.2"
script="plugin.gd"

View File

@ -1,488 +0,0 @@
@tool
extends EditorPlugin
## This variable indicates whether the active tab is 3D
var is_in_3d_tab: bool = false
## The position of the mouse used to raycast into the 3D world
var mouse_position: Vector2
## The camera used for raycasting to calculate the position
## for the 3D cursor
var temp_camera: Camera3D
## The Editor Viewport used to get the mouse position
var editor_viewport: SubViewport
## The camera that displays what the user sees in the 3D editor tab
var editor_camera: Camera3D
## The root node of the active scene
var edited_scene_root: Node
## The scene used to instantiate the 3D Cursor
var cursor_scene: PackedScene
## The instance of the 3D Cursor
var cursor: Cursor3D
## The scene used to instantiate the pie menu for the 3D Cursor
var pie_menu_scene: PackedScene
## The instance of the pie menu for the 3D Cursor
var pie_menu: PieMenu
## A reference to the [EditorCommandPalette] singleton used to add
## some useful actions to the command palette such as '3D Cursor to Origin'
## or '3D Cursor to selected object' like in Blender
var command_palette: EditorCommandPalette
## The InputEvent holding the MouseButton event to trigger the
## set position function of the 3D Cursor
var input_event_set_3d_cursor: InputEventMouseButton
var input_event_show_pie_menu: InputEventKey
## The boolean that ensures the _recover_cursor function is executed once
var cursor_set: bool = false
## The instance of the Undo Redo class
var undo_redo: EditorUndoRedoManager
func _enter_tree() -> void:
# Register the switching of tabs in the editor. We only want the
# 3D Cursor functionality within the 3D tab
connect("main_screen_changed", _on_main_scene_changed)
# We want to place newly added Nodes that inherit [Node3D] at
# the location of the 3D Cursor. Therefore we listen to the
# node_added event
get_tree().connect("node_added", _on_node_added)
# Loading the 3D Cursor scene for later instancing
cursor_scene = preload("res://addons/godot_3d_cursor/3d_cursor.tscn")
pie_menu_scene = preload("res://addons/godot_3d_cursor/pie_menu.tscn")
command_palette = EditorInterface.get_command_palette()
# Adding the previously mentioned actions
command_palette.add_command("3D Cursor to Origin", "3D Cursor/3D Cursor to Origin", _3d_cursor_to_origin)
command_palette.add_command("3D Cursor to Selected Object", "3D Cursor/3D Cursor to Selected Object", _3d_cursor_to_selected_objects)
command_palette.add_command("Selected Object to 3D Cursor", "3D Cursor/Selected Object to 3D Cursor", _selected_object_to_3d_cursor)
# Adding the remove 3D Cursor in Scene action
command_palette.add_command("Remove 3D Cursor from Scene", "3D Cursor/Remove 3D Cursor from Scene", _remove_3d_cursor_from_scene)
command_palette.add_command("Toggle 3D Cursor", "3D Cursor/Toggle 3D Cursor", _toggle_3d_cursor)
editor_viewport = EditorInterface.get_editor_viewport_3d()
editor_camera = editor_viewport.get_camera_3d()
# Get the reference to the UndoRedo instance of the editor
undo_redo = get_undo_redo()
# Instantiating the pie menu for the 3D Cursor commands
pie_menu = pie_menu_scene.instantiate()
pie_menu.hide()
# Connecting the button events from the pie menu to the corresponding function
pie_menu.connect("cursor_to_origin_pressed", _3d_cursor_to_origin)
pie_menu.connect("cursor_to_selected_objects_pressed", _3d_cursor_to_selected_objects)
pie_menu.connect("selected_object_to_cursor_pressed", _selected_object_to_3d_cursor)
pie_menu.connect("remove_cursor_from_scene_pressed", _remove_3d_cursor_from_scene)
pie_menu.connect("toggle_cursor_pressed", _toggle_3d_cursor)
add_child(pie_menu)
# Setting up the InputMap so that we can set the 3D Cursor
# by Shift + Right Click
if not InputMap.has_action("3d_cursor_set_location"):
InputMap.add_action("3d_cursor_set_location")
input_event_set_3d_cursor = InputEventMouseButton.new()
input_event_set_3d_cursor.button_index = MOUSE_BUTTON_RIGHT
InputMap.action_add_event("3d_cursor_set_location", input_event_set_3d_cursor)
# Adding the action that shows the pie menu for the 3D Cursor commands.
if not InputMap.has_action("3d_cursor_show_pie_menu"):
InputMap.add_action("3d_cursor_show_pie_menu")
input_event_show_pie_menu = InputEventKey.new()
input_event_show_pie_menu.keycode = KEY_S
InputMap.action_add_event("3d_cursor_show_pie_menu", input_event_show_pie_menu)
func _exit_tree() -> void:
# Removing listeners
disconnect("main_screen_changed", _on_main_scene_changed)
get_tree().disconnect("node_added", _on_node_added)
pie_menu.disconnect("cursor_to_origin_pressed", _3d_cursor_to_origin)
pie_menu.disconnect("cursor_to_selected_objects_pressed", _3d_cursor_to_selected_objects)
pie_menu.disconnect("selected_object_to_cursor_pressed", _selected_object_to_3d_cursor)
pie_menu.disconnect("remove_cursor_from_scene_pressed", _remove_3d_cursor_from_scene)
pie_menu.disconnect("toggle_cursor_pressed", _toggle_3d_cursor)
# Removing the actions from the [EditorCommandPalette]
command_palette.remove_command("3D Cursor/3D Cursor to Origin")
command_palette.remove_command("3D Cursor/3D Cursor to Selected Object")
command_palette.remove_command("3D Cursor/Selected Object to 3D Cursor")
command_palette.remove_command("3D Cursor/Remove 3D Cursor from Scene")
command_palette.remove_command("3D Cursor/Toggle 3D Cursor")
command_palette = null
# Removing the '3D Cursor set Location' action from the InputMap
if InputMap.has_action("3d_cursor_set_location"):
InputMap.action_erase_event("3d_cursor_set_location", input_event_set_3d_cursor)
InputMap.erase_action("3d_cursor_set_location")
# Removing the 'Show Pie Menu' action from the InputMap
if InputMap.has_action("3d_cursor_show_pie_menu"):
InputMap.action_erase_event("3d_cursor_show_pie_menu", input_event_show_pie_menu)
InputMap.erase_action("3d_cursor_show_pie_menu")
# Removing and freeing the helper objects
if temp_camera != null and editor_viewport != null:
editor_viewport.remove_child(temp_camera)
temp_camera.queue_free()
# Deleting the 3D Cursor
if cursor != null:
cursor.queue_free()
cursor_scene = null
# Deleting the pie menu
if pie_menu != null:
pie_menu.queue_free()
pie_menu_scene = null
func _process(delta: float) -> void:
# Only allow setting the 3D Cursors location in 3D tab
if not is_in_3d_tab:
return
# If the action is not yet set up: return
if not InputMap.has_action("3d_cursor_set_location"):
return
# Set the location of the 3D Cursor
if Input.is_key_pressed(KEY_SHIFT) and Input.is_action_just_pressed("3d_cursor_set_location"):
mouse_position = editor_viewport.get_mouse_position()
_get_selection()
if cursor == null or not cursor.is_inside_tree():
return
if Input.is_key_pressed(KEY_SHIFT) and Input.is_action_just_pressed("3d_cursor_show_pie_menu"):
pie_menu.visible = not pie_menu.visible
_set_visibility_toggle_label()
func _input(event: InputEvent) -> void:
if event.is_released():
return
if not pie_menu.visible:
return
if pie_menu.hit_any_button():
return
if event is InputEventKey and event.keycode == KEY_S and event.is_echo():
return
if event is InputEventKey or event is InputEventMouseButton:
pie_menu.hide()
# CAUTION: Do not mess with this statement! It can render your editor
# responseless. If it happens remove the plugin and restart the engine.
editor_viewport.set_input_as_handled()
## Checks whether the current active tab is named '3D'
## returns true if so, otherwise false
func _on_main_scene_changed(screen_name: String) -> void:
is_in_3d_tab = screen_name == "3D"
## Connected to the node_added event of the get_tree()
func _on_node_added(node: Node) -> void:
if not _cursor_available():
return
if EditorInterface.get_edited_scene_root() != cursor.owner:
return
if node.name == cursor.name:
return
if cursor.is_ancestor_of(node):
return
if not node is Node3D:
return
# Apply the position of the new node to the 3D Cursors position if the
# 3D cursor is available, the node is not the 3D cursor itself, the node
# is no descendant of the 3D Cursor and the node inherits [Node3D]
node.global_position = cursor.global_position
## Set the postion of the 3D Cursor to the origin (or [Vector3.ZERO])
func _3d_cursor_to_origin() -> void:
if not _cursor_available():
return
_create_undo_redo_action(
cursor,
"global_position",
Vector3.ZERO,
"Move 3D Cursor to Origin",
)
## Set the position of the 3D Cursor to the selected object and if multiple
## Nodes are selected to the average of the positions of all selected nodes
## that inherit [Node3D]
func _3d_cursor_to_selected_objects() -> void:
if not _cursor_available():
return
# Get the selection and through this the selected nodes as an Array of Nodes
var selection: EditorSelection = EditorInterface.get_selection()
var selected_nodes: Array[Node] = selection.get_selected_nodes()
if selected_nodes.is_empty():
return
if selected_nodes.size() == 1 and not selected_nodes.front() is Node3D:
return
# If only one Node is selected and it inherits Node3D set the position
# of the 3D Cursor to its position
if selected_nodes.size() == 1:
_create_undo_redo_action(
cursor,
"global_position",
selected_nodes.front().global_position,
"Move 3D Cursor to selected Object",
)
return
# Introduce a count variable to keep track of the amount of valid positions
# to calculate the average position later
var count = 0
var position_sum: Vector3 = Vector3.ZERO
for node in selected_nodes:
if not (node is Node3D or node is Cursor3D):
continue
# If the node is a valid object increment count and add the position
# to position_sum
count += 1
position_sum += node.global_position
if count == 0:
return
# Calculate the average position for multiple selected Nodes and set
# the 3D Cursor to this position
var average_position = position_sum / count
_create_undo_redo_action(
cursor,
"global_position",
average_position,
"Move 3D Cursor to selected Objects",
)
cursor.global_position = average_position
## Set the position of the selected object that inherits [Node3D]
## to the position of the 3D Cursor. If multiple nodes are selected the first
## valid node (i.e. a node that inherits [Node3D]) will be moved to
## position of the 3D Cursor. This funcitonality is disabled if the cursor
## is not set or hidden in the scene.
func _selected_object_to_3d_cursor() -> void:
if not _cursor_available():
return
# Get the selection and through this the selected nodes as an Array of Nodes
var selection: EditorSelection = EditorInterface.get_selection()
var selected_nodes: Array[Node] = selection.get_selected_nodes()
if selected_nodes.is_empty():
return
if selected_nodes.size() == 1 and not selected_nodes.front() is Node3D:
return
selected_nodes = selected_nodes.filter(func(node): return node is Node3D and not node is Cursor3D)
if selected_nodes.is_empty():
return
_create_undo_redo_action(
selected_nodes.front(),
"global_position",
cursor.global_position,
"Move Object to 3D Cursor"
)
## Disable the 3D Cursor to prevent the node placement at the position of
## the 3D Cursor.
func _toggle_3d_cursor() -> void:
if not _cursor_available(true):
return
cursor.visible = not cursor.visible
_set_visibility_toggle_label()
## Sets the correct label on the toggle visibility button in the pie menu
func _set_visibility_toggle_label() -> void:
pie_menu.change_toggle_label(cursor.visible)
## Remove every 3D Cursor from the scene including the active one.
func _remove_3d_cursor_from_scene() -> void:
if cursor == null:
return
# Remove the active 3D Cursor
cursor.queue_free()
cursor = null
# Get the root nodes children to filter for old instances of [Cursor3D]
var root_children = edited_scene_root.get_children()
if root_children.any(func(node): return node is Cursor3D):
# Iterate over all old instances and free them
for old_cursor: Cursor3D in root_children.filter(func(node): return node is Cursor3D):
old_cursor.queue_free()
## Check whether the 3D Cursor is set up and ready for use. A hidden 3D Cursor
## should also disable its functionality. Therefore this function yields false
## if the cursor is hidden in the scene
func _cursor_available(ignore_hidden = false) -> bool:
# CAUTION: Do not mess with this statement! It can render your editor
# responseless. If it happens remove the plugin and restart the engine.
editor_viewport.set_input_as_handled()
if cursor == null:
return false
if not cursor.is_inside_tree():
return false
if ignore_hidden and not cursor.is_visible_in_tree():
return true
if not cursor.is_visible_in_tree():
return false
return true
## This function uses raycasting to determine the position of the mouse click
## to set the position of the 3D Cursor. This means that it is necessary for
## the clicked on objects to have a collider the raycast can hit
func _get_selection() -> void:
# If the scene is switched stop
if edited_scene_root != null and edited_scene_root != EditorInterface.get_edited_scene_root() and cursor != null:
# Reset scene root, viewport and camera for new scene
edited_scene_root = null
editor_viewport = EditorInterface.get_editor_viewport_3d()
editor_camera = editor_viewport.get_camera_3d()
# Clear the 3D Cursor on the old screen.
cursor.queue_free()
cursor = null
if not cursor_set:
_recover_cursor()
if temp_camera == null:
# Set up the temp_camera to resemble the one of the 3D Viewport
_create_temp_camera()
# Get the transform of the camera from the 3D Viewport
var editor_camera_transform = _get_editor_camera_transform()
# Position the temp_camera so that it is exactly where the 3D Viewport
# camera is located
temp_camera.global_transform = editor_camera_transform
# if the editor_camera_transform is Transform3D.IDENTITY that means
# that for some reason the editor_camera is null.
if editor_camera_transform == Transform3D.IDENTITY:
return
# Set up the raycast parameters
var ray_origin = temp_camera.project_ray_origin(mouse_position)
var ray_end = temp_camera.project_position(mouse_position, 1000)
var ray_length = 1000
if edited_scene_root == null:
edited_scene_root = EditorInterface.get_edited_scene_root()
# The space state where the raycast should be performed in
var space_state = edited_scene_root.get_world_3d().direct_space_state
# Perform a raycast with the parameters above and store the result
var result = space_state.intersect_ray(PhysicsRayQueryParameters3D.create(ray_origin, ray_end))
var just_created: bool = false
# When the cursor is not yet created instantiate it, add it to the scene
# and position it at the collision detected by the raycast
if cursor == null:
cursor = cursor_scene.instantiate()
edited_scene_root.add_child(cursor)
cursor.owner = edited_scene_root
just_created = true
# If the cursor is not in the node tree at this point it means that the
# user probably deleted it. Then add it again
if not cursor.is_inside_tree():
edited_scene_root.add_child(cursor)
cursor.owner = edited_scene_root
just_created = true
# No collision means do nothing
if result.is_empty():
return
if just_created:
# Position the 3D Cursor to the position of the collision
cursor.global_transform.origin = result.position
return
_create_undo_redo_action(
cursor,
"global_position",
result.position,
"Set Position for 3D Cursor"
)
## This function creates the temp_camera and sets it up so that it resembles
## the camera from 3D Tab itself
func _create_temp_camera() -> void:
temp_camera = Camera3D.new()
temp_camera.hide()
# Add the temp_camera to the editor_viewport so that we can perform raycasts
# later on
editor_viewport.add_child(temp_camera)
# These are the most important settings the temp_camera needs to copy
# from the editor_camera so that their image is congruent
temp_camera.fov = editor_camera.fov
temp_camera.near = editor_camera.near
temp_camera.far = editor_camera.far
## This function returns the transform of the camera from the 3D Editor itself
func _get_editor_camera_transform() -> Transform3D:
if editor_camera != null:
return editor_camera.get_camera_transform()
return Transform3D.IDENTITY
## This function recovers any 3D Cursor present in the scene if you reload
## the project
func _recover_cursor() -> void:
# This boolean ensures this function is run exactly once
cursor_set = true
# Gets the children of the active scenes root node
var root_children = EditorInterface.get_edited_scene_root().get_children()
# Checks whether there are any nodes of type [Cursor3D] in the list of
# children
if root_children.any(func(node): return node is Cursor3D):
# Get the first and probably only instance of [Cursor3D] and assign
# it to the cursor variable. Now the 3D Cursor is considered recovered
cursor = root_children.filter(func(node): return node is Cursor3D).front()
func _create_undo_redo_action(node: Node3D, property: String, value: Variant, action_name: String = "") -> void:
if node == null or property.is_empty() or value == null:
return
if action_name.is_empty():
action_name = "Set " + property + " for " + node.name
undo_redo.create_action(action_name)
var old_value: Variant = node.get(property)
undo_redo.add_do_property(node, property, value)
undo_redo.add_undo_property(node, property, old_value)
undo_redo.commit_action()

View File

@ -1 +0,0 @@
uid://bjeulwhnkq10f

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

View File

@ -1,40 +0,0 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://r1rpga7n1quy"
path="res://.godot/imported/selection_indicator.png-2775b0425d2acc692b5fb62566ad8521.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/godot_3d_cursor/selection_indicator.png"
dest_files=["res://.godot/imported/selection_indicator.png-2775b0425d2acc692b5fb62566ad8521.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
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/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
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.

Before

Width:  |  Height:  |  Size: 7.1 KiB

View File

@ -1,40 +0,0 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dd7qbrp08e8qe"
path="res://.godot/imported/selection_ring.png-dfbd0ecaedb53139c0c4b6c57699fb8f.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/godot_3d_cursor/selection_ring.png"
dest_files=["res://.godot/imported/selection_ring.png-dfbd0ecaedb53139c0c4b6c57699fb8f.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
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/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
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

View File

@ -64,8 +64,8 @@ func toggle_3d_collision_shape_visibility() -> void:
or node is GPUParticlesCollisionBox3D \ or node is GPUParticlesCollisionBox3D \
or node is GPUParticlesCollisionHeightField3D \ or node is GPUParticlesCollisionHeightField3D \
or node is GPUParticlesCollisionSDF3D \ or node is GPUParticlesCollisionSDF3D \
or node is GPUParticlesCollisionSphere3D:# \ or node is GPUParticlesCollisionSphere3D \
#or node is CSGPrimitive3D: or node is CSGPrimitive3D:
# remove and re-add the node to the tree to force a redraw # remove and re-add the node to the tree to force a redraw
# https://github.com/godotengine/godot/blob/26b1fd0d842fa3c2f090ead47e8ea7cd2d6515e1/scene/3d/collision_object_3d.cpp#L39 # https://github.com/godotengine/godot/blob/26b1fd0d842fa3c2f090ead47e8ea7cd2d6515e1/scene/3d/collision_object_3d.cpp#L39
var parent: Node = node.get_parent() var parent: Node = node.get_parent()

View File

@ -1,27 +0,0 @@
# ProtoShape tooling
## Shapes
- [ProtoRamp](proto_ramp/README.md)
## Gizmos
The gizmo for `ProtoRamp` supports setting 3 properties:
- Width
- Height
- Depth
It utilizes `ProtoGizmoUtils` for advanced 3D math calculations and plane projections to get the desired handle drag offset and set the properties accordingly.
### Undo/Redo support
[ProtoRampGizmos](proto_ramp/proto_ramp_gizmos.gd) supports scene-wide undo/redo functionality. It uses the `EditorUndoRedoManager` to set up ramp properties, so the editor takes gizmo-based modifications into account! Editor now warns you to save on exit if you have unsaved changes made with the gizmos.
### [ProtoGizmoWrapper](proto_gizmo_wrapper/README.md)
`ProtoGizmoWrapper` is an advanced wrapper for creating gizmo functionality for custom 3D nodes. It exposes 2 signals to implement custom gizmos for your nodes to *redraw* and *update* the properties of your node.
The gizmo is an `EditorNode3DGizmoPlugin` and is visible when the `ProtoRamp` node or a children of `ProtoGizmoWrapper` is selected. Selection hightlights the mesh with a transparent blue color and shows handles, which you can drag to adjust the shape.
https://github.com/HLCaptain/proto-shape/assets/22623259/1db3f18d-4d90-400f-9d33-7b03d44f62c7

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1007 B

View File

@ -1,41 +0,0 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bkrb0hpbnnlve"
path.s3tc="res://.godot/imported/proto-gizmo-handler.png-4cc70ab2e8b20344f35efde1c0e3d8c1.s3tc.ctex"
metadata={
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
[deps]
source_file="res://addons/proto_shape/icon/proto-gizmo-handler.png"
dest_files=["res://.godot/imported/proto-gizmo-handler.png-4cc70ab2e8b20344f35efde1c0e3d8c1.s3tc.ctex"]
[params]
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
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/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
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

@ -1,51 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="24"
height="24"
version="1.1"
id="svg2"
sodipodi:docname="proto-gizmo-handler.svg"
inkscape:version="1.4-beta (62f545ba5e, 2024-04-22)"
inkscape:export-filename="proto-gizmo-handlers.png"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96"
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">
<defs
id="defs2" />
<sodipodi:namedview
id="namedview2"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="20.771262"
inkscape:cx="17.837145"
inkscape:cy="13.359805"
inkscape:window-width="2560"
inkscape:window-height="1369"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="svg2" />
<circle
cx="12"
cy="12"
fill-opacity="0.294"
id="circle1"
style="stroke-width:2.4"
r="12" />
<circle
cx="12"
cy="12"
fill="#ff5f5f"
stroke="#ffffff"
id="circle2"
style="fill:#8da5ff;fill-opacity:1;stroke-width:2.4"
r="8.3999996" />
</svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -1,43 +0,0 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dpo2412p634n8"
path="res://.godot/imported/proto-gizmo-handler.svg-450f3c4251bc782c6a7cb75ed4928a42.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/proto_shape/icon/proto-gizmo-handler.svg"
dest_files=["res://.godot/imported/proto-gizmo-handler.svg-450f3c4251bc782c6a7cb75ed4928a42.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
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/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
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.

Before

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -1,40 +0,0 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://5cxcoew7dwry"
path="res://.godot/imported/proto-gizmo-wrapper-icon-mini.png-1a69b62ae400df904dfb4e09a5f63122.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/proto_shape/icon/proto-gizmo-wrapper-icon-mini.png"
dest_files=["res://.godot/imported/proto-gizmo-wrapper-icon-mini.png-1a69b62ae400df904dfb4e09a5f63122.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
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/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
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.

Before

Width:  |  Height:  |  Size: 13 KiB

View File

@ -1,40 +0,0 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://yd88id1ixiwv"
path="res://.godot/imported/proto-gizmo-wrapper-icon.png-74f8ebc9cdc56ecf6bd0c731cb0bf5b3.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/proto_shape/icon/proto-gizmo-wrapper-icon.png"
dest_files=["res://.godot/imported/proto-gizmo-wrapper-icon.png-74f8ebc9cdc56ecf6bd0c731cb0bf5b3.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
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/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
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

View File

@ -1,81 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="16"
height="16"
viewBox="0 0 4.2333333 4.2333333"
version="1.1"
id="svg1"
sodipodi:docname="proto-gizmo-wrapper-icon.svg"
inkscape:version="1.4-beta (62f545ba5e, 2024-04-22)"
inkscape:export-filename="proto-gizmo-wrapper-icon-mini.png"
inkscape:export-xdpi="144"
inkscape:export-ydpi="144"
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="namedview1"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="true"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
inkscape:zoom="32"
inkscape:cx="7"
inkscape:cy="5.796875"
inkscape:window-width="2560"
inkscape:window-height="1369"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="layer1"
showgrid="false" />
<defs
id="defs1" />
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="matrix(0.01570519,0,0,0.01570519,-0.01085763,-0.01086595)">
<path
id="path2"
style="display:none;fill:none;fill-opacity:0.137324;stroke:#000000;stroke-width:11.1125;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:0.3;paint-order:fill markers stroke"
inkscape:transform-center-x="-2.1913894e-06"
d="m 125.59893,11.847581 -5.87813,30.705801 c -0.31705,1.656156 -4.01587,2.484026 -4.9426,1.075243 L 97.475068,17.325206 c -3.659186,-5.562533 -19.740202,1.18625 -18.394101,7.706781 l 6.310354,30.567427 c 0.344133,1.666987 -2.754458,3.911949 -4.162986,2.956089 L 55.099247,40.823705 C 49.607182,37.096662 37.314199,49.388504 41.041586,54.880057 l 17.733448,26.126658 c 0.955949,1.408397 -1.289222,4.5067 -2.956364,4.1626 L 25.248399,78.859547 c -6.521137,-1.345976 -13.270548,14.733546 -7.707496,18.39239 l 26.305865,17.301513 c 1.408914,0.92665 0.580966,4.62513 -1.075345,4.94214 l -30.708656,5.87759 c -7.8363854,1.49989 -7.6699653,18.5043 0,19.97232 l 30.708656,5.87758 c 1.656311,0.31703 2.484259,4.0155 1.075345,4.94215 l -26.305865,17.30151 c -5.563052,3.65884 1.186357,19.73838 7.707496,18.39239 l 30.570271,-6.30978 c 1.667142,-0.34409 3.912313,2.7542 2.956364,4.16261 l -17.733448,26.12667 c -3.727386,5.49155 8.565594,17.78339 14.057661,14.05636 l 26.129088,-17.73182 c 1.408528,-0.95585 4.507119,1.28911 4.162986,2.9561 l -6.310354,30.56742 c -1.346101,6.52053 14.734915,13.26931 18.394101,7.70678 L 114.7782,227.09006 c 0.92673,-1.40878 4.62555,-0.58092 4.9426,1.07524 l 5.87813,30.7058 c 1.50001,7.83565 18.50603,7.66924 19.97418,0 l 5.87812,-30.7058 c 0.31705,-1.65616 4.01588,-2.48402 4.94261,-1.07524 l 17.30312,26.30341 c 3.65919,5.56253 19.74021,-1.18625 18.39411,-7.70678 l -6.31037,-30.56742 c -0.34413,-1.66699 2.75446,-3.91195 4.16299,-2.9561 l 26.12909,17.73182 c 5.49208,3.72703 17.78506,-8.56481 14.05767,-14.05636 L 212.397,189.71196 c -0.95594,-1.40841 1.28922,-4.5067 2.95636,-4.16261 l 30.57027,6.30978 c 6.52114,1.34599 13.27056,-14.73355 7.70749,-18.39239 l -26.30586,-17.30151 c -1.4089,-0.92665 -0.58097,-4.62512 1.07534,-4.94215 l 30.70867,-5.87758 c 8.68099,-1.66153 5.98046,-18.82752 0.2815,-19.9183 l -30.99017,-5.93161 c -1.65629,-0.31701 -2.48424,-4.01549 -1.07534,-4.94214 L 253.7681,97.161909 c 5.54137,-3.64458 -1.10705,-19.692922 -7.60276,-18.35212 l -30.81198,6.36 c -1.66727,0.344146 -3.91238,-2.754572 -2.95636,-4.163074 l 17.75572,-26.159356 c 3.72463,-5.48746 -8.55926,-17.770207 -14.04724,-14.045928 l -26.16179,17.754072 c -1.40863,0.955933 -4.50763,-1.288982 -4.16345,-2.956089 l 6.36057,-30.809108 c 1.34094,-6.495104 -14.70888,-13.142911 -18.35379,-7.602051 l -17.39318,26.44037 c -0.92673,1.408783 -4.62556,0.580911 -4.94261,-1.075243 l -5.93215,-30.987289 c -1.37881,-7.2024177 -18.51277,-7.0703436 -19.92015,0.281488 z"
sodipodi:nodetypes="sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss" />
<path
id="path2-5"
style="display:none;fill:#ffffff;fill-opacity:1;stroke:#b4b4b4;stroke-width:24.3401;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke"
inkscape:transform-center-x="-2.363361e-06"
d="m 113.09293,23.444456 c -8.04551,1.603632 -16.995544,-4.331742 -24.581627,-1.208716 -7.611041,3.1333 -9.804775,13.670088 -16.66062,18.224526 -6.846479,4.548216 -17.412977,2.471313 -23.22596,8.282489 -5.816562,5.814755 -3.742882,16.387597 -8.294811,23.237685 -4.552052,6.850272 -15.077148,9.044823 -18.210588,16.649358 -3.126689,7.588152 2.781683,16.540592 1.192533,24.592352 -1.589747,8.05478 -10.449551,14.09338 -10.450495,22.30354 -9.44e-4,8.21356 8.860022,14.25693 10.449696,22.31519 1.58763,8.04789 -4.314249,16.99512 -1.190745,24.58017 3.132678,7.60732 13.654906,9.81017 18.20769,16.6627 4.549095,6.84698 2.485402,17.41054 8.298101,23.22328 5.812659,5.8127 16.376118,3.74916 23.223055,8.29823 6.852584,4.55282 9.055571,15.07502 16.662965,18.20769 7.585061,3.12347 16.532276,-2.77838 24.580176,-1.19077 8.05829,1.58965 14.10171,10.45057 22.3153,10.44961 8.21012,-9.6e-4 14.24869,-8.8607 22.30342,-10.45043 8.05179,-1.58914 17.00425,4.31929 24.59243,1.19261 7.60459,-3.13344 9.7992,-13.65855 16.6495,-18.21064 6.85002,-4.55191 17.42277,-2.47837 23.23744,-8.29492 5.8112,-5.81308 3.73417,-16.37971 8.28245,-23.22624 4.55438,-6.85573 15.09109,-9.04929 18.22442,-16.66019 3.12311,-7.58608 -2.81217,-16.53618 -1.20851,-24.58172 1.60996,-8.07711 10.5799,-14.09102 10.58251,-22.32702 0.003,-8.21804 -8.95934,-14.22147 -10.54533,-22.28502 -1.58898,-8.07874 4.46221,-17.053786 1.32245,-24.665144 -3.14287,-7.61889 -13.76673,-9.723175 -18.34604,-16.575549 -4.57477,-6.845575 -2.46622,-17.446457 -8.28816,-23.268438 -5.8219,-5.821946 -16.4227,-3.713547 -23.26824,-8.28828 -6.85251,-4.579395 -8.95698,-15.203401 -16.57606,-18.346244 -7.61133,-3.139645 -16.58622,2.911713 -24.6649,1.322784 -8.06357,-1.585959 -14.06696,-10.548033 -22.28502,-10.545443 -8.23601,0.0026 -14.2499,8.972617 -22.32703,10.58255 z"
sodipodi:nodetypes="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" />
<path
sodipodi:type="star"
style="fill:#ffffff;fill-opacity:1;stroke:#b4b4b4;stroke-width:1.61;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-dashoffset:0;paint-order:fill markers stroke"
id="path1"
inkscape:flatsided="false"
sodipodi:sides="12"
sodipodi:cx="8"
sodipodi:cy="8"
sodipodi:r1="7.25"
sodipodi:r2="5.8363571"
sodipodi:arg1="-1.5707963"
sodipodi:arg2="-1.3089969"
inkscape:rounded="0.19871627"
inkscape:randomized="0"
d="m 8.0000002,0.75 c 0.439068,1e-8 1.0864532,1.4988728 1.5105603,1.612512 C 9.9346676,2.4761511 11.244756,1.5017819 11.625,1.7213159 c 0.380244,0.219534 0.19146,1.8412886 0.501928,2.1517565 0.310468,0.310468 1.932222,0.1216837 2.151756,0.5019278 0.219534,0.380244 -0.754835,1.6903325 -0.641196,2.1144396 C 13.751127,6.9135469 15.25,7.5609322 15.25,8.0000002 c 0,0.439068 -1.498873,1.0864532 -1.612512,1.5105603 -0.113639,0.4241071 0.86073,1.7341955 0.641196,2.1144395 -0.219534,0.380244 -1.841288,0.19146 -2.151756,0.501928 C 11.81646,12.437396 12.005244,14.05915 11.625,14.278684 11.244756,14.498218 9.9346673,13.523849 9.5105602,13.637488 9.0864531,13.751127 8.4390678,15.25 7.9999998,15.25 7.5609318,15.25 6.9135466,13.751127 6.4894395,13.637488 6.0653324,13.523849 4.7552438,14.498218 4.3749998,14.278684 3.9947558,14.05915 4.1835401,12.437396 3.8730722,12.126928 3.5626043,11.81646 1.9408497,12.005244 1.7213157,11.625 1.5017818,11.244756 2.476151,9.9346673 2.3625119,9.5105602 2.2488727,9.0864531 0.74999999,8.4390678 0.75,7.9999998 0.75000001,7.5609318 2.2488728,6.9135466 2.362512,6.4894395 2.4761511,6.0653324 1.5017819,4.7552438 1.7213159,4.3749998 1.9408499,3.9947558 3.5626045,4.1835401 3.8730724,3.8730722 4.1835404,3.5626043 3.9947561,1.9408497 4.3750002,1.7213157 4.7552442,1.5017818 6.0653327,2.476151 6.4894398,2.3625119 6.9135469,2.2488727 7.5609322,0.74999999 8.0000002,0.75 Z"
transform="matrix(16.732069,0,0,16.731613,1.6118621,1.6118507)" />
<circle
style="display:inline;fill:#ff5f5f;fill-opacity:1;stroke:none;stroke-width:8.81507;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill"
id="path3"
cx="135.46632"
cy="135.46684"
r="67.387489" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 8.6 KiB

View File

@ -1,43 +0,0 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bhgl0xyyytune"
path="res://.godot/imported/proto-gizmo-wrapper-icon.svg-3927e78352256edd1286e1ee01c9bee9.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/proto_shape/icon/proto-gizmo-wrapper-icon.svg"
dest_files=["res://.godot/imported/proto-gizmo-wrapper-icon.svg-3927e78352256edd1286e1ee01c9bee9.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
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/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
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.

Before

Width:  |  Height:  |  Size: 9.2 KiB

View File

@ -1,40 +0,0 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cltx6vocg7rfm"
path="res://.godot/imported/proto-ramp-icon.png-3135a56706d7082ddb1524561da4bad1.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/proto_shape/icon/proto-ramp-icon.png"
dest_files=["res://.godot/imported/proto-ramp-icon.png-3135a56706d7082ddb1524561da4bad1.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
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/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
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.

Before

Width:  |  Height:  |  Size: 73 KiB

View File

@ -1,40 +0,0 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bhqug4bqtc5ay"
path="res://.godot/imported/proto-shape-icon.png-9ff7624efc04c6128c436057018bb46d.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/proto_shape/icon/proto-shape-icon.png"
dest_files=["res://.godot/imported/proto-shape-icon.png-9ff7624efc04c6128c436057018bb46d.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
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/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
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

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 1.2 MiB

View File

@ -1,43 +0,0 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cvundrxfgnyhn"
path="res://.godot/imported/proto-shape-icon.svg-8b4b44dede01bdec8a626e48489697a9.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/proto_shape/icon/proto-shape-icon.svg"
dest_files=["res://.godot/imported/proto-shape-icon.svg-8b4b44dede01bdec8a626e48489697a9.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
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/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
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

View File

@ -1,7 +0,0 @@
[plugin]
name="ProtoShape"
description="ProtoShape is a Godot plugin that adds a library of dynamic shapes like ramps and stairs to quickly block out your maps and iterate on your ideas. Create your custom dynamic shapes more easily with the included Gizmo system."
author="Illyan"
version="1.1.5"
script="proto_shape.gd"

View File

@ -1,39 +0,0 @@
# ProtoGizmo
ProtoGizmo is an `EditorNode3DGizmoPlugin` that provides a base for creating custom gizmos in the Godot editor. It is used to create custom gizmos for the `ProtoShape` addon. With the use of `ProtoGizmoWrapper`, you can create custom gizmos for your 3D nodes.
## Default materials
- `proto_handler` - Same as internal "handlers" material for gizmo handles, but blue instead of redish color.
- `selected` - Material for selected nodes (bluish transparent color).
- `main` - Base redish color material for general or debuging use. (Used for drawing camera projected debug planes).
## ProtoGizmoUtils
ProtoGizmoUtils are advanced 3D math utilities used for calculating handle offsets and projecting planes for gizmos based on the camera position and screen coordinates. The projected plane, the user can drag the handles on can be drawn via `ProtoGizmoUtils::debug_draw_handle_grid` on gizmo *redraw*.
### Calculate handle offset in 3D space
`ProtoGizmoUtils::get_handle_offset` calculates the offset of the dragged handle in the 3D space on a camera projected plane.
Properties:
- `camera: Camera3D` - Camera used for calculating the plane the `screen_pos` is projected on.
- `screen_pos: Vector2` - Screen position of the mouse cursor.
- `local_gizmo_position: Vector3` - Gizmo position in the node's local space.
- `local_offset_axis: Vector3` - Axis the handle can be dragged on in node's local space. Used for calculating the plane the `screen_pos` is projected on.
- `node: Node3D` - Node the gizmo is attached to. Used to get global transform and position.
Returns: `Vector3` - Offset of the dragged handle in the 3D space on a camera projected plane in global space.
Unfortunately, to get the proper offsets, projections, offsets and drawing of the gizmos, some transitions must be made between the local and global space to get the result. The `camera.position` is in global space, so the `local_gizmo_position` and `local_offset_axis` must be transformed to global space to get the proper offset from projecting `screen_pos` onto a global space plane.
#### Get camera oriented plane
The global plane is created by using 3 points:
- `global_gizmo_position` - The gizmo position in global space, transformed from `local_gizmo_position` with the Node3D's `global_position` and `global_transform.basis`.
- `global_offset_axis` - The axis the handle can be dragged on in global space, transformed from `local_offset_axis` with the Node3D's `global_transform.basis`.
- A point on the line defined by `camera.position` closest to another line defined by `global_gizmo_position` and `global_offset_axis`. The line with point `camera.position` is perpendicular to the other line and its axis is the plane's normal vector, so the plane is always oriented to the camera. The calculation is found in `ProtoGizmoUtils::get_camera_oriented_plane`.
The plane can be visualized by drawing a grid with `ProtoGizmoUtils::debug_draw_handle_grid`.

View File

@ -1,81 +0,0 @@
extends EditorNode3DGizmoPlugin
const ProtoGizmoWrapper = preload("res://addons/proto_shape/proto_gizmo_wrapper/proto_gizmo_wrapper.gd")
const ProtoRamp = preload("res://addons/proto_shape/proto_ramp/proto_ramp.gd")
# Must be initialized externally by ProtoShape plugin
var undo_redo: EditorUndoRedoManager
signal snapping_changed(snapping: bool)
signal fine_snapping_changed(fine_snapping: bool)
# Must be initialized externally by ProtoShape plugin
var _snapping: bool = false
var snapping: bool: set = set_snapping, get = get_snapping
var _fine_snapping: bool = false
var fine_snapping: bool: set = set_fine_snapping, get = get_fine_snapping
func set_snapping(snapping: bool) -> void:
_snapping = snapping
snapping_changed.emit(snapping)
func set_fine_snapping(fine_snapping: bool) -> void:
_fine_snapping = fine_snapping
fine_snapping_changed.emit(fine_snapping)
func get_snapping() -> bool:
return _snapping
func get_fine_snapping() -> bool:
return _fine_snapping
func _init() -> void:
create_material("main", Color(1, 0.3725, 0.3725, 0.5))
create_material("selected", Color(0, 0, 1, 0.1))
create_handle_material("proto_handler", false, load("res://addons/proto_shape/icon/proto-gizmo-handler.png"))
func _has_gizmo(node: Node3D) -> bool:
if node.get_parent() is ProtoGizmoWrapper or node is ProtoRamp:
return true
else:
return false
func _get_gizmo_name() -> String:
return "ProtoGizmo"
func _redraw(gizmo: EditorNode3DGizmo) -> void:
var node := gizmo.get_node_3d()
if node is ProtoRamp:
node.gizmos.redraw_gizmos(gizmo, self)
return
if node.get_parent() is ProtoGizmoWrapper:
node.get_parent().redraw_gizmos_for_child(gizmo, self)
return
func _set_handle(
gizmo: EditorNode3DGizmo,
handle_id: int,
secondary: bool,
camera: Camera3D,
screen_pos: Vector2) -> void:
var node := gizmo.get_node_3d()
if node is ProtoRamp:
node.gizmos.set_handle(gizmo, self, handle_id, secondary, camera, screen_pos)
return
if node.get_parent() is ProtoGizmoWrapper:
node.get_parent().set_handle_for_child(gizmo, self, handle_id, secondary, camera, screen_pos)
return
func _commit_handle(
gizmo: EditorNode3DGizmo,
handle_id: int,
secondary: bool,
restore: Variant,
cancel: bool) -> void:
var node := gizmo.get_node_3d()
if node is ProtoRamp:
node.gizmos.commit_handle(gizmo, handle_id, secondary, restore, cancel)
return
if node.get_parent() is ProtoGizmoWrapper:
node.get_parent().commit_handle_for_child(gizmo, handle_id, secondary, restore, cancel)
return

View File

@ -1 +0,0 @@
uid://dld6sttc0b5f3

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