328 lines
7.1 KiB
C#
328 lines
7.1 KiB
C#
|
|
using Godot;
|
|
using System.Collections.Generic;
|
|
using System;
|
|
namespace Rokojori
|
|
{
|
|
[Tool]
|
|
[GlobalClass,Icon("res://addons/rokojori_action_library/Icons/SensorManager.svg")]
|
|
public partial class SensorManager: Node
|
|
{
|
|
[Export]
|
|
public bool initializeOnReady = true;
|
|
|
|
[Export]
|
|
public Sensor[] sensors = new Sensor[ 0 ];
|
|
|
|
[Export]
|
|
public SensorGroup[] sensorGroups = new SensorGroup[ 0 ];
|
|
|
|
[Export]
|
|
public bool processSensors = false;
|
|
|
|
[Export]
|
|
public Node[] autoScanForSensors = new Node[ 0 ];
|
|
|
|
[Export]
|
|
public bool separateMouseAndKeyboardTracking = false;
|
|
|
|
[Export]
|
|
public Action onActiveDeviceChange;
|
|
public readonly EventSlot<Null> _onActiveDeviceChange = new EventSlot<Null>();
|
|
|
|
[ExportGroup("Read Only")]
|
|
[Export]
|
|
public SensorDevice[] deviceList = new SensorDevice[]{};
|
|
|
|
[Export]
|
|
public float[] deviceLastInputTimeStamp = new float[]{};
|
|
|
|
[ExportGroup("Testing")]
|
|
|
|
[Export]
|
|
public SensorDevice testingLastActiveDevice;
|
|
|
|
|
|
|
|
|
|
List<SensorRunner> runners = new List<SensorRunner>();
|
|
List<iOnInputSensor> inputers = new List<iOnInputSensor>();
|
|
Dictionary<Sensor,SensorRunner> sensorToRunner = new Dictionary<Sensor, SensorRunner>();
|
|
|
|
|
|
KeyboardDevice keyboardDevice = new KeyboardDevice();
|
|
MouseDevice mouseDevice = new MouseDevice();
|
|
GamePadDevice gamePadDevice = new GamePadDevice();
|
|
MultiSensorDevice mouseKeyboardDevice = new MultiSensorDevice();
|
|
|
|
DateTime _startTime;
|
|
|
|
|
|
public SensorDevice lastActiveDevice
|
|
{
|
|
get
|
|
{
|
|
if ( testingLastActiveDevice != null )
|
|
{
|
|
return testingLastActiveDevice;
|
|
}
|
|
|
|
var highest = Lists.IndexOfHighestValue( Lists.From( deviceLastInputTimeStamp ), t => t );
|
|
|
|
if ( highest == -1 )
|
|
{
|
|
return null;
|
|
}
|
|
|
|
return deviceList[ highest ];
|
|
}
|
|
|
|
}
|
|
|
|
void UpdateDevice( SensorDevice d )
|
|
{
|
|
var lastActive = lastActiveDevice;
|
|
|
|
var index = Arrays.IndexOf( deviceList, d );
|
|
|
|
if ( index == -1 )
|
|
{
|
|
deviceList = Arrays.Add( deviceList, d );
|
|
index = deviceList.Length - 1;
|
|
deviceLastInputTimeStamp = Arrays.Add( deviceLastInputTimeStamp, 0 );
|
|
}
|
|
|
|
deviceLastInputTimeStamp[ index ] = (float) ( DateTime.Now - _startTime ).TotalSeconds;
|
|
|
|
if ( lastActive == lastActiveDevice )
|
|
{
|
|
return;
|
|
}
|
|
|
|
Action.Trigger( onActiveDeviceChange );
|
|
_onActiveDeviceChange.DispatchEvent( null );
|
|
|
|
}
|
|
|
|
public void UpdateLastActiveDevice( Sensor sensor, int index )
|
|
{
|
|
if ( keyboardDevice.ContainsSensor( sensor ) )
|
|
{
|
|
UpdateDevice( separateMouseAndKeyboardTracking ? keyboardDevice : mouseKeyboardDevice );
|
|
|
|
return;
|
|
}
|
|
|
|
if ( mouseDevice.ContainsSensor( sensor ) )
|
|
{
|
|
UpdateDevice( separateMouseAndKeyboardTracking ? mouseDevice : mouseKeyboardDevice );
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( gamePadDevice.ContainsSensor( sensor ) )
|
|
{
|
|
var device = Arrays.Find( deviceList, d => d is GamePadDevice gpd && gpd.deviceIndex == index );
|
|
|
|
if ( device == null )
|
|
{
|
|
var gpd = new GamePadDevice();
|
|
gpd.deviceIndex = index;
|
|
gpd.deviceName = Input.GetJoyName( index );
|
|
|
|
device = gpd;
|
|
}
|
|
|
|
UpdateDevice( device );
|
|
}
|
|
}
|
|
|
|
public override void _Ready()
|
|
{
|
|
_startTime = DateTime.Now;
|
|
mouseKeyboardDevice.devices = new SensorDevice[]{ mouseDevice, keyboardDevice };
|
|
|
|
if ( ! initializeOnReady )
|
|
{
|
|
return;
|
|
}
|
|
|
|
CreateRunners();
|
|
}
|
|
|
|
public override void _Input( InputEvent ev )
|
|
{
|
|
inputers.ForEach(
|
|
( inp )=>
|
|
{
|
|
inp._Input( ev );
|
|
}
|
|
);
|
|
}
|
|
|
|
public override void _Process( double delta )
|
|
{
|
|
if ( Engine.IsEditorHint() || ! processSensors )
|
|
{
|
|
return;
|
|
}
|
|
|
|
runners.ForEach( r => r.Update( (float) delta ) );
|
|
}
|
|
|
|
public void Register( Sensor s, SensorInputHandler sih )
|
|
{
|
|
var sensorRunner = sensorToRunner[ s ];
|
|
|
|
if ( sensorRunner.listeners.Contains( sih ) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
sensorRunner.listeners.Add( sih );
|
|
}
|
|
|
|
public void Unregister( Sensor s, SensorInputHandler sih )
|
|
{
|
|
var sensorRunner = sensorToRunner[ s ];
|
|
sensorRunner.listeners.Remove( sih );
|
|
}
|
|
|
|
public static void Register( SensorInputHandler handler, params Sensor[] sensors )
|
|
{
|
|
var sm = Unique<SensorManager>.Get();
|
|
|
|
foreach ( var s in sensors )
|
|
{
|
|
if ( s == null )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
( handler as Node ).LogInfo( "Registrating", HierarchyName.Of( (Node)handler) );
|
|
sm.Register( s, handler );
|
|
}
|
|
}
|
|
|
|
public static void Unregister( SensorInputHandler handler, params Sensor[] sensors )
|
|
{
|
|
var sm = Unique<SensorManager>.Get();
|
|
|
|
foreach ( var s in sensors )
|
|
{
|
|
if ( s == null )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
( handler as Node ).LogInfo( "Unregistrating" );
|
|
|
|
sm.Unregister( s, handler );
|
|
}
|
|
}
|
|
|
|
HashSet<Sensor> sensorsSet = new HashSet<Sensor>();
|
|
|
|
void AddSensor( Sensor s )
|
|
{
|
|
if ( s == null || sensorsSet.Contains( s ) )
|
|
{
|
|
// this.LogInfo( "Not including:", HierarchyName.Of( s ) );
|
|
return;
|
|
}
|
|
|
|
this.LogInfo( "Including:", HierarchyName.Of( s ) );
|
|
|
|
AddSensorsFrom( s );
|
|
|
|
sensorsSet.Add( s );
|
|
runners.Add( new SensorRunner( s ) );
|
|
}
|
|
|
|
HashSet<object> objects = new HashSet<object>();
|
|
|
|
void AddSensorsFrom( object obj )
|
|
{
|
|
if ( obj == null || objects.Contains( obj ) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
objects.Add( obj );
|
|
|
|
var sensors = ReflectionHelper.GetDataMemberValues<Sensor>( obj );
|
|
|
|
sensors.ForEach(
|
|
s =>
|
|
{
|
|
AddSensor( s );
|
|
}
|
|
);
|
|
|
|
var sensorArrays = ReflectionHelper.GetDataMemberValues<Sensor[]>( obj );
|
|
|
|
sensorArrays.ForEach(
|
|
s =>
|
|
{
|
|
for ( int i = 0; i < s.Length; i++ )
|
|
{
|
|
AddSensor( s[ i ] );
|
|
}
|
|
}
|
|
);
|
|
|
|
var resources = ReflectionHelper.GetDataMemberValues<Resource>( obj );
|
|
|
|
resources.ForEach( r => AddSensorsFrom( r ) );
|
|
|
|
}
|
|
|
|
void CreateRunners()
|
|
{
|
|
if ( sensors == null )
|
|
{
|
|
sensors = new Sensor[]{};
|
|
}
|
|
|
|
if ( sensorGroups == null )
|
|
{
|
|
sensorGroups = new SensorGroup[]{};
|
|
}
|
|
|
|
foreach ( var s in sensors )
|
|
{
|
|
AddSensor( s );
|
|
}
|
|
|
|
foreach ( var g in sensorGroups )
|
|
{
|
|
foreach ( var s in g.sensors )
|
|
{
|
|
AddSensor( s );
|
|
}
|
|
}
|
|
|
|
foreach ( var n in autoScanForSensors )
|
|
{
|
|
Nodes.ForEach<Node>( n, cn=> AddSensorsFrom( cn ) );
|
|
}
|
|
|
|
runners.ForEach(
|
|
r =>
|
|
{
|
|
sensorToRunner[ r.sensor ] = r;
|
|
|
|
if ( r.sensor is iOnInputSensor oi )
|
|
{
|
|
inputers.Add( oi );
|
|
}
|
|
}
|
|
);
|
|
|
|
|
|
this.LogInfo( "Created runners:", runners.Count );
|
|
}
|
|
}
|
|
} |