using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Threading.Tasks;
namespace SCJMapper_V2.Layout
{
// The Json file for a controller
/*
{
"MapName" : "T.16000M Joystick (right)",
"MapImage" : "T16000M.jpg",
"InputDevices" :[
{
"InputType": "J1",
"DeviceName": "T16000M",
"DeviceProdGuid": ["{B10A044F-0000-0000-0000-504944564944}"],
"Controls": [
{ "Input": "B1", "Type": "Digital", "X": 2044, "Y": 604, "Width": 642, "Height": 108, "Cmt": "Primary trigger" },
...
]
}
]
}
*/
///
/// The Device Mapping File
///
[DataContract]
class DeviceFile
{
[DataMember( IsRequired = true )]
public string MapName { get; set; }
[DataMember( IsRequired = true )]
public string MapImage { get; set; } // The map Image
[DataMember]
public List InputDevices { get; set; } = new List( );
///
/// Create all possible ShapeItems for this Mapping File
///
public void CreateShapes()
{
for ( int i = 0; i < InputDevices.Count; i++ ) {
InputDevices[i].CreateShapes( );
}
}
///
/// Find a Control entry with the given product guid and input command
///
/// the Device Prduct PID VID string in lowecase
/// the Item (device property)
/// If true it looks for the InputTypeNumber 1 (InputType="x1") else for the next
/// The found Control or Null
public Control FindItem( string pidVid, string input, bool firstInstance )
{
if ( string.IsNullOrEmpty( pidVid ) ) return null;
if ( string.IsNullOrEmpty( input ) ) return null;
for ( int i = 0; i < InputDevices.Count; i++ ) {
if ( InputDevices[i].DevicePIDVID.Contains( pidVid ) ) { // can have multiple PID VIDs for a device (alternates)
// input can be: {modifier+}Input
string[] e = input.Split( new char[] { '+' } );
string effInput = e[e.Length - 1]; // last item is the real input
// returns if we are asked for the first instance and it is the first one (default)
if ( firstInstance && ( InputDevices[i].InputTypeNumber == 1 ) ) {
return InputDevices[i].FindItem( effInput );
}
else if ( !firstInstance && InputDevices[i].InputTypeNumber > 1 ) {
return InputDevices[i].FindItem( effInput ); // not first and J2.. - return any other (more than 2 not supported)
}
}
}
return null;
}
///
/// Get all devices with Name (only first GUID is returned)
///
///
public List Devices()
{
var ret = new List( );
for ( int i = 0; i < InputDevices.Count; i++ ) {
if ( !ret.Exists( x => x.DevGuid == InputDevices[i].DevDescriptor.DevGuid ) )
ret.Add( InputDevices[i].DevDescriptor );
}
return ret;
}
}
///
/// One Game Device
///
[DataContract]
class Device
{
[DataMember( IsRequired = true )]
public string InputType { get; set; } // Joystick, Throttle, Pedal, Gamepad, Keyboard, Other
[DataMember( IsRequired = true )]
public string DeviceName { get; set; } // The device name
[DataMember( IsRequired = true )]
public List DeviceProdGuid { get; set; } = new List( ); // The device product GUIDs as read by DirecInput
[DataMember]
public List Controls { get; set; } = new List( );// The list of Controls supported (see below)
// non Json
///
/// Describes a known device
/// Used for the Layout Debug Mode
///
public class DeviceDescriptor
{
public string DevGuid { get; set; } = "";
public string DevName { get; set; } = "";
public override string ToString()
{
return DevName;
}
}
public DeviceDescriptor DevDescriptor
{
get {
return new DeviceDescriptor( ) { DevGuid = DeviceProdGuid[0], DevName = DeviceName };
}
}
public string InputTypeLetter { get => InputType.Substring( 0, 1 ); }
public int InputTypeNumber
{
get {
if ( InputType.Length > 1 ) {
if ( int.TryParse( InputType.Substring( 1 ), out int num ) ) {
return num;
}
}
return 1; //default
}
}
///
/// returns the PID VID part of the GUID (seems how this is composed in Win)
///
public List DevicePIDVID
{
get {
var ret = new List( );
foreach ( string s in DeviceProdGuid ) {
string pv = s.Substring( 1, 8 ).ToLowerInvariant( ); // this is "{12345678-0000-0000 etc}
ret.Add( pv );
}
return ret;
}
}
///
/// Find a Control entry with the given input command
///
/// the Item (device property)
/// The found Control or Null
public Control FindItem( string input )
{
for ( int i = 0; i < Controls.Count; i++ ) {
if ( input == Controls[i].Input ) {
return Controls[i];
}
}
return null;
}
///
/// Create all possible ShapeItems for this Device
///
public void CreateShapes()
{
for ( int i = 0; i < Controls.Count; i++ ) {
Controls[i].CreateShapes( );
}
}
}
///
/// One Device Input (command)
///
[DataContract]
class Control
{
[DataMember( IsRequired = true )]
public string Input { get; set; } = ""; // buttonN, hatN_up,_right,_down,_left, [rot]xyz, sliderN (CryInput notification)
[DataMember]
public string Type { get; set; } = ""; // "" or Analog or Digital
[DataMember( IsRequired = true )]
public int X { get; set; } = 0; // X label pos (left=0)
[DataMember( IsRequired = true )]
public int Y { get; set; } = 0; // Y label pos (top=0)
[DataMember( IsRequired = true )]
public int Width { get; set; } = 600; // Label field width
[DataMember]
public int Height { get; set; } = 54; // Label field height
[DataMember]
public string Cmt { get; set; } = ""; // Comment
// non Json
///
/// A queue with all available text fields
/// Take one and Insert the Display text and then add it to the DisplayList
/// If exhausted - well bad luck..
///
public Queue ShapeItems = null;
// Base layout values to get enough fields and still have readable text
private const float c_baseFontSize = 16F;
///
/// Create all possible ShapeItems for this Control
///
public void CreateShapes()
{
// this is a bit messy...
// have to allocate a number of Rectangles to draw into but the layout rects are very different in size..
this.ShapeItems = new Queue( ); // get rid of previous ones
// create a reference font
int baseHeight = MapProps.MapFont.Height;
int baseWidth = MapProps.MapFont.Height * 12; // Lets see if this is good or needs adjustment
// live values from base
int nCols = Width / baseWidth;
int nLines = Height / baseHeight;
for ( int l = 0; l < nLines; l++ ) {
for ( int c = 0; c < nCols; c++ ) {
var sh = new ShapeItem {
X = X + c * baseWidth,
Y = Y + l * baseHeight + 2, // offset Y by 2 pix to have it more centered
Width = baseWidth,
Height = baseHeight
};
ShapeItems.Enqueue( sh );
}
}
}
}
}