Page 1 of 2

About the new frontend in development ...

Posted: Sat Jan 20, 2024 4:51 pm
by segaduck
Hi everyone,

It's the new frontend i am developing right now.
I've studied C# from the beginning and try my best to develop it as possible. I know i am in a very slow pace, wish you guys will like it when I finish.
Here is what I did so far. Enjoy.

https://www.youtube.com/watch?v=OGzriGmIZ6E

Re: About the new frontend in development ...

Posted: Sat Jan 20, 2024 5:52 pm
by segaduck
SuerpM3UI_0121.jpg
SuerpM3UI_0121.jpg (225.73 KiB) Viewed 3344 times

Re: About the new frontend in development ...

Posted: Sat Jan 20, 2024 6:41 pm
by ToBul
This looks really nice. Beautiful, simple, sleek aesthetic.
Supermodel has needed a good UI for a while now.
Great work.
You must have done some sort of coding before ?

Re: About the new frontend in development ...

Posted: Sun Jan 21, 2024 4:45 pm
by Masked Ninja
It looks great, please make sure you add all the commands.
Thank you so much... :D

Re: About the new frontend in development ...

Posted: Mon Jan 22, 2024 9:06 am
by segaduck
I will implement all config parameters such as -true-hz- of the latest version Supermodel for sure.
What I am struggling right now is the keys/buttons/joystick mapping UI, and wish I can find a best way to finish it ASAP.

Re: About the new frontend in development ...

Posted: Mon Jan 22, 2024 2:13 pm
by Viking245
segaduck wrote: Mon Jan 22, 2024 9:06 am What I am struggling right now is the keys/buttons/joystick mapping UI, and wish I can find a best way to finish it ASAP.
I've used SharpDX (and SharpDX.XInput and SharpDX.DirectInput) in the past to capture inputs. Though now 'archived', it may still be useful or lead you in the right direction.

If you'd like any help with the project, feel free to DM me. You can keep 100% of the credit for the project. Makes no matter to me. :D (I did try to DM you, but 'lurkers' aren't allowed. ;) )

Re: About the new frontend in development ...

Posted: Tue Jan 23, 2024 5:20 pm
by segaduck
Viking245 wrote: Mon Jan 22, 2024 2:13 pm
segaduck wrote: Mon Jan 22, 2024 9:06 am What I am struggling right now is the keys/buttons/joystick mapping UI, and wish I can find a best way to finish it ASAP.
I've used SharpDX (and SharpDX.XInput and SharpDX.DirectInput) in the past to capture inputs. Though now 'archived', it may still be useful or lead you in the right direction.

If you'd like any help with the project, feel free to DM me. You can keep 100% of the credit for the project. Makes no matter to me. :D (I did try to DM you, but 'lurkers' aren't allowed. ;) )
Hi, Viking245,

Nice to meet you here. It is very welcome to invite you to join the new frontend project's development, and I believe we can finish the project sooner with your great help.

I've tried SharpDX.XInput in the development and get the inputs successfully. What I am confused is how to map the naming in SharpDX.Xinput or Dinput to the Suerpmodel's naming. For example, in Supermodel "JOY1_BUTTON1" to SharpDX's names, especially there are more than only 1 joystick connected.

I am thinking if you can develop a C# class with method which will return the user's input name once a time and I will implement other UI and Key mapping stuff for each game. Or you can give me other suggestion will be great.
Thank you.

Following are the source codes that I've written for Joystick input testing UI.
======================================================================================
using System;
using System.Data;
using System.Drawing;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Timer = System.Windows.Forms.Timer;
using System.Drawing.Drawing2D;
using SharpDX.XInput;
using SharpDX.DirectInput;
using SharpDX.Mathematics.Interop;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.TextBox;

namespace SuperM3UI
{
public partial class FormControlTest : Form
{
private Timer updateTimer;
private Controller controller;
int JStickPos;
int JStickPos_pre;

int shiftX = 120;
int shiftY = 120;
int shiftUR = 84;
int ballPosX = 220;
int ballPosY = 170;
Bitmap myBitmap;

Rectangle expansionRectangle;


public Image sourceImage;

public FormControlTest()
{
InitializeComponent();

// Initialize Timer
updateTimer = new Timer();
updateTimer.Interval = 16; // every16ms, around 60fps
updateTimer.Tick += UpdateTimer_Tick;

// Intialize JStick Position on UI
JStickPos = 5;
JStickPos_pre = 5;
sourceImage = Image.FromFile(@"C:\Development\SuperM3UI\SuperM3UI\icons\sticks-ball-mid.png");
myBitmap = new Bitmap(@"C:\Development\SuperM3UI\SuperM3UI\icons\sticks-ball-mid.png");

// Initialize Xbox controller
controller = new Controller(UserIndex.One);

if (!controller.IsConnected)
{
MessageBox.Show("Xbox Controller is not connected。");
}
}

private void FormControlTest_Load(object sender, EventArgs e)
{
updateTimer.Start();
this.Location = new System.Drawing.Point(this.Location.X + 110, this.Location.Y + 65);

}

private void UpdateTimer_Tick(object sender, EventArgs e)
{
if (controller.IsConnected)
{
State st = controller.GetState();
//lb_PosX.Text = "Parent's X/Y =" + this.Parent.Location.X.ToString() + "//" + this.Parent.Location.Y.ToString();
//lb_PosY.Text = "It's X/Y =" + this.Location.X.ToString() + "//" + this.Location.Y.ToString();

// Checked buttons / joystick 's input
Boolean A_Btn_Now_pressed = ((st.Gamepad.Buttons & GamepadButtonFlags.A) != 0);
if (A_Btn_Now_pressed) { picBox_GreenBtnPress.Visible = true; } else { picBox_GreenBtnPress.Visible = false; }
//labelButton_A.Text = $"A Button: {A_Btn_Now_pressed}";

Boolean B_Btn_Now_pressed = ((st.Gamepad.Buttons & GamepadButtonFlags.B) != 0);
if (B_Btn_Now_pressed) { picBox_BlueBtnPress.Visible = true; } else { picBox_BlueBtnPress.Visible = false; }
//labelButton_B.Text = $"B Button: {(st.Gamepad.Buttons & GamepadButtonFlags.B) != 0}";

Boolean X_Btn_Now_pressed = ((st.Gamepad.Buttons & GamepadButtonFlags.X) != 0);
if (X_Btn_Now_pressed) { picBox_PinkBtnPress.Visible = true; } else { picBox_PinkBtnPress.Visible = false; }
//labelButton_X.Text = $"X Button: {(st.Gamepad.Buttons & GamepadButtonFlags.X) != 0}";

Boolean Y_Btn_Now_pressed = ((st.Gamepad.Buttons & GamepadButtonFlags.Y) != 0);
if (Y_Btn_Now_pressed) { picBox_RedBtnPress.Visible = true; } else { picBox_RedBtnPress.Visible = false; }
//labelButton_Y.Text = $"Y Button: {(st.Gamepad.Buttons & GamepadButtonFlags.Y) != 0}";


if ((st.Gamepad.Buttons & GamepadButtonFlags.DPadUp) != 0)
{
JStickPos = 8;
if ((st.Gamepad.Buttons & GamepadButtonFlags.DPadUp) != 0 && (st.Gamepad.Buttons & GamepadButtonFlags.DPadRight) != 0) JStickPos = 9;
if ((st.Gamepad.Buttons & GamepadButtonFlags.DPadUp) != 0 && (st.Gamepad.Buttons & GamepadButtonFlags.DPadLeft) != 0) JStickPos = 7;
}

if ((st.Gamepad.Buttons & GamepadButtonFlags.DPadDown) != 0)
{
JStickPos = 2;
if ((st.Gamepad.Buttons & GamepadButtonFlags.DPadDown) != 0 && (st.Gamepad.Buttons & GamepadButtonFlags.DPadRight) != 0) JStickPos = 3;
if ((st.Gamepad.Buttons & GamepadButtonFlags.DPadDown) != 0 && (st.Gamepad.Buttons & GamepadButtonFlags.DPadLeft) != 0) JStickPos = 1;
}

if ((st.Gamepad.Buttons & GamepadButtonFlags.DPadRight) != 0)
{
JStickPos = 6;
if ((st.Gamepad.Buttons & GamepadButtonFlags.DPadRight) != 0 && (st.Gamepad.Buttons & GamepadButtonFlags.DPadUp) != 0) JStickPos = 9;
if ((st.Gamepad.Buttons & GamepadButtonFlags.DPadRight) != 0 && (st.Gamepad.Buttons & GamepadButtonFlags.DPadDown) != 0) JStickPos = 3;
}

if ((st.Gamepad.Buttons & GamepadButtonFlags.DPadLeft) != 0)
{
JStickPos = 4;
if ((st.Gamepad.Buttons & GamepadButtonFlags.DPadLeft) != 0 && (st.Gamepad.Buttons & GamepadButtonFlags.DPadUp) != 0) JStickPos = 7;
if ((st.Gamepad.Buttons & GamepadButtonFlags.DPadLeft) != 0 && (st.Gamepad.Buttons & GamepadButtonFlags.DPadDown) != 0) JStickPos = 1;
}

if (((st.Gamepad.Buttons & GamepadButtonFlags.DPadLeft) == 0) && ((st.Gamepad.Buttons & GamepadButtonFlags.DPadRight) == 0)
&& ((st.Gamepad.Buttons & GamepadButtonFlags.DPadUp) == 0) && ((st.Gamepad.Buttons & GamepadButtonFlags.DPadDown) == 0))
{
JStickPos = 5;
}
if (JStickPos_pre != JStickPos) panel1.Invalidate();
JStickPos_pre = JStickPos;
}
}

private void FormControlTest_FormClosed(object sender, FormClosedEventArgs e)
{
updateTimer.Stop();
}

private void rjButton2_Click(object sender, EventArgs e)
{
this.Close();
}

private void panel1_Paint(object sender, PaintEventArgs e)
{
Graphics graphics = e.Graphics;
expansionRectangle = new Rectangle(ballPosX, ballPosY, myBitmap.Width * 14 / 10, myBitmap.Height * 14 / 10);


// Draw a portion of the source image.
if (JStickPos == 1)
{
expansionRectangle = new Rectangle(ballPosX - shiftUR, ballPosY + shiftUR, myBitmap.Width * 14 / 10, myBitmap.Height * 14 / 10);
graphics.DrawImage(myBitmap, expansionRectangle);
}
if (JStickPos == 2)
{
expansionRectangle = new Rectangle(ballPosX, ballPosY + shiftY, myBitmap.Width * 14 / 10, myBitmap.Height * 14 / 10);
graphics.DrawImage(myBitmap, expansionRectangle);
}
if (JStickPos == 3)
{
expansionRectangle = new Rectangle(ballPosX + shiftUR, ballPosY + shiftUR, myBitmap.Width * 14 / 10, myBitmap.Height * 14 / 10);
graphics.DrawImage(myBitmap, expansionRectangle);
}
if (JStickPos == 4)
{
expansionRectangle = new Rectangle(ballPosX - shiftX, ballPosY, myBitmap.Width * 14 / 10, myBitmap.Height * 14 / 10);
graphics.DrawImage(myBitmap, expansionRectangle);
}
if (JStickPos == 5)
{
expansionRectangle = new Rectangle(ballPosX, ballPosY, myBitmap.Width * 14 / 10, myBitmap.Height * 14 / 10);
graphics.DrawImage(myBitmap, expansionRectangle);
}
if (JStickPos == 6)
{
expansionRectangle = new Rectangle(ballPosX + shiftX, ballPosY, myBitmap.Width * 14 / 10, myBitmap.Height * 14 / 10);
graphics.DrawImage(myBitmap, expansionRectangle);
}
if (JStickPos == 7)
{
expansionRectangle = new Rectangle(ballPosX - shiftUR, ballPosY - shiftUR, myBitmap.Width * 14 / 10, myBitmap.Height * 14 / 10);
graphics.DrawImage(myBitmap, expansionRectangle);
}
if (JStickPos == 8)
{
expansionRectangle = new Rectangle(ballPosX, ballPosY - shiftY, myBitmap.Width * 14 / 10, myBitmap.Height * 14 / 10);
graphics.DrawImage(myBitmap, expansionRectangle);
}
if (JStickPos == 9)
{
expansionRectangle = new Rectangle(ballPosX + shiftUR, ballPosY - shiftUR, myBitmap.Width * 14 / 10, myBitmap.Height * 14 / 10);
graphics.DrawImage(myBitmap, expansionRectangle);
}
}
}
}
======================================================================================

Re: About the new frontend in development ...

Posted: Tue Jan 23, 2024 5:41 pm
by segaduck
The video clip of my testing implement of Joystick input testing.

https://youtu.be/YXV8efEmFfk

However, it's a quite old version codes which I used C# Winforms and I am learning and using WPF to develop the new codes for much better outlook of the UI.

Re: About the new frontend in development ...

Posted: Wed Jan 24, 2024 1:45 pm
by Viking245
segaduck wrote: Tue Jan 23, 2024 5:41 pm However, it's a quite old version codes which I used C# Winforms and I am learning and using WPF to develop the new codes for much better outlook of the UI.
WPF will definitely look WAY better than WinForms. ;) Which Framework are you using?

What I am confused is how to map the naming in SharpDX.Xinput or Dinput to the Suerpmodel's naming.
Say you ask the user to select an input for 'Player 1 - Coin'. This can trigger a Method that has a Do/While loop to wait for a controller Button press (or time out). The Method captures the input and returns the transposed value. i.e. they want to use the Back Buton. (truncated method)

Edit: moved 'State st =' to inside do loop

Code: Select all

public string GetControllerInput()
{
	TimeSpan timeout = TimeSpan.FromSeconds(5);
	var stopwatch = Stopwatch.StartNew();
	
	//State st = controller.GetState();

	do
	{
		//needs to be inside do loop
		State st = controller.GetState();
		
		if ((st.Gamepad.Buttons & GamepadButtonFlags.Back) != 0)
		{
			return "KEY_1,JOY1_BUTTON7";
		}
		
		//... all other possible inputs
	}
	while (stopwatch.Elapsed < timeout);
		
	return string.Empty;
}	
To get Controller #2, #3 etc., probably need to declare all [possible] controllers.

Code: Select all

Controller controller1 = new Controller(UserIndex.One);
Controller controller2 = new Controller(UserIndex.Two);
Controller controller3 = new Controller(UserIndex.Three);
//.... etc.
Then in the above method, account for the 'possibilities'.

Code: Select all

State st1 = controller1.GetState();
State st2 = controller2.GetState();
State st3 = controller3.GetState();

//...
if ((st1.Gamepad.Buttons & GamepadButtonFlags.Back) != 0)
{
	return "KEY_1,JOY1_BUTTON7";
}

if ((st2.Gamepad.Buttons & GamepadButtonFlags.Back) != 0)
{
	return "KEY_1,JOY2_BUTTON7";
}
//...
Then.. however you plan to 'ask the question', followed up with

Code: Select all

string InputCoin1 = GetControllerInput();
if (InputCoin1 == string.Empty)
{
	//do something to indicate there's no 'InputCoin1'
}
Hope that helps. Or at least gives you some momentum. This is just one way of doing it, as I'm sure there's at least 50 others. ;)

Re: About the new frontend in development ...

Posted: Thu Jan 25, 2024 6:35 pm
by segaduck
Viking245 wrote: Wed Jan 24, 2024 1:45 pm
segaduck wrote: Tue Jan 23, 2024 5:41 pm However, it's a quite old version codes which I used C# Winforms and I am learning and using WPF to develop the new codes for much better outlook of the UI.
WPF will definitely look WAY better than WinForms. ;) Which Framework are you using?

I used the standard WPF for Microsoft in the beginning, but I changed to use Avalonia with MVVM community toolkit and rewrite everything now.

What I am confused is how to map the naming in SharpDX.Xinput or Dinput to the Suerpmodel's naming.
Say you ask the user to select an input for 'Player 1 - Coin'. This can trigger a Method that has a Do/While loop to wait for a controller Button press (or time out). The Method captures the input and returns the transposed value. i.e. they want to use the Back Buton. (truncated method)

Edit: moved 'State st =' to inside do loop

Code: Select all

public string GetControllerInput()
{
	TimeSpan timeout = TimeSpan.FromSeconds(5);
	var stopwatch = Stopwatch.StartNew();
	
	//State st = controller.GetState();

	do
	{
		//needs to be inside do loop
		State st = controller.GetState();
		
		if ((st.Gamepad.Buttons & GamepadButtonFlags.Back) != 0)
		{
			return "KEY_1,JOY1_BUTTON7";
		}
		
		//... all other possible inputs
	}
	while (stopwatch.Elapsed < timeout);
		
	return string.Empty;
}	
To get Controller #2, #3 etc., probably need to declare all [possible] controllers.

Code: Select all

Controller controller1 = new Controller(UserIndex.One);
Controller controller2 = new Controller(UserIndex.Two);
Controller controller3 = new Controller(UserIndex.Three);
//.... etc.
Then in the above method, account for the 'possibilities'.

Code: Select all

State st1 = controller1.GetState();
State st2 = controller2.GetState();
State st3 = controller3.GetState();

//...
if ((st1.Gamepad.Buttons & GamepadButtonFlags.Back) != 0)
{
	return "KEY_1,JOY1_BUTTON7";
}

if ((st2.Gamepad.Buttons & GamepadButtonFlags.Back) != 0)
{
	return "KEY_1,JOY2_BUTTON7";
}
//...
Then.. however you plan to 'ask the question', followed up with

Code: Select all

string InputCoin1 = GetControllerInput();
if (InputCoin1 == string.Empty)
{
	//do something to indicate there's no 'InputCoin1'
}
Hope that helps. Or at least gives you some momentum. This is just one way of doing it, as I'm sure there's at least 50 others. ;)
Thanks for your great help and wonderful advice. It is very useful information for me.
However, I am so busy in working recently. I may restart to write new codes in Feb.
Keep in touch !!!