mirror of
https://github.com/Relintai/broken_seals.git
synced 2024-11-13 20:47:19 +01:00
Also added gdpose and godot-plugin-refresher addons.
This commit is contained in:
parent
32648325e0
commit
847640d35b
4
game/addons/.gitignore
vendored
4
game/addons/.gitignore
vendored
@ -3,4 +3,8 @@
|
||||
!module_manager/**
|
||||
!Godoxel
|
||||
!Godoxel/**
|
||||
!godot-plugin-refresher
|
||||
!godot-plugin-refresher/**
|
||||
!gdpose
|
||||
!gdpose/**
|
||||
!addon_versions
|
||||
|
@ -1,3 +1,4 @@
|
||||
Godotxel 6e3b61c2887e51c767d0c2417e0b293a35f904ac from https://github.com/aaronfranke/GraphicsEditor
|
||||
|
||||
gdpose ba80c648b04d5dc416f69d1d3bac280a2e02b3a0 from https://github.com/BastiaanOlij/gdpose
|
||||
godot-plugin-refresher e2b12f448b9fc112fd0f4acdc6de8df6180b464e from https://github.com/godot-extended-libraries/godot-plugin-refresher
|
||||
|
||||
|
21
game/addons/gdpose/LICENSE
Normal file
21
game/addons/gdpose/LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 Bastiaan Olij
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
23
game/addons/gdpose/README.md
Normal file
23
game/addons/gdpose/README.md
Normal file
@ -0,0 +1,23 @@
|
||||
# gdpose
|
||||
Plugin to make skeletons poseable in the editor
|
||||
|
||||
Note: this is still a work in progress
|
||||
|
||||
For more info see my streams on Youtube:
|
||||
- [Stream #16](https://youtu.be/LtJCLWorenc)
|
||||
- [Stream #17](https://youtu.be/zFVmMPe9Skc)
|
||||
|
||||
# TODOs
|
||||
Minimum work needed to make this more feasible:
|
||||
- Add undo feature
|
||||
- Improve bone selection menu
|
||||
- Add option to add keyframe for selected bone
|
||||
|
||||
Nice to figure out:
|
||||
- Make it possible to select bones by clicking on them
|
||||
- Make a better widget for rotations
|
||||
- Add code to determine correct direction of rotation
|
||||
|
||||
# License
|
||||
This project is provided under an MIT license.
|
||||
See LICENSE for further details.
|
32
game/addons/gdpose/SkeletonPopup.gd
Normal file
32
game/addons/gdpose/SkeletonPopup.gd
Normal file
@ -0,0 +1,32 @@
|
||||
tool
|
||||
extends MenuButton
|
||||
|
||||
var skeleton : Skeleton = null
|
||||
|
||||
func edit(new_skeleton : Skeleton):
|
||||
skeleton = new_skeleton
|
||||
|
||||
# update our menu
|
||||
var popup = get_popup()
|
||||
if popup:
|
||||
popup.clear()
|
||||
|
||||
if skeleton:
|
||||
for idx in range(0, skeleton.get_bone_count()):
|
||||
var parent = skeleton.get_bone_parent(idx)
|
||||
if parent != -1:
|
||||
var name = skeleton.get_bone_name(idx)
|
||||
popup.add_item(name, idx)
|
||||
|
||||
func select_bone(id):
|
||||
print("select bone " + str(id))
|
||||
|
||||
var gizmo : BoneSpatialGizmo = skeleton.gizmo
|
||||
if gizmo:
|
||||
gizmo.set_selected_bone(id)
|
||||
skeleton.update_gizmo()
|
||||
|
||||
func _ready():
|
||||
var popup = get_popup()
|
||||
if popup:
|
||||
popup.connect("id_pressed", self, "select_bone")
|
11
game/addons/gdpose/SkeletonPopup.tscn
Normal file
11
game/addons/gdpose/SkeletonPopup.tscn
Normal file
@ -0,0 +1,11 @@
|
||||
[gd_scene load_steps=2 format=2]
|
||||
|
||||
[ext_resource path="res://addons/gdpose/SkeletonPopup.gd" type="Script" id=1]
|
||||
|
||||
[node name="SkeletonPopup" type="MenuButton"]
|
||||
text = "GDPose"
|
||||
items = [ "Test1", null, 0, false, false, 0, 0, null, "", false, "Test2", null, 0, false, false, 1, 0, null, "", false ]
|
||||
script = ExtResource( 1 )
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
179
game/addons/gdpose/bonegizmo.gd
Normal file
179
game/addons/gdpose/bonegizmo.gd
Normal file
@ -0,0 +1,179 @@
|
||||
tool
|
||||
extends EditorSpatialGizmo
|
||||
|
||||
class_name BoneSpatialGizmo
|
||||
|
||||
var offset = 0.1
|
||||
var handle_dist = 0.1 # Distance of gizmo to bone origin
|
||||
var selected_bone = -1 # Bone we are animating
|
||||
|
||||
var is_posing = false
|
||||
var start_pose = Transform()
|
||||
var start_point = Vector2()
|
||||
|
||||
var handle_idx = Array() # Handles we've added
|
||||
|
||||
const handle_rot_x = -2
|
||||
const handle_rot_y = -3
|
||||
const handle_rot_z = -4
|
||||
|
||||
func set_selected_bone(idx):
|
||||
var skeleton : Skeleton = get_spatial_node()
|
||||
if !skeleton:
|
||||
return
|
||||
|
||||
if idx >= 0 and idx < skeleton.get_bone_count():
|
||||
selected_bone = idx
|
||||
else:
|
||||
selected_bone = -1
|
||||
|
||||
func get_handle_name(index):
|
||||
var skeleton : Skeleton = get_spatial_node()
|
||||
if !skeleton:
|
||||
return "No skeleton"
|
||||
|
||||
var idx = handle_idx[index]
|
||||
if idx == handle_rot_x:
|
||||
return "Rotate X"
|
||||
elif idx == handle_rot_y:
|
||||
return "Rotate Y"
|
||||
elif idx == handle_rot_z:
|
||||
return "Rotate Z"
|
||||
else:
|
||||
return "huh???"
|
||||
|
||||
func get_handle_value(index):
|
||||
var skeleton : Skeleton = get_spatial_node()
|
||||
if !skeleton:
|
||||
return "No skeleton"
|
||||
|
||||
var idx = handle_idx[index]
|
||||
if selected_bone >= 0:
|
||||
return skeleton.get_bone_pose(selected_bone)
|
||||
else:
|
||||
return "No selected bone"
|
||||
|
||||
func set_handle(index, camera, point):
|
||||
var idx = handle_idx[index]
|
||||
var skeleton : Skeleton = get_spatial_node()
|
||||
if !skeleton:
|
||||
return "No skeleton"
|
||||
|
||||
if !is_posing:
|
||||
start_point = point
|
||||
start_pose = skeleton.get_bone_pose(selected_bone)
|
||||
is_posing = true
|
||||
print("start posing " + str(start_pose))
|
||||
return
|
||||
|
||||
var moved = point - start_point
|
||||
var distance = moved.x + moved.y
|
||||
|
||||
# calculate our new transform (in local space)
|
||||
var new_pose : Transform = start_pose
|
||||
if idx == handle_rot_x:
|
||||
# rotate around X
|
||||
new_pose = new_pose.rotated(start_pose.basis.x.normalized(), distance * 0.01)
|
||||
elif idx == handle_rot_y:
|
||||
# rotate around Y
|
||||
new_pose = new_pose.rotated(start_pose.basis.y.normalized(), distance * 0.01)
|
||||
elif idx == handle_rot_z:
|
||||
# rotate around Z
|
||||
new_pose = new_pose.rotated(start_pose.basis.z.normalized(), distance * 0.01)
|
||||
|
||||
skeleton.set_bone_pose(selected_bone, new_pose)
|
||||
skeleton.update_gizmo()
|
||||
|
||||
func commit_handle(index, restore, cancel = false):
|
||||
# var idx = handle_idx[index]
|
||||
|
||||
print("Commit")
|
||||
is_posing = false
|
||||
|
||||
var skeleton : Skeleton = get_spatial_node()
|
||||
if !skeleton:
|
||||
return
|
||||
|
||||
if selected_bone == -1:
|
||||
return
|
||||
|
||||
if (cancel):
|
||||
skeleton.set_bone_pose(selected_bone, restore)
|
||||
|
||||
func redraw():
|
||||
clear()
|
||||
|
||||
var skeleton : Skeleton = get_spatial_node()
|
||||
if !skeleton:
|
||||
return
|
||||
|
||||
var lines_material = get_plugin().get_material("skeleton", self)
|
||||
var selected_material = get_plugin().get_material("selected", self)
|
||||
var handles_material = get_plugin().get_material("handles", self)
|
||||
var handles = PoolVector3Array()
|
||||
handle_idx.clear()
|
||||
|
||||
# loop through our bones
|
||||
for idx in range(0, skeleton.get_bone_count()):
|
||||
var parent = skeleton.get_bone_parent(idx)
|
||||
if parent != -1:
|
||||
var lines = PoolVector3Array()
|
||||
var parent_transform = skeleton.get_bone_global_pose(parent)
|
||||
var bone_transform = skeleton.get_bone_global_pose(idx)
|
||||
|
||||
var parent_pos = parent_transform.origin
|
||||
var bone_pos = bone_transform.origin
|
||||
var delta = bone_pos - parent_pos
|
||||
var length = delta.length()
|
||||
|
||||
var p1 = parent_pos + (delta * offset) + parent_transform.basis.x * length * offset
|
||||
var p2 = parent_pos + (delta * offset) + parent_transform.basis.z * length * offset
|
||||
var p3 = parent_pos + (delta * offset) - parent_transform.basis.x * length * offset
|
||||
var p4 = parent_pos + (delta * offset) - parent_transform.basis.z * length * offset
|
||||
|
||||
lines.push_back(parent_pos)
|
||||
lines.push_back(p1)
|
||||
lines.push_back(p1)
|
||||
lines.push_back(bone_pos)
|
||||
|
||||
lines.push_back(parent_pos)
|
||||
lines.push_back(p2)
|
||||
lines.push_back(p2)
|
||||
lines.push_back(bone_pos)
|
||||
|
||||
lines.push_back(parent_pos)
|
||||
lines.push_back(p3)
|
||||
lines.push_back(p3)
|
||||
lines.push_back(bone_pos)
|
||||
|
||||
lines.push_back(parent_pos)
|
||||
lines.push_back(p4)
|
||||
lines.push_back(p4)
|
||||
lines.push_back(bone_pos)
|
||||
|
||||
lines.push_back(p1)
|
||||
lines.push_back(p2)
|
||||
lines.push_back(p2)
|
||||
lines.push_back(p3)
|
||||
lines.push_back(p3)
|
||||
lines.push_back(p4)
|
||||
lines.push_back(p4)
|
||||
lines.push_back(p1)
|
||||
|
||||
if parent == selected_bone:
|
||||
add_lines(lines, selected_material, false)
|
||||
else:
|
||||
add_lines(lines, lines_material, false)
|
||||
|
||||
if idx == selected_bone:
|
||||
handles.push_back(bone_pos + bone_transform.basis.x * handle_dist)
|
||||
handle_idx.push_back(handle_rot_x)
|
||||
|
||||
handles.push_back(bone_pos + bone_transform.basis.y * handle_dist)
|
||||
handle_idx.push_back(handle_rot_y)
|
||||
|
||||
handles.push_back(bone_pos + bone_transform.basis.z * handle_dist)
|
||||
handle_idx.push_back(handle_rot_z)
|
||||
|
||||
if handles.size() > 0:
|
||||
add_handles(handles, handles_material)
|
22
game/addons/gdpose/bonegizmoplugin.gd
Normal file
22
game/addons/gdpose/bonegizmoplugin.gd
Normal file
@ -0,0 +1,22 @@
|
||||
tool
|
||||
extends EditorSpatialGizmoPlugin
|
||||
|
||||
const BoneGizmo = preload("res://addons/gdpose/bonegizmo.gd")
|
||||
|
||||
func get_name():
|
||||
return "BoneGizmo"
|
||||
|
||||
func get_priority():
|
||||
return 100
|
||||
|
||||
func create_gizmo(spatial):
|
||||
if spatial is Skeleton:
|
||||
return BoneGizmo.new()
|
||||
else:
|
||||
return null
|
||||
|
||||
func _init():
|
||||
create_material("skeleton", Color(0.6, 0.6, 0.0))
|
||||
create_material("selected", Color(1.0, 1.0, 0.0))
|
||||
create_handle_material("handles")
|
||||
|
7
game/addons/gdpose/plugin.cfg
Normal file
7
game/addons/gdpose/plugin.cfg
Normal file
@ -0,0 +1,7 @@
|
||||
[plugin]
|
||||
|
||||
name="gdpose"
|
||||
description="Pose editor"
|
||||
author="Bastiaan Olij"
|
||||
version="1"
|
||||
script="plugin.gd"
|
39
game/addons/gdpose/plugin.gd
Normal file
39
game/addons/gdpose/plugin.gd
Normal file
@ -0,0 +1,39 @@
|
||||
tool
|
||||
extends EditorPlugin
|
||||
|
||||
const BoneGizmoPlugin = preload("res://addons/gdpose/bonegizmoplugin.gd")
|
||||
const SkeletonPopup = preload("res://addons/gdpose/SkeletonPopup.tscn")
|
||||
|
||||
var skeleton_popup_instance
|
||||
var bone_gizmo = BoneGizmoPlugin.new()
|
||||
|
||||
func get_plugin_name():
|
||||
return "GD Pose Plugin"
|
||||
|
||||
func _enter_tree():
|
||||
# Initialization of the plugin goes here.
|
||||
add_spatial_gizmo_plugin(bone_gizmo)
|
||||
|
||||
# add our menu
|
||||
skeleton_popup_instance = SkeletonPopup.instance()
|
||||
add_control_to_container(EditorPlugin.CONTAINER_SPATIAL_EDITOR_MENU, skeleton_popup_instance)
|
||||
skeleton_popup_instance.visible = false
|
||||
|
||||
func _exit_tree():
|
||||
remove_spatial_gizmo_plugin(bone_gizmo)
|
||||
if skeleton_popup_instance:
|
||||
remove_control_from_container(EditorPlugin.CONTAINER_SPATIAL_EDITOR_MENU, skeleton_popup_instance)
|
||||
skeleton_popup_instance.queue_free()
|
||||
skeleton_popup_instance = null
|
||||
|
||||
func make_visible(visible):
|
||||
if skeleton_popup_instance:
|
||||
skeleton_popup_instance.visible = visible
|
||||
|
||||
func handles(object):
|
||||
return object is Skeleton
|
||||
|
||||
func edit(object):
|
||||
var skeleton : Skeleton = object
|
||||
if skeleton_popup_instance:
|
||||
skeleton_popup_instance.edit(skeleton)
|
21
game/addons/godot-plugin-refresher/LICENSE
Normal file
21
game/addons/godot-plugin-refresher/LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018 Will Nations
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
24
game/addons/godot-plugin-refresher/README.md
Normal file
24
game/addons/godot-plugin-refresher/README.md
Normal file
@ -0,0 +1,24 @@
|
||||
# godot-plugin-refresher
|
||||
|
||||
This plugin simplifies plugin development for those wanting to make tools for the Godot Editor.
|
||||
|
||||
It adds a dropdown and refresh button to the toolbar. *Other* plugins' directory names will show up in the dropdown, and clicking the refresh button will simply toggle the plugin off and then back on.
|
||||
|
||||
This makes it much easier to iterate on a single plugin since rather than having to...
|
||||
|
||||
1. Click Project Settings.
|
||||
2. Go to Plugins tab (first time).
|
||||
3. Find the desired plugin.
|
||||
4. Click the dropdown.
|
||||
5. Select the opposite option.
|
||||
6. Click the dropdown again.
|
||||
7. Click the original option.
|
||||
8. Close the Project Settings.
|
||||
|
||||
You instead just...
|
||||
|
||||
1. Click the dropdown (first time).
|
||||
2. Select your WIP plugin (first time).
|
||||
3. Click the refresh button.
|
||||
|
||||
Please consider starring the repo if you like the project and let me know if you have any feedback for bugs / feature improvements in the Issues. If you'd like to support my work, please [send tips to my Kofi](https://ko-fi.com/willnationsdev). Cheers!
|
7
game/addons/godot-plugin-refresher/plugin.cfg
Normal file
7
game/addons/godot-plugin-refresher/plugin.cfg
Normal file
@ -0,0 +1,7 @@
|
||||
[plugin]
|
||||
|
||||
name="Godot Plugin Refresher"
|
||||
description="A toolbar addition to facilitate toggling off/on a selected plugin."
|
||||
author="willnationsdev"
|
||||
version="1.0"
|
||||
script="plugin_refresher_plugin.gd"
|
53
game/addons/godot-plugin-refresher/plugin_refresher.gd
Normal file
53
game/addons/godot-plugin-refresher/plugin_refresher.gd
Normal file
@ -0,0 +1,53 @@
|
||||
tool
|
||||
extends HBoxContainer
|
||||
|
||||
signal request_refresh_plugin(p_name)
|
||||
signal confirm_refresh_plugin(p_name)
|
||||
|
||||
onready var options = $OptionButton
|
||||
|
||||
func _ready():
|
||||
$RefreshButton.icon = get_icon('Reload', 'EditorIcons')
|
||||
|
||||
func update_items(p_plugins):
|
||||
if not options:
|
||||
return
|
||||
options.clear()
|
||||
var plugin_dirs = p_plugins.keys()
|
||||
for idx in plugin_dirs.size():
|
||||
var plugin_dirname = plugin_dirs[idx]
|
||||
var plugin_name = p_plugins[plugin_dirname]
|
||||
options.add_item(plugin_name, idx)
|
||||
options.set_item_metadata(idx, plugin_dirname)
|
||||
|
||||
func select_plugin(p_name):
|
||||
if not options:
|
||||
return
|
||||
if p_name == null or p_name.empty():
|
||||
return
|
||||
|
||||
for idx in options.get_item_count():
|
||||
var plugin = options.get_item_metadata(idx)
|
||||
if plugin == p_name:
|
||||
options.selected = options.get_item_id(idx)
|
||||
break
|
||||
|
||||
func _on_RefreshButton_pressed():
|
||||
if options.selected == -1:
|
||||
return # nothing selected
|
||||
|
||||
var plugin = options.get_item_metadata(options.selected)
|
||||
if not plugin or plugin.empty():
|
||||
return
|
||||
emit_signal("request_refresh_plugin", plugin)
|
||||
|
||||
func show_warning(p_name):
|
||||
$ConfirmationDialog.dialog_text = """
|
||||
Plugin `%s` is currently disabled.\n
|
||||
Do you want to enable it now?
|
||||
""" % [p_name]
|
||||
$ConfirmationDialog.popup_centered()
|
||||
|
||||
func _on_ConfirmationDialog_confirmed():
|
||||
var plugin = options.get_item_metadata(options.selected)
|
||||
emit_signal('confirm_refresh_plugin', plugin)
|
32
game/addons/godot-plugin-refresher/plugin_refresher.tscn
Normal file
32
game/addons/godot-plugin-refresher/plugin_refresher.tscn
Normal file
@ -0,0 +1,32 @@
|
||||
[gd_scene load_steps=2 format=2]
|
||||
|
||||
[ext_resource path="res://addons/godot-plugin-refresher/plugin_refresher.gd" type="Script" id=1]
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer"]
|
||||
margin_right = 40.0
|
||||
margin_bottom = 40.0
|
||||
script = ExtResource( 1 )
|
||||
|
||||
[node name="VSeparator" type="VSeparator" parent="."]
|
||||
margin_right = 4.0
|
||||
margin_bottom = 40.0
|
||||
|
||||
[node name="OptionButton" type="OptionButton" parent="."]
|
||||
margin_left = 8.0
|
||||
margin_right = 158.0
|
||||
margin_bottom = 40.0
|
||||
rect_min_size = Vector2( 150, 0 )
|
||||
|
||||
[node name="RefreshButton" type="ToolButton" parent="."]
|
||||
margin_left = 162.0
|
||||
margin_right = 174.0
|
||||
margin_bottom = 40.0
|
||||
|
||||
[node name="ConfirmationDialog" type="ConfirmationDialog" parent="."]
|
||||
margin_right = 278.0
|
||||
margin_bottom = 110.0
|
||||
rect_min_size = Vector2( 300, 70 )
|
||||
window_title = "Plugin Refresher"
|
||||
dialog_autowrap = true
|
||||
[connection signal="pressed" from="RefreshButton" to="." method="_on_RefreshButton_pressed"]
|
||||
[connection signal="confirmed" from="ConfirmationDialog" to="." method="_on_ConfirmationDialog_confirmed"]
|
125
game/addons/godot-plugin-refresher/plugin_refresher_plugin.gd
Normal file
125
game/addons/godot-plugin-refresher/plugin_refresher_plugin.gd
Normal file
@ -0,0 +1,125 @@
|
||||
tool
|
||||
extends EditorPlugin
|
||||
|
||||
const ADDONS_PATH = "res://addons/"
|
||||
const PLUGIN_CONFIG_DIR = 'plugins/plugin_refresher'
|
||||
const PLUGIN_CONFIG = 'settings.cfg'
|
||||
const SETTINGS = 'settings'
|
||||
const SETTING_RECENT = 'recently_used'
|
||||
|
||||
var plugin_config = ConfigFile.new()
|
||||
var refresher
|
||||
|
||||
func _enter_tree():
|
||||
refresher = preload("plugin_refresher.tscn").instance()
|
||||
add_control_to_container(CONTAINER_TOOLBAR, refresher)
|
||||
|
||||
# Watch whether any plugin is changed, added or removed on the filesystem
|
||||
var efs = get_editor_interface().get_resource_filesystem()
|
||||
efs.connect("filesystem_changed", self, "_on_filesystem_changed")
|
||||
|
||||
refresher.connect("request_refresh_plugin", self, "_on_request_refresh_plugin")
|
||||
refresher.connect("confirm_refresh_plugin", self, "_on_confirm_refresh_plugin")
|
||||
|
||||
_reload_plugins_list()
|
||||
_load_settings()
|
||||
|
||||
func _exit_tree():
|
||||
remove_control_from_container(CONTAINER_TOOLBAR, refresher)
|
||||
refresher.free()
|
||||
|
||||
func _reload_plugins_list():
|
||||
var refresher_dir = get_plugin_path().get_file()
|
||||
var plugins = {}
|
||||
var origins = {}
|
||||
|
||||
var dir = Directory.new()
|
||||
dir.open(ADDONS_PATH)
|
||||
dir.list_dir_begin(true, true)
|
||||
var file = dir.get_next()
|
||||
while file:
|
||||
var addon_dir = ADDONS_PATH.plus_file(file)
|
||||
if dir.dir_exists(addon_dir) and file != refresher_dir:
|
||||
var display_name = file
|
||||
var plugin_config_path = addon_dir.plus_file("plugin.cfg")
|
||||
if not dir.file_exists(plugin_config_path):
|
||||
continue # not a plugin
|
||||
var plugin_cfg = ConfigFile.new()
|
||||
plugin_cfg.load(plugin_config_path)
|
||||
display_name = plugin_cfg.get_value("plugin", "name", file)
|
||||
if not display_name in origins:
|
||||
origins[display_name] = [file]
|
||||
else:
|
||||
origins[display_name].append(file)
|
||||
plugins[file] = display_name
|
||||
file = dir.get_next()
|
||||
|
||||
# Specify the exact plugin name in parenthesis in case of naming collisions.
|
||||
for display_name in origins:
|
||||
var plugin_names = origins[display_name]
|
||||
if plugin_names.size() > 1:
|
||||
for n in plugin_names:
|
||||
plugins[n] = "%s (%s)" % [display_name, n]
|
||||
|
||||
refresher.update_items(plugins)
|
||||
|
||||
func _load_settings():
|
||||
var path = get_config_path()
|
||||
|
||||
var fs = Directory.new()
|
||||
if not fs.file_exists(path):
|
||||
# Create new if running for the first time
|
||||
var config = ConfigFile.new()
|
||||
fs.make_dir_recursive(path.get_base_dir())
|
||||
config.save(path)
|
||||
else:
|
||||
plugin_config.load(path)
|
||||
|
||||
func _save_settings():
|
||||
plugin_config.save(get_config_path())
|
||||
|
||||
func get_config_path():
|
||||
var dir = get_editor_interface().get_editor_settings().get_project_settings_dir()
|
||||
var home = dir.plus_file(PLUGIN_CONFIG_DIR)
|
||||
var path = home.plus_file(PLUGIN_CONFIG)
|
||||
|
||||
return path
|
||||
|
||||
func _on_filesystem_changed():
|
||||
if refresher:
|
||||
_reload_plugins_list()
|
||||
refresher.select_plugin(get_recent_plugin())
|
||||
|
||||
func get_recent_plugin():
|
||||
if not plugin_config.has_section_key(SETTINGS, SETTING_RECENT):
|
||||
return null # not saved yet
|
||||
|
||||
var recent = plugin_config.get_value(SETTINGS, SETTING_RECENT)
|
||||
return recent
|
||||
|
||||
func _on_request_refresh_plugin(p_name):
|
||||
assert(not p_name.empty())
|
||||
|
||||
var disabled = not get_editor_interface().is_plugin_enabled(p_name)
|
||||
if disabled:
|
||||
refresher.show_warning(p_name)
|
||||
else:
|
||||
refresh_plugin(p_name)
|
||||
|
||||
func _on_confirm_refresh_plugin(p_name):
|
||||
refresh_plugin(p_name)
|
||||
|
||||
func get_plugin_path():
|
||||
return get_script().resource_path.get_base_dir()
|
||||
|
||||
func refresh_plugin(p_name):
|
||||
print("Refreshing plugin: ", p_name)
|
||||
|
||||
var enabled = get_editor_interface().is_plugin_enabled(p_name)
|
||||
if enabled: # can only disable an active plugin
|
||||
get_editor_interface().set_plugin_enabled(p_name, false)
|
||||
|
||||
get_editor_interface().set_plugin_enabled(p_name, true)
|
||||
|
||||
plugin_config.set_value(SETTINGS, SETTING_RECENT, p_name)
|
||||
_save_settings()
|
Loading…
Reference in New Issue
Block a user