Camera Locking Update
This commit is contained in:
parent
f472d031a8
commit
e2a1171e5e
|
|
@ -91,12 +91,12 @@ public partial class RokojoriPlugin: EditorPlugin
|
||||||
// return _instance;
|
// return _instance;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
public override void _EnablePlugin()
|
public void EnablePlugin()
|
||||||
{
|
{
|
||||||
this.LogInfo();
|
this.LogInfo();
|
||||||
AddAutoloadSingleton( RokojoriRootAutoLoad, RokojoriRootAutoLoadPath );
|
AddAutoloadSingleton( RokojoriRootAutoLoad, RokojoriRootAutoLoadPath );
|
||||||
|
|
||||||
|
|
||||||
EnsureHiddenProjectPath( RokojoriProjectInternalPath );
|
EnsureHiddenProjectPath( RokojoriProjectInternalPath );
|
||||||
EnsureHiddenProjectPath( RokojoriSettingsPath );
|
EnsureHiddenProjectPath( RokojoriSettingsPath );
|
||||||
EnsureHiddenProjectPath( RokojoriCachePath );
|
EnsureHiddenProjectPath( RokojoriCachePath );
|
||||||
|
|
@ -147,7 +147,7 @@ public partial class RokojoriPlugin: EditorPlugin
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public override void _DisablePlugin()
|
public void DisablePlugin()
|
||||||
{
|
{
|
||||||
this.LogInfo();
|
this.LogInfo();
|
||||||
RemoveAutoloadSingleton( RokojoriRootAutoLoad );
|
RemoveAutoloadSingleton( RokojoriRootAutoLoad );
|
||||||
|
|
|
||||||
|
|
@ -63,11 +63,16 @@ namespace Rokojori
|
||||||
// return;
|
// return;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
if ( target == null )
|
if ( target == null || ! IsInstanceValid( target ) )
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( lockTarget != null && ! IsInstanceValid( lockTarget ) )
|
||||||
|
{
|
||||||
|
lockTarget = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// var tl = TimeLineManager.Ensure( timeLine );
|
// var tl = TimeLineManager.Ensure( timeLine );
|
||||||
// var delta = tl.delta;
|
// var delta = tl.delta;
|
||||||
|
|
|
||||||
|
|
@ -65,6 +65,18 @@ namespace Rokojori
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( pointable != null && ! IsInstanceValid( pointable ) )
|
||||||
|
{
|
||||||
|
pointable = null;
|
||||||
|
|
||||||
|
if ( engageSensor.isActive && engageSensor is ActivationModeSensor ams )
|
||||||
|
{
|
||||||
|
ams.Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
onLockReleased?.Trigger();
|
||||||
|
}
|
||||||
|
|
||||||
UpdateClosestCandidate();
|
UpdateClosestCandidate();
|
||||||
|
|
||||||
var wasLocked = pointable != null;
|
var wasLocked = pointable != null;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,194 @@
|
||||||
|
#if TOOLS
|
||||||
|
|
||||||
|
using Godot;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Rokojori.Tools
|
||||||
|
{
|
||||||
|
using Rokojori;
|
||||||
|
|
||||||
|
// Like Node.Duplicate(), but [Export] Node/array/list members that point outside the
|
||||||
|
// duplicated subtree (parent, siblings, cousins, ...) keep pointing at the original
|
||||||
|
// external target instead of being nulled out. Members pointing inside the subtree are
|
||||||
|
// remapped to the corresponding duplicated node, same as native duplicate already does.
|
||||||
|
public static class NodeDuplicator
|
||||||
|
{
|
||||||
|
public static Node DuplicateDeep( Node original )
|
||||||
|
{
|
||||||
|
if ( original == null )
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var parent = original.GetParent();
|
||||||
|
|
||||||
|
if ( parent == null )
|
||||||
|
{
|
||||||
|
original.LogError( "Duplicate Deep needs a parent node, can't duplicate the scene root." );
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var duplicate = original.Duplicate( (int) Node.DuplicateFlags.Default );
|
||||||
|
|
||||||
|
parent.AddChild( duplicate );
|
||||||
|
parent.MoveChild( duplicate, original.GetIndex() + 1 );
|
||||||
|
|
||||||
|
SetOwnerRecursively( duplicate, original.Owner );
|
||||||
|
RemapExternalReferences( original, duplicate );
|
||||||
|
|
||||||
|
duplicate.LogInfo( "Duplicated", original.Name, "as", duplicate.Name );
|
||||||
|
|
||||||
|
return duplicate;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SetOwnerRecursively( Node node, Node sceneOwner )
|
||||||
|
{
|
||||||
|
if ( sceneOwner == null )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
node.Owner = sceneOwner;
|
||||||
|
|
||||||
|
foreach ( Node child in node.GetChildren() )
|
||||||
|
{
|
||||||
|
SetOwnerRecursively( child, sceneOwner );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void RemapExternalReferences( Node originalRoot, Node duplicateRoot )
|
||||||
|
{
|
||||||
|
var originalNodes = new List<Node>();
|
||||||
|
var duplicateNodes = new List<Node>();
|
||||||
|
|
||||||
|
NodesWalker.Get().Iterate( originalRoot, n => originalNodes.Add( n ), false );
|
||||||
|
NodesWalker.Get().Iterate( duplicateRoot, n => duplicateNodes.Add( n ), false );
|
||||||
|
|
||||||
|
var originalToDuplicate = new Dictionary<Node, Node>();
|
||||||
|
|
||||||
|
for ( var i = 0; i < originalNodes.Count && i < duplicateNodes.Count; i++ )
|
||||||
|
{
|
||||||
|
originalToDuplicate[ originalNodes[ i ] ] = duplicateNodes[ i ];
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( var i = 0; i < originalNodes.Count; i++ )
|
||||||
|
{
|
||||||
|
RemapNodeExports( originalNodes[ i ], duplicateNodes[ i ], originalToDuplicate );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void RemapNodeExports( Node original, Node duplicate, Dictionary<Node, Node> map )
|
||||||
|
{
|
||||||
|
var properties = original.GetPropertyList();
|
||||||
|
|
||||||
|
foreach ( var propertyInfo in properties )
|
||||||
|
{
|
||||||
|
var dict = (Godot.Collections.Dictionary) propertyInfo;
|
||||||
|
|
||||||
|
if ( ! IsStored( dict ) )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var name = dict[ "name" ].AsString();
|
||||||
|
|
||||||
|
if ( string.IsNullOrEmpty( name ) )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var type = (Variant.Type) dict[ "type" ].AsInt32();
|
||||||
|
|
||||||
|
if ( type == Variant.Type.Object )
|
||||||
|
{
|
||||||
|
RemapSingleProperty( original, duplicate, name, map );
|
||||||
|
}
|
||||||
|
else if ( type == Variant.Type.Array )
|
||||||
|
{
|
||||||
|
RemapArrayProperty( original, duplicate, name, map );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool IsStored( Godot.Collections.Dictionary propertyInfo )
|
||||||
|
{
|
||||||
|
if ( ! propertyInfo.ContainsKey( "usage" ) )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var usage = propertyInfo[ "usage" ].AsInt64();
|
||||||
|
return ( usage & (long) PropertyUsageFlags.Storage ) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void RemapSingleProperty( Node original, Node duplicate, string name, Dictionary<Node, Node> map )
|
||||||
|
{
|
||||||
|
var value = original.Get( name );
|
||||||
|
|
||||||
|
if ( value.VariantType != Variant.Type.Object )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( value.AsGodotObject() is not Node targetNode )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var remapped = Remap( targetNode, map );
|
||||||
|
|
||||||
|
if ( remapped != targetNode )
|
||||||
|
{
|
||||||
|
duplicate.Set( name, remapped );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void RemapArrayProperty( Node original, Node duplicate, string name, Dictionary<Node, Node> map )
|
||||||
|
{
|
||||||
|
var value = original.Get( name );
|
||||||
|
|
||||||
|
if ( value.VariantType != Variant.Type.Array )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var array = value.AsGodotArray();
|
||||||
|
var changed = false;
|
||||||
|
|
||||||
|
for ( var i = 0; i < array.Count; i++ )
|
||||||
|
{
|
||||||
|
var element = array[ i ];
|
||||||
|
|
||||||
|
if ( element.VariantType != Variant.Type.Object || element.AsGodotObject() is not Node elementNode )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var remapped = Remap( elementNode, map );
|
||||||
|
|
||||||
|
if ( remapped != elementNode )
|
||||||
|
{
|
||||||
|
array[ i ] = remapped;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( changed )
|
||||||
|
{
|
||||||
|
duplicate.Set( name, array );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Node Remap( Node originalTarget, Dictionary<Node, Node> map )
|
||||||
|
{
|
||||||
|
if ( map.TryGetValue( originalTarget, out var mapped ) )
|
||||||
|
{
|
||||||
|
return mapped;
|
||||||
|
}
|
||||||
|
|
||||||
|
return originalTarget;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
uid://bigysvcanctvn
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
#if TOOLS
|
||||||
|
|
||||||
|
using Godot;
|
||||||
|
|
||||||
|
namespace Rokojori.Tools
|
||||||
|
{
|
||||||
|
using Rokojori;
|
||||||
|
|
||||||
|
[Tool]
|
||||||
|
public partial class RJ_EditorBridge : RefCounted
|
||||||
|
{
|
||||||
|
public void LogHello( Node node )
|
||||||
|
{
|
||||||
|
node.LogInfo( "Hello" );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DuplicateDeep( Node node )
|
||||||
|
{
|
||||||
|
NodeDuplicator.DuplicateDeep( node );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
uid://b83jwjb1m4uae
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
@tool
|
||||||
|
extends EditorContextMenuPlugin
|
||||||
|
|
||||||
|
const EditorBridgeScript = preload( "res://addons/rokojori_action_library/Tools/Editor/RJ_EditorBridge.cs" )
|
||||||
|
|
||||||
|
var bridge = EditorBridgeScript.new()
|
||||||
|
|
||||||
|
|
||||||
|
func _popup_menu( paths:PackedStringArray ) -> void:
|
||||||
|
add_context_menu_item( "Log Hello", _on_log_hello )
|
||||||
|
add_context_menu_item( "Duplicate Deep", _on_duplicate_deep )
|
||||||
|
|
||||||
|
|
||||||
|
func _on_log_hello( nodes:Array ) -> void:
|
||||||
|
for node in nodes:
|
||||||
|
bridge.LogHello( node )
|
||||||
|
|
||||||
|
|
||||||
|
func _on_duplicate_deep( nodes:Array ) -> void:
|
||||||
|
for node in nodes:
|
||||||
|
bridge.DuplicateDeep( node )
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
uid://bgopgmdisn1df
|
||||||
|
|
@ -4,4 +4,4 @@ name="Rokojori Action Library"
|
||||||
description="Library for actions, assets and effects"
|
description="Library for actions, assets and effects"
|
||||||
author="Rokojori"
|
author="Rokojori"
|
||||||
version="0.6"
|
version="0.6"
|
||||||
script="RokojoriPlugin.cs"
|
script="plugin.gd"
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
@tool
|
||||||
|
extends EditorPlugin
|
||||||
|
|
||||||
|
const RokojoriPluginScript = preload( "res://addons/rokojori_action_library/RokojoriPlugin.cs" )
|
||||||
|
const NodeContextMenuScript = preload( "res://addons/rokojori_action_library/Tools/Editor/RJ_NodeContextMenu.gd" )
|
||||||
|
|
||||||
|
var csPlugin
|
||||||
|
var nodeContextMenu
|
||||||
|
|
||||||
|
|
||||||
|
func _ensure_cs_plugin() -> void:
|
||||||
|
if csPlugin == null:
|
||||||
|
csPlugin = RokojoriPluginScript.new()
|
||||||
|
add_child( csPlugin )
|
||||||
|
|
||||||
|
|
||||||
|
func _enter_tree() -> void:
|
||||||
|
_ensure_cs_plugin()
|
||||||
|
|
||||||
|
nodeContextMenu = NodeContextMenuScript.new()
|
||||||
|
add_context_menu_plugin( EditorContextMenuPlugin.CONTEXT_SLOT_SCENE_TREE, nodeContextMenu )
|
||||||
|
|
||||||
|
|
||||||
|
func _exit_tree() -> void:
|
||||||
|
if nodeContextMenu:
|
||||||
|
remove_context_menu_plugin( nodeContextMenu )
|
||||||
|
nodeContextMenu = null
|
||||||
|
|
||||||
|
if csPlugin:
|
||||||
|
csPlugin.queue_free()
|
||||||
|
csPlugin = null
|
||||||
|
|
||||||
|
|
||||||
|
func _enable_plugin() -> void:
|
||||||
|
_ensure_cs_plugin()
|
||||||
|
csPlugin.EnablePlugin()
|
||||||
|
|
||||||
|
|
||||||
|
func _disable_plugin() -> void:
|
||||||
|
if csPlugin:
|
||||||
|
csPlugin.DisablePlugin()
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
uid://c3fvpug0mdv5l
|
||||||
Loading…
Reference in New Issue