diff --git a/Artemis/Artemis/Artemis.csproj b/Artemis/Artemis/Artemis.csproj
index 8d31a8a77..b56f3704b 100644
--- a/Artemis/Artemis/Artemis.csproj
+++ b/Artemis/Artemis/Artemis.csproj
@@ -382,6 +382,50 @@
GtaVView.xaml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ProjectCarsView.xaml
+
+
@@ -566,6 +610,7 @@
+
@@ -796,6 +841,10 @@
Designer
MSBuild:Compile
+
+ MSBuild:Compile
+ Designer
+
Designer
MSBuild:Compile
diff --git a/Artemis/Artemis/ArtemisBootstrapper.cs b/Artemis/Artemis/ArtemisBootstrapper.cs
index 30f3b2d3c..754eed3cc 100644
--- a/Artemis/Artemis/ArtemisBootstrapper.cs
+++ b/Artemis/Artemis/ArtemisBootstrapper.cs
@@ -90,11 +90,15 @@ namespace Artemis
ContractResolver = _kernel.Get()
};
JsonConvert.DefaultSettings = () => settings;
+
+ //TODO DarthAffe 17.12.2016: Is this the right location for this?
+ ActiveWindowHelper.Initialize();
}
protected override void OnExit(object sender, EventArgs e)
{
_kernel.Dispose();
+ ActiveWindowHelper.Dispose();
base.OnExit(sender, e);
}
diff --git a/Artemis/Artemis/DAL/ProfileProvider.cs b/Artemis/Artemis/DAL/ProfileProvider.cs
index 728a683d7..1e0a61dca 100644
--- a/Artemis/Artemis/DAL/ProfileProvider.cs
+++ b/Artemis/Artemis/DAL/ProfileProvider.cs
@@ -152,13 +152,14 @@ namespace Artemis.DAL
File.WriteAllText(path, json);
}
- public static void InsertGif(string effectName, string profileName, string layerName, Bitmap gifFile, string fileName)
+ public static void InsertGif(string effectName, string profileName, string layerName, Bitmap gifFile,
+ string fileName)
{
var directories = new DirectoryInfo(ProfileFolder).GetDirectories();
var profiles = new List();
foreach (var directoryInfo in directories)
profiles.AddRange(ReadProfiles(directoryInfo.Name + "/effectName").Where(d => d.Name == profileName));
-
+
// Extract the GIF file
var gifDir = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + @"\Artemis\gifs";
Directory.CreateDirectory(gifDir);
@@ -219,23 +220,31 @@ namespace Artemis.DAL
///
private static void InstallDefaults()
{
- // Only install the defaults once per session
- if (_installedDefaults)
- return;
- _installedDefaults = true;
+ try
+ {
+ // Only install the defaults once per session
+ if (_installedDefaults)
+ return;
+ _installedDefaults = true;
- // Load the ZIP from resources
- var stream = Assembly.GetExecutingAssembly()
- .GetManifestResourceStream("Artemis.Resources.Keyboards.default-profiles.zip");
+ // Load the ZIP from resources
+ var stream = Assembly.GetExecutingAssembly()
+ .GetManifestResourceStream("Artemis.Resources.Keyboards.default-profiles.zip");
- // Extract it over the old defaults in case one was updated
- if (stream == null)
- return;
- var archive = new ZipArchive(stream);
- archive.ExtractToDirectory(ProfileFolder, true);
+ // Extract it over the old defaults in case one was updated
+ if (stream == null)
+ return;
+ var archive = new ZipArchive(stream);
+ archive.ExtractToDirectory(ProfileFolder, true);
- InsertGif("WindowsProfile", "Demo (duplicate to keep changes)", "GIF", Resources.demo_gif, "demo-gif");
+ InsertGif("WindowsProfile", "Demo (duplicate to keep changes)", "GIF", Resources.demo_gif, "demo-gif");
+ }
+ catch (IOException e)
+ {
+ Logger.Warn(e, "Failed to place default profiles, perhaps there are two instances of Artemis " +
+ "starting at the same time?");
+ }
}
///
diff --git a/Artemis/Artemis/Managers/LoopManager.cs b/Artemis/Artemis/Managers/LoopManager.cs
index 4892d203e..a7c8e3ccc 100644
--- a/Artemis/Artemis/Managers/LoopManager.cs
+++ b/Artemis/Artemis/Managers/LoopManager.cs
@@ -62,16 +62,7 @@ namespace Artemis.Managers
}
catch (Exception e)
{
- if (_canShowException)
- {
- Execute.OnUIThread(delegate
- {
- _canShowException = false;
- _loopTimer.Stop();
- App.GetArtemisExceptionViewer(e).ShowDialog();
- Environment.Exit(0);
- });
- }
+ _logger.Warn(e, "Exception in render loop");
}
}
diff --git a/Artemis/Artemis/Models/EffectModel.cs b/Artemis/Artemis/Models/EffectModel.cs
index ff2f3e409..eb1552d00 100644
--- a/Artemis/Artemis/Models/EffectModel.cs
+++ b/Artemis/Artemis/Models/EffectModel.cs
@@ -75,59 +75,62 @@ namespace Artemis.Models
{
if ((Profile == null) || (DataModel == null) || (DeviceManager.ActiveKeyboard == null))
return;
-
+
lock (DataModel)
{
- // Get all enabled layers who's conditions are met
- var renderLayers = GetRenderLayers(keyboardOnly);
+ lock (Profile)
+ {
+ // Get all enabled layers who's conditions are met
+ var renderLayers = GetRenderLayers(keyboardOnly);
- // If the profile has no active LUA wrapper, create one
- if (!string.IsNullOrEmpty(Profile.LuaScript))
- Profile.Activate(DeviceManager.ActiveKeyboard);
+ // If the profile has no active LUA wrapper, create one
+ if (!string.IsNullOrEmpty(Profile.LuaScript))
+ Profile.Activate(DeviceManager.ActiveKeyboard);
- // Render the keyboard layer-by-layer
- var keyboardRect = DeviceManager.ActiveKeyboard.KeyboardRectangle(KeyboardScale);
- using (var g = Graphics.FromImage(frame.KeyboardBitmap))
- {
- Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Keyboard),
- DataModel, keyboardRect, false, true, "keyboard");
- }
- // Render mice layer-by-layer
- var devRec = new Rect(0, 0, 40, 40);
- using (var g = Graphics.FromImage(frame.MouseBitmap))
- {
- Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Mouse),
- DataModel, devRec, false, true, "mouse");
- }
- // Render headsets layer-by-layer
- using (var g = Graphics.FromImage(frame.HeadsetBitmap))
- {
- Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Headset),
- DataModel, devRec, false, true, "headset");
- }
- // Render generic devices layer-by-layer
- using (var g = Graphics.FromImage(frame.GenericBitmap))
- {
- Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Generic),
- DataModel, devRec, false, true, "generic");
- }
- // Render mousemats layer-by-layer
- using (var g = Graphics.FromImage(frame.MousematBitmap))
- {
- Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Mousemat),
- DataModel, devRec, false, true, "mousemat");
- }
+ // Render the keyboard layer-by-layer
+ var keyboardRect = DeviceManager.ActiveKeyboard.KeyboardRectangle(KeyboardScale);
+ using (var g = Graphics.FromImage(frame.KeyboardBitmap))
+ {
+ Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Keyboard),
+ DataModel, keyboardRect, false, true, "keyboard");
+ }
+ // Render mice layer-by-layer
+ var devRec = new Rect(0, 0, 40, 40);
+ using (var g = Graphics.FromImage(frame.MouseBitmap))
+ {
+ Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Mouse),
+ DataModel, devRec, false, true, "mouse");
+ }
+ // Render headsets layer-by-layer
+ using (var g = Graphics.FromImage(frame.HeadsetBitmap))
+ {
+ Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Headset),
+ DataModel, devRec, false, true, "headset");
+ }
+ // Render generic devices layer-by-layer
+ using (var g = Graphics.FromImage(frame.GenericBitmap))
+ {
+ Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Generic),
+ DataModel, devRec, false, true, "generic");
+ }
+ // Render mousemats layer-by-layer
+ using (var g = Graphics.FromImage(frame.MousematBitmap))
+ {
+ Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Mousemat),
+ DataModel, devRec, false, true, "mousemat");
+ }
- // Trace debugging
- if (DateTime.Now.AddSeconds(-2) <= LastTrace || Logger == null)
- return;
+ // Trace debugging
+ if (DateTime.Now.AddSeconds(-2) <= LastTrace || Logger == null)
+ return;
- LastTrace = DateTime.Now;
- var dmJson = JsonConvert.SerializeObject(DataModel, Formatting.Indented);
- Logger.Trace("Effect datamodel as JSON: \r\n{0}", dmJson);
- Logger.Trace("Effect {0} has to render {1} layers", Name, renderLayers.Count);
- foreach (var renderLayer in renderLayers)
- Logger.Trace("- Layer name: {0}, layer type: {1}", renderLayer.Name, renderLayer.LayerType);
+ LastTrace = DateTime.Now;
+ var dmJson = JsonConvert.SerializeObject(DataModel, Formatting.Indented);
+ Logger.Trace("Effect datamodel as JSON: \r\n{0}", dmJson);
+ Logger.Trace("Effect {0} has to render {1} layers", Name, renderLayers.Count);
+ foreach (var renderLayer in renderLayers)
+ Logger.Trace("- Layer name: {0}, layer type: {1}", renderLayer.Name, renderLayer.LayerType);
+ }
}
}
diff --git a/Artemis/Artemis/Modules/Effects/WindowsProfile/WindowsProfileDataModel.cs b/Artemis/Artemis/Modules/Effects/WindowsProfile/WindowsProfileDataModel.cs
index 400bfa441..7efdf765f 100644
--- a/Artemis/Artemis/Modules/Effects/WindowsProfile/WindowsProfileDataModel.cs
+++ b/Artemis/Artemis/Modules/Effects/WindowsProfile/WindowsProfileDataModel.cs
@@ -14,6 +14,7 @@ namespace Artemis.Modules.Effects.WindowsProfile
Performance = new PerformanceDataModel();
CurrentTime = new CurrentTime();
Keyboard = new KbDataModel();
+ ActiveWindow = new ActiveWindow();
}
public CpuDataModel Cpu { get; set; }
@@ -22,6 +23,7 @@ namespace Artemis.Modules.Effects.WindowsProfile
public GooglePlayMusic GooglePlayMusic { get; set; }
public CurrentTime CurrentTime { get; set; }
public KbDataModel Keyboard { get; set; }
+ public ActiveWindow ActiveWindow { get; set; }
}
[MoonSharpUserData]
@@ -110,4 +112,11 @@ namespace Artemis.Modules.Effects.WindowsProfile
public bool CapsLock { get; set; }
public bool ScrollLock { get; set; }
}
+
+ [MoonSharpUserData]
+ public class ActiveWindow
+ {
+ public string ProcessName { get; set; }
+ public string WindowTitle { get; set; }
+ }
}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Effects/WindowsProfile/WindowsProfileModel.cs b/Artemis/Artemis/Modules/Effects/WindowsProfile/WindowsProfileModel.cs
index 724535874..7a5607c43 100644
--- a/Artemis/Artemis/Modules/Effects/WindowsProfile/WindowsProfileModel.cs
+++ b/Artemis/Artemis/Modules/Effects/WindowsProfile/WindowsProfileModel.cs
@@ -9,6 +9,7 @@ using Artemis.DAL;
using Artemis.Managers;
using Artemis.Models;
using Artemis.Profiles.Layers.Models;
+using Artemis.Utilities;
using Newtonsoft.Json;
using SpotifyAPI.Local;
@@ -52,6 +53,7 @@ namespace Artemis.Modules.Effects.WindowsProfile
UpdateMusicPlayers(dataModel);
UpdateDay(dataModel);
UpdateKeyStates(dataModel);
+ UpdateActiveWindow(dataModel);
}
#region Current Time
@@ -66,7 +68,7 @@ namespace Artemis.Modules.Effects.WindowsProfile
}
#endregion
-
+
#region CPU
private void SetupCpu()
@@ -249,6 +251,12 @@ namespace Artemis.Modules.Effects.WindowsProfile
dataModel.Keyboard.ScrollLock = ((ushort)GetKeyState(0x91) & 0xffff) != 0;
}
+ private void UpdateActiveWindow(WindowsProfileDataModel dataModel)
+ {
+ dataModel.ActiveWindow.ProcessName = ActiveWindowHelper.ActiveWindowProcessName;
+ dataModel.ActiveWindow.WindowTitle = ActiveWindowHelper.ActiveWindowWindowTitle;
+ }
+
#endregion
}
}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/ProjectCars/Data/_eNums/_EnumGetDescription.cs b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_eNums/_EnumGetDescription.cs
new file mode 100644
index 000000000..8e4b201ba
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_eNums/_EnumGetDescription.cs
@@ -0,0 +1,28 @@
+using System;
+using System.ComponentModel;
+
+namespace Artemis.Modules.Games.ProjectCars.Data
+{
+ public static class EnumOperations
+ {
+ public static T StringToEnum(string name)
+ {
+ return (T) Enum.Parse(typeof(T), name);
+ }
+ }
+
+ public static class EnumGetDescription
+ {
+ public static string GetDescription(this Enum enumObj)
+ {
+ var fieldInfo = enumObj.GetType().GetField(enumObj.ToString());
+
+ var attribArray = fieldInfo.GetCustomAttributes(false);
+
+ if (attribArray.Length == 0)
+ return enumObj.ToString();
+ var attrib = attribArray[0] as DescriptionAttribute;
+ return attrib.Description;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/ProjectCars/Data/_eNums/eAPIStructLengths.cs b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_eNums/eAPIStructLengths.cs
new file mode 100644
index 000000000..d30d35694
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_eNums/eAPIStructLengths.cs
@@ -0,0 +1,8 @@
+namespace Artemis.Modules.Games.ProjectCars.Data
+{
+ public enum eAPIStructLengths
+ {
+ STRING_LENGTH_MAX = 64,
+ NUM_PARTICIPANTS = 64
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/ProjectCars/Data/_eNums/eCarFlags.cs b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_eNums/eCarFlags.cs
new file mode 100644
index 000000000..480eff262
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_eNums/eCarFlags.cs
@@ -0,0 +1,17 @@
+using System;
+using System.ComponentModel;
+
+namespace Artemis.Modules.Games.ProjectCars.Data
+{
+ [Flags]
+ public enum eCarFlags
+ {
+ [Description("None")] NONE = 0,
+ [Description("Headlight")] CAR_HEADLIGHT = 1,
+ [Description("Engine Active")] CAR_ENGINE_ACTIVE = 2,
+ [Description("Engine Warning")] CAR_ENGINE_WARNING = 4,
+ [Description("Speed Limiter")] CAR_SPEED_LIMITER = 8,
+ [Description("ABS")] CAR_ABS = 16,
+ [Description("Handbrake")] CAR_HANDBRAKE = 32
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/ProjectCars/Data/_eNums/eCrashDamageState.cs b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_eNums/eCrashDamageState.cs
new file mode 100644
index 000000000..4510be83c
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_eNums/eCrashDamageState.cs
@@ -0,0 +1,13 @@
+namespace Artemis.Modules.Games.ProjectCars.Data
+{
+ public enum eCrashDamageState
+ {
+ CRASH_DAMAGE_NONE = 0,
+ CRASH_DAMAGE_OFFTRACK,
+ CRASH_DAMAGE_LARGE_PROP,
+ CRASH_DAMAGE_SPINNING,
+ CRASH_DAMAGE_ROLLING,
+ //-------------
+ CRASH_MAX
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/ProjectCars/Data/_eNums/eCurrentSector.cs b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_eNums/eCurrentSector.cs
new file mode 100644
index 000000000..fe9c9bef9
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_eNums/eCurrentSector.cs
@@ -0,0 +1,16 @@
+using System.ComponentModel;
+
+namespace Artemis.Modules.Games.ProjectCars.Data
+{
+ public enum eCurrentSector
+ {
+ [Description("Invalid Sector")] SECTOR_INVALID = 0,
+ [Description("Sector Start")] SECTOR_START,
+ [Description("Sector 1")] SECTOR_SECTOR1,
+ [Description("Sector 2")] SECTOR_SECTOR2,
+ [Description("Sector 3")] SECTOR_FINISH,
+ [Description("Sector Stop??")] SECTOR_STOP,
+ //-------------
+ SECTOR_MAX
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/ProjectCars/Data/_eNums/eFlagColors.cs b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_eNums/eFlagColors.cs
new file mode 100644
index 000000000..65b404243
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_eNums/eFlagColors.cs
@@ -0,0 +1,19 @@
+using System.ComponentModel;
+
+namespace Artemis.Modules.Games.ProjectCars.Data
+{
+ public enum eFlagColors
+ {
+ [Description("No Flag")] FLAG_COLOUR_NONE = 0, // Not used for actual flags, only for some query functions
+ [Description("Green Flag")] FLAG_COLOUR_GREEN, // End of danger zone, or race started
+ [Description("Blue Flag")] FLAG_COLOUR_BLUE, // Faster car wants to overtake the participant
+ [Description("White Flag")] FLAG_COLOUR_WHITE, // Approaching a slow car
+ [Description("Yellow Flag")] FLAG_COLOUR_YELLOW, // Danger on the racing surface itself
+ [Description("Double Yellow Flag")] FLAG_COLOUR_DOUBLE_YELLOW,
+ // Danger that wholly or partly blocks the racing surface
+ [Description("Black Flag")] FLAG_COLOUR_BLACK, // Participant disqualified
+ [Description("Chequered Flag")] FLAG_COLOUR_CHEQUERED, // Chequered flag
+ //-------------
+ FLAG_COLOUR_MAX
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/ProjectCars/Data/_eNums/eFlagReason.cs b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_eNums/eFlagReason.cs
new file mode 100644
index 000000000..4329a671f
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_eNums/eFlagReason.cs
@@ -0,0 +1,14 @@
+using System.ComponentModel;
+
+namespace Artemis.Modules.Games.ProjectCars.Data
+{
+ public enum eFlagReason
+ {
+ [Description("No Reason")] FLAG_REASON_NONE = 0,
+ [Description("Solo Crash")] FLAG_REASON_SOLO_CRASH,
+ [Description("Vehicle Crash")] FLAG_REASON_VEHICLE_CRASH,
+ [Description("Vehicle Obstruction")] FLAG_REASON_VEHICLE_OBSTRUCTION,
+ //-------------
+ FLAG_REASON_MAX
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/ProjectCars/Data/_eNums/eGameState.cs b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_eNums/eGameState.cs
new file mode 100644
index 000000000..cc1019ab9
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_eNums/eGameState.cs
@@ -0,0 +1,16 @@
+using System.ComponentModel;
+
+namespace Artemis.Modules.Games.ProjectCars.Data
+{
+ //public class eGameState {public eGameState eGameState { get; set; }}
+
+ public enum eGameState
+ {
+ [Description("Waiting for game to start...")] GAME_EXITED = 0,
+ [Description("In Menus")] GAME_FRONT_END,
+ [Description("In Session")] GAME_INGAME_PLAYING,
+ [Description("Game Paused")] GAME_INGAME_PAUSED,
+ //-------------
+ GAME_MAX
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/ProjectCars/Data/_eNums/eHeaderVersion.cs b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_eNums/eHeaderVersion.cs
new file mode 100644
index 000000000..eec98af56
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_eNums/eHeaderVersion.cs
@@ -0,0 +1,7 @@
+namespace Artemis.Modules.Games.ProjectCars.Data
+{
+ internal enum eHeaderVersion
+ {
+ SHARED_MEMORY_VERSION = 5
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/ProjectCars/Data/_eNums/ePitMode.cs b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_eNums/ePitMode.cs
new file mode 100644
index 000000000..db41f5f37
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_eNums/ePitMode.cs
@@ -0,0 +1,15 @@
+using System.ComponentModel;
+
+namespace Artemis.Modules.Games.ProjectCars.Data
+{
+ public enum ePitMode
+ {
+ [Description("None")] PIT_MODE_NONE = 0,
+ [Description("Pit Entry")] PIT_MODE_DRIVING_INTO_PITS,
+ [Description("In Pits")] PIT_MODE_IN_PIT,
+ [Description("Pit Exit")] PIT_MODE_DRIVING_OUT_OF_PITS,
+ [Description("Pit Garage")] PIT_MODE_IN_GARAGE,
+ //-------------
+ PIT_MODE_MAX
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/ProjectCars/Data/_eNums/ePitSchedule.cs b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_eNums/ePitSchedule.cs
new file mode 100644
index 000000000..dc664d6cd
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_eNums/ePitSchedule.cs
@@ -0,0 +1,14 @@
+using System.ComponentModel;
+
+namespace Artemis.Modules.Games.ProjectCars.Data
+{
+ public enum ePitSchedule
+ {
+ [Description("None")] PIT_SCHEDULE_NONE = 0, // Nothing scheduled
+ [Description("Standard")] PIT_SCHEDULE_STANDARD, // Used for standard pit sequence
+ [Description("Drive Through")] PIT_SCHEDULE_DRIVE_THROUGH, // Used for drive-through penalty
+ [Description("Stop Go")] PIT_SCHEDULE_STOP_GO, // Used for stop-go penalty
+ //-------------
+ PIT_SCHEDULE_MAX
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/ProjectCars/Data/_eNums/eRaceState.cs b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_eNums/eRaceState.cs
new file mode 100644
index 000000000..4d168223d
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_eNums/eRaceState.cs
@@ -0,0 +1,17 @@
+using System.ComponentModel;
+
+namespace Artemis.Modules.Games.ProjectCars.Data
+{
+ public enum eRaceState
+ {
+ [Description("Invalid")] RACESTATE_INVALID = 0,
+ [Description("Not started")] RACESTATE_NOT_STARTED,
+ [Description("Racing")] RACESTATE_RACING,
+ [Description("Finished")] RACESTATE_FINISHED,
+ [Description("Disqualified")] RACESTATE_DISQUALIFIED,
+ [Description("Retired")] RACESTATE_RETIRED,
+ [Description("DNF")] RACESTATE_DNF,
+ //-------------
+ RACESTATE_MAX
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/ProjectCars/Data/_eNums/eSessionState.cs b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_eNums/eSessionState.cs
new file mode 100644
index 000000000..d89200864
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_eNums/eSessionState.cs
@@ -0,0 +1,17 @@
+using System.ComponentModel;
+
+namespace Artemis.Modules.Games.ProjectCars.Data
+{
+ public enum eSessionState
+ {
+ [Description("No Session")] SESSION_INVALID = 0,
+ [Description("Practise")] SESSION_PRACTICE,
+ [Description("Testing")] SESSION_TEST,
+ [Description("Qualifying")] SESSION_QUALIFY,
+ [Description("Formation Lap")] SESSION_FORMATIONLAP,
+ [Description("Racing")] SESSION_RACE,
+ [Description("Time Trial")] SESSION_TIME_ATTACK,
+ //-------------
+ SESSION_MAX
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/ProjectCars/Data/_eNums/eTerrain.cs b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_eNums/eTerrain.cs
new file mode 100644
index 000000000..e5e604075
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_eNums/eTerrain.cs
@@ -0,0 +1,45 @@
+using System.ComponentModel;
+
+namespace Artemis.Modules.Games.ProjectCars.Data
+{
+ public enum eTerrain
+ {
+ [Description("TERRAIN_ROAD")] TERRAIN_ROAD = 0,
+ [Description("TERRAIN_LOW_GRIP_ROAD")] TERRAIN_LOW_GRIP_ROAD,
+ [Description("TERRAIN_BUMPY_ROAD1")] TERRAIN_BUMPY_ROAD1,
+ [Description("TERRAIN_BUMPY_ROAD2")] TERRAIN_BUMPY_ROAD2,
+ [Description("TERRAIN_BUMPY_ROAD3")] TERRAIN_BUMPY_ROAD3,
+ [Description("TERRAIN_MARBLES")] TERRAIN_MARBLES,
+ [Description("TERRAIN_GRASSY_BERMS")] TERRAIN_GRASSY_BERMS,
+ [Description("TERRAIN_GRASS")] TERRAIN_GRASS,
+ [Description("TERRAIN_GRAVEL")] TERRAIN_GRAVEL,
+ [Description("TERRAIN_BUMPY_GRAVEL")] TERRAIN_BUMPY_GRAVEL,
+ [Description("TERRAIN_RUMBLE_STRIPS")] TERRAIN_RUMBLE_STRIPS,
+ [Description("TERRAIN_DRAINS")] TERRAIN_DRAINS,
+ [Description("TERRAIN_TYREWALLS")] TERRAIN_TYREWALLS,
+ [Description("TERRAIN_CEMENTWALLS")] TERRAIN_CEMENTWALLS,
+ [Description("TERRAIN_GUARDRAILS")] TERRAIN_GUARDRAILS,
+ [Description("TERRAIN_SAND")] TERRAIN_SAND,
+ [Description("TERRAIN_BUMPY_SAND")] TERRAIN_BUMPY_SAND,
+ [Description("TERRAIN_DIRT")] TERRAIN_DIRT,
+ [Description("TERRAIN_BUMPY_DIRT")] TERRAIN_BUMPY_DIRT,
+ [Description("TERRAIN_DIRT_ROAD")] TERRAIN_DIRT_ROAD,
+ [Description("TERRAIN_BUMPY_DIRT_ROAD")] TERRAIN_BUMPY_DIRT_ROAD,
+ [Description("TERRAIN_PAVEMENT")] TERRAIN_PAVEMENT,
+ [Description("TERRAIN_DIRT_BANK")] TERRAIN_DIRT_BANK,
+ [Description("TERRAIN_WOOD")] TERRAIN_WOOD,
+ [Description("TERRAIN_DRY_VERGE")] TERRAIN_DRY_VERGE,
+ [Description("TERRAIN_EXIT_RUMBLE_STRIPS")] TERRAIN_EXIT_RUMBLE_STRIPS,
+ [Description("TERRAIN_GRASSCRETE")] TERRAIN_GRASSCRETE,
+ [Description("TERRAIN_LONG_GRASS")] TERRAIN_LONG_GRASS,
+ [Description("TERRAIN_SLOPE_GRASS")] TERRAIN_SLOPE_GRASS,
+ [Description("TERRAIN_COBBLES")] TERRAIN_COBBLES,
+ [Description("TERRAIN_SAND_ROAD")] TERRAIN_SAND_ROAD,
+ [Description("TERRAIN_BAKED_CLAY")] TERRAIN_BAKED_CLAY,
+ [Description("TERRAIN_ASTROTURF")] TERRAIN_ASTROTURF,
+ [Description("TERRAIN_SNOWHALF")] TERRAIN_SNOWHALF,
+ [Description("TERRAIN_SNOWFULL")] TERRAIN_SNOWFULL,
+ //-------------
+ [Description("TERRAIN_MAX")] TERRAIN_MAX
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/ProjectCars/Data/_eNums/eTyreFlags.cs b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_eNums/eTyreFlags.cs
new file mode 100644
index 000000000..8f6dd4bd1
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_eNums/eTyreFlags.cs
@@ -0,0 +1,9 @@
+namespace Artemis.Modules.Games.ProjectCars.Data
+{
+ public enum eTyreFlags
+ {
+ TYRE_ATTACHED = 1 << 0,
+ TYRE_INFLATED = 1 << 1,
+ TYRE_IS_ON_GROUND = 1 << 2
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/ProjectCars/Data/_eNums/eTyres.cs b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_eNums/eTyres.cs
new file mode 100644
index 000000000..4e689c039
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_eNums/eTyres.cs
@@ -0,0 +1,12 @@
+namespace Artemis.Modules.Games.ProjectCars.Data
+{
+ public enum eTyres
+ {
+ TYRE_FRONT_LEFT = 0,
+ TYRE_FRONT_RIGHT,
+ TYRE_REAR_LEFT,
+ TYRE_REAR_RIGHT,
+ //--------------
+ TYRE_MAX
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/ProjectCars/Data/_eNums/eVector.cs b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_eNums/eVector.cs
new file mode 100644
index 000000000..686c13e79
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_eNums/eVector.cs
@@ -0,0 +1,11 @@
+namespace Artemis.Modules.Games.ProjectCars.Data
+{
+ public enum eVector
+ {
+ VEC_X = 0,
+ VEC_Y,
+ VEC_Z,
+ //-------------
+ VEC_MAX
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/ProjectCars/Data/_pCarsAPIClass/CarDamage.cs b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_pCarsAPIClass/CarDamage.cs
new file mode 100644
index 000000000..0f2539572
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_pCarsAPIClass/CarDamage.cs
@@ -0,0 +1,44 @@
+using System.ComponentModel;
+
+namespace Artemis.Modules.Games.ProjectCars.Data
+{
+ public partial class pCarsDataClass : INotifyPropertyChanged
+ {
+ private float maerodamage; // [ RANGE = 0.0f->1.0f ]
+ private eCrashDamageState mcrashstate; // [ enum (Type#4) Crash Damage State ]
+ private float menginedamage; // [ RANGE = 0.0f->1.0f ]
+
+ public eCrashDamageState mCrashState
+ {
+ get { return mcrashstate; }
+ set
+ {
+ if (mcrashstate == value)
+ return;
+ SetProperty(ref mcrashstate, value);
+ }
+ }
+
+ public float mAeroDamage
+ {
+ get { return maerodamage; }
+ set
+ {
+ if (maerodamage == value)
+ return;
+ SetProperty(ref maerodamage, value);
+ }
+ }
+
+ public float mEngineDamage
+ {
+ get { return menginedamage; }
+ set
+ {
+ if (menginedamage == value)
+ return;
+ SetProperty(ref menginedamage, value);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/ProjectCars/Data/_pCarsAPIClass/CarState.cs b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_pCarsAPIClass/CarState.cs
new file mode 100644
index 000000000..1d7c449e9
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_pCarsAPIClass/CarState.cs
@@ -0,0 +1,288 @@
+using System.ComponentModel;
+
+namespace Artemis.Modules.Games.ProjectCars.Data
+{
+ public partial class pCarsDataClass : INotifyPropertyChanged
+ {
+ private bool mantilockactive; // [ UNITS = boolean ] [ RANGE = false->true ] [ UNSET = false ]
+ private bool mboostactive; // [ UNITS = boolean ] [ RANGE = false->true ] [ UNSET = false ]
+ private float mboostamount; // [ RANGE = 0.0f->100.0f ]
+ private float mbrake; // [ RANGE = 0.0f->1.0f ]
+ private eCarFlags mcarflags = eCarFlags.NONE; // [ enum (Type#6) Car Flags ]
+ private float mclutch; // [ RANGE = 0.0f->1.0f ]
+ private float mfuelcapacity; // [ UNITS = Liters ] [ RANGE = 0.0f->1.0f ] [ UNSET = 0.0f ]
+ private float mfuellevel; // [ RANGE = 0.0f->1.0f ]
+ private float mfuelpressurekpa; // [ UNITS = Kilopascal ] [ RANGE = 0.0f->... ] [ UNSET = 0.0f ]
+
+ private int mgear;
+ // [ RANGE = -1 (Reverse) 0 (Neutral) 1 (Gear 1) 2 (Gear 2) etc... ] [ UNSET = 0 (Neutral) ]
+
+ private float mlastopponentcollisionindex; // [ RANGE = 0->STORED_PARTICIPANTS_MAX ] [ UNSET = -1 ]
+ private float mlastopponentcollisionmagnitude; // [ RANGE = 0.0f->... ]
+ private float mmaxrpm; // [ UNITS = Revolutions per minute ] [ RANGE = 0.0f->... ] [ UNSET = 0.0f ]
+ public int mnumgears; // [ RANGE = 0->... ] [ UNSET = -1 ]
+ private float modometerkm; // [ RANGE = 0.0f->... ] [ UNSET = -1.0f ]
+ private float moilpressurekpa; // [ UNITS = Kilopascal ] [ RANGE = 0.0f->... ] [ UNSET = 0.0f ]
+ private float moiltempcelsius; // [ UNITS = Celsius ] [ UNSET = 0.0f ]
+ private float mrpm; // [ UNITS = Revolutions per minute ] [ RANGE = 0.0f->... ] [ UNSET = 0.0f ]
+ private float mspeed; // [ UNITS = Metres per-second ] [ RANGE = 0.0f->... ]
+ private float msteering; // [ RANGE = -1.0f->1.0f ]
+ private float mthrottle; // [ RANGE = 0.0f->1.0f ]
+ private float mwaterpressurekpa; // [ UNITS = Kilopascal ] [ RANGE = 0.0f->... ] [ UNSET = 0.0f ]
+ private float mwatertempcelsius; // [ UNITS = Celsius ] [ UNSET = 0.0f ]
+
+ public eCarFlags mCarFlags
+ {
+ get { return mcarflags; }
+ set
+ {
+ if (mcarflags == value)
+ return;
+ SetProperty(ref mcarflags, value);
+ }
+ }
+
+ public float mOilTempCelsius
+ {
+ get { return moiltempcelsius; }
+ set
+ {
+ if (moiltempcelsius == value)
+ return;
+ SetProperty(ref moiltempcelsius, value);
+ }
+ }
+
+ public float mOilPressureKPa
+ {
+ get { return moilpressurekpa; }
+ set
+ {
+ if (moilpressurekpa == value)
+ return;
+ SetProperty(ref moilpressurekpa, value);
+ }
+ }
+
+ public float mWaterTempCelsius
+ {
+ get { return mwatertempcelsius; }
+ set
+ {
+ if (mwatertempcelsius == value)
+ return;
+ SetProperty(ref mwatertempcelsius, value);
+ }
+ }
+
+ public float mWaterPressureKPa
+ {
+ get { return mwaterpressurekpa; }
+ set
+ {
+ if (mwaterpressurekpa == value)
+ return;
+ SetProperty(ref mwaterpressurekpa, value);
+ }
+ }
+
+ public float mFuelPressureKPa
+ {
+ get { return mfuelpressurekpa; }
+ set
+ {
+ if (mfuelpressurekpa == value)
+ return;
+ SetProperty(ref mfuelpressurekpa, value);
+ }
+ }
+
+ public float mFuelLevel
+ {
+ get { return mfuellevel; }
+ set
+ {
+ if (mfuellevel == value)
+ return;
+ SetProperty(ref mfuellevel, value);
+ }
+ }
+
+ public float mFuelCapacity
+ {
+ get { return mfuelcapacity; }
+ set
+ {
+ if (mfuelcapacity == value)
+ return;
+ SetProperty(ref mfuelcapacity, value);
+ }
+ }
+
+ public float mSpeed
+ {
+ get { return mspeed; }
+ set
+ {
+ if (mspeed == value)
+ return;
+ SetProperty(ref mspeed, value);
+ }
+ }
+
+
+ public float mRPM
+ {
+ get { return mrpm; }
+ set
+ {
+ if (mrpm == value)
+ return;
+ SetProperty(ref mrpm, value);
+ }
+ }
+
+ public float mMaxRPM
+ {
+ get { return mmaxrpm; }
+ set
+ {
+ if (mmaxrpm == value)
+ return;
+ SetProperty(ref mmaxrpm, value);
+ }
+ }
+
+ public float mBrake
+ {
+ get { return mbrake; }
+ set
+ {
+ if (mbrake == value)
+ return;
+ SetProperty(ref mbrake, value);
+ }
+ }
+
+ public float mThrottle
+ {
+ get { return mthrottle; }
+ set
+ {
+ if (mthrottle == value)
+ return;
+ SetProperty(ref mthrottle, value);
+ }
+ }
+
+ public float mClutch
+ {
+ get { return mclutch; }
+ set
+ {
+ if (mclutch == value)
+ return;
+ SetProperty(ref mclutch, value);
+ }
+ }
+
+ public float mSteering
+ {
+ get { return msteering; }
+ set
+ {
+ if (msteering == value)
+ return;
+ SetProperty(ref msteering, value);
+ }
+ }
+
+ public int mGear
+ {
+ get { return mgear; }
+ set
+ {
+ if (mgear == value)
+ return;
+ SetProperty(ref mgear, value);
+ }
+ }
+
+ public int mNumGears
+ {
+ get { return mnumgears; }
+ set
+ {
+ if (mnumgears == value)
+ return;
+ SetProperty(ref mnumgears, value);
+ }
+ }
+
+ public float mOdometerKM
+ {
+ get { return modometerkm; }
+ set
+ {
+ if (modometerkm == value)
+ return;
+ SetProperty(ref modometerkm, value);
+ }
+ }
+
+ public bool mAntiLockActive
+ {
+ get { return mantilockactive; }
+ set
+ {
+ if (mantilockactive == value)
+ return;
+ SetProperty(ref mantilockactive, value);
+ }
+ }
+
+ public float mLastOpponentCollisionIndex
+ {
+ get { return mlastopponentcollisionindex; }
+ set
+ {
+ if (mlastopponentcollisionindex == value)
+ return;
+ SetProperty(ref mlastopponentcollisionindex, value);
+ }
+ }
+
+ public float mLastOpponentCollisionMagnitude
+ {
+ get { return mlastopponentcollisionmagnitude; }
+ set
+ {
+ if (mlastopponentcollisionmagnitude == value)
+ return;
+ SetProperty(ref mlastopponentcollisionmagnitude, value);
+ }
+ }
+
+ public bool mBoostActive
+ {
+ get { return mboostactive; }
+ set
+ {
+ if (mboostactive == value)
+ return;
+ SetProperty(ref mboostactive, value);
+ }
+ }
+
+ public float mBoostAmount
+ {
+ get { return mboostamount; }
+ set
+ {
+ if (mboostamount == value)
+ return;
+ SetProperty(ref mboostamount, value);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/ProjectCars/Data/_pCarsAPIClass/Classes/LapTimeClass.cs b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_pCarsAPIClass/Classes/LapTimeClass.cs
new file mode 100644
index 000000000..fa7e6f64d
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_pCarsAPIClass/Classes/LapTimeClass.cs
@@ -0,0 +1,74 @@
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Runtime.CompilerServices;
+
+namespace Artemis.Modules.Games.ProjectCars.Data
+{
+ public partial class pCarsDataClass : INotifyPropertyChanged
+ {
+ public class LapTimesClass : INotifyPropertyChanged
+ {
+ private float ltlaptime;
+ private float ltsect1;
+ private float ltsect2;
+ private float ltsect3;
+
+ public float ltLapTime
+ {
+ get { return ltlaptime; }
+ set
+ {
+ if (ltlaptime == value)
+ return;
+ SetProperty(ref ltlaptime, value);
+ }
+ }
+
+ public float ltSect1
+ {
+ get { return ltsect1; }
+ set
+ {
+ if (ltsect1 == value)
+ return;
+ SetProperty(ref ltsect1, value);
+ }
+ }
+
+ public float ltSect2
+ {
+ get { return ltsect2; }
+ set
+ {
+ if (ltsect2 == value)
+ return;
+ SetProperty(ref ltsect2, value);
+ }
+ }
+
+ public float ltSect3
+ {
+ get { return ltsect3; }
+ set
+ {
+ if (ltsect3 == value)
+ return;
+ SetProperty(ref ltsect3, value);
+ }
+ }
+
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ private void SetProperty(ref T field, T value, [CallerMemberName] string name = "")
+ {
+ if (!EqualityComparer.Default.Equals(field, value))
+ {
+ field = value;
+ var handler = PropertyChanged;
+ if (handler != null)
+ handler(this, new PropertyChangedEventArgs(name));
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/ProjectCars/Data/_pCarsAPIClass/Classes/ParticipantClass.cs b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_pCarsAPIClass/Classes/ParticipantClass.cs
new file mode 100644
index 000000000..d2f669755
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_pCarsAPIClass/Classes/ParticipantClass.cs
@@ -0,0 +1,123 @@
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Runtime.CompilerServices;
+
+namespace Artemis.Modules.Games.ProjectCars.Data
+{
+ public partial class pCarsDataClass : INotifyPropertyChanged
+ {
+ public class pCarsParticipantsClass : INotifyPropertyChanged
+ {
+ private uint parcurrentlap;
+ private float parcurrentlapdistance;
+ private eCurrentSector parcurrentsector;
+ private bool parisactive;
+ private uint parlapscompleted;
+ private string parname;
+ private uint parraceposition;
+ private List parworldposition;
+
+ public bool parIsActive
+ {
+ get { return parisactive; }
+ set
+ {
+ if (parisactive == value)
+ return;
+ SetProperty(ref parisactive, value);
+ }
+ }
+
+ public string parName
+ {
+ get { return parname; }
+ set
+ {
+ if (parname == value)
+ return;
+ SetProperty(ref parname, value);
+ }
+ } // [ string ]
+
+ public List parWorldPosition
+ {
+ get { return parworldposition; }
+ set
+ {
+ if (parworldposition == value)
+ return;
+ SetProperty(ref parworldposition, value);
+ }
+ } // [ UNITS = World Space X Y Z ]
+
+ public float parCurrentLapDistance
+ {
+ get { return parcurrentlapdistance; }
+ set
+ {
+ if (parcurrentlapdistance == value)
+ return;
+ SetProperty(ref parcurrentlapdistance, value);
+ }
+ } // [ UNITS = Metres ] [ RANGE = 0.0f->... ] [ UNSET = 0.0f ]
+
+ public uint parRacePosition
+ {
+ get { return parraceposition; }
+ set
+ {
+ if (parraceposition == value)
+ return;
+ SetProperty(ref parraceposition, value);
+ }
+ } // [ RANGE = 1->... ] [ UNSET = 0 ]
+
+ public uint parLapsCompleted
+ {
+ get { return parlapscompleted; }
+ set
+ {
+ if (parlapscompleted == value)
+ return;
+ SetProperty(ref parlapscompleted, value);
+ }
+ } // [ RANGE = 0->... ] [ UNSET = 0 ]
+
+ public uint parCurrentLap
+ {
+ get { return parcurrentlap; }
+ set
+ {
+ if (parcurrentlap == value)
+ return;
+ SetProperty(ref parcurrentlap, value);
+ }
+ } // [ RANGE = 0->... ] [ UNSET = 0 ]
+
+ public eCurrentSector parCurrentSector
+ {
+ get { return parcurrentsector; }
+ set
+ {
+ if (parcurrentsector == value)
+ return;
+
+ SetProperty(ref parcurrentsector, value);
+ }
+ } // [ enum (Type#4) Current Sector ]
+
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ private void SetProperty(ref T field, T value, [CallerMemberName] string name = "")
+ {
+ if (!EqualityComparer.Default.Equals(field, value))
+ {
+ field = value;
+ var handler = PropertyChanged;
+ if (handler != null)
+ handler(this, new PropertyChangedEventArgs(name));
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/ProjectCars/Data/_pCarsAPIClass/EventInfo.cs b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_pCarsAPIClass/EventInfo.cs
new file mode 100644
index 000000000..2e97ffea5
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_pCarsAPIClass/EventInfo.cs
@@ -0,0 +1,58 @@
+using System.ComponentModel;
+
+namespace Artemis.Modules.Games.ProjectCars.Data
+{
+ public partial class pCarsDataClass : INotifyPropertyChanged
+ {
+ // Vehicle & Track information
+
+ private uint mlapsinevent; // [ RANGE = 0->... ] [ UNSET = 0 ]
+ private float mtracklength;
+ private string mtracklocation;
+ private string mtrackvariant;
+
+ public uint mLapsInEvent
+ {
+ get { return mlapsinevent; }
+ set
+ {
+ if (mlapsinevent == value)
+ return;
+ SetProperty(ref mlapsinevent, value);
+ }
+ }
+
+ public string mTrackLocation
+ {
+ get { return mtracklocation; }
+ set
+ {
+ if (mtracklocation == value)
+ return;
+ SetProperty(ref mtracklocation, value);
+ }
+ }
+
+ public string mTrackVariant
+ {
+ get { return mtrackvariant; }
+ set
+ {
+ if (mtrackvariant == value)
+ return;
+ SetProperty(ref mtrackvariant, value);
+ }
+ }
+
+ public float mTrackLength
+ {
+ get { return mtracklength; }
+ set
+ {
+ if (mtracklength == value)
+ return;
+ SetProperty(ref mtracklength, value);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/ProjectCars/Data/_pCarsAPIClass/Flags.cs b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_pCarsAPIClass/Flags.cs
new file mode 100644
index 000000000..780d2f972
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_pCarsAPIClass/Flags.cs
@@ -0,0 +1,32 @@
+using System.ComponentModel;
+
+namespace Artemis.Modules.Games.ProjectCars.Data
+{
+ public partial class pCarsDataClass : INotifyPropertyChanged
+ {
+ private eFlagColors mflagcolour;
+ private eFlagReason mflagreason;
+
+ public eFlagColors mFlagColour
+ {
+ get { return mflagcolour; }
+ set
+ {
+ if (mflagcolour == value)
+ return;
+ SetProperty(ref mflagcolour, value);
+ }
+ } // [ enum (Type#5) Flag Colour ]
+
+ public eFlagReason mFlagReason
+ {
+ get { return mflagreason; }
+ set
+ {
+ if (mflagreason == value)
+ return;
+ SetProperty(ref mflagreason, value);
+ }
+ } // [ enum (Type#6) Flag Reason ]
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/ProjectCars/Data/_pCarsAPIClass/GameState.cs b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_pCarsAPIClass/GameState.cs
new file mode 100644
index 000000000..40e812f32
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_pCarsAPIClass/GameState.cs
@@ -0,0 +1,46 @@
+using System.ComponentModel;
+
+namespace Artemis.Modules.Games.ProjectCars.Data
+{
+ public partial class pCarsDataClass : INotifyPropertyChanged
+ {
+ // Session Type
+
+ private eGameState mgamestate = eGameState.GAME_EXITED; // [ enum (Type#1) Game state ]
+ private eRaceState mracestate; // [ RANGE = 0->... ]
+ private eSessionState msessionstate = eSessionState.SESSION_INVALID; // [ enum (Type#2) Session state ]
+
+ public eGameState mGameState
+ {
+ get { return mgamestate; }
+ set
+ {
+ if (mgamestate == value)
+ return;
+ SetProperty(ref mgamestate, value);
+ }
+ }
+
+ public eSessionState mSessionState
+ {
+ get { return msessionstate; }
+ set
+ {
+ if (msessionstate == value)
+ return;
+ SetProperty(ref msessionstate, value);
+ }
+ }
+
+ public eRaceState mRaceState
+ {
+ get { return mracestate; }
+ set
+ {
+ if (mracestate == value)
+ return;
+ SetProperty(ref mracestate, value);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/ProjectCars/Data/_pCarsAPIClass/Methods/pCarsAPI-MapStructToClass.cs b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_pCarsAPIClass/Methods/pCarsAPI-MapStructToClass.cs
new file mode 100644
index 000000000..f3b720188
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_pCarsAPIClass/Methods/pCarsAPI-MapStructToClass.cs
@@ -0,0 +1,216 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+
+namespace Artemis.Modules.Games.ProjectCars.Data
+{
+ public partial class pCarsDataClass : INotifyPropertyChanged
+ {
+ public pCarsDataClass MapStructToClass(pCarsAPIStruct pcarsDataStruct, pCarsDataClass pCarsData)
+ {
+ //pCarsDataClass pCarsData = new pCarsDataClass();
+ pCarsData.mVersion = pcarsDataStruct.mVersion;
+ pCarsData.mBuildVersion = pcarsDataStruct.mBuildVersion;
+
+ // Session type
+ pCarsData.mGameState = (eGameState) pcarsDataStruct.mGameState;
+ pCarsData.mSessionState = (eSessionState) pcarsDataStruct.mSessionState;
+ pCarsData.mRaceState = (eRaceState) pcarsDataStruct.mRaceState;
+
+ pCarsData.mViewedParticipantIndex = pcarsDataStruct.mViewedParticipantIndex;
+ pCarsData.mNumParticipants = pcarsDataStruct.mNumParticipants;
+
+ if (pCarsData.mPlayerParticipantIndex < 0)
+ pCarsData.mPlayerParticipantIndex = pCarsData.mViewedParticipantIndex;
+
+ for (var loop = 0; loop < (uint) eAPIStructLengths.NUM_PARTICIPANTS; loop++)
+ {
+ if (pCarsData.listParticipantInfo.Count != (uint) eAPIStructLengths.NUM_PARTICIPANTS)
+ for (var i = 0; i < (uint) eAPIStructLengths.NUM_PARTICIPANTS; i++)
+ pCarsData.listParticipantInfo.Add(new pCarsParticipantsClass());
+
+ if (pcarsDataStruct.mParticipantData[loop].mCurrentLap != 0)
+ {
+ var newPartData = new pCarsParticipantsClass
+ {
+ parIsActive = pcarsDataStruct.mParticipantData[loop].mIsActive,
+ parName = pcarsDataStruct.mParticipantData[loop].mName,
+ parWorldPosition = new List(pcarsDataStruct.mParticipantData[loop].mWorldPosition),
+ parCurrentLapDistance = pcarsDataStruct.mParticipantData[loop].mCurrentLapDistance,
+ parRacePosition = pcarsDataStruct.mParticipantData[loop].mRacePosition,
+ parLapsCompleted = pcarsDataStruct.mParticipantData[loop].mLapsCompleted,
+ parCurrentLap = pcarsDataStruct.mParticipantData[loop].mCurrentLap,
+ parCurrentSector = (eCurrentSector) pcarsDataStruct.mParticipantData[loop].mCurrentSector
+ };
+
+ pCarsData.listParticipantInfo[loop] = newPartData;
+ }
+ }
+
+ // Unfiltered Input
+ pCarsData.mUnfilteredThrottle = pcarsDataStruct.mUnfilteredThrottle;
+ pCarsData.mUnfilteredBrake = pcarsDataStruct.mUnfilteredBrake;
+ pCarsData.mUnfilteredSteering = pcarsDataStruct.mUnfilteredSteering;
+ pCarsData.mUnfilteredClutch = pcarsDataStruct.mUnfilteredClutch;
+
+ // Vehicle & Track information
+ pCarsData.mCarName = pcarsDataStruct.mCarName;
+ pCarsData.mCarClassName = pcarsDataStruct.mCarClassName;
+ pCarsData.mLapsInEvent = pcarsDataStruct.mLapsInEvent;
+ pCarsData.mTrackLocation = pcarsDataStruct.mTrackLocation;
+ pCarsData.mTrackVariant = pcarsDataStruct.mTrackVariation;
+ pCarsData.mTrackLength = pcarsDataStruct.mTrackLength;
+
+ // Timing & Scoring
+ pCarsData.mLapInvalidated = pcarsDataStruct.mLapInvalidated;
+ pCarsData.mLastLapTime = pcarsDataStruct.mLastLapTime;
+ pCarsData.mCurrentTime = pcarsDataStruct.mCurrentTime;
+
+ pCarsData.mSplitTimeAhead = pcarsDataStruct.mSplitTimeAhead;
+ pCarsData.mSplitTimeBehind = pcarsDataStruct.mSplitTimeBehind;
+ pCarsData.mSplitTime = pcarsDataStruct.mSplitTime;
+ pCarsData.mEventTimeRemaining = pcarsDataStruct.mEventTimeRemaining;
+
+
+ //make sure that the collections are not empty
+ if (pCarsData.mCurrentLapTime.Count == 0)
+ pCarsData.mCurrentLapTime = new ObservableCollection {new LapTimesClass()};
+
+ if (pCarsData.mSessionFastestLapTime.Count == 0)
+ pCarsData.mSessionFastestLapTime = new ObservableCollection {new LapTimesClass()};
+
+ if (pCarsData.mPersonalFastestLapTime.Count == 0)
+ pCarsData.mPersonalFastestLapTime = new ObservableCollection {new LapTimesClass()};
+
+ if (pCarsData.mWorldFastestLapTime.Count == 0)
+ pCarsData.mWorldFastestLapTime = new ObservableCollection {new LapTimesClass()};
+
+ //create the new entry at index 0
+ //index 0 is the first in the collection
+ //a collection is required for the datagrid binding
+
+ pCarsData.mCurrentLapTime[0] = new LapTimesClass
+ {
+ ltLapTime = pcarsDataStruct.mCurrentTime,
+ ltSect1 = pcarsDataStruct.mCurrentSector1Time,
+ ltSect2 = pcarsDataStruct.mCurrentSector2Time,
+ ltSect3 = pcarsDataStruct.mCurrentSector3Time
+ };
+
+ pCarsData.mSessionFastestLapTime[0] = new LapTimesClass
+ {
+ ltLapTime = pcarsDataStruct.mSessionFastestLapTime,
+ ltSect1 = pcarsDataStruct.mSessionFastestSector1Time,
+ ltSect2 = pcarsDataStruct.mSessionFastestSector2Time,
+ ltSect3 = pcarsDataStruct.mSessionFastestSector3Time
+ };
+
+ pCarsData.mPersonalFastestLapTime[0] = new LapTimesClass
+ {
+ ltLapTime = pcarsDataStruct.mPersonalFastestLapTime,
+ ltSect1 = pcarsDataStruct.mPersonalFastestSector1Time,
+ ltSect2 = pcarsDataStruct.mPersonalFastestSector2Time,
+ ltSect3 = pcarsDataStruct.mPersonalFastestSector3Time
+ };
+
+ pCarsData.mWorldFastestLapTime[0] = new LapTimesClass
+ {
+ ltLapTime = pcarsDataStruct.mWorldFastestLapTime,
+ ltSect1 = pcarsDataStruct.mWorldFastestSector1Time,
+ ltSect2 = pcarsDataStruct.mWorldFastestSector2Time,
+ ltSect3 = pcarsDataStruct.mWorldFastestSector3Time
+ };
+
+ // Flags
+ pCarsData.mFlagColour = (eFlagColors) pcarsDataStruct.mHighestFlagColour;
+ pCarsData.mFlagReason = (eFlagReason) pcarsDataStruct.mHighestFlagReason;
+
+ // Pit Info
+ pCarsData.mPitMode = (ePitMode) pcarsDataStruct.mPitMode;
+ pCarsData.mPitSchedule = (ePitSchedule) pcarsDataStruct.mPitSchedule;
+
+ // Car State
+ pCarsData.mCarFlags = (eCarFlags) pcarsDataStruct.mCarFlags;
+ pCarsData.mOilTempCelsius = pcarsDataStruct.mOilTempCelsius;
+ pCarsData.mOilPressureKPa = pcarsDataStruct.mOilPressureKPa;
+ pCarsData.mWaterTempCelsius = pcarsDataStruct.mWaterTempCelsius;
+ pCarsData.mWaterPressureKPa = pcarsDataStruct.mWaterPressureKPa;
+ pCarsData.mFuelPressureKPa = pcarsDataStruct.mFuelPressureKPa;
+
+ pCarsData.mFuelLevel = (float) Math.Round(pcarsDataStruct.mFuelLevel*pcarsDataStruct.mFuelCapacity, 2);
+ pCarsData.mFuelCapacity = pcarsDataStruct.mFuelCapacity;
+ pCarsData.mSpeed = pcarsDataStruct.mSpeed;
+ pCarsData.mRPM = pcarsDataStruct.mRPM;
+ pCarsData.mMaxRPM = pcarsDataStruct.mMaxRPM;
+
+ //logger.Trace("mRPM = " + pCarsData.mRPM);
+ //logger.Trace("mMaxRPM = " + pCarsData.mMaxRPM);
+ //
+ pCarsData.mBrake = pcarsDataStruct.mBrake;
+ pCarsData.mThrottle = pcarsDataStruct.mThrottle;
+ pCarsData.mClutch = pcarsDataStruct.mClutch;
+ pCarsData.mSteering = pcarsDataStruct.mSteering;
+ pCarsData.mGear = pcarsDataStruct.mGear;
+ pCarsData.mNumGears = pcarsDataStruct.mNumGears;
+ pCarsData.mOdometerKM = pcarsDataStruct.mOdometerKM;
+ pCarsData.mAntiLockActive = pcarsDataStruct.mAntiLockActive;
+
+ pCarsData.mLastOpponentCollisionIndex = pcarsDataStruct.mLastOpponentCollisionIndex;
+ pCarsData.mLastOpponentCollisionMagnitude = pcarsDataStruct.mLastOpponentCollisionMagnitude;
+
+ pCarsData.mBoostActive = pcarsDataStruct.mBoostActive;
+ pCarsData.mBoostAmount = pcarsDataStruct.mBoostAmount;
+
+ // Motion & Device Related
+ //////pCarsData.mWorldPosition = new List(pcarsDataStruct.mWorldPosition);
+ pCarsData.mOrientation = new List(pcarsDataStruct.mOrientation);
+ pCarsData.mLocalVelocity = new List(pcarsDataStruct.mLocalVelocity);
+ pCarsData.mWorldVelocity = new List(pcarsDataStruct.mWorldVelocity);
+ pCarsData.mAngularVelocity = new List(pcarsDataStruct.mAngularVelocity);
+ pCarsData.mLocalAcceleration = new List(pcarsDataStruct.mLocalAcceleration);
+ pCarsData.mWorldAcceleration = new List(pcarsDataStruct.mWorldAcceleration);
+ pCarsData.mExtentsCentre = new List(pcarsDataStruct.mExtentsCentre);
+
+ // Wheels / Tyres
+ //pCarsData.mTyreFlags = pcarsDataStruct.mTyreFlags.Select(i => (eTyreFlags)i).ToList();
+ //pCarsData.mTerrain = pcarsDataStruct.mTerrain.Select(i => (eTerrain)i).ToList();
+
+ pCarsData.mTyreFlags = new List(pcarsDataStruct.mTyreFlags);
+ pCarsData.mTerrain = new List(pcarsDataStruct.mTerrain);
+ pCarsData.mTyreY = new List(pcarsDataStruct.mTyreY);
+ pCarsData.mTyreRPS = new List(pcarsDataStruct.mTyreRPS);
+ pCarsData.mTyreSlipSpeed = new List(pcarsDataStruct.mTyreSlipSpeed);
+ pCarsData.mTyreTemp = new List(pcarsDataStruct.mTyreTemp);
+ pCarsData.mTyreGrip = new List(pcarsDataStruct.mTyreGrip);
+ pCarsData.mTyreHeightAboveGround = new List(pcarsDataStruct.mTyreHeightAboveGround);
+ pCarsData.mTyreLateralStiffness = new List(pcarsDataStruct.mTyreLateralStiffness);
+ pCarsData.mTyreWear = new List(pcarsDataStruct.mTyreWear);
+ pCarsData.mBrakeDamage = new List(pcarsDataStruct.mBrakeDamage);
+ pCarsData.mSuspensionDamage = new List(pcarsDataStruct.mSuspensionDamage);
+
+ pCarsData.mBrakeTempCelsius = new List(pcarsDataStruct.mBrakeTempCelsius);
+ pCarsData.mTyreTreadTemp = new List(pcarsDataStruct.mTyreTreadTemp);
+ pCarsData.mTyreLayerTemp = new List(pcarsDataStruct.mTyreLayerTemp);
+ pCarsData.mTyreCarcassTemp = new List(pcarsDataStruct.mTyreCarcassTemp);
+ pCarsData.mTyreRimTemp = new List(pcarsDataStruct.mTyreRimTemp);
+ pCarsData.mTyreInternalAirTemp = new List(pcarsDataStruct.mTyreInternalAirTemp);
+
+ // Car Damage
+ pCarsData.mCrashState = (eCrashDamageState) pcarsDataStruct.mCrashState;
+ pCarsData.mAeroDamage = pcarsDataStruct.mAeroDamage;
+ pCarsData.mEngineDamage = pcarsDataStruct.mEngineDamage;
+
+ // Weather
+ pCarsData.mAmbientTemperature = pcarsDataStruct.mAmbientTemperature;
+ pCarsData.mTrackTemperature = pcarsDataStruct.mTrackTemperature;
+ pCarsData.mRainDensity = pcarsDataStruct.mRainDensity;
+ pCarsData.mWindSpeed = pcarsDataStruct.mWindSpeed;
+ pCarsData.mWindDirectionX = pcarsDataStruct.mWindDirectionX;
+ pCarsData.mWindDirectionY = pcarsDataStruct.mWindDirectionY;
+ pCarsData.mCloudBrightness = pcarsDataStruct.mCloudBrightness;
+
+ return pCarsData;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/ProjectCars/Data/_pCarsAPIClass/MotionDevice.cs b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_pCarsAPIClass/MotionDevice.cs
new file mode 100644
index 000000000..c534f95ed
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_pCarsAPIClass/MotionDevice.cs
@@ -0,0 +1,94 @@
+using System.Collections.Generic;
+using System.ComponentModel;
+
+namespace Artemis.Modules.Games.ProjectCars.Data
+{
+ public partial class pCarsDataClass : INotifyPropertyChanged
+ {
+ private List mangularvelocity; // [ UNITS = Radians per-second ]
+ private List mextentscentre; // [ UNITS = Local Space X Y Z ]
+ private List mlocalacceleration; // [ UNITS = Metres per-second ]
+ private List mlocalvelocity; // [ UNITS = Metres per-second ]
+ // Motion & Device Related
+ private List morientation; // [ UNITS = Euler Angles ]
+ private List mworldacceleration; // [ UNITS = Metres per-second ]
+ private List mworldvelocity; // [ UNITS = Metres per-second ]
+
+ public List mOrientation
+ {
+ get { return morientation; }
+ set
+ {
+ if (morientation == value)
+ return;
+ SetProperty(ref morientation, value);
+ }
+ }
+
+ public List mLocalVelocity
+ {
+ get { return mlocalvelocity; }
+ set
+ {
+ if (mlocalvelocity == value)
+ return;
+ SetProperty(ref mlocalvelocity, value);
+ }
+ }
+
+ public List mWorldVelocity
+ {
+ get { return mworldvelocity; }
+ set
+ {
+ if (mworldvelocity == value)
+ return;
+ SetProperty(ref mworldvelocity, value);
+ }
+ }
+
+ public List mAngularVelocity
+ {
+ get { return mangularvelocity; }
+ set
+ {
+ if (mangularvelocity == value)
+ return;
+ SetProperty(ref mangularvelocity, value);
+ }
+ }
+
+ public List mLocalAcceleration
+ {
+ get { return mlocalacceleration; }
+ set
+ {
+ if (mlocalacceleration == value)
+ return;
+ SetProperty(ref mlocalacceleration, value);
+ }
+ }
+
+ public List mWorldAcceleration
+ {
+ get { return mworldacceleration; }
+ set
+ {
+ if (mworldacceleration == value)
+ return;
+ SetProperty(ref mworldacceleration, value);
+ }
+ }
+
+ public List mExtentsCentre
+ {
+ get { return mextentscentre; }
+ set
+ {
+ if (mextentscentre == value)
+ return;
+ SetProperty(ref mextentscentre, value);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/ProjectCars/Data/_pCarsAPIClass/ParticipantInfo.cs b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_pCarsAPIClass/ParticipantInfo.cs
new file mode 100644
index 000000000..5e9fbdecc
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_pCarsAPIClass/ParticipantInfo.cs
@@ -0,0 +1,59 @@
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+
+namespace Artemis.Modules.Games.ProjectCars.Data
+{
+ public partial class pCarsDataClass : INotifyPropertyChanged
+ {
+ private ObservableCollection listparticipantinfo =
+ new ObservableCollection();
+
+ private int mnumparticipants;
+ private int mplayerparticipantindex = -1;
+ private int mviewedparticipantindex = -1;
+
+ public int mPlayerParticipantIndex
+ {
+ get { return mplayerparticipantindex; }
+ set
+ {
+ if (mplayerparticipantindex == value)
+ return;
+ SetProperty(ref mplayerparticipantindex, value);
+ }
+ }
+
+ public int mViewedParticipantIndex
+ {
+ get { return mviewedparticipantindex; }
+ set
+ {
+ if (mviewedparticipantindex == value)
+ return;
+ SetProperty(ref mviewedparticipantindex, value);
+ }
+ }
+
+ public int mNumParticipants
+ {
+ get { return mnumparticipants; }
+ set
+ {
+ if (mnumparticipants == value)
+ return;
+ SetProperty(ref mnumparticipants, value);
+ }
+ }
+
+ public ObservableCollection listParticipantInfo
+ {
+ get { return listparticipantinfo; }
+ set
+ {
+ if (listparticipantinfo == value)
+ return;
+ SetProperty(ref listparticipantinfo, value);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/ProjectCars/Data/_pCarsAPIClass/PitInfo.cs b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_pCarsAPIClass/PitInfo.cs
new file mode 100644
index 000000000..299a63694
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_pCarsAPIClass/PitInfo.cs
@@ -0,0 +1,32 @@
+using System.ComponentModel;
+
+namespace Artemis.Modules.Games.ProjectCars.Data
+{
+ public partial class pCarsDataClass : INotifyPropertyChanged
+ {
+ private ePitMode mpitmode; // [ enum (Type#7) Pit Mode ]
+ private ePitSchedule mpitschedule; // [ enum (Type#8) Pit Stop Schedule ]
+
+ public ePitMode mPitMode
+ {
+ get { return mpitmode; }
+ set
+ {
+ if (mpitmode == value)
+ return;
+ SetProperty(ref mpitmode, value);
+ }
+ } // [ enum (Type#6) Flag Reason ]
+
+ public ePitSchedule mPitSchedule
+ {
+ get { return mpitschedule; }
+ set
+ {
+ if (mpitschedule == value)
+ return;
+ SetProperty(ref mpitschedule, value);
+ }
+ } // [ enum (Type#6) Flag Reason ]
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/ProjectCars/Data/_pCarsAPIClass/Timings.cs b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_pCarsAPIClass/Timings.cs
new file mode 100644
index 000000000..b68ef96ab
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_pCarsAPIClass/Timings.cs
@@ -0,0 +1,155 @@
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+
+namespace Artemis.Modules.Games.ProjectCars.Data
+{
+ public partial class pCarsDataClass : INotifyPropertyChanged
+ {
+ private float mbestlaptime; // [ UNITS = seconds ] [ RANGE = 0.0f->... ] [ UNSET = -1.0f ]
+ private ObservableCollection mcurrentlaptime = new ObservableCollection();
+ private float mcurrenttime; // [ UNITS = seconds ] [ RANGE = 0.0f->... ] [ UNSET = 0.0f ]
+ private float meventtimeremaining; // [ UNITS = milli-seconds ] [ RANGE = 0.0f->... ] [ UNSET = -1.0f ]
+ private bool mlapinvalidated; // [ UNITS = boolean ] [ RANGE = false->true ] [ UNSET = false ]
+ private float mlastlaptime; // [ UNITS = seconds ] [ RANGE = 0.0f->... ] [ UNSET = 0.0f ]
+ private ObservableCollection mpersonalfastestlaptime = new ObservableCollection();
+ private ObservableCollection msessionfastestlaptime = new ObservableCollection();
+ private float msplittime; // [ UNITS = seconds ] [ RANGE = 0.0f->... ] [ UNSET = 0.0f ]
+ private float msplittimeahead; // [ UNITS = seconds ] [ RANGE = 0.0f->... ] [ UNSET = -1.0f ]
+ private float msplittimebehind; // [ UNITS = seconds ] [ RANGE = 0.0f->... ] [ UNSET = -1.0f ]
+ private ObservableCollection mworldfastestlaptime = new ObservableCollection();
+
+
+ public bool mLapInvalidated
+ {
+ get { return mlapinvalidated; }
+ set
+ {
+ if (mlapinvalidated == value)
+ return;
+ SetProperty(ref mlapinvalidated, value);
+ }
+ }
+
+ public float mBestLapTime
+ {
+ get { return mbestlaptime; }
+ set
+ {
+ if (mbestlaptime == value)
+ return;
+ SetProperty(ref mbestlaptime, value);
+ }
+ }
+
+ public float mLastLapTime
+ {
+ get { return mlastlaptime; }
+ set
+ {
+ if (mlastlaptime == value)
+ return;
+ SetProperty(ref mlastlaptime, value);
+ }
+ }
+
+ public float mCurrentTime
+ {
+ get { return mcurrenttime; }
+ set
+ {
+ if (mcurrenttime == value)
+ return;
+ SetProperty(ref mcurrenttime, value);
+ }
+ }
+
+ public float mSplitTimeAhead
+ {
+ get { return msplittimeahead; }
+ set
+ {
+ if (msplittimeahead == value)
+ return;
+ SetProperty(ref msplittimeahead, value);
+ }
+ }
+
+ public float mSplitTimeBehind
+ {
+ get { return msplittimebehind; }
+ set
+ {
+ if (msplittimebehind == value)
+ return;
+ SetProperty(ref msplittimebehind, value);
+ }
+ }
+
+ public float mSplitTime
+ {
+ get { return msplittime; }
+ set
+ {
+ if (msplittime == value)
+ return;
+ SetProperty(ref msplittime, value);
+ }
+ }
+
+
+ public float mEventTimeRemaining
+ {
+ get { return meventtimeremaining; }
+ set
+ {
+ if (meventtimeremaining == value)
+ return;
+ SetProperty(ref meventtimeremaining, value);
+ }
+ }
+
+ public ObservableCollection mCurrentLapTime
+ {
+ get { return mcurrentlaptime; }
+ set
+ {
+ if (mcurrentlaptime == value)
+ return;
+ SetProperty(ref mcurrentlaptime, value);
+ }
+ }
+
+ public ObservableCollection mSessionFastestLapTime
+ {
+ get { return msessionfastestlaptime; }
+ set
+ {
+ if (msessionfastestlaptime == value)
+ return;
+ SetProperty(ref msessionfastestlaptime, value);
+ }
+ }
+
+ public ObservableCollection mPersonalFastestLapTime
+ {
+ get { return mpersonalfastestlaptime; }
+ set
+ {
+ if (mpersonalfastestlaptime == value)
+ return;
+ SetProperty(ref mpersonalfastestlaptime, value);
+ }
+ }
+
+ public ObservableCollection mWorldFastestLapTime
+ {
+ get { return mworldfastestlaptime; }
+ set
+ {
+ if (mworldfastestlaptime == value)
+ return;
+ SetProperty(ref mworldfastestlaptime, value);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/ProjectCars/Data/_pCarsAPIClass/UnfilteredInput.cs b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_pCarsAPIClass/UnfilteredInput.cs
new file mode 100644
index 000000000..a24bdc3b6
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_pCarsAPIClass/UnfilteredInput.cs
@@ -0,0 +1,58 @@
+using System.ComponentModel;
+
+namespace Artemis.Modules.Games.ProjectCars.Data
+{
+ public partial class pCarsDataClass : INotifyPropertyChanged
+ {
+ private float munfilteredbrake; // [ RANGE = 0.0f->1.0f ]
+ private float munfilteredclutch; // [ RANGE = 0.0f->1.0f ]
+ private float munfilteredsteering; // [ RANGE = -1.0f->1.0f ]
+ // Unfiltered Input
+
+ private float munfilteredthrottle; // [ RANGE = 0.0f->1.0f ]
+
+ public float mUnfilteredThrottle
+ {
+ get { return munfilteredthrottle; }
+ set
+ {
+ if (munfilteredthrottle == value)
+ return;
+ SetProperty(ref munfilteredthrottle, value);
+ }
+ }
+
+ public float mUnfilteredBrake
+ {
+ get { return munfilteredbrake; }
+ set
+ {
+ if (munfilteredbrake == value)
+ return;
+ SetProperty(ref munfilteredbrake, value);
+ }
+ }
+
+ public float mUnfilteredSteering
+ {
+ get { return munfilteredsteering; }
+ set
+ {
+ if (munfilteredsteering == value)
+ return;
+ SetProperty(ref munfilteredsteering, value);
+ }
+ }
+
+ public float mUnfilteredClutch
+ {
+ get { return munfilteredclutch; }
+ set
+ {
+ if (munfilteredclutch == value)
+ return;
+ SetProperty(ref munfilteredclutch, value);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/ProjectCars/Data/_pCarsAPIClass/Vehicle.cs b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_pCarsAPIClass/Vehicle.cs
new file mode 100644
index 000000000..4cb78009e
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_pCarsAPIClass/Vehicle.cs
@@ -0,0 +1,34 @@
+using System.ComponentModel;
+
+namespace Artemis.Modules.Games.ProjectCars.Data
+{
+ public partial class pCarsDataClass : INotifyPropertyChanged
+ {
+ private string mcarclassname;
+ // Vehicle & Track information
+
+ private string mcarname;
+
+ public string mCarName
+ {
+ get { return mcarname; }
+ set
+ {
+ if (mcarname == value)
+ return;
+ SetProperty(ref mcarname, value);
+ }
+ }
+
+ public string mCarClassName
+ {
+ get { return mcarclassname; }
+ set
+ {
+ if (mcarclassname == value)
+ return;
+ SetProperty(ref mcarclassname, value);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/ProjectCars/Data/_pCarsAPIClass/Version.cs b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_pCarsAPIClass/Version.cs
new file mode 100644
index 000000000..c22cc1a37
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_pCarsAPIClass/Version.cs
@@ -0,0 +1,32 @@
+using System.ComponentModel;
+
+namespace Artemis.Modules.Games.ProjectCars.Data
+{
+ public partial class pCarsDataClass : INotifyPropertyChanged
+ {
+ private uint mbuildversion; // [ RANGE = 0->... ]
+ private uint mversion; // [ RANGE = 0->... ]
+
+ public uint mVersion
+ {
+ get { return mversion; }
+ set
+ {
+ if (mversion == value)
+ return;
+ SetProperty(ref mversion, value);
+ }
+ }
+
+ public uint mBuildVersion
+ {
+ get { return mbuildversion; }
+ set
+ {
+ if (mbuildversion == value)
+ return;
+ SetProperty(ref mbuildversion, value);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/ProjectCars/Data/_pCarsAPIClass/Weather.cs b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_pCarsAPIClass/Weather.cs
new file mode 100644
index 000000000..fcdab172c
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_pCarsAPIClass/Weather.cs
@@ -0,0 +1,92 @@
+using System.ComponentModel;
+
+namespace Artemis.Modules.Games.ProjectCars.Data
+{
+ public partial class pCarsDataClass : INotifyPropertyChanged
+ {
+ private float mambienttemperature; // [ UNITS = Celsius ] [ UNSET = 25.0f ]
+ private float mcloudbrightness; // [ RANGE = 0.0f->... ]
+ private float mraindensity; // [ UNITS = How much rain will fall ] [ RANGE = 0.0f->1.0f ]
+ private float mtracktemperature; // [ UNITS = Celsius ] [ UNSET = 30.0f ]
+ private float mwinddirectionx; // [ UNITS = Normalised Vector X ]
+ private float mwinddirectiony; // [ UNITS = Normalised Vector Y ]
+ private float mwindspeed; // [ RANGE = 0.0f->100.0f ] [ UNSET = 2.0f ]
+
+ public float mAmbientTemperature
+ {
+ get { return mambienttemperature; }
+ set
+ {
+ if (mambienttemperature == value)
+ return;
+ SetProperty(ref mambienttemperature, value);
+ }
+ }
+
+ public float mTrackTemperature
+ {
+ get { return mtracktemperature; }
+ set
+ {
+ if (mtracktemperature == value)
+ return;
+ SetProperty(ref mtracktemperature, value);
+ }
+ }
+
+ public float mRainDensity
+ {
+ get { return mraindensity; }
+ set
+ {
+ if (mraindensity == value)
+ return;
+ SetProperty(ref mraindensity, value);
+ }
+ }
+
+ public float mWindSpeed
+ {
+ get { return mwindspeed; }
+ set
+ {
+ if (mwindspeed == value)
+ return;
+ SetProperty(ref mwindspeed, value);
+ }
+ }
+
+ public float mWindDirectionX
+ {
+ get { return mwinddirectionx; }
+ set
+ {
+ if (mwinddirectionx == value)
+ return;
+ SetProperty(ref mwinddirectionx, value);
+ }
+ }
+
+ public float mWindDirectionY
+ {
+ get { return mwinddirectiony; }
+ set
+ {
+ if (mwinddirectiony == value)
+ return;
+ SetProperty(ref mwinddirectiony, value);
+ }
+ }
+
+ public float mCloudBrightness
+ {
+ get { return mcloudbrightness; }
+ set
+ {
+ if (mcloudbrightness == value)
+ return;
+ SetProperty(ref mcloudbrightness, value);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/ProjectCars/Data/_pCarsAPIClass/WheelTyre.cs b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_pCarsAPIClass/WheelTyre.cs
new file mode 100644
index 000000000..dc7748769
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_pCarsAPIClass/WheelTyre.cs
@@ -0,0 +1,226 @@
+using System.Collections.Generic;
+using System.ComponentModel;
+
+namespace Artemis.Modules.Games.ProjectCars.Data
+{
+ public partial class pCarsDataClass : INotifyPropertyChanged
+ {
+ private List mbrakedamage; // [ RANGE = 0.0f->1.0f ]
+ private List mbraketempcelsius; // [ RANGE = 0.0f->1.0f ]
+ private List msuspensiondamage; // [ RANGE = 0.0f->1.0f ]
+ private List mterrain; // [ enum (Type#3) Terrain Materials ]
+ private List mtyrecarcasstemp; // [ RANGE = 0.0f->1.0f ]
+ private List mtyreflags; // [ enum (Type#7) Tyre Flags ]
+ private List mtyregrip; // [ RANGE = 0.0f->1.0f ]
+ private List mtyreheightaboveground; // [ UNITS = Local Space Y ]
+ private List mtyreinternalairtemp; // [ RANGE = 0.0f->1.0f ]
+ private List mtyrelateralstiffness; // [ UNITS = Lateral stiffness coefficient used in tyre deformation ]
+ private List mtyrelayertemp; // [ RANGE = 0.0f->1.0f ]
+ private List mtyrerimtemp; // [ RANGE = 0.0f->1.0f ]
+ private List mtyrerps; // [ UNITS = Revolutions per second ]
+ private List mtyreslipspeed; // [ UNITS = Metres per-second ]
+ private List mtyretemp; // [ UNITS = Celsius ] [ UNSET = 0.0f ]
+ private List mtyretreadtemp; // [ RANGE = 0.0f->1.0f ]
+ private List mtyrewear; // [ RANGE = 0.0f->1.0f ]
+ private List mtyrey; // [ UNITS = Local Space Y ]
+
+
+ public List mTyreFlags
+ {
+ get { return mtyreflags; }
+ set
+ {
+ if (mtyreflags == value)
+ return;
+ SetProperty(ref mtyreflags, value);
+ }
+ }
+
+ public List mTerrain
+ {
+ get { return mterrain; }
+ set
+ {
+ if (mterrain == value)
+ return;
+ SetProperty(ref mterrain, value);
+ }
+ }
+
+ public List mTyreY
+ {
+ get { return mtyrey; }
+ set
+ {
+ if (mtyrey == value)
+ return;
+ SetProperty(ref mtyrey, value);
+ }
+ }
+
+ public List mTyreRPS
+ {
+ get { return mtyrerps; }
+ set
+ {
+ if (mtyrerps == value)
+ return;
+ SetProperty(ref mtyrerps, value);
+ }
+ }
+
+ public List mTyreSlipSpeed
+ {
+ get { return mtyreslipspeed; }
+ set
+ {
+ if (mtyreslipspeed == value)
+ return;
+ SetProperty(ref mtyreslipspeed, value);
+ }
+ }
+
+ public List mTyreTemp
+ {
+ get { return mtyretemp; }
+ set
+ {
+ if (mtyretemp == value)
+ return;
+ SetProperty(ref mtyretemp, value);
+ }
+ }
+
+ public List mTyreGrip
+ {
+ get { return mtyregrip; }
+ set
+ {
+ if (mtyregrip == value)
+ return;
+ SetProperty(ref mtyregrip, value);
+ }
+ }
+
+ public List mTyreHeightAboveGround
+ {
+ get { return mtyreheightaboveground; }
+ set
+ {
+ if (mtyreheightaboveground == value)
+ return;
+ SetProperty(ref mtyreheightaboveground, value);
+ }
+ }
+
+ public List mTyreLateralStiffness
+ {
+ get { return mtyrelateralstiffness; }
+ set
+ {
+ if (mtyrelateralstiffness == value)
+ return;
+ SetProperty(ref mtyrelateralstiffness, value);
+ }
+ }
+
+ public List mTyreWear
+ {
+ get { return mtyrewear; }
+ set
+ {
+ if (mtyrewear == value)
+ return;
+ SetProperty(ref mtyrewear, value);
+ }
+ }
+
+ public List mBrakeDamage
+ {
+ get { return mbrakedamage; }
+ set
+ {
+ if (mbrakedamage == value)
+ return;
+ SetProperty(ref mbrakedamage, value);
+ }
+ }
+
+ public List mSuspensionDamage
+ {
+ get { return msuspensiondamage; }
+ set
+ {
+ if (msuspensiondamage == value)
+ return;
+ SetProperty(ref msuspensiondamage, value);
+ }
+ }
+
+ public List mBrakeTempCelsius
+ {
+ get { return mbraketempcelsius; }
+ set
+ {
+ if (mbraketempcelsius == value)
+ return;
+ SetProperty(ref mbraketempcelsius, value);
+ }
+ }
+
+ public List mTyreTreadTemp
+ {
+ get { return mtyretreadtemp; }
+ set
+ {
+ if (mtyretreadtemp == value)
+ return;
+ SetProperty(ref mtyretreadtemp, value);
+ }
+ }
+
+ public List mTyreLayerTemp
+ {
+ get { return mtyrelayertemp; }
+ set
+ {
+ if (mtyrelayertemp == value)
+ return;
+ SetProperty(ref mtyrelayertemp, value);
+ }
+ }
+
+ public List mTyreCarcassTemp
+ {
+ get { return mtyrecarcasstemp; }
+ set
+ {
+ if (mtyrecarcasstemp == value)
+ return;
+ SetProperty(ref mtyrecarcasstemp, value);
+ }
+ }
+
+ public List mTyreRimTemp
+ {
+ get { return mtyrerimtemp; }
+ set
+ {
+ if (mtyrerimtemp == value)
+ return;
+ SetProperty(ref mtyrerimtemp, value);
+ }
+ }
+
+ public List mTyreInternalAirTemp
+ {
+ get { return mtyreinternalairtemp; }
+ set
+ {
+ if (mtyreinternalairtemp == value)
+ return;
+ SetProperty(ref mtyreinternalairtemp, value);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/ProjectCars/Data/_pCarsAPIClass/pCarsAPI-Class.cs b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_pCarsAPIClass/pCarsAPI-Class.cs
new file mode 100644
index 000000000..ec68ddbd4
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_pCarsAPIClass/pCarsAPI-Class.cs
@@ -0,0 +1,28 @@
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Runtime.CompilerServices;
+
+namespace Artemis.Modules.Games.ProjectCars.Data
+{
+ public partial class pCarsDataClass : INotifyPropertyChanged
+ {
+ //public void Initialise()
+ //{
+ // mRPM = 0;
+ //}
+
+
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ private void SetProperty(ref T field, T value, [CallerMemberName] string name = "")
+ {
+ if (!EqualityComparer.Default.Equals(field, value))
+ {
+ field = value;
+ var handler = PropertyChanged;
+ if (handler != null)
+ handler(this, new PropertyChangedEventArgs(name));
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/ProjectCars/Data/_pCarsAPIStruct/pCarsAPI-ReadAPI.cs b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_pCarsAPIStruct/pCarsAPI-ReadAPI.cs
new file mode 100644
index 000000000..1a96c74b5
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_pCarsAPIStruct/pCarsAPI-ReadAPI.cs
@@ -0,0 +1,62 @@
+using System;
+using System.IO;
+using System.IO.MemoryMappedFiles;
+using System.Runtime.InteropServices;
+
+namespace Artemis.Modules.Games.ProjectCars.Data
+{
+ public class pCarsAPI_GetData
+ {
+ private static pCarsAPIStruct structCurrent = new pCarsAPIStruct();
+ private static MemoryMappedFile memoryMappedFile;
+ private static GCHandle handle;
+ private static int sharedmemorysize;
+ private static byte[] sharedMemoryReadBuffer;
+ private static bool isSharedMemoryInitialised;
+
+ private static bool InitialiseSharedMemory()
+ {
+ try
+ {
+ memoryMappedFile = MemoryMappedFile.OpenExisting("$pcars$");
+ sharedmemorysize = Marshal.SizeOf(typeof(pCarsAPIStruct));
+ sharedMemoryReadBuffer = new byte[sharedmemorysize];
+ isSharedMemoryInitialised = true;
+
+ return true;
+ }
+ catch (Exception ex)
+ {
+ return false;
+ }
+ }
+
+ public static Tuple ReadSharedMemoryData()
+ {
+ var _pcarsapistruct = new pCarsAPIStruct();
+
+ try
+ {
+ if (memoryMappedFile == null)
+ InitialiseSharedMemory();
+
+ using (var sharedMemoryStreamView = memoryMappedFile.CreateViewStream())
+ {
+ var _SharedMemoryStream = new BinaryReader(sharedMemoryStreamView);
+ sharedMemoryReadBuffer = _SharedMemoryStream.ReadBytes(sharedmemorysize);
+ handle = GCHandle.Alloc(sharedMemoryReadBuffer, GCHandleType.Pinned);
+ _pcarsapistruct =
+ (pCarsAPIStruct) Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(pCarsAPIStruct));
+ handle.Free();
+ }
+
+ return new Tuple(true, _pcarsapistruct);
+ }
+ catch (Exception ex)
+ {
+ //return false in the tuple as the read failed
+ return new Tuple(false, _pcarsapistruct);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/ProjectCars/Data/_pCarsAPIStruct/pCarsAPI-Struct.cs b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_pCarsAPIStruct/pCarsAPI-Struct.cs
new file mode 100644
index 000000000..d766f3996
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/ProjectCars/Data/_pCarsAPIStruct/pCarsAPI-Struct.cs
@@ -0,0 +1,215 @@
+using System.Runtime.InteropServices;
+
+namespace Artemis.Modules.Games.ProjectCars.Data
+{
+ public struct pCarsAPIParticipantStruct
+ {
+ [MarshalAs(UnmanagedType.I1)] public bool mIsActive;
+
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = (int) eAPIStructLengths.STRING_LENGTH_MAX)] public string mName;
+ // [ string ]
+
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = (int) eVector.VEC_MAX)] public float[] mWorldPosition;
+ // [ UNITS = World Space X Y Z ]
+
+ public float mCurrentLapDistance; // [ UNITS = Metres ] [ RANGE = 0.0f->... ] [ UNSET = 0.0f ]
+ public uint mRacePosition; // [ RANGE = 1->... ] [ UNSET = 0 ]
+ public uint mLapsCompleted; // [ RANGE = 0->... ] [ UNSET = 0 ]
+ public uint mCurrentLap; // [ RANGE = 0->... ] [ UNSET = 0 ]
+ public uint mCurrentSector; // [ enum (Type#4) Current Sector ]
+ }
+
+ public struct pCarsAPIStruct
+ {
+ //SMS supplied data structure
+ // Version Number
+ public uint mVersion; // [ RANGE = 0->... ]
+ public uint mBuildVersion; // [ RANGE = 0->... ] [ UNSET = 0 ]
+
+ // Session type
+ public uint mGameState; // [ enum (Type#1) Game state ]
+ public uint mSessionState; // [ enum (Type#2) Session state ]
+ public uint mRaceState; // [ enum (Type#3) Race State ]
+
+ // Participant Info
+ public int mViewedParticipantIndex; // [ RANGE = 0->STORED_PARTICIPANTS_MAX ] [ UNSET = -1 ]
+ public int mNumParticipants; // [ RANGE = 0->STORED_PARTICIPANTS_MAX ] [ UNSET = -1 ]
+
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = (int) eAPIStructLengths.NUM_PARTICIPANTS)] public
+ pCarsAPIParticipantStruct[] mParticipantData;
+
+ // Unfiltered Input
+ public float mUnfilteredThrottle; // [ RANGE = 0.0f->1.0f ]
+ public float mUnfilteredBrake; // [ RANGE = 0.0f->1.0f ]
+ public float mUnfilteredSteering; // [ RANGE = -1.0f->1.0f ]
+ public float mUnfilteredClutch; // [ RANGE = 0.0f->1.0f ]
+
+ // Vehicle & Track information
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = (int) eAPIStructLengths.STRING_LENGTH_MAX)] public string
+ mCarName; // [ string ]
+
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = (int) eAPIStructLengths.STRING_LENGTH_MAX)] public string
+ mCarClassName; // [ string ]
+
+ public uint mLapsInEvent; // [ RANGE = 0->... ] [ UNSET = 0 ]
+
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = (int) eAPIStructLengths.STRING_LENGTH_MAX)] public string
+ mTrackLocation; // [ string ]
+
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = (int) eAPIStructLengths.STRING_LENGTH_MAX)] public string
+ mTrackVariation; // [ string ]
+
+ public float mTrackLength; // [ UNITS = Metres ] [ RANGE = 0.0f->... ] [ UNSET = 0.0f ]
+
+ // Timing & Scoring
+ public bool mLapInvalidated; // [ UNITS = boolean ] [ RANGE = false->true ] [ UNSET = false ]
+ public float mSessionFastestLapTime; // [ UNITS = seconds ] [ RANGE = 0.0f->... ] [ UNSET = -1.0f ]
+ public float mLastLapTime; // [ UNITS = seconds ] [ RANGE = 0.0f->... ] [ UNSET = 0.0f ]
+ public float mCurrentTime; // [ UNITS = seconds ] [ RANGE = 0.0f->... ] [ UNSET = 0.0f ]
+ public float mSplitTimeAhead; // [ UNITS = seconds ] [ RANGE = 0.0f->... ] [ UNSET = -1.0f ]
+ public float mSplitTimeBehind; // [ UNITS = seconds ] [ RANGE = 0.0f->... ] [ UNSET = -1.0f ]
+ public float mSplitTime; // [ UNITS = seconds ] [ RANGE = 0.0f->... ] [ UNSET = 0.0f ]
+ public float mEventTimeRemaining; // [ UNITS = milli-seconds ] [ RANGE = 0.0f->... ] [ UNSET = -1.0f ]
+ public float mPersonalFastestLapTime; // [ UNITS = seconds ] [ RANGE = 0.0f->... ] [ UNSET = -1.0f ]
+ public float mWorldFastestLapTime; // [ UNITS = seconds ] [ RANGE = 0.0f->... ] [ UNSET = -1.0f ]
+ public float mCurrentSector1Time; // [ UNITS = seconds ] [ RANGE = 0.0f->... ] [ UNSET = -1.0f ]
+ public float mCurrentSector2Time; // [ UNITS = seconds ] [ RANGE = 0.0f->... ] [ UNSET = -1.0f ]
+ public float mCurrentSector3Time; // [ UNITS = seconds ] [ RANGE = 0.0f->... ] [ UNSET = -1.0f ]
+ public float mSessionFastestSector1Time; // [ UNITS = seconds ] [ RANGE = 0.0f->... ] [ UNSET = -1.0f ]
+ public float mSessionFastestSector2Time; // [ UNITS = seconds ] [ RANGE = 0.0f->... ] [ UNSET = -1.0f ]
+ public float mSessionFastestSector3Time; // [ UNITS = seconds ] [ RANGE = 0.0f->... ] [ UNSET = -1.0f ]
+ public float mPersonalFastestSector1Time; // [ UNITS = seconds ] [ RANGE = 0.0f->... ] [ UNSET = -1.0f ]
+ public float mPersonalFastestSector2Time; // [ UNITS = seconds ] [ RANGE = 0.0f->... ] [ UNSET = -1.0f ]
+ public float mPersonalFastestSector3Time; // [ UNITS = seconds ] [ RANGE = 0.0f->... ] [ UNSET = -1.0f ]
+ public float mWorldFastestSector1Time; // [ UNITS = seconds ] [ RANGE = 0.0f->... ] [ UNSET = -1.0f ]
+ public float mWorldFastestSector2Time; // [ UNITS = seconds ] [ RANGE = 0.0f->... ] [ UNSET = -1.0f ]
+ public float mWorldFastestSector3Time; // [ UNITS = seconds ] [ RANGE = 0.0f->... ] [ UNSET = -1.0f ]
+
+ // Flags
+ public uint mHighestFlagColour; // [ enum (Type#5) Flag Colour ]
+ public uint mHighestFlagReason; // [ enum (Type#6) Flag Reason ]
+
+ // Pit Info
+ public uint mPitMode; // [ enum (Type#7) Pit Mode ]
+ public uint mPitSchedule; // [ enum (Type#8) Pit Stop Schedule ]
+
+ // Car State
+ public uint mCarFlags; // [ enum (Type#6) Car Flags ]
+ public float mOilTempCelsius; // [ UNITS = Celsius ] [ UNSET = 0.0f ]
+ public float mOilPressureKPa; // [ UNITS = Kilopascal ] [ RANGE = 0.0f->... ] [ UNSET = 0.0f ]
+ public float mWaterTempCelsius; // [ UNITS = Celsius ] [ UNSET = 0.0f ]
+ public float mWaterPressureKPa; // [ UNITS = Kilopascal ] [ RANGE = 0.0f->... ] [ UNSET = 0.0f ]
+ public float mFuelPressureKPa; // [ UNITS = Kilopascal ] [ RANGE = 0.0f->... ] [ UNSET = 0.0f ]
+ public float mFuelLevel; // [ RANGE = 0.0f->1.0f ]
+ public float mFuelCapacity; // [ UNITS = Liters ] [ RANGE = 0.0f->1.0f ] [ UNSET = 0.0f ]
+ public float mSpeed; // [ UNITS = Metres per-second ] [ RANGE = 0.0f->... ]
+ public float mRPM; // [ UNITS = Revolutions per minute ] [ RANGE = 0.0f->... ] [ UNSET = 0.0f ]
+ public float mMaxRPM; // [ UNITS = Revolutions per minute ] [ RANGE = 0.0f->... ] [ UNSET = 0.0f ]
+ public float mBrake; // [ RANGE = 0.0f->1.0f ]
+ public float mThrottle; // [ RANGE = 0.0f->1.0f ]
+ public float mClutch; // [ RANGE = 0.0f->1.0f ]
+ public float mSteering; // [ RANGE = -1.0f->1.0f ]
+
+ public int mGear;
+ // [ RANGE = -1 (Reverse) 0 (Neutral) 1 (Gear 1) 2 (Gear 2) etc... ] [ UNSET = 0 (Neutral) ]
+
+ public int mNumGears; // [ RANGE = 0->... ] [ UNSET = -1 ]
+ public float mOdometerKM; // [ RANGE = 0.0f->... ] [ UNSET = -1.0f ]
+ public bool mAntiLockActive; // [ UNITS = boolean ] [ RANGE = false->true ] [ UNSET = false ]
+ public int mLastOpponentCollisionIndex; // [ RANGE = 0->STORED_PARTICIPANTS_MAX ] [ UNSET = -1 ]
+ public float mLastOpponentCollisionMagnitude; // [ RANGE = 0.0f->... ]
+ public bool mBoostActive; // [ UNITS = boolean ] [ RANGE = false->true ] [ UNSET = false ]
+ public float mBoostAmount; // [ RANGE = 0.0f->100.0f ]
+
+ // Motion & Device Related
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = (int) eVector.VEC_MAX)] public float[] mOrientation;
+ // [ UNITS = Euler Angles ]
+
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = (int) eVector.VEC_MAX)] public float[] mLocalVelocity;
+ // [ UNITS = Metres per-second ]
+
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = (int) eVector.VEC_MAX)] public float[] mWorldVelocity;
+ // [ UNITS = Metres per-second ]
+
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = (int) eVector.VEC_MAX)] public float[] mAngularVelocity;
+ // [ UNITS = Radians per-second ]
+
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = (int) eVector.VEC_MAX)] public float[] mLocalAcceleration;
+ // [ UNITS = Metres per-second ]
+
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = (int) eVector.VEC_MAX)] public float[] mWorldAcceleration;
+ // [ UNITS = Metres per-second ]
+
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = (int) eVector.VEC_MAX)] public float[] mExtentsCentre;
+ // [ UNITS = Local Space X Y Z ]
+
+ // Wheels / Tyres
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = (int) eTyres.TYRE_MAX)] public uint[] mTyreFlags;
+ // [ enum (Type#7) Tyre Flags ]
+
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = (int) eTyres.TYRE_MAX)] public uint[] mTerrain;
+ // [ enum (Type#3) Terrain Materials ]
+
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = (int) eTyres.TYRE_MAX)] public float[] mTyreY;
+ // [ UNITS = Local Space Y ]
+
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = (int) eTyres.TYRE_MAX)] public float[] mTyreRPS;
+ // [ UNITS = Revolutions per second ]
+
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = (int) eTyres.TYRE_MAX)] public float[] mTyreSlipSpeed;
+ // [ UNITS = Metres per-second ]
+
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = (int) eTyres.TYRE_MAX)] public float[] mTyreTemp;
+ // [ UNITS = Celsius ] [ UNSET = 0.0f ]
+
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = (int) eTyres.TYRE_MAX)] public float[] mTyreGrip;
+ // [ RANGE = 0.0f->1.0f ]
+
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = (int) eTyres.TYRE_MAX)] public float[] mTyreHeightAboveGround;
+ // [ UNITS = Local Space Y ]
+
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = (int) eTyres.TYRE_MAX)] public float[] mTyreLateralStiffness;
+ // [ UNITS = Lateral stiffness coefficient used in tyre deformation ]
+
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = (int) eTyres.TYRE_MAX)] public float[] mTyreWear;
+ // [ RANGE = 0.0f->1.0f ]
+
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = (int) eTyres.TYRE_MAX)] public float[] mBrakeDamage;
+ // [ RANGE = 0.0f->1.0f ]
+
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = (int) eTyres.TYRE_MAX)] public float[] mSuspensionDamage;
+ // [ RANGE = 0.0f->1.0f ]
+
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = (int) eTyres.TYRE_MAX)] public float[] mBrakeTempCelsius;
+ // [ RANGE = 0.0f->1.0f ]
+
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = (int) eTyres.TYRE_MAX)] public float[] mTyreTreadTemp;
+ // [ UNITS = Kelvin ]
+
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = (int) eTyres.TYRE_MAX)] public float[] mTyreLayerTemp;
+ // [ UNITS = Kelvin ]
+
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = (int) eTyres.TYRE_MAX)] public float[] mTyreCarcassTemp;
+ // [ UNITS = Kelvin ]
+
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = (int) eTyres.TYRE_MAX)] public float[] mTyreRimTemp;
+ // [ UNITS = Kelvin ]
+
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = (int) eTyres.TYRE_MAX)] public float[] mTyreInternalAirTemp;
+ // [ UNITS = Kelvin ]
+
+ // Car Damage
+ public uint mCrashState; // [ enum (Type#4) Crash Damage State ]
+ public float mAeroDamage; // [ RANGE = 0.0f->1.0f ]
+ public float mEngineDamage; // [ RANGE = 0.0f->1.0f ]
+
+ // Weather
+ public float mAmbientTemperature; // [ UNITS = Celsius ] [ UNSET = 25.0f ]
+ public float mTrackTemperature; // [ UNITS = Celsius ] [ UNSET = 30.0f ]
+ public float mRainDensity; // [ UNITS = How much rain will fall ] [ RANGE = 0.0f->1.0f ]
+ public float mWindSpeed; // [ RANGE = 0.0f->100.0f ] [ UNSET = 2.0f ]
+ public float mWindDirectionX; // [ UNITS = Normalised Vector X ]
+ public float mWindDirectionY; // [ UNITS = Normalised Vector Y ]
+ public float mCloudBrightness; // [ RANGE = 0.0f->... ]
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/ProjectCars/ProjectCarsDataModel.cs b/Artemis/Artemis/Modules/Games/ProjectCars/ProjectCarsDataModel.cs
new file mode 100644
index 000000000..9271a0f1e
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/ProjectCars/ProjectCarsDataModel.cs
@@ -0,0 +1,17 @@
+using Artemis.Models.Interfaces;
+using Artemis.Modules.Games.ProjectCars.Data;
+using MoonSharp.Interpreter;
+
+namespace Artemis.Modules.Games.ProjectCars
+{
+ [MoonSharpUserData]
+ public class ProjectCarsDataModel : IDataModel
+ {
+ public ProjectCarsDataModel()
+ {
+ GameData = new pCarsDataClass();
+ }
+
+ public pCarsDataClass GameData { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/ProjectCars/ProjectCarsModel.cs b/Artemis/Artemis/Modules/Games/ProjectCars/ProjectCarsModel.cs
new file mode 100644
index 000000000..aa82cf26f
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/ProjectCars/ProjectCarsModel.cs
@@ -0,0 +1,63 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using Artemis.DAL;
+using Artemis.Managers;
+using Artemis.Models;
+using Artemis.Modules.Games.ProjectCars.Data;
+using Artemis.Profiles.Layers.Models;
+using Artemis.Properties;
+using Artemis.Services;
+using Artemis.Settings;
+using Artemis.Utilities;
+using Ninject.Extensions.Logging;
+
+namespace Artemis.Modules.Games.ProjectCars
+{
+ public class ProjectCarsModel : GameModel
+ {
+ private readonly MetroDialogService _dialogService;
+
+ public ProjectCarsModel(DeviceManager deviceManager, MetroDialogService dialogService)
+ : base(deviceManager, SettingsProvider.Load(), new ProjectCarsDataModel())
+ {
+ _dialogService = dialogService;
+ Name = "ProjectCars";
+ ProcessName = "pCARS64";
+ Scale = 4;
+ Enabled = Settings.Enabled;
+ Initialized = false;
+ }
+
+ public int Scale { get; set; }
+
+ public override void Dispose()
+ {
+ Initialized = false;
+ base.Dispose();
+ }
+
+ public override void Enable()
+ {
+ Initialized = true;
+ }
+
+ public override void Update()
+ {
+ var dataModel = (ProjectCarsDataModel) DataModel;
+ var returnTuple = pCarsAPI_GetData.ReadSharedMemoryData();
+
+ // item1 is the true/false indicating a good read or not
+ if (returnTuple.Item1)
+ {
+ // map the data that's read from the struct and map it to the class
+ dataModel.GameData = dataModel.GameData.MapStructToClass(returnTuple.Item2, dataModel.GameData);
+ }
+ }
+
+ public override List GetRenderLayers(bool keyboardOnly)
+ {
+ return Profile.GetRenderLayers(DataModel, keyboardOnly);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/ProjectCars/ProjectCarsSettings.cs b/Artemis/Artemis/Modules/Games/ProjectCars/ProjectCarsSettings.cs
new file mode 100644
index 000000000..4c2cdaab5
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/ProjectCars/ProjectCarsSettings.cs
@@ -0,0 +1,9 @@
+using Artemis.Settings;
+
+namespace Artemis.Modules.Games.ProjectCars
+{
+ public class ProjectCarsSettings : GameSettings
+ {
+ public string GameDirectory { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/ProjectCars/ProjectCarsView.xaml b/Artemis/Artemis/Modules/Games/ProjectCars/ProjectCarsView.xaml
new file mode 100644
index 000000000..86adeed7d
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/ProjectCars/ProjectCarsView.xaml
@@ -0,0 +1,86 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The Euro Truck Simulator 2 module uses code from the
+
+ ETS2 Telemetry Web Server
+
+ project by Funbit
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/ProjectCars/ProjectCarsView.xaml.cs b/Artemis/Artemis/Modules/Games/ProjectCars/ProjectCarsView.xaml.cs
new file mode 100644
index 000000000..2181dc015
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/ProjectCars/ProjectCarsView.xaml.cs
@@ -0,0 +1,18 @@
+using System.Windows.Controls;
+using System.Windows.Navigation;
+
+namespace Artemis.Modules.Games.ProjectCars
+{
+ public partial class ProjectCarsView : UserControl
+ {
+ public ProjectCarsView()
+ {
+ InitializeComponent();
+ }
+
+ private void Hyperlink_RequestNavigate(object sender, RequestNavigateEventArgs e)
+ {
+ System.Diagnostics.Process.Start(e.Uri.ToString());
+ }
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/ProjectCars/ProjectCarsViewModel.cs b/Artemis/Artemis/Modules/Games/ProjectCars/ProjectCarsViewModel.cs
new file mode 100644
index 000000000..955b14efa
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/ProjectCars/ProjectCarsViewModel.cs
@@ -0,0 +1,16 @@
+using Artemis.Managers;
+using Artemis.Models;
+using Artemis.ViewModels.Abstract;
+using Ninject;
+
+namespace Artemis.Modules.Games.ProjectCars
+{
+ public sealed class ProjectCarsViewModel : GameViewModel
+ {
+ public ProjectCarsViewModel(MainManager main, IKernel kernel,
+ [Named("ProjectCarsModel")] GameModel model) : base(main, model, kernel)
+ {
+ DisplayName = "Project CARS";
+ }
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Profiles/Layers/Models/LayerConditionModel.cs b/Artemis/Artemis/Profiles/Layers/Models/LayerConditionModel.cs
index 0f04dfddf..d48cb5097 100644
--- a/Artemis/Artemis/Profiles/Layers/Models/LayerConditionModel.cs
+++ b/Artemis/Artemis/Profiles/Layers/Models/LayerConditionModel.cs
@@ -21,38 +21,41 @@ namespace Artemis.Profiles.Layers.Models
public bool ConditionMet(IDataModel subject)
{
- if (string.IsNullOrEmpty(Field) || string.IsNullOrEmpty(Value) || string.IsNullOrEmpty(Type))
- return false;
-
- var inspect = GeneralHelpers.GetPropertyValue(subject, Field);
- if (inspect == null)
- return false;
-
- // Put the subject in a list, allowing Dynamic Linq to be used.
- if (Type == "String")
+ lock (subject)
{
- return _interpreter.Eval($"subject.{Field}.ToLower(){Operator}(value)",
- new Parameter("subject", subject.GetType(), subject),
- new Parameter("value", Value.ToLower()));
- }
+ if (string.IsNullOrEmpty(Field) || string.IsNullOrEmpty(Value) || string.IsNullOrEmpty(Type))
+ return false;
- Parameter rightParam = null;
- switch (Type)
- {
- case "Enum":
- var enumType = GeneralHelpers.GetPropertyValue(subject, Field).GetType();
- rightParam = new Parameter("value", Enum.Parse(enumType, Value));
- break;
- case "Boolean":
- rightParam = new Parameter("value", bool.Parse(Value));
- break;
- case "Int32":
- rightParam = new Parameter("value", int.Parse(Value));
- break;
- }
+ var inspect = GeneralHelpers.GetPropertyValue(subject, Field);
+ if (inspect == null)
+ return false;
- return _interpreter.Eval($"subject.{Field} {Operator} value",
- new Parameter("subject", subject.GetType(), subject), rightParam);
+ // Put the subject in a list, allowing Dynamic Linq to be used.
+ if (Type == "String")
+ {
+ return _interpreter.Eval($"subject.{Field}.ToLower(){Operator}(value)",
+ new Parameter("subject", subject.GetType(), subject),
+ new Parameter("value", Value.ToLower()));
+ }
+
+ Parameter rightParam = null;
+ switch (Type)
+ {
+ case "Enum":
+ var enumType = GeneralHelpers.GetPropertyValue(subject, Field).GetType();
+ rightParam = new Parameter("value", Enum.Parse(enumType, Value));
+ break;
+ case "Boolean":
+ rightParam = new Parameter("value", bool.Parse(Value));
+ break;
+ case "Int32":
+ rightParam = new Parameter("value", int.Parse(Value));
+ break;
+ }
+
+ return _interpreter.Eval($"subject.{Field} {Operator} value",
+ new Parameter("subject", subject.GetType(), subject), rightParam);
+ }
}
}
}
\ No newline at end of file
diff --git a/Artemis/Artemis/Profiles/Layers/Types/AmbientLight/AmbientLightType.cs b/Artemis/Artemis/Profiles/Layers/Types/AmbientLight/AmbientLightType.cs
index c176040f9..5795bdbb0 100644
--- a/Artemis/Artemis/Profiles/Layers/Types/AmbientLight/AmbientLightType.cs
+++ b/Artemis/Artemis/Profiles/Layers/Types/AmbientLight/AmbientLightType.cs
@@ -70,6 +70,8 @@ namespace Artemis.Profiles.Layers.Types.AmbientLight
properties.AmbientLightBrush = new DrawingBrush(new ImageDrawing
(BitmapSource.Create(width, height, 96, 96, ScreenCaptureManager.LastCapturePixelFormat, null, _lastData,
stride), new Rect(0, 0, width, height)));
+
+ layerModel.ApplyProperties(true);
}
public void Draw(LayerModel layerModel, DrawingContext c)
diff --git a/Artemis/Artemis/Properties/AssemblyInfo.cs b/Artemis/Artemis/Properties/AssemblyInfo.cs
index 3b0d98cfa..7e493dfdf 100644
--- a/Artemis/Artemis/Properties/AssemblyInfo.cs
+++ b/Artemis/Artemis/Properties/AssemblyInfo.cs
@@ -53,7 +53,7 @@ using System.Windows;
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.6.1.0")]
-[assembly: AssemblyFileVersion("1.6.1.0")]
+[assembly: AssemblyVersion("1.7.0.0")]
+[assembly: AssemblyFileVersion("1.7.0.0")]
[assembly: InternalsVisibleTo("Artemis.Explorables")]
diff --git a/Artemis/Artemis/Utilities/ActiveWindowHelper.cs b/Artemis/Artemis/Utilities/ActiveWindowHelper.cs
new file mode 100644
index 000000000..2b4e712f7
--- /dev/null
+++ b/Artemis/Artemis/Utilities/ActiveWindowHelper.cs
@@ -0,0 +1,110 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace Artemis.Utilities
+{
+ public static class ActiveWindowHelper
+ {
+ #region DLL-Imports
+
+ private delegate void WinEventDelegate(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime);
+
+ [DllImport("user32.dll")]
+ private static extern IntPtr SetWinEventHook(uint eventMin, uint eventMax, IntPtr hmodWinEventProc, WinEventDelegate lpfnWinEventProc, uint idProcess, uint idThread, uint dwFlags);
+
+ [DllImport("user32.dll")]
+ private static extern bool UnhookWinEvent(IntPtr hWinEventHook);
+
+ [DllImport("user32.dll")]
+ private static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);
+
+ [DllImport("user32.dll")]
+ private static extern IntPtr GetWindowThreadProcessId(IntPtr hWnd, out uint processId);
+
+ #endregion
+
+ #region Constants
+
+ private const uint WINEVENT_OUTOFCONTEXT = 0;
+ private const uint EVENT_SYSTEM_FOREGROUND = 3;
+
+ private const int MAX_TITLE_LENGTH = 256;
+
+ #endregion
+
+ #region Properties & Fields
+
+ // DarthAffe 17.12.2016: We need to keep a reference to this or it might get collected by the garbage collector and cause some random crashes afterwards.
+ private static WinEventDelegate _activeWindowChangedDelegate;
+ private static IntPtr _winEventHook;
+
+ public static string ActiveWindowProcessName { get; private set; }
+ public static string ActiveWindowWindowTitle { get; private set; }
+
+ #endregion
+
+ #region Methods
+
+ private static void ActiveWindowChanged(IntPtr hWinEventHook, uint eventType,
+ IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
+ {
+ ActiveWindowProcessName = GetActiveWindowProcessName(hwnd) ?? string.Empty;
+ ActiveWindowWindowTitle = GetActiveWindowTitle(hwnd) ?? string.Empty;
+ }
+
+ private static string GetActiveWindowProcessName(IntPtr hwnd)
+ {
+ try
+ {
+ uint pid;
+ GetWindowThreadProcessId(hwnd, out pid);
+ return System.Diagnostics.Process.GetProcessById((int)pid).ProcessName;
+ }
+ catch
+ {
+ return null;
+ }
+ }
+
+ private static string GetActiveWindowTitle(IntPtr hwnd)
+ {
+ try
+ {
+ StringBuilder buffer = new StringBuilder(MAX_TITLE_LENGTH);
+ return GetWindowText(hwnd, buffer, MAX_TITLE_LENGTH) > 0 ? buffer.ToString() : null;
+ }
+ catch
+ {
+ return null;
+ }
+ }
+
+ public static void Initialize()
+ {
+ try
+ {
+ if (_winEventHook != IntPtr.Zero) return;
+
+ _activeWindowChangedDelegate = ActiveWindowChanged;
+ _winEventHook = SetWinEventHook(EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_FOREGROUND, IntPtr.Zero, _activeWindowChangedDelegate, 0, 0, WINEVENT_OUTOFCONTEXT);
+ }
+ catch { /* catch'em all - I don't want it to crash here */ }
+ }
+
+ public static void Dispose()
+ {
+ try
+ {
+ if (_winEventHook == IntPtr.Zero) return;
+
+ UnhookWinEvent(_winEventHook);
+ _activeWindowChangedDelegate = null;
+ _winEventHook = IntPtr.Zero;
+ }
+ catch { /* catch'em all - I don't want it to crash here */ }
+ }
+
+ #endregion
+ }
+}
diff --git a/Artemis/Artemis/Utilities/Logging.cs b/Artemis/Artemis/Utilities/Logging.cs
index a69e103fc..b8c0bf913 100644
--- a/Artemis/Artemis/Utilities/Logging.cs
+++ b/Artemis/Artemis/Utilities/Logging.cs
@@ -36,11 +36,13 @@ namespace Artemis.Utilities
// Step 3. Set target properties
debuggerTarget.Layout = @"${logger:shortName=True} - ${uppercase:${level}}: ${message}";
- fileTarget.FileName = "${specialfolder:folder=MyDocuments}/Artemis/logs/${shortdate}.txt";
fileTarget.Layout = "${longdate}|${level:uppercase=true}|${logger}|${message} ${exception:format=tostring}";
- fileTarget.EnableFileDelete = true;
+ fileTarget.FileName = "${specialfolder:folder=MyDocuments}/Artemis/logs/log.txt";
+ fileTarget.ArchiveFileName = "${specialfolder:folder=MyDocuments}/Artemis/logs/log-{#}.txt";
+ fileTarget.ArchiveEvery = FileArchivePeriod.Day;
+ fileTarget.ArchiveNumbering = ArchiveNumberingMode.Date;
+ fileTarget.ArchiveOldFileOnStartup = true;
fileTarget.MaxArchiveFiles = 7;
- fileTarget.ArchiveEvery = FileArchivePeriod.Minute;
// Step 4. Define rules
var rule1 = new LoggingRule("*", logLevel, debuggerTarget);
@@ -53,9 +55,12 @@ namespace Artemis.Utilities
// Step 5. Activate the configuration
LogManager.Configuration = config;
- // Log as fatal so it always shows
+ // Log as fatal so it always shows, add some spacing since this indicates the start of a new log
var logger = LogManager.GetCurrentClassLogger();
- logger.Fatal("INFO: Set log level to {0}", logLevel);
+ var logMsg = $" INFO: Set log level to {logLevel} ";
+ logger.Fatal(new string('-', logMsg.Length));
+ logger.Fatal(logMsg);
+ logger.Fatal(new string('-', logMsg.Length));
}
private static void MemoryTargetOnEventReceived(LogEventInfo logEventInfo)
diff --git a/Artemis/Artemis/ViewModels/Flyouts/FlyoutSettingsViewModel.cs b/Artemis/Artemis/ViewModels/Flyouts/FlyoutSettingsViewModel.cs
index c038d47ba..cda9415c9 100644
--- a/Artemis/Artemis/ViewModels/Flyouts/FlyoutSettingsViewModel.cs
+++ b/Artemis/Artemis/ViewModels/Flyouts/FlyoutSettingsViewModel.cs
@@ -1,3 +1,4 @@
+using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Dynamic;
@@ -12,6 +13,7 @@ using Caliburn.Micro;
using MahApps.Metro.Controls;
using NLog;
using ILogger = Ninject.Extensions.Logging.ILogger;
+using Process = System.Diagnostics.Process;
namespace Artemis.ViewModels.Flyouts
{
@@ -201,6 +203,12 @@ namespace Artemis.ViewModels.Flyouts
MainManager.EnableProgram();
}
+ public void ShowLogs()
+ {
+ var logPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + @"\Artemis\logs";
+ System.Diagnostics.Process.Start(logPath);
+ }
+
public void ShowDebug()
{
IWindowManager manager = new WindowManager();
diff --git a/Artemis/Artemis/Views/Flyouts/FlyoutSettingsView.xaml b/Artemis/Artemis/Views/Flyouts/FlyoutSettingsView.xaml
index 8b50fe0dc..2beb89dd5 100644
--- a/Artemis/Artemis/Views/Flyouts/FlyoutSettingsView.xaml
+++ b/Artemis/Artemis/Views/Flyouts/FlyoutSettingsView.xaml
@@ -102,16 +102,19 @@
+