Skip to content

blekenbleu/JSONio

Repository files navigation

SimHub JSONio plugin

from SimHubPluginSdk

What

 
A common list of custom SimHub properties with some values potentially specific to each sim and car.
In this example, properties are managed for ShakeIt Wheel Slip haptics:

  • a C# list of games
    • each Game object a name, game-specific defaults Property List<> and CList of Car objects
      • each Car object a carID and its List<> of Property objects
        • each Property object a Name and Value
  • Properties to be managed are configured in JSONio.ini.

How

  • instead of just copying that SimHubPluginSdk repository
    • created a new Visual Studio JSONio WPF project, then quit
    • deleted everything in that project except JSONio.sln and JSONio.csproj
    • copied Properties/ and source files from SimHubPluginSdk/
    • performed GVIM split diff on JSONio.sln and JSONio.csproj to preserve new ProjectGuid, etc
    • forgot to update namespace from User.PluginSdk to JSONio e.g. in Properties/...!
    • easily missed namespace in .xaml called xmlns:local="clr-namespace:..."
  • this.AddAction("ChangeProperties",(a, b) => saves changed Car properties list,
    then loads properties matching changed Car.ID and Game gname.
    • updates Values list from defaults for Game gname if no Car.ID match
    • could implement this.AddEvent("CarChange");
      in public void Init(PluginManager pluginManager),
      • then this.TriggerEvent("CarChange");
        in public void DataUpdate(PluginManager pluginManager, ref GameData data)
    • but instead let SimHub do it, by JSONio.ini:
       [ExportEvent]
       name='CarChange'
       trigger=changed(20, [DataCorePlugin.GameData.CarId]) 
      


- my experience:  SimHub ignored this Source when JSONio.ini was first loaded...

  • in JSONio.cs Init()
    • create games object
      • populate from configured .json file, if existing
    • populate simValues object from saved Settings, games and JASONio.ini
    • in this.AddAction("ChangeProperties",(a, b)
      • create new Game object in games when none match current Game name
      • set game for matching games.data.name
    • additional this.AddAction()s for modifying Car and defaults values

My understanding of C# is that games could be a jagged array,
but jagged List<> better supports e.g. adding and deleting elements, based on JSONio.ini.

To Do   24 Apr 2024

  • done stop mouse click messing with selected property in UI
  • done property indicating a new car
  • done manage some SimHub properties not-per car, e.g. ShakeIt frequency limits
    • some tricks:
      • conversion to/from Car class has uses only first pCount List<Values>,
        which GameHandler class uses to save cars into Games data for .json file.
      • JSONio knows about properties beyond pCount in List<Values> simValues...
        • these are NOT saved in .json files
        • these ARE available as SimHub properties e.g. for ShakeIt
        • these ARE available for value changes in user interface
    • refactored to use only List<Values> simValues for user interface;
      • using JSONio.ini, convert from/to DataPluginSettings Settings in Init()/End()
      • restore/save simValue.Current values from/to GameHandler games.Car from/to JSONio.json
  • done slim .json format storing only one instance of property names, instead of redundantly per-car
  • OxyPlot integration

New to me

  • C# List<> patterns, particularly with non-trivial objects.
  • C# JSON
    • In Visual Studio, add Newtonsoft.Json.NET package...
    • pretty-print JSON from C# AKA serialize
       	using Newtonsoft.Json;
      
       	if (games.Save_Car(current, gname) || changed)
       	{
       		string js = JsonConvert.SerializeObject(games.data, Formatting.Indented);
      
    • Eventually, Read and Parse a JSON File in C# AKA deserialize
       	if (File.Exists(path))  
       	{  
       		games = JsonSerializer.Deserialize<Games>(File.ReadAllText(path));  
       	} else changed = true;  
      
  • C# WPF DataGrid in XAML  -  more references
    • 4 column table:
      • property name
      • default value
      • previous value
      • current value
    • XML header of row labels, as above
    • programatically add a row for each property configured
    • highlight current value of only selected property
    • first steps in Visual Studio:
      • click Control.xaml
      • select View->Designer
      • drag in DataGrid from Common WPF Controls
      • drag in buttons for previous, next, +, -, etc
  • C# Dispatcher.Invoke()
    • WPF DataGrid user interface updates want a method.
    • Invoking method on WPF DataGrid resources is disallowed from other threads.
    • Dispatcher.Invoke() is less code than subscribing to PropertyChanged events

Updates

			<DataGrid.Columns>
				<DataGridTextColumn Header="Property" Binding="{Binding Name}" />
				<DataGridTextColumn Header="Default" Binding="{Binding Default}" />
				<DataGridTextColumn Header="Current" Binding="{Binding Current}" />
				<DataGridTextColumn Header="Previous" Binding="{Binding Previous}" />
			</DataGrid.Columns>
		...
		public class Values
		{
			public string Name { get; set; }
			public string Default { get; set; }
			public string Current { get; set; }
			public string Previous { get; set; }
		}
		...
		public List<Values> simValues;

		public SettingsControl()
		{
			InitializeComponent();

			simValues = new List<Values>();
			dg.ItemsSource = simValues;
		}
- bind WPF button clicks directly to Plugin Action methods
  • 4 Apr: - test buttons
    - populate List<Values> from existing current, previous, etc

  • 5 Apr: - fully functional by buttons
    - Select hightlight forced for button changes, will not work for dashboard
    - simValues updated from original Lists, pending refactor
    - property updates by dashboard should work...

  • 7 Apr: - fully functional by buttons and dashboard
    - thanks to arguably sketch code rearranging...
    - still to do:  fully integrate simValues in JSONio.cs

  • C# WPF XY plot:  SimHub already uses OxyPlot

  • 12 May 2024 - MessageBox

    • SimHub Event triggers do not work from plugin Init()
    • MessageBox() during Init() (e.g. for JASONio.ini configuration errors)
      provokes extensive SimHub log error message.
    • for game runtime, added "JSONioOOps" TriggerEvent and
      this.AddAction("OopsMessageBox", (a, b) => OOpsMB());
  • 12 Oct - sync most code to SlipGrip branch

13 Oct - configurable slider

  • instead of hard-coded to Gscale
  • configured in NCalcScripts/JSONio.ini,
    where value may be any name in JSONio.properties, e.g.:
[ExportProperty]
name='JSONio.slider'
value='Gscale' 

About

Read and write JSON e.g. for car properties

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages