Universal Control Remapper (UCR) - v0.1.22 28th Oct 2018

Post gaming related scripts
User avatar
evilC
Posts: 4772
Joined: 27 Feb 2014, 12:30

Re: Universal Control Remapper (UCR) - v0.1.14 12th Mar 2017

02 May 2017, 14:29

Yeah, sorry, my web host screwed up my website, so I had to move to a new host.
Seeing as the URL is identical, you are possibly still seeing the old web server.

Regarding the problem being with UCR loading while there are a bunch of plugins already present - I suppose I could modify the sample script so that it adds a bunch of plugins before it shows the GUI for the first time.
User avatar
evilC
Posts: 4772
Joined: 27 Feb 2014, 12:30

Re: Universal Control Remapper (UCR) - v0.1.14 12th Mar 2017

02 May 2017, 14:42

Here is a version of the script which adds 20 plugins before showing the GUI - let's see if this reproduces the issue.

Rather than mess around with compiled EXEs and stuff, here is what to do:

1) Take UCR.exe from your UCR folder, make a copy and rename it PluginTest.exe
2) Take the script below and save it in the same folder as PluginTest.ahk
3) Double-click PluginTest.exe to run the script using AHK_H

Code: Select all

#SingleInstance force

Gui +Hwndhwnd
mc := new MainClass(hwnd)

Loop 20 {
	mc.AddPlugin()
}
mc.Show()
return

^Esc::
GuiClose:
	ExitApp

class MainClass {
	PluginHeight := 35
	PluginWidth := 450
	FrameWidth := this.PluginWidth + 50
	Plugins := {}		; Holds plugin instances
	PluginOrder := []	; Holds order of plugins
	
	__New(hMainGui){
		this.MainGui := new WrappedGui(hMainGui)
		this.MainGui.GuiCmd("+Resize")

		this.AddButton := this.MainGui.AddControl("Button", this.AddPlugin.Bind(this), "Center w" this.FrameWidth " aw", "Add Plugin")
		this.PluginFrame := new WrappedGui()
		this.PluginFrame.GuiCmd("-Caption")
		this.PluginFrame.GuiCmd("+VScroll")
		this.PluginFrame.GuiCmd("Color", "Black")
		
		this.MainGui.GuiCmd("Add", "Gui", "xm y+5 w" this.FrameWidth " h200 aw ah", this.PluginFrame.hwnd)
		
		; You cannot remove a Gui if you add it with Gui, Add, Gui...
		; So we have to use +Parent to attach plugins to the parent Gui
		; We therefore use a Spacer GuiControl in the plugin area to force the scrollbar to the desired size
		this.Spacer := this.PluginFrame.AddControl("Edit", 0, "x5 y0 w5 h0")
		this.SetSpacerHeight(0)
	}
	
	Show(){
		this.MainGui.GuiCmd("Show", "x0 y0")
	}
	
	AddPlugin(){
		scroll_pos := this.PluginFrame.GetScrollPos()
		
		plugin := new Plugin(this)
		
		this.Plugins[plugin.Guid] := plugin
		this.PluginOrder.Push(plugin.Guid)
		
		plugin_height := plugin.GetHeight()
		ypos := this.Spacer.Height + 5
		plugin.ypos := ypos
		adjusted_pos := ypos - scroll_pos
		plugin.GuiCmd("Show", "x15 y" adjusted_pos " w" this.PluginWidth " h" this.PluginHeight)
		this.SetSpacerHeight(this.Spacer.Height + plugin_height + 5)
	}
	
	RemovePlugin(id){
		scroll_pos := this.PluginFrame.GetScrollPos()
		
		plugin := this.Plugins[id]
		plugin_height := plugin.GetHeight()
		plugin.GuiCmd("Destroy")
		old_guid := plugin.Guid
		old_order := this.GetPluginOrder(old_guid)
		this.Plugins.Delete(old_guid)
		
		max := this.PluginOrder.Length()
		
		Loop % max - old_order {
			id := old_order + A_Index
			guid := this.PluginOrder[id]
			plugin := this.Plugins[guid]
			plugin.ypos -= plugin_height + 4
			adjusted_pos := plugin.ypos - scroll_pos
			plugin.GuiCmd("Show", "x15 y" adjusted_pos)
		}
		this.PluginOrder.RemoveAt(old_order)
		this.SetSpacerHeight(this.Spacer.Height - plugin_height - 4)
	}
	
	ReorderPlugin(guid, dir){
		scroll_pos := this.PluginFrame.GetScrollPos()
		
		; Find the order of the plugin that the user clicked on
		passed_order := this.GetPluginOrder(guid)
		if (passed_order == 0 || (dir == -1 && passed_order == 1) || (dir == 1 && passed_order == this.PluginOrder.Length()))
			return	; top tried to move up bottom tried to move down

		; Gui swapping is handled as if the user had always clicked Move Down
		; If user clicks Move Up, swap the inputs
		if (dir == - 1){
			top_guid := this.PluginOrder[passed_order - 1]
			bot_guid := guid
		} else {
			top_guid := guid
			bot_guid := this.PluginOrder[passed_order + 1]
		}
		top_plugin := this.Plugins[top_guid]
		bot_plugin := this.Plugins[bot_guid]
		
		; Move the "top" gui down and the "bot" gui up
		top_y := top_plugin.ypos
		bot_plugin.Move(top_y, scroll_pos)
		top_plugin.Move(bot_plugin.ypos + bot_plugin.GetHeight() + 4, scroll_pos)	; ToDo - Fix Bodge for GetHeight()

		; Swap the PluginOrder
		top_id := this.PluginOrder.RemoveAt(passed_order)
		this.PluginOrder.InsertAt(passed_order + dir, top_id)
	}
	
	SetSpacerHeight(height){
		this.Spacer.Height := height
		this.Spacer.CtrlCmd("Move", "h" this.Spacer.Height)
	}
	
	GetPluginOrder(guid){
		for i, candidate in this.PluginOrder {
			if (candidate == guid){
				return i
			}
		}
		return 0
	}
}

class Plugin extends WrappedGui {
	ypos := 0
	__New(parent){
		static short_id := 1
		this.Guid := CreateGuid()
		this.Parent := parent
		base.__New(0)
		this.AddControl("Text", 0, "y10", "Plugin #" short_id " - " this.Guid)
		this.AddControl("Button", parent.RemovePlugin.Bind(parent, this.Guid), "x+5 yp-5", "Remove")
		this.AddControl("Button", parent.ReorderPlugin.Bind(parent, this.Guid, -1), "x+5 yp", "Up")
		this.AddControl("Button", parent.ReorderPlugin.Bind(parent, this.Guid, 1), "x+5 yp", "Down")
		this.GuiCmd("-Caption")
		this.GuiCmd("+Parent" parent.hwnd)
		this.GuiCmd("Show", "Hide")	; Force layout, so we can get size
		short_id++
	}
	
	Move(ypos, scroll_pos){
		this.GuiCmd("Show", "x15 y" ypos - scroll_pos)
		this.ypos := ypos
	}
}

class WrappedGui {
	__New(hwnd := 0, options := ""){
		if (hwnd == 0){
			Gui, New, hwndhwnd
		}
		this.hwnd := hwnd
	}
	
	GuiCmd(cmd, aParams*){
		Gui, % this.hwnd ":" cmd, % aParams[1], % aParams[2], % aParams[3]
	}
	
	AddControl(type, callback := 0, aParams*){
		return new WrappedControl(this, type, callback, aParams*)
	}
	
	GetScrollPos(){
		static SCROLLINFO:="UINT cbSize;UINT fMask;int  nMin;int  nMax;UINT nPage;int  nPos;int  nTrackPos"
				,scroll:=Struct(SCROLLINFO,{cbSize:sizeof(SCROLLINFO),fMask:4})
		GetScrollInfo(this.hwnd,true,scroll[])
		return scroll.nPos
	}
	
	GetHeight(){
		ControlGetPos,,,,h,,% "ahk_id " this.hwnd
		return h
	}
}

class WrappedControl {
	__New(parent, type, callback := 0, aParams*){
		this.Parent := parent
		Gui, % this.Parent.hwnd ":Add", % type, % "hwndhwnd " aParams[1], % aParams[2]
		this.hwnd := hwnd
		if (callback != 0){
			this.CtrlCmd("+g", callback)
		}
	}
	
	CtrlCmd(cmd, param3){
		GuiControl, % cmd, % this.hwnd, % param3
	}
}

CreateGUID(){
	VarSetCapacity(foo_guid, 16, 0)
	if !(DllCall("ole32.dll\CoCreateGuid", "Ptr", &foo_guid))
	{
		VarSetCapacity(tmp_guid, 38 * 2 + 1)
		DllCall("ole32.dll\StringFromGUID2", "Ptr", &foo_guid, "Ptr", &tmp_guid, "Int", 38 + 1)
		fin_guid := StrGet(&tmp_guid, "UTF-16")
	}
	return SubStr(fin_guid, 2, 36)
}
Helgef
Posts: 4411
Joined: 17 Jul 2016, 01:02
Contact:

Re: Universal Control Remapper (UCR) - v0.1.14 12th Mar 2017

02 May 2017, 14:51

I have no problem with this script.
cuyo001
Posts: 7
Joined: 12 Dec 2016, 20:25

Re: Universal Control Remapper (UCR) - v0.1.14 12th Mar 2017

02 May 2017, 20:29

I played with the GUI changing it all sizes, moving the window, maximizing/minimizing, moving plugins up/down, deleting all plugins, creating new plugins, and this is what I found:

streching the window like the image hides the scrollbar but i was able to see all plugins using the mouse wheel.
Image




but streching the window like this I was unable to view the last 4 plugins, also note that the scrollbar dissapeared.
Image




I was making the window bigger but still the lasts plugins dont show up.
Image




to this size I was able to view the last plugin (I was using 20), also noted that the scrollbar was hiden beyond the window limit.
Image




the number of plugins seems not to affect this nor the creation or deletion, if the window is smaller than it was on launching the last plugins dont show up
Guest

Re: Universal Control Remapper (UCR) - v0.1.14 12th Mar 2017

04 May 2017, 02:46

Hello,

this program is my real salvage!!! I have searched the last months to find something that could do things, UCR is able to do.

I'm building a homecockpit and have searched for a replacement method to program pots in the way the old Thrustmaster FLCS/TQS or the Cougar were able to do. Move Radar Antenna Dial forward, produce something like a, b, c, d.... and back ....d, c, b, a or simple the same keystroke like +, +, +, +..... for moving the pod in one direction and -, -, -, -.... in the other direction.

Your program is able to do the first thing and I was able to edit the number of ranges to 20, which fits a bit better for flightsimulation :D , but the second example I have shown above isn't possible at the moment.

You could do bindings to two buttons to an axis, but it would be really nice to make something like: axis to one direction produces a selectable number of "a" ( "a" only as a placeholder here same with "b" ) and axis in back the opposite direction produces the same number of "b" as selected for the "a" . It should be something comparable to the ranges used in your "Axis range to Buttons" but only as a repeat of one keypress or a macro in one direction and another keypress or macro in the opposite direction, with the ability to choose the number of characters produced.

This way you are able to make something like a lever connected to a pot which puts for example "flaps down" to different stages with the use of "a a a a ...." and flaps up with the use of "b b b b ..... . Not all simulators have the possibility to bind analog axis to all of there options. That's why your program is so much help for sim pit builders!

Another feature could be an option to simulate mouse input with selectable axis of devices. This way you could use a thumb stick on a HOTAS to control the mouse cursor. This makes it possible to make something like the microstick at the HOTAS Cougar.

Hope you could help a little bit! I know that it's possible to make the needed options by yourself with the use of AHK, but I'm a totally "noob" in coding and I'm not the only one :D . Your program is really so much help if you are building a homepit! Have searched a long time to find something which is able to do things UCR can do, but for windows nothing exists. For the MAC there is a program called "controler mate", but for windows there are only progs like Xpadder or Pinnacle Game Profiler, which focus more on gamepads.
Viper1970-actually

Re: Universal Control Remapper (UCR) - v0.1.14 12th Mar 2017

04 May 2017, 09:58

Hello once again, as guest (like to activate my account, but something is still wrong with getting the email. Already contacted the admin) ;)

In my last post I think it's not really clear what I meant with the function repeating the same character for an axis.

It should essentially work the same way like an encoder does, with the exception that the function uses a potentiometer. This pot should function like a throttle or a slider, not a centering axis. If you rotate it clockwise it should generate (repeat the same) one character or macro (eg. a or Shift A) till you reach the stop and and if you rotate it counter clockwise it should create another character or macro (eg. b or Shift B). The different macros should only change if you change the direction of the rotation. Thrustmaster had this option to program it to its antenna dials at the old TQS or the more modern Cougar. Don't know if you familiar with the Thrustmaster HOTAS?

I know that you could use an encoder for doing this, but the problem is, if you built an DIY-HOTAS and you use an encoder for the dials instead of a potentiometer, you could only use this single character repeat. If you want to use a funtion like your "Axis Range To Buttons" you couldn't emulate this with an encoder, cause of the different Characters it uses.

Another feature I stated above could be a joystick to mouse emulation for using a microstick in the HOTAS. I've seen such a script for AutoHotKey and have tried to implement it to UCR, but as said before I'm a noob in coding :D . The result know is, aside from that you aren't able to choose the device and its axis with an option in the GUI, that every time I start UCR the Joystick to Mouse emulation already starts in the background. I wanted to make it as a plugin you can seperatly choose, but it doesn't matter if you activate the plugin or not, it simply starts with the start of UCR :crazy: .

Apologize me, I don't want to shove you in any way, but there are so many good methods out there to built own DIY Flight Controller, as the MMJoy2 concept for example, but those projects allways lacks on a good software which is able to configure your selfbuilt device. Most simulations today (eg. Falcon BMS 4.33.3) let you freely configure plain DirectX axis for the most of the functions they offer, but if you want to play more older sims, too (eg. EECH Allmods) you sometimes don't have an ingame setting or it lacks many features. That's where your EXCELLENT PIECE OF SOFTWARE could do the trick.

Regards Sven (Viper1970)
User avatar
evilC
Posts: 4772
Joined: 27 Feb 2014, 12:30

Re: Universal Control Remapper (UCR) - v0.1.14 12th Mar 2017

05 May 2017, 14:16

I hear ya. I have a Leo board myself...

What you want sounds fairly simple to do in UCR, but I am not sure it would work as you intend.
I knocked up a quick proof-of-concept for you by taking the AxisToButtons plugin and rewriting the main function that controls how it works. I did not alter the Init() function that builds the GUI

Save this file to plugins\user

If you look at the code, it is actually a lot simpler than the normal AxisToButtons plugin ;)

Code: Select all

/*
Remaps a physical joystick axis to a pair of button outputs
Requires the StickOps library and the vJoy library
*/
class AxisToButtonsEncoder extends _UCR.Classes.Plugin {
	Type := "Remapper (Axis To Buttons ENCODER)"
	Description := "Maps a joystick axis input to a pair of button outputs, behaves like an Encoder"
	LastState := 0
	; Set up the GUI to allow the user to select inputs and outputs
	Init(){
		iow := 125
		Gui, Add, GroupBox, Center xm ym w240 h70 section, Input Axis
		Gui, Add, Text, % "Center xs+5 yp+15 w" iow, Axis
		Gui, Add, Text, % "Center x+5 w100 ys+15", Preview
		this.AddControl("InputAxis", "InputAxis", 0, this.MyInputChangedState.Bind(this), "xs+5 yp+15")
		this.AddControl("AxisPreview", "", 0, this.IOControls.InputAxis, "x+5 yp+5 w100", 50)

		Gui, Add, GroupBox, Center x255 ym w90 h70 section, Settings
		Gui, Add, Text, % "xs+5 yp+20", Invert
		this.AddControl("CheckBox", "Invert", 0, "xs+60 yp w25")
		Gui, Add, Text, % "xs+5 y+10", DeadZone
		this.AddControl("Edit", "Deadzone", 0, "xs+60 yp-3 w25", "20")
		
		Gui, Add, GroupBox, Center x350 ym w325 h70 section, Output Buttons
		Gui, Add, Text, % "Center xs+35 yp+15 w" iow, Low
		Gui, Add, Text, % "Center x+10 yp w" iow, High
		this.AddControl("OutputButton", "OB1", 0, "xs+35 yp+15")
		this.AddControl("OutputButton", "OB2", 0, "x+5 yp")
		this.AddControl("ButtonPreview", "", 0, this.IOControls.OB2, "x+5 yp+5")
		this.AddControl("ButtonPreview", "", 0, this.IOControls.OB1, "xs+5 yp")
	}
	
	; The user moved the selected input axis. Manipulate the output buttons accordingly
	MyInputChangedState(value){
		; This bit just converts from a 0...100 range to a -50...+50 range
		value := UCR.Libraries.StickOps.AHKToInternal(value)
		; Applies deadzone if it is enabled
		dz := this.GuiControls.Deadzone.Get()
		if (dz){
			value := UCR.Libraries.StickOps.Deadzone(value, dz)
		}
		; Inverts axis if it is enabled
		if (this.GuiControls.Invert.Get()){
			value := UCR.Libraries.StickOps.Invert(value)
		}
		
		; This is the bit that does the rotary encoding
		if (value < this.LastState){
			; Axis moved towards low
			this.IOControls["OB1"].Set(1)
			;Sleep 50 ; You might need these sleeps, you might not
			this.IOControls["OB1"].Set(0)
		} else if (value > this.LastState){
			; Axis moved towards high
			this.IOControls["OB2"].Set(1)
			;Sleep 50
			this.IOControls["OB2"].Set(0)
		} else {
			; Should never happen, but just in case
			return
		}
		this.LastState := value
	}
}
The thing is... because of the way the UCR works (Polls stick every 10ms), then if you move the axis quickly, it generates less characters than if you move it slowly.
Last edited by evilC on 05 May 2017, 14:24, edited 3 times in total.
User avatar
evilC
Posts: 4772
Joined: 27 Feb 2014, 12:30

Re: Universal Control Remapper (UCR) - v0.1.14 12th Mar 2017

05 May 2017, 14:19

Thinking about it a little more - if you NEED there to always be a consistent number of button presses, no matter how fast you move the axis, then we could maybe say "The complete range is 100 button presses". Then, if you, for example, managed to move the axis the entire length within 1 tick, it would send 100 button presses.

This isn't trivial, but it is do-able, but we would probably need to set off a timer thread to send the button presses without tying up the main processing function.
TheFatal
Posts: 34
Joined: 30 Jan 2016, 06:58

Re: Universal Control Remapper (UCR) - v0.1.14 12th Mar 2017

06 May 2017, 10:26

hey evilC

i have 1 more question: can i run scripts with "while" loops instead of "if" ?

repeat sequences while i hold a button

can i use somehow "while" loop in this plugin ?

Code: Select all

class test1 extends _Plugin {
	Type := "test1"
	Description := "Your description here"
	; The Init() method of a plugin is called when one is added. Use it to create your Gui etc
	Init(){
		; Create the GUI
		; Add a hotkey, and give it the name "MyHk1". All hotkey objects can be accessed via this.InputButtons[name]
		; Have it call MyHkChangedState when it changes state.
		this.AddInputButton("IB1", 0, this.MyHkChangedState.Bind(this), "xm ym w200")
		; Add an Output, and give it the name "MyOp1". All output objects can be accessed via this.OutputButtons[name]
		this.AddOutputButton("OB6", 0, "xm yp+25 w200")
		this.AddOutputAxis("OutputAxis1", 0, "xm yp+25 w125")
		this.AddOutputAxis("OutputAxis2", 0, "xm yp+25 w125")
	}
 
	; Called when the hotkey changes state (key is pressed or released)
	MyHkChangedState(e){
			if (e){	; Only do this on press of the Input Button (e=1), do nothing on release (e=0)
			static StickOps := UCR.Libraries.StickOps
			; The input button was pressed, send the sequence of actions

			; X Axis Back
			this.OutputAxes.OutputAxis1.SetState(StickOps.AHKToVjoy(0))	
			Sleep 25
			; X Axis Centre
			this.OutputAxes.OutputAxis1.SetState(StickOps.AHKToVjoy(50))
			Sleep 25
			; X Axis Back
			this.OutputAxes.OutputAxis1.SetState(StickOps.AHKToVjoy(0))
			Sleep 25
			; X Axis Centre
			this.OutputAxes.OutputAxis1.SetState(StickOps.AHKToVjoy(50))
			Sleep 100
			; Y Axis Down
			this.OutputAxes.OutputAxis2.SetState(StickOps.AHKToVjoy(100))
			Sleep 25
			; X Axis Back
			this.OutputAxes.OutputAxis1.SetState(StickOps.AHKToVjoy(0))
			Sleep 25
			; X Axis Centre
			this.OutputAxes.OutputAxis1.SetState(StickOps.AHKToVjoy(50))
			; Y Axis Centre
			this.OutputAxes.OutputAxis2.SetState(StickOps.AHKToVjoy(50))
			
	} else {
			; X Axis Centre
			this.OutputAxes.OutputAxis1.SetState(StickOps.AHKToVjoy(50))
			; Y Axis Centre
			this.OutputAxes.OutputAxis2.SetState(StickOps.AHKToVjoy(50))

		}
	}

}
User avatar
evilC
Posts: 4772
Joined: 27 Feb 2014, 12:30

Re: Universal Control Remapper (UCR) - v0.1.14 12th Mar 2017

06 May 2017, 12:20

No, you don't want to use while loops as this will tie up the main function of the plugin.
Instead, use timers, like so:

Just work out how long all your input takes (Sending a key event takes ~50ms, Axes are basically instant) and adjust the tick rate of the timer accordingly.
eg if it takes 100ms to do each send, you probably want a timer rate of 200 or something.

Code: Select all

class test1 extends _Plugin {
	Type := "test1"
	Description := "Your description here"
	; The Init() method of a plugin is called when one is added. Use it to create your Gui etc
	Init(){
		; Create the GUI
		; Add a hotkey, and give it the name "MyHk1". All hotkey objects can be accessed via this.InputButtons[name]
		; Have it call MyHkChangedState when it changes state.
		this.AddInputButton("IB1", 0, this.MyHkChangedState.Bind(this), "xm ym w200")
		; Add an Output, and give it the name "MyOp1". All output objects can be accessed via this.OutputButtons[name]
		this.AddOutputButton("OB6", 0, "xm yp+25 w200")
		this.AddOutputAxis("OutputAxis1", 0, "xm yp+25 w125")
		this.AddOutputAxis("OutputAxis2", 0, "xm yp+25 w125")
		
		; New code
		this.LastState := 0
		; Store the timer object as a class property, so we can start/stop the timer easily
		this.TimerFn := this.Timer.Bind(this)
	}
 
	; Called when the hotkey changes state (key is pressed or released)
	MyHkChangedState(e){
		if (e != this.LastState){
			; We changed state
			fn := this.TimerFn
			if (e){
				SetTimer, % fn, 100 ; You will probably need to alter the time
			} else {
				SetTimer, % fn, Off
			}
		}
		this.LastState := e
	}
	
	Timer(){
		static StickOps := UCR.Libraries.StickOps
		this.OutputAxes.OutputAxis1.SetState(StickOps.AHKToVjoy(50))
	}

}
Helgef
Posts: 4411
Joined: 17 Jul 2016, 01:02
Contact:

Re: Universal Control Remapper (UCR) - v0.1.14 12th Mar 2017

06 May 2017, 12:28

Also note that you are either using an outdated version of ucr or that plugin will not work.
User avatar
evilC
Posts: 4772
Joined: 27 Feb 2014, 12:30

Re: Universal Control Remapper (UCR) - v0.1.14 12th Mar 2017

12 May 2017, 14:10

Billysims has been asking me about a joystick to mouse plugin - I am kinda busy at the moment, but I thought I would at least post up a basic example of how it would be done - I just took the axismerger plugin and altered it a bit.
There's no OutputDelta class in UCR, so I just hard-wired it with a DLLcall, but no biggie as there is nothing to "select" as an output anyway.

[Edit #1] Updated so now the mouse moves while the stick is outside the deadzone, set deadzone to default to 15 (Else hilarity can ensue as your mouse goes AWOL)

Code: Select all

/*
Merges two physical axes into one virtual axis
Requires the StickOps library and the vJoy library
*/
class AxesToMouse extends _UCR.Classes.Plugin {
	Type := "Remapper (Axes To Mouse)"
	Description := "Maps two input axes to mouse output"
	
	AxisStates := [0,0]
	MouseIsMoving := 0
	
	; Set up the GUI to allow the user to select input and output axes
	Init(){
		Gui, Add, Text, % "xm w125 Center", Input Axis 1
		Gui, Add, Text, % "x+5 w125 Center", Input Axis 2
		this.AddControl("InputAxis", "InputAxis1", 0, this.MyInputChangedState.Bind(this, 1), "xm w125")
		this.AddControl("InputAxis", "InputAxis2", 0, this.MyInputChangedState.Bind(this, 2), "Section x+5 w125")
		
		Gui, Add, Text, % "xm w125 Center", Input 1 Preview
		Gui, Add, Text, % "x+5 yp w125 Center", Input 2 Preview
		this.AddControl("AxisPreview", "", 0, this.IOControls.InputAxis1, "xm w125", 50)
		this.AddControl("AxisPreview", "", 0, this.IOControls.InputAxis2, "x+5 yp w125", 50)
		Gui, Add, Text, % "x50", Invert
		this.AddControl("CheckBox", "Invert1", this.MyEditChanged.Bind(this), "x+5 yp")
		
		Gui, Add, Text, % "x180 yp", Invert
		this.AddControl("CheckBox", "Invert2", this.MyEditChanged.Bind(this), "x+5 yp")
		
		Gui, Add, Text, % "x270 y40 w50 Center", Deadzone
		Gui, Add, Text, % "x+5 yp w50 Center", Sensitivity
		
		this.AddControl("Edit", "Deadzone", this.MyEditChanged.Bind(this), "x270 yp+20 w30", "15")
		Gui, Add, Text, % "x+0 yp+3", `%
		this.AddControl("Edit", "Sensitivity", this.MyEditChanged.Bind(this), "x+15 yp-3 w30", "100")
		Gui, Add, Text, % "x+0 yp+3", `%
		
		this.MoveMouseFn := this.MoveMouse.Bind(this)
	}
	
	; The user moved the selected input axis. Manipulate the output axis accordingly
	MyInputChangedState(axis, value){
		value := UCR.Libraries.StickOps.AHKToInternal(value)
		
		; Apply input axis inversions
		if (inv := this.GuiControls["Invert" axis].Get()){
			value := UCR.Libraries.StickOps.Invert(value)
		}
		
		; Apply deadzone
		if (dz := this.GuiControls.Deadzone.Get()){
			value := UCR.Libraries.StickOps.Deadzone(value, dz)
		}
		
		; Adjust sensitivity
		if (dz := this.GuiControls.Sensitivity.Get()){
			value := UCR.Libraries.StickOps.Sensitivity(value, dz)
		}
		
		; Store new value for the changed axis in array
		this.AxisStates[axis]  := value
		
		fn := this.MoveMouseFn
		
		; Start or stop the timer as appropriate
		mouse_should_be_moving := this.AxisStates[1] || this.AxisStates[2]
		if (this.MouseIsMoving && !mouse_should_be_moving){
			this.MouseIsMoving := 0
			SetTimer, % fn, Off
		} else if (mouse_should_be_moving && !this.MouseIsMoving){
			this.MouseIsMoving := 1
			SetTimer, % fn, 10
		}
	}
	
	MoveMouse(){
		DllCall("mouse_event", uint, 1, int, this.AxisStates[1], int, this.AxisStates[2], uint, 0, int, 0)
	}
}
User avatar
evilC
Posts: 4772
Joined: 27 Feb 2014, 12:30

Re: Universal Control Remapper (UCR) - v0.1.14 12th Mar 2017

13 May 2017, 09:22

This is an experimental plugin to map 2 input buttons to 3 output buttons
The two inputs map to two outputs as normal, but if both are held, then the 3rd output is held.
When you release one of the buttons after holding both, the 3rd output is released, and the output button that is left pressed is re-held

eg
hold input 1, output 1 held
hold input 2, output 1 released, output 3 held
release input 1, output 3 released, output 2 held (Because input 2 is now the only input held)

Code: Select all

class ButtonsToButtons extends _UCR.Classes.Plugin {
	Type := "Remapper (2 Buttons To 3 Buttons)"
	Description := "Remaps two InputButtons to three OutputButtons"
	
	InputStates := [0,0]
	OutputStates := [0,0,0]
	
	Init(){
		iow := 125
		Gui, Add, GroupBox, Center xm ym w270 h85 section, Input Buttons
		Gui, Add, Text, % "Center xs+5 yp+30 w" iow, Input 1
		Gui, Add, Text, % "Center x+10 w" iow " yp", Input 2
		this.AddControl("InputButton", "IB1", 0, this.ButtonInput.Bind(this, 1), " xs+5 yp+15")
		this.AddControl("ButtonPreviewThin", "", 0, this.IOControls.IB1, "x+0 yp")
		this.AddControl("InputButton", "IB2", 0, this.ButtonInput.Bind(this, 2), "x+5 yp")
		this.AddControl("ButtonPreviewThin", "", 0, this.IOControls.IB2, "x+0 yp")

		Gui, Add, GroupBox, Center x285 ym w390 h85 section, Output Buttons
		Gui, Add, Text, % "Center xs+5 yp+30 w" iow, Output 1
		Gui, Add, Text, % "Center x+0 w" iow " yp", Output 2
		Gui, Add, Text, % "Center x+0 w" iow " yp", Output 3
		this.AddControl("OutputButton", "OB1", 0, "xs+5 yp+15")
		this.AddControl("OutputButton", "OB2", 0, "x+5 yp")
		this.AddControl("OutputButton", "OB3", 0, "x+5 yp")
	}
	
	; One of the input buttons was pressed or released
	ButtonInput(btn, value){
		;OutputDebug % "UCR| Axis: " axis ", btn: " btn ", value: " value
		if (this.InputStates[btn] = value)
			return	; filter repeats if not in Incremental Mode
		
		this.InputStates[btn] := value
		both_inputs_held := this.InputStates[1] && this.InputStates[2]
				
		if (value){
			; Input pressed
			if (both_inputs_held){
				; Both buttons now pressed
				; Release the other output
				this.SetOutputState(3 - btn, 0)
				; Hold the 3rd output
				this.SetOutputState(3, 1)
			} else {
				; Hold the output for the input that was held
				this.SetOutputState(btn, 1)
			}
		} else {
			; Input released
			if (this.OutputStates[3]){
				; Both buttons were held
				this.SetOutputState(3, 0)
				; Press the output for the OTHER input, as that is now the only input held
				this.SetOutputState(3 - btn, 1)
			} else {
				; Release the output for the input that was held
				this.SetOutputState(btn, 0)
			}
		}
	}
	
	SetOutputState(output, state){
		this.IOControls["OB" output].Set(state)
		this.OutputStates[output] := state
	}
}
-Viper1970

Re: Universal Control Remapper (UCR) - v0.1.14 12th Mar 2017

17 May 2017, 06:29

Hello EvilC,

many thanks for your reply and the script you made!!!! Hadn't much time the last weeks for my hobby. I will test your script as soon as possible.
Have to resolder some things that aren't working the way I have planned them :lol:

Sadly I'm still not able to login the forum. I have contacted the admin twice but no reply. I'm registered but still can't login, cause I have to confirm my account. No way to do it, never get a confirmation-mail.

Regards Viper
Slayie

Re: Universal Control Remapper (UCR) - v0.1.14 12th Mar 2017

23 May 2017, 20:57

Hi evilC, I absolutely love the work you did with this, I've been searching for something like this for a long time. The only problem I have is the fact that (as you said in the description) now I'm actually trying to completely re-map my joystick (with vJoy) and when I try to get into whatever game if I press a button it works on "both" joysticks. You said the only way to actually use it properly now is to somehow make the game ignore the physical controller, the problem is I have no idea how I would actually do that... Does anyone have any suggestion about this?
Also, I've seen you talk about the GameBind plugin but I didn't really get what it's used for and if it could help me in this case.
User avatar
evilC
Posts: 4772
Joined: 27 Feb 2014, 12:30

Re: Universal Control Remapper (UCR) - v0.1.14 12th Mar 2017

24 May 2017, 04:21

GameBind is one solution for this issue.
What it does is to delay all your mappings by a second or two.

So to bind the game to a vJoy button
1) Go into the game bind menu
2) Press the joystick button you wish to bind
3) QUICKLY click Bind in the game and do not touch your physical stick
4) After a second or two, UCR will press the vJoy button, and seeing as you are not touching the physical stick at this point, the game only sees the vJoy button get pressed.
5) Once you are ready to play, disable GameBind

Another alternative that often works is to start the game with the physical stick not plugged in.
Many games only enumerate sticks when they start up, so if the stick was not plugged in when the game starts (vJoy is always plugged in) then the game should utterly ignore it.

At some point in the next 6 months or so, we should have a solution that lets us properly hide the physical stick. Until then, we need to use one of these two methods.
Slayie

Re: Universal Control Remapper (UCR) - v0.1.14 12th Mar 2017

24 May 2017, 07:44

Thank you very much for the quick response, and all the nice work you're doing. I'll try it out hoping for the best!
julioronaldi175
Posts: 1
Joined: 29 May 2017, 07:42

Re: Universal Control Remapper (UCR) - v0.1.14 12th Mar 2017

29 May 2017, 07:53

Hi someone thanks for this tool.. I want help now.. As i want to try it in a racing simulator.. The ButtonToAxis plugin is needed. What i wanted is like this:

When the throttle (keyboard button) pressed, the x axis output will increase slightly by a specified number, like 5. But i found a problem, that the input to lower the x axis is not working. I use F1 to LOW and F2 to HIGH. When i press F2 repeatedly, it will move as increment..but F1 doesn't work. HELP!!! How can i race with full throttle all the times?? xD
User avatar
evilC
Posts: 4772
Joined: 27 Feb 2014, 12:30

Re: Universal Control Remapper (UCR) - v0.1.14 12th Mar 2017

29 May 2017, 10:06

Sounds like you want incremental mode

Tick "Incremental mode" box
Set "Low" edit box to 5 and "High" edit box to 5
Bind F1 to Low and F2 to High

Then F1 will lower axis by 5, F2 will raise axis by 5

Return to “Gaming”

Who is online

Users browsing this forum: No registered users and 13 guests