📄
SPAD.neXt
  • SPAD.neXt Manual
  • About SPAD.neXt
  • Getting Started
    • System Requirements
    • Supported hardware
      • Check Hardware
    • Installation
      • Simulation Specifc Steps
        • SimConnect Configuration
        • MSFS: Enable PMDG data access
        • X-Plane Configuration
    • First Start
      • Configuration Wizard
    • Common Tasks and Issues
      • SPAD
        • Online Services
        • Fresh reinstall
        • Move SPAD.neXt to new Computer
        • License Issues
      • MSFS Specific Topics
      • X-Plane specific Topics
      • Saitek/Logitech MP/RP blinking
      • USB Powermanagement
  • Guides and Videos
    • New User Series
    • MSFS SimConnect
    • L:Vars / H:Events and B:Events
    • Features & Functions
    • Device Specific
      • Arduino / SPAD Serial
      • Authentikit
      • Cockpit Simulator CDU
      • Honeycomb
      • Joystick (Generic HID)
      • miniCockpit
      • RealSimGear
      • Saitek/Logitech
      • Script Panel
      • Stream Deck
      • Thrustmaster TCA
      • vFIP
      • Virtual Avionics
      • vJoy
      • VRinsight
      • X-Touch MC Mode
      • X-Touch Midi Mode
    • Simulation Specific
      • ATR 600 (MSFS)
      • AS CRJ 550/700/900/1000 (MSFS)
      • FBW A32NX (MSFS)
      • FFX/MG HJet (MSFS)
      • FFX Vision Jet (MSFS)
      • FSW C414AW (MSFS)
      • PMDG 737 (MSFS)
      • PMDG 777 (MSFS)
      • SWS Kodiak (MSFS)
      • WT CJ4 (MSFS)
      • WT G1000 NXi (MSFS)
      • PMDG 777 (P3D)
  • User Interface
    • UI Familiarization
      • Home Page
      • Profiles Page
  • Features
    • Expressions
      • Values
      • Referencing Simulation Data
      • Operators
      • Functions
      • Examples
    • Tuner Acceleration
    • Event Execution Order
  • Simulations
    • MSFS 2024
    • MSFS 2020
    • X-Plane
      • Pre-Requisites
      • Dataref Tool
      • Helping Spad Help You
      • Dataref vs. Command: Know Your Copilots
      • Basic Flight Controls – Axis Setup
    • P3d and FSX
    • Other
  • Hardware specific
    • USB HUB Requirements
    • CPFlight Devices
    • Saitek FIP (Flight Instrument Panel)
      • Saitek FIP: Driver & Function Check
    • Loupedeck Image Devices
    • Midi Devices
      • X-Touch Mini
    • Serial (COM) Devices
    • Skalarki
    • VRInsight Overhead
  • Extending and API's
    • Gauges and Extensions
      • SPAD Gauges: GaugeSettings
    • C# Scripting Interface
      • C# Scripting: ScriptStub
      • C# Scripting: Provide Values
      • C# Scripting: PreCompile
    • Device Interface
      • Device Communication Flow
        • Device INIT-Phase
        • Device CONFIG-Phase
          • Device options
          • Device COLORSET configuration
          • Device PROFILE configuration
          • Device OUTPUT Configuration
          • Device INPUT configuration
            • Device input AXIS
            • Device input ENCODER
            • Device input PUSHBUTTON
            • Device input ROTARY
            • Device input SWITCH
            • Device input SWITCH3
            • Device LABEL
          • Device config: Advanced topics
        • Device STATESCAN-Phase
      • Device General Commands
      • Device commands
        • Page-Control
      • Device SPAD.neXt Events (2)
      • Device Simulation Events (Channel 4)
      • Device Data (Channel 5)
      • Device LED Update (Channel 6)
      • Device Display Update (Channel 7)
      • Device Input Updates (Channel 8)
      • Device Virtual Power
      • Device Custom UI
      • Device HTML UI
      • Device preconfigured definition
      • Serial V2
        • Command 1,RAISE
        • Command: 0,AUTH
    • X-Plane Datarefs & Commands
    • FSUIPC: Custom Offsets
    • RestAPI
    • HTML Rendering API
    • Other API's
  • FAQ
    • General FAQ
    • MSFS: Lost profile aircraft assigments
  • Changes
    • 0.9.21
    • 0.9.14.0
    • 0.9.13.39
  • Glossar
  • Old-Docs
    • Old-Getting-Started-Guide
Powered by GitBook
On this page

Was this helpful?

  1. Extending and API's
  2. C# Scripting Interface

C# Scripting: ScriptStub

Starting with 0.9.18 SPAD.neXt.Interfaces contains an abstract ScriptStub which can be used for easier implementation:

/// <summary>
/// A basic Script Stub for free use
/// </summary>
public abstract class ScriptStub : IScript, IScriptCreation
{
    /// <summary>
    /// String to prefix all datat with. Data will be available as LOCAL:[PREFIX]_[name]
    /// </summary>
    protected abstract string ScriptDataPrefix { get; }
    protected abstract void InitializeScript();
    protected abstract void DeinitializeScript();

    /// <summary>
    /// Interface to Application for this Script
    /// </summary>
    protected IApplication Application { get; private set; }
    /// <summary>
    /// Our logger for the script.
    /// </summary>
    protected ILogger ScriptLogger { get; private set; }
    protected CancellationTokenSource CancelTokenSource { get; private set; } = new CancellationTokenSource();
    protected CancellationToken CancelToken => CancelTokenSource.Token;
    
    /// <summary>
    /// The loaded SPAD.neXtprofile has changed
    /// </summary>
    protected EventHandler<IProfile, string> ProfileChanged;
    /// <summary>
    /// The active aircraft/vehicle has changed
    /// </summary>
    protected EventHandler<IAircraft, string> AircraftChanged;
    /// <summary>
    /// A flight has been started
    /// </summary>
    protected EventHandler<ISimulationInterface, IAircraft> FlightStarted;
    /// <summary>
    /// The flight ended
    /// </summary>
    protected EventHandler<ISimulationInterface, SimulationGamestate> FlightEnded;
    /// <summary>
    /// The Simulation gamestate has changed (NewState,OldState)
    /// </summary>
    protected EventHandler<ISimulationInterface,SimulationGamestate, SimulationGamestate> GameStateChanged; 

    private Dictionary<string, IDataDefinition> scriptDataValues = new Dictionary<string, IDataDefinition>(StringComparer.InvariantCultureIgnoreCase);
    public void Initialize(IApplication app)
    {
        Application = app;
        ScriptLogger = app.GetLogger("Script." + ScriptDataPrefix);
        scriptDataValues = new Dictionary<string, IDataDefinition>(StringComparer.InvariantCultureIgnoreCase);
        ScriptLogger.Debug("Initialize");
        Application.RegisterSimulationConnected(simulationConnected);
        Application.ActiveProfileChanged += (s, e) => ProfileChanged?.Invoke(Application.ActiveProfile, e.PropertyName);
        Application.AircraftChanged += (s, e) => AircraftChanged?.Invoke(Application.CurrentAircraft, e.PropertyName);
        SafeCall(() => InitializeScript());
    }

    private void simulationConnected(SimulationConfiguration sender, IValueProvider e)
    {
        if (sender != null && sender.SimulationInterface is ISimulationInterface simulationInterface)
        {
            simulationInterface.SimulationGamestateChanged -= SimulationInterface_SimulationGamestateChanged;
            simulationInterface.SimulationGamestateChanged += SimulationInterface_SimulationGamestateChanged;
        }
    }

    private void SimulationInterface_SimulationGamestateChanged(ISimulationInterface sender, SimulationGamestate newState, SimulationGamestate oldState)
    {
        SafeCall(() =>
        {
            if (newState != oldState)
            {
                if (newState == SimulationGamestate.Flying)
                {
                    FlightStarted?.Invoke(sender, Application.CurrentAircraft);
                }
                else
                {
                    FlightEnded?.Invoke(sender, newState);
                }
            }
            GameStateChanged?.Invoke(sender, oldState, newState);
        });
    }

    public void Deinitialize()
    {
        ScriptLogger.Debug("Deinitialize");
        CancelTokenSource.Cancel();
        SafeCall(() => DeinitializeScript());
        scriptDataValues?.Clear();
        scriptDataValues = null;
    }

    protected IDataDefinition GetOrCreateScriptDataValue(string name)
    {
        if (name.Contains(":"))
        {
            throw new InvalidCastException("Symbol ':' is not allowed in datanames");
        }
        var realName = "LOCAL:" + ScriptDataPrefix + "_" + name;
        if (scriptDataValues.TryGetValue(name, out var data))
            return data;
        data = EventSystem.GetDataDefinition(realName);
        scriptDataValues[name] = data;
        return data;
    }
    protected T GetScriptDataValue<T>(string name, T defaultValue = default)
    {
        var data = GetOrCreateScriptDataValue(name);
        return data.GetValueAs<T>(defaultValue);
    }
    protected void SetScriptDataValue(string name, object value)
    {
        var data = GetOrCreateScriptDataValue(name);
        if (data != null) { data.SetRawValue(value); }
    }

    private void SafeCall(Action _call)
    {
        try
        {
            _call();
        }
        catch (Exception ex)
        {
            ScriptLogger.Error(ex.ToString());
        }
    }
}
PreviousC# Scripting InterfaceNextC# Scripting: Provide Values

Last updated 9 months ago

Was this helpful?