Skip to content

Commit

Permalink
Add planes and graphics APIs
Browse files Browse the repository at this point in the history
  • Loading branch information
wegylexy committed Aug 24, 2021
1 parent b9a8ed8 commit d29c30d
Show file tree
Hide file tree
Showing 17 changed files with 1,812 additions and 1,583 deletions.
60 changes: 29 additions & 31 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,52 +4,50 @@ P/Invoke for X-Plane plugin library manager
## Reference Packages
`Microsoft.DotNet.ILCompiler` must be a top level dependency for native AOT:
```xml
<PackageReference Include="FlyByWireless.XPLM" Version="1.0.3-*"/>
<PackageReference Include="FlyByWireless.XPLM" Version="1.0.4-*"/>
<PackageReference Include="Microsoft.DotNet.ILCompiler" Version="6.0.0-*"/>
```
## Implement
The plugin must implement `FlyByWireless.XPLM.XPluginBase` as `XPlugin` in its assembly root namespace:
```cs
using FlyByWireless.XPLM;
using System;

namespace XplTemplate
namespace XplTemplate;

sealed class XPlugin : XPluginBase
{
sealed class XPlugin : XPluginBase
{
public override string? Name => "Fly by Wireless";
public override string? Signature => "hk.timtim.flybywireless";
public override string? Description => "X-Plane plugin library template.";
public override string? Name => "Fly by Wireless";
public override string? Signature => "hk.timtim.flybywireless";
public override string? Description => "X-Plane plugin library template.";

public XPlugin() : base()
public XPlugin() : base()
{
// e.g. check for API support
if (Utilities.Versions.XPLMVersion < 303)
{
// e.g. check for API support
if (Utilities.Versions.XPLMVersion < 303)
{
throw new NotSupportedException("TCAS override not supported.");
}
throw new NotSupportedException("TCAS override not supported.");
}
}

public override void Dispose()
{
// TODO: uninitialize
}
public override void Dispose()
{
// TODO: uninitialize
}

public override void Enable()
{
// TODO: start loops
}
public override void Enable()
{
// TODO: start loops
}

public override void Disable()
{
// TODO: stop loops
}
public override void Disable()
{
// TODO: stop loops
}

public override void ReceiveMessage(int from, int message, nint param)
{
// TODO: handle message from aother plugin
base.ReceiveMessage(from, message, param);
}
public override void ReceiveMessage(int from, int message, nint param)
{
// TODO: handle message from aother plugin
base.ReceiveMessage(from, message, param);
}
}
```
Expand Down
102 changes: 50 additions & 52 deletions XPL/Program.cs
Original file line number Diff line number Diff line change
@@ -1,79 +1,77 @@
using FlyByWireless.XPLM;
using FlyByWireless.XPLM.DataAccess;
using FlyByWireless.XPLM.Processing;
using System;

namespace XplTemplate
namespace XplTemplate;

sealed class XPlugin : XPluginBase
{
sealed class XPlugin : XPluginBase
{
public override string? Name => "Fly by Wireless";
public override string? Signature => "hk.timtim.flybywireless";
public override string? Description => "X-Plane plugin library template.";
public override string? Name => "Fly by Wireless";
public override string? Signature => "hk.timtim.flybywireless";
public override string? Description => "X-Plane plugin library template.";

readonly DataRef _overrideTcas;
readonly FlightLoop _myLoop;
readonly DataRef _overrideTcas;
readonly FlightLoop _myLoop;

public XPlugin() : base()
public XPlugin() : base()
{
// e.g. check for API support
if (Utilities.Versions.XPLMVersion < 303)
{
// e.g. check for API support
if (Utilities.Versions.XPLMVersion < 303)
{
throw new NotSupportedException("TCAS override not supported.");
}
throw new NotSupportedException("TCAS override not supported.");
}

// Example: finds datarefs
_overrideTcas = DataRef.Find("sim/operation/override/override_TCAS")!;
DataRef
bearing = DataRef.Find("sim/cockpit2/tcas/indicators/relative_bearing_degs")!,
distance = DataRef.Find("sim/cockpit2/tcas/indicators/relative_distance_mtrs")!,
altitude = DataRef.Find("sim/cockpit2/tcas/indicators/relative_altitude_mtrs")!;
// Example: finds datarefs
_overrideTcas = DataRef.Find("sim/operation/override/override_TCAS")!;
DataRef
bearing = DataRef.Find("sim/cockpit2/tcas/indicators/relative_bearing_degs")!,
distance = DataRef.Find("sim/cockpit2/tcas/indicators/relative_distance_mtrs")!,
altitude = DataRef.Find("sim/cockpit2/tcas/indicators/relative_altitude_mtrs")!;

// Example: registers my flight loop
_myLoop = new FlightLoop(FlightLoopPhase.AfterFlightModel, (elapsedSinceLastCall, elapsedTimeSinceLastFlightLoop, counter) =>
{
// Example: registers my flight loop
_myLoop = new FlightLoop(FlightLoopPhase.AfterFlightModel, (elapsedSinceLastCall, elapsedTimeSinceLastFlightLoop, counter) =>
{
// TODO: set number of planes
var count = 2;
Span<float> values = stackalloc float[count];
Span<float> values = stackalloc float[count];
// TODO: set bearings
bearing.AsFloatVector(0).Write(values);
// TODO: set distances
distance.AsFloatVector(0).Write(values);
// TODO: set altitudes
altitude.AsFloatVector(0).Write(values);
// Schedules for one second later
return 1;
});
}
return 1;
});
}

public override void Dispose()
{
// Example: unregisters my flight loop
_myLoop.Dispose();
}
public override void Dispose()
{
// Example: unregisters my flight loop
_myLoop.Dispose();
}

public override void Enable()
{
// Example: overrides TCAS
_overrideTcas.AsInt = 1;
public override void Enable()
{
// Example: overrides TCAS
_overrideTcas.AsInt = 1;

// Example: starts my flight loop one cycle after registration, i.e. immediately
_myLoop.Schedule(-1, false);
}
// Example: starts my flight loop one cycle after registration, i.e. immediately
_myLoop.Schedule(-1, false);
}

public override void Disable()
{
// Example: stops my flight loop
_myLoop.Schedule(0, false);
public override void Disable()
{
// Example: stops my flight loop
_myLoop.Schedule(0, false);

// Example: clears TCAS override
_overrideTcas.AsInt = 0;
}
// Example: clears TCAS override
_overrideTcas.AsInt = 0;
}

public override void ReceiveMessage(int from, int message, nint param)
{
// TODO: handle message from aother plugin
base.ReceiveMessage(from, message, param);
}
public override void ReceiveMessage(int from, int message, nint param)
{
// TODO: handle message from aother plugin
base.ReceiveMessage(from, message, param);
}
}
4 changes: 2 additions & 2 deletions XPL/XPL.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@
<RepositoryType>git</RepositoryType>
<Nullable>enable</Nullable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Version>1.0.3-alpha</Version>
<Version>1.0.4-alpha</Version>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="FlyByWireless.XPLM" Version="1.0.3-*" />
<PackageReference Include="FlyByWireless.XPLM" Version="1.0.4-*" />
<PackageReference Include="Microsoft.DotNet.ILCompiler" Version="6.0.0-*" />
</ItemGroup>

Expand Down
113 changes: 56 additions & 57 deletions XPLM/Camera.cs
Original file line number Diff line number Diff line change
@@ -1,83 +1,82 @@
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

namespace FlyByWireless.XPLM
namespace FlyByWireless.XPLM;

public enum CameraControlDuration
{
public enum CameraControlDuration
{
Uncontrolled,
UntilViewChanges,
Forever
}
Uncontrolled,
UntilViewChanges,
Forever
}

public readonly struct CameraPosition
{
public readonly float X, Y, Z, Pitch, Heading, Roll, Zoom;
public readonly struct CameraPosition
{
public readonly float X, Y, Z, Pitch, Heading, Roll, Zoom;

public CameraPosition(float x, float y, float z, float pitch, float heading, float roll, float zoom) =>
(X, Y, Z, Pitch, Heading, Roll, Zoom) = (x, y, z, pitch, heading, roll, zoom);
}
public CameraPosition(float x, float y, float z, float pitch, float heading, float roll, float zoom) =>
(X, Y, Z, Pitch, Heading, Roll, Zoom) = (x, y, z, pitch, heading, roll, zoom);
}

public delegate bool CameraControl(out CameraPosition? cameraPosition, bool isLosingControl);
public delegate bool CameraControl(out CameraPosition? cameraPosition, bool isLosingControl);

public static class Camera
public static class Camera
{
static GCHandle? _handle;

public static unsafe void Control(CameraControlDuration howLong, CameraControl control)
{
static GCHandle? _handle;
[DllImport(Defs.Lib)]
static extern void XPLMControlCamera(CameraControlDuration howLong, delegate* unmanaged<ref CameraPosition, int, nint, int> control, nint state);

public static unsafe void Control(CameraControlDuration howLong, CameraControl control)
[UnmanagedCallersOnly]
static int C(ref CameraPosition cameraPosition, int isLosingControl, nint state)
{
[DllImport(Defs.Lib)]
static extern void XPLMControlCamera(CameraControlDuration howLong, delegate* unmanaged<ref CameraPosition, int, nint, int> control, nint state);
var c = ((CameraControl)GCHandle.FromIntPtr(state).Target!)(out var position, isLosingControl != 0);
if (position.HasValue && !Unsafe.IsNullRef(ref cameraPosition))
cameraPosition = position!.Value;
return c ? 1 : 0;
}

[UnmanagedCallersOnly]
static int C(ref CameraPosition cameraPosition, int isLosingControl, nint state)
{
var c = ((CameraControl)GCHandle.FromIntPtr(state).Target!)(out var position, isLosingControl != 0);
if (position.HasValue && !Unsafe.IsNullRef(ref cameraPosition))
cameraPosition = position!.Value;
return c ? 1 : 0;
}
if (_handle.HasValue)
_handle.Value.Free();
_handle = GCHandle.Alloc(control);
XPLMControlCamera(howLong, &C, GCHandle.ToIntPtr(_handle.Value));
}

if (_handle.HasValue)
_handle.Value.Free();
_handle = GCHandle.Alloc(control);
XPLMControlCamera(howLong, &C, GCHandle.ToIntPtr(_handle.Value));
}
public static void DontControl()
{
[DllImport(Defs.Lib)]
static extern void XPLMDontControlCamera();

public static void DontControl()
XPLMDontControlCamera();
if (_handle.HasValue)
{
[DllImport(Defs.Lib)]
static extern void XPLMDontControlCamera();

XPLMDontControlCamera();
if (_handle.HasValue)
{
_handle.Value.Free();
_handle = null;
}
_handle.Value.Free();
_handle = null;
}
}

public static CameraControlDuration IsBeingControlled
public static CameraControlDuration IsBeingControlled
{
get
{
get
{
[DllImport(Defs.Lib)]
static extern int XPLMIsCameraBeingControlled(out CameraControlDuration duration);
[DllImport(Defs.Lib)]
static extern int XPLMIsCameraBeingControlled(out CameraControlDuration duration);

return XPLMIsCameraBeingControlled(out var duration) != 0 ? duration : default;
}
return XPLMIsCameraBeingControlled(out var duration) != 0 ? duration : default;
}
}

public static CameraPosition Position
public static CameraPosition Position
{
get
{
get
{
[DllImport(Defs.Lib)]
static extern void XPLMReadCameraPosition(out CameraPosition cameraPosition);
[DllImport(Defs.Lib)]
static extern void XPLMReadCameraPosition(out CameraPosition cameraPosition);

XPLMReadCameraPosition(out var position);
return position;
}
XPLMReadCameraPosition(out var position);
return position;
}
}
}
Loading

0 comments on commit d29c30d

Please sign in to comment.