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

Post gaming related scripts
Oliver
Posts: 27
Joined: 11 Jan 2018, 10:50

Re: Universal Control Remapper (UCR) - v0.1.19 26th Dec 2017

13 Jan 2018, 07:37

Ah OK! I thought I had to actually use it but it's merely an example of the GUI, got it.
User avatar
evilC
Posts: 4822
Joined: 27 Feb 2014, 12:30

Re: Universal Control Remapper (UCR) - v0.1.19 26th Dec 2017

13 Jan 2018, 08:50

I made it a bit more production ready - you no longer need to add 0,0 at the start and 100,100 at the end.
I also added a little bit of validation / ordering logic

I packaged it all up into a UCR plugin - hopefully this should be functional and do what you need

Code: Select all

class AxisToAxisDetent extends _UCR.Classes.Plugin {
	Type := "Remapper (Axis To Axis with Detent)"
	Description := "Maps an axis input to a virtual axis output (With Detent)"
	vAxis := 0
	vDevice := 0
	; Set up the GUI to allow the user to select input and output axes
	Init(){
		Gui, Add, GroupBox, % "xm w135 h130 section Center", Input Axis
		this.AddControl("InputAxis", "IA1", 0, this.MyInputChangedState.Bind(this), "xp+5 w125 y25")
		this.AddControl("AxisPreview", "", 0, this.IOControls.IA1, "xp y+5 w125", 50)
		
		Gui, Add, GroupBox, % "x150 ym w60 h130 section Center", Invert
		this.AddControl("CheckBox", "Invert", 0, "xs+25 w30 y40")
		
		Gui, Add, GroupBox, % "x220 ym w150 h130 section Center", Detent settings
		this.SegmentManager := new this.SegmentControl(this.OnSegmentChanged.Bind(this), this, "xs+10 y25")
		
		Gui, Add, GroupBox, % "x385 ym w135 h130 section Center", Output Virtual Axis
		this.AddControl("OutputAxis", "OA1", this.MyOutputChangedValue.Bind(this), "xs+5 y25 w125")
		this.AddControl("AxisPreview", "", 0, this.IOControls.OA1, "xp y+5 w125", 50)
		
		this.AddControl("Edit", "Segments", this.OnSettingsLoad.Bind(this), "x+25 yp hidden")
	}
	
	OnSegmentChanged(value){
		GuiControl, , % this.GuiControls.Segments.hwnd, % value
	}
	
	OnSettingsLoad(value){
		if (value != ""){
			this.SegmentManager.LoadSettings(value)
		}
	}
	
	; The user changed options - store stick and axis selected for fast retreival
	MyOutputChangedValue(value){
		this.vAxis := value.Binding[1]
		this.vDevice := value.DeviceID
		this.OutputBound := value.IsBound()
	}
	
	; The user moved the selected input axis. Manipulate the output axis accordingly
	MyInputChangedState(value){
		value := UCR.Libraries.StickOps.AHKToInternal(value)
		if (this.OutputBound){
			if (this.GuiControls.Invert.Get()){
				value := UCR.Libraries.StickOps.Invert(value)
			}
			value := UCR.Libraries.StickOps.InternalToAHK(value)
			
			value := this.SegmentManager.GetValue(value)
			
			this.IOControls.OA1.Set(value)
		}
	}
	
	class SegmentControl {
		Segments := []
		Points := []
		
		__New(callback, parent, options := ""){
			this.parent := parent
			this.callback := callback
			Gui, Add, ListView, % "hwndhwnd w100 h75 section " options, Input|Output
			LV_ModifyCol(1, 45)
			LV_ModifyCol(2, 45)
			this.hLV := hwnd
			Gui, Add, Button, hwndhwnd x+5 yp w20 h75, -
			fn := this.DeleteClicked.Bind(this)
			GuiControl, +g, % hwnd, % fn
			Gui, Add, Edit, xs y+5 hwndhwnd w45
			this.hEditInput := hwnd
			Gui, Add, Edit, x+10 yp hwndhwnd w45
			this.hEditOutput := hwnd
			Gui, Add, Button, hwndhwnd x+5 yp w20, +
			fn := this.AddClicked.Bind(this)
			GuiControl, +g, % hwnd, % fn
		}
		
		; Set save to false when loading settings, to avoid triggering save on load
		_AddPoint(i, o, save := true){
			if (!this.IsNumeric(i) || !this.IsNumeric(o)){
				return false
			}
			inserted := false
			for index, obj in this.Points {
				if (obj[1] == i)
					return false
				if (obj[1] > i){
					this.Points.Insert(index, [i,o])
					inserted := true
					break
				}
			}
			if (!inserted){
				this.Points.push([i, o])
			}
			this.BuildSegments()
			if (save){
				this.SaveSettings()
			}
			return true
		}
		
		_RemovePoint(index){
			this.Points.RemoveAt(index)
			this.BuildSegments()
			this.SaveSettings()
		}
		
		LoadSettings(str){
			chunks := StrSplit(str, "|")
			for i, pt in chunks {
				p := StrSplit(pt, ",")
				res := this._AddPoint(p[1], p[2], false)
			}
		}
		
		SaveSettings(){
			str := ""
			for i, chunk in this.Points {
				if (i > 1){
					str .= "|"
				}
				str .= chunk[1] "," chunk[2]
			}
			this.callback.Call(str)
		}
		
		BuildSegments(){
			gui, % this.parent.hwnd ":default"
			Gui, ListView, % this.hLV
			LV_Delete()
			if (this.Points.Length() == 0){
				return
			}
			for i, p in this.Points {
				LV_Add(, p[1], p[2])
			}
			pts := this.Points.clone()
			;~ pts.Insert(1, [0,0])
			pts.Push([100,100])
			;~ p0 := pts.removeat(1)
			p0 := [0,0]
			this.Segments := []
			for i, p1 in pts {
				this.Segments.push( {k : (p1.2-p0.2) / (p1.1-p0.1) , m : ( p1.1*p0.2 - p0.1*p1.2 ) / (p1.1-p0.1), end : p1.1 } ), p0 := p1
			}
		}
		
		AddClicked(){
			GuiControlGet, i, , % this.hEditInput
			GuiControlGet, o, , % this.hEditOutput
			if (!this._AddPoint(i, o)){
				SoundBeep, 200, 500
			}
		}
		
		DeleteClicked(){
			Gui, ListView, % this.hLV
			row := LV_GetNext()
			this._RemovePoint(row)
		}
		
		IsNumeric(str){
			if str is number
				return true
			return false
		}
		
		GetValue(x){
			for i, seg in this.Segments
				if (x <= seg.end)
					return x*seg.k+seg.m
		}
	}
	
}
Oliver
Posts: 27
Joined: 11 Jan 2018, 10:50

Re: Universal Control Remapper (UCR) - v0.1.19 26th Dec 2017

13 Jan 2018, 09:33

Yeah basically [0,0] at the start and [100,100] at the end do not need to be user selectable as they have to be there anyway.

Gonna try it in a couple of hours! The GUI and all seems to work perfectly so far.
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Universal Control Remapper (UCR) - v0.1.19 26th Dec 2017

13 Jan 2018, 12:34

It seems fine evilC :thumbup:. (As far as I can see using the vJoy feeder)
Oliver
Posts: 27
Joined: 11 Jan 2018, 10:50

Re: Universal Control Remapper (UCR) - v0.1.19 26th Dec 2017

13 Jan 2018, 13:13

Whatever you do, I'm happy, because it works!
User avatar
evilC
Posts: 4822
Joined: 27 Feb 2014, 12:30

Re: Universal Control Remapper (UCR) - v0.1.19 26th Dec 2017

13 Jan 2018, 13:57

OK, I made the settings box visible, plus added a "Copy Current" button to place the current value of the input axis into the Input box of the GuiControl.

Image

Code: Select all

class AxisToAxisDetent extends _UCR.Classes.Plugin {
	Type := "Remapper (Axis To Axis with Detent)"
	Description := "Maps an axis input to a virtual axis output (With Detent)"
	vAxis := 0
	vDevice := 0
	; Set up the GUI to allow the user to select input and output axes
	Init(){
		Gui, Add, GroupBox, % "xm w135 h130 section Center", Input Axis
		this.AddControl("InputAxis", "IA1", 0, this.MyInputChangedState.Bind(this), "xs+5 w125 y25")
		this.AddControl("AxisPreview", "", 0, this.IOControls.IA1, "xs+5 y+5 w125", 50)

		fn := this.UseCurrentClicked.Bind(this)
		Gui, Add, Button, hwndhwnd xs+5 y+5 w125, Copy Current >>>>
		GuiControl, +g, % hwnd, % fn

		Gui, Add, GroupBox, % "x160 ym w60 h130 section Center", Invert
		this.AddControl("CheckBox", "Invert", 0, "xs+25 w30 y40")
		
		Gui, Add, GroupBox, % "x235 ym w150 h130 section Center", Breakpoint settings
		this.SegmentManager := new this.SegmentControl(this.OnSegmentChanged.Bind(this), this, "xs+10 y25")
		
		Gui, Add, GroupBox, % "x400 ym w135 h130 section Center", Output Virtual Axis
		this.AddControl("OutputAxis", "OA1", this.MyOutputChangedValue.Bind(this), "xs+5 y25 w125")
		this.AddControl("AxisPreview", "", 0, this.IOControls.OA1, "xp y+5 w125", 50)
		
		Gui, Add, GroupBox, x540 ym w135 h130 section center, Settings String
		Gui, Add, Text, xs+5 y25, Copy this to another plugin`nof the same kind`nto duplicate settings
		this.AddControl("Edit", "Segments", this.OnSettingsLoad.Bind(this), "xs+5 y+10")
	}
	
	OnSegmentChanged(value){
		GuiControl, , % this.GuiControls.Segments.hwnd, % value
	}
	
	OnSettingsLoad(value){
		this.SegmentManager.LoadSettings(value)
	}
	
	UseCurrentClicked(){
		this.SegmentManager.SetInputBox(Round(this.IOControls.IA1.Get(), 2))
	}
	
	; The user changed options - store stick and axis selected for fast retreival
	MyOutputChangedValue(value){
		this.vAxis := value.Binding[1]
		this.vDevice := value.DeviceID
		this.OutputBound := value.IsBound()
	}
	
	; The user moved the selected input axis. Manipulate the output axis accordingly
	MyInputChangedState(value){
		value := UCR.Libraries.StickOps.AHKToInternal(value)
		if (this.OutputBound){
			if (this.GuiControls.Invert.Get()){
				value := UCR.Libraries.StickOps.Invert(value)
			}
			value := UCR.Libraries.StickOps.InternalToAHK(value)
			
			value := this.SegmentManager.GetValue(value)
			
			this.IOControls.OA1.Set(value)
		}
	}
	
	class SegmentControl {
		Segments := []
		Points := []
		
		__New(callback, parent, options := ""){
			this.parent := parent
			this.callback := callback
			Gui, Add, ListView, % "hwndhwnd w110 h75 section " options, Input|Output
			LV_ModifyCol(1, 50)
			LV_ModifyCol(2, 50)
			this.hLV := hwnd
			Gui, Add, Button, hwndhwnd x+5 yp w20 h75, -
			fn := this.DeleteClicked.Bind(this)
			GuiControl, +g, % hwnd, % fn
			Gui, Add, Edit, xs y+5 hwndhwnd w50
			this.hEditInput := hwnd
			Gui, Add, Edit, x+10 yp hwndhwnd w50
			this.hEditOutput := hwnd
			Gui, Add, Button, hwndhwnd x+5 yp w20, +
			fn := this.AddClicked.Bind(this)
			GuiControl, +g, % hwnd, % fn
		}
		
		; Set save to false when loading settings, to avoid triggering save on load
		_AddPoint(i, o){
			if (!this.IsNumeric(i) || !this.IsNumeric(o)){
				return false
			}
			inserted := false
			for index, obj in this.Points {
				if (obj[1] == i)
					return false
				if (obj[1] > i){
					this.Points.Insert(index, [round(i, 2), round(o, 2)])
					inserted := true
					break
				}
			}
			if (!inserted){
				this.Points.push([i, o])
			}
			return true
		}
		
		_RemovePoint(index){
			this.Points.RemoveAt(index)
			this.BuildSegments()
			this.SaveSettings()
		}
		
		LoadSettings(str){
			this.Points := []
			chunks := StrSplit(str, "|")
			for i, pt in chunks {
				p := StrSplit(pt, ",")
				res := this._AddPoint(p[1], p[2], false)
			}
			this.BuildSegments()
		}
		
		SaveSettings(){
			str := ""
			for i, chunk in this.Points {
				if (i > 1){
					str .= "|"
				}
				str .= chunk[1] "," chunk[2]
			}
			this.callback.Call(str)
		}
		
		SetInputBox(value){
			GuiControl, , % this.hEditInput, % value
		}
		
		BuildSegments(){
			gui, % this.parent.hwnd ":default"
			Gui, ListView, % this.hLV
			LV_Delete()
			for i, p in this.Points {
				LV_Add(, p[1], p[2])
			}
			pts := this.Points.clone()
			;~ pts.Insert(1, [0,0])
			pts.Push([100,100])
			;~ p0 := pts.removeat(1)
			p0 := [0,0]
			this.Segments := []
			for i, p1 in pts {
				this.Segments.push( {k : (p1.2-p0.2) / (p1.1-p0.1) , m : ( p1.1*p0.2 - p0.1*p1.2 ) / (p1.1-p0.1), end : p1.1 } ), p0 := p1
			}
		}
		
		AddClicked(){
			GuiControlGet, i, , % this.hEditInput
			GuiControlGet, o, , % this.hEditOutput
			if (!this._AddPoint(i, o)){
				SoundBeep, 200, 500
				return
			}
			this.BuildSegments()
			this.SaveSettings()
		}
		
		DeleteClicked(){
			Gui, ListView, % this.hLV
			row := LV_GetNext()
			this._RemovePoint(row)
		}
		
		IsNumeric(str){
			if str is number
				return true
			return false
		}
		
		GetValue(x){
			for i, seg in this.Segments
				if (x <= seg.end)
					return x*seg.k+seg.m
		}
	}
	
}
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Universal Control Remapper (UCR) - v0.1.19 26th Dec 2017

13 Jan 2018, 14:03

Maybe you should allow to add points with the same breakpoint, eg, [50,0] [50,70] causes a jump (step) after 50. Although, the difference between that and [50,0] [50.01, 70] isn't noticable. Also, the listview is too small (win7, normal dpi), when I add a point I get scroll-bars, which lies inside the listview.

Cheers.
Oliver
Posts: 27
Joined: 11 Jan 2018, 10:50

Re: Universal Control Remapper (UCR) - v0.1.19 26th Dec 2017

14 Jan 2018, 04:54

Gents, the copy current function does not take into account the invert checkbox. E.g. when I place my physical throttle at 70% (30% in UCR's terms), select invert, and hit copy current, it creates a breapoint at 30% instead of 70%.
User avatar
evilC
Posts: 4822
Joined: 27 Feb 2014, 12:30

Re: Universal Control Remapper (UCR) - v0.1.19 26th Dec 2017

14 Jan 2018, 13:06

If invert is selected, clicking "Copy Current" adds inverted value.

Code: Select all

class AxisToAxisDetent extends _UCR.Classes.Plugin {
	Type := "Remapper (Axis To Axis with Detent)"
	Description := "Maps an axis input to a virtual axis output (With Detent)"
	vAxis := 0
	vDevice := 0
	; Set up the GUI to allow the user to select input and output axes
	Init(){
		Gui, Add, GroupBox, % "xm w135 h130 section Center", Input Axis
		this.AddControl("InputAxis", "IA1", 0, this.MyInputChangedState.Bind(this), "xs+5 w125 y25")
		this.AddControl("AxisPreview", "", 0, this.IOControls.IA1, "xs+5 y+5 w125", 50)

		fn := this.UseCurrentClicked.Bind(this)
		Gui, Add, Button, hwndhwnd xs+5 y+5 w125, Copy Current >>>>
		GuiControl, +g, % hwnd, % fn

		Gui, Add, GroupBox, % "x160 ym w60 h130 section Center", Invert
		this.AddControl("CheckBox", "Invert", 0, "xs+25 w30 y40")
		
		Gui, Add, GroupBox, % "x235 ym w150 h130 section Center", Breakpoint settings
		this.SegmentManager := new this.SegmentControl(this.OnSegmentChanged.Bind(this), this, "xs+10 y25")
		
		Gui, Add, GroupBox, % "x400 ym w135 h130 section Center", Output Virtual Axis
		this.AddControl("OutputAxis", "OA1", this.MyOutputChangedValue.Bind(this), "xs+5 y25 w125")
		this.AddControl("AxisPreview", "", 0, this.IOControls.OA1, "xp y+5 w125", 50)
		
		Gui, Add, GroupBox, x540 ym w135 h130 section center, Settings String
		Gui, Add, Text, xs+5 y25, Copy this to another plugin`nof the same kind`nto duplicate settings
		this.AddControl("Edit", "Segments", this.OnSettingsLoad.Bind(this), "xs+5 y+10")
	}
	
	OnSegmentChanged(value){
		GuiControl, , % this.GuiControls.Segments.hwnd, % value
	}
	
	OnSettingsLoad(value){
		this.SegmentManager.LoadSettings(value)
	}
	
	UseCurrentClicked(){
		value := UCR.Libraries.StickOps.AHKToInternal(this.IOControls.IA1.Get())
		if (this.GuiControls.Invert.Get()){
			value := UCR.Libraries.StickOps.Invert(value)
		}
		value := UCR.Libraries.StickOps.InternalToAHK(value)
		this.SegmentManager.SetInputBox(Round(value, 2))
	}
	
	; The user changed options - store stick and axis selected for fast retreival
	MyOutputChangedValue(value){
		this.vAxis := value.Binding[1]
		this.vDevice := value.DeviceID
		this.OutputBound := value.IsBound()
	}
	
	; The user moved the selected input axis. Manipulate the output axis accordingly
	MyInputChangedState(value){
		value := UCR.Libraries.StickOps.AHKToInternal(value)
		if (this.OutputBound){
			if (this.GuiControls.Invert.Get()){
				value := UCR.Libraries.StickOps.Invert(value)
			}
			value := UCR.Libraries.StickOps.InternalToAHK(value)
			
			value := this.SegmentManager.GetValue(value)
			
			this.IOControls.OA1.Set(value)
		}
	}
	
	class SegmentControl {
		Segments := []
		Points := []
		
		__New(callback, parent, options := ""){
			this.parent := parent
			this.callback := callback
			Gui, Add, ListView, % "hwndhwnd w110 h75 section " options, Input|Output
			LV_ModifyCol(1, 50)
			LV_ModifyCol(2, 50)
			this.hLV := hwnd
			Gui, Add, Button, hwndhwnd x+5 yp w20 h75, -
			fn := this.DeleteClicked.Bind(this)
			GuiControl, +g, % hwnd, % fn
			Gui, Add, Edit, xs y+5 hwndhwnd w50
			this.hEditInput := hwnd
			Gui, Add, Edit, x+10 yp hwndhwnd w50
			this.hEditOutput := hwnd
			Gui, Add, Button, hwndhwnd x+5 yp w20, +
			fn := this.AddClicked.Bind(this)
			GuiControl, +g, % hwnd, % fn
		}
		
		; Set save to false when loading settings, to avoid triggering save on load
		_AddPoint(i, o){
			if (!this.IsNumeric(i) || !this.IsNumeric(o)){
				return false
			}
			inserted := false
			for index, obj in this.Points {
				if (obj[1] == i)
					return false
				if (obj[1] > i){
					this.Points.Insert(index, [round(i, 2), round(o, 2)])
					inserted := true
					break
				}
			}
			if (!inserted){
				this.Points.push([i, o])
			}
			return true
		}
		
		_RemovePoint(index){
			this.Points.RemoveAt(index)
			this.BuildSegments()
			this.SaveSettings()
		}
		
		LoadSettings(str){
			this.Points := []
			chunks := StrSplit(str, "|")
			for i, pt in chunks {
				p := StrSplit(pt, ",")
				res := this._AddPoint(p[1], p[2], false)
			}
			this.BuildSegments()
		}
		
		SaveSettings(){
			str := ""
			for i, chunk in this.Points {
				if (i > 1){
					str .= "|"
				}
				str .= chunk[1] "," chunk[2]
			}
			this.callback.Call(str)
		}
		
		SetInputBox(value){
			value := UCR.Libraries.StickOps.AHKToInternal(value)
			if (this.GuiControls.Invert.Get()){
				value := UCR.Libraries.StickOps.Invert(value)
			}
			value := UCR.Libraries.StickOps.InternalToAHK(value)
			GuiControl, , % this.hEditInput, % value
		}
		
		BuildSegments(){
			gui, % this.parent.hwnd ":default"
			Gui, ListView, % this.hLV
			LV_Delete()
			for i, p in this.Points {
				LV_Add(, p[1], p[2])
			}
			pts := this.Points.clone()
			;~ pts.Insert(1, [0,0])
			pts.Push([100,100])
			;~ p0 := pts.removeat(1)
			p0 := [0,0]
			this.Segments := []
			for i, p1 in pts {
				this.Segments.push( {k : (p1.2-p0.2) / (p1.1-p0.1) , m : ( p1.1*p0.2 - p0.1*p1.2 ) / (p1.1-p0.1), end : p1.1 } ), p0 := p1
			}
		}
		
		AddClicked(){
			GuiControlGet, i, , % this.hEditInput
			GuiControlGet, o, , % this.hEditOutput
			if (!this._AddPoint(i, o)){
				SoundBeep, 200, 500
				return
			}
			this.BuildSegments()
			this.SaveSettings()
		}
		
		DeleteClicked(){
			Gui, ListView, % this.hLV
			row := LV_GetNext()
			this._RemovePoint(row)
		}
		
		IsNumeric(str){
			if str is number
				return true
			return false
		}
		
		GetValue(x){
			for i, seg in this.Segments
				if (x <= seg.end)
					return x*seg.k+seg.m
		}
	}
	
}
Last edited by evilC on 15 Jan 2018, 05:32, edited 1 time in total.
Oliver
Posts: 27
Joined: 11 Jan 2018, 10:50

Re: Universal Control Remapper (UCR) - v0.1.19 26th Dec 2017

15 Jan 2018, 01:06

Hmm, not for me it doesn't.
Oliver
Posts: 27
Joined: 11 Jan 2018, 10:50

Re: Universal Control Remapper (UCR) - v0.1.19 26th Dec 2017

15 Jan 2018, 13:52

Well, to put it bluntly, I've got everything I asked for.

What are your plans? Or you looking to further tweak or add settings? I'd say it serves it's purpose very well right now! Maybe indeed the option to set the values and have a graph as visual representation of what you've just set.
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Universal Control Remapper (UCR) - v0.1.19 26th Dec 2017

15 Jan 2018, 14:03

The ListView problem I had was easy to fix by changing to

Code: Select all

LV_ModifyCol(1, 44)
LV_ModifyCol(2, 44)
in AxisToAxisDetent.SegmentControl.__new.

Cheers. :wave:
User avatar
evilC
Posts: 4822
Joined: 27 Feb 2014, 12:30

Re: Universal Control Remapper (UCR) - v0.1.19 26th Dec 2017

15 Jan 2018, 15:17

Looks like the listview was simply not wide enough to properly accommodate 100.00, so I made it bigger.
Barring any other issues, I think this one should be the final version:

Code: Select all

class AxisToAxisDetent extends _UCR.Classes.Plugin {
	Type := "Remapper (Axis To Axis with Detent)"
	Description := "Maps an axis input to a virtual axis output (With Detent)"
	vAxis := 0
	vDevice := 0
	; Set up the GUI to allow the user to select input and output axes
	Init(){
		Gui, Add, GroupBox, % "xm w135 h130 section Center", Input Axis
		this.AddControl("InputAxis", "IA1", 0, this.MyInputChangedState.Bind(this), "xs+5 w125 y25")
		this.AddControl("AxisPreview", "", 0, this.IOControls.IA1, "xs+5 y+5 w125", 50)

		fn := this.UseCurrentClicked.Bind(this)
		Gui, Add, Button, hwndhwnd xs+5 y+5 w125, Copy Current >>>>
		GuiControl, +g, % hwnd, % fn

		Gui, Add, GroupBox, % "x155 ym w60 h130 section Center", Invert
		this.AddControl("CheckBox", "Invert", 0, "xs+25 w30 y40")
		
		Gui, Add, GroupBox, % "x225 ym w170 h130 section Center", Breakpoint settings
		this.SegmentManager := new this.SegmentControl(this.OnSegmentChanged.Bind(this), this, "xs+10 y25")
		
		Gui, Add, GroupBox, % "x400 ym w135 h130 section Center", Output Virtual Axis
		this.AddControl("OutputAxis", "OA1", this.MyOutputChangedValue.Bind(this), "xs+5 y25 w125")
		this.AddControl("AxisPreview", "", 0, this.IOControls.OA1, "xp y+5 w125", 50)
		
		Gui, Add, GroupBox, x540 ym w135 h130 section center, Settings String
		Gui, Add, Text, xs+5 y25, Copy this to another plugin`nof the same kind`nto duplicate settings
		this.AddControl("Edit", "Segments", this.OnSettingsLoad.Bind(this), "xs+5 y+10")
	}
	
	OnSegmentChanged(value){
		GuiControl, , % this.GuiControls.Segments.hwnd, % value
	}
	
	OnSettingsLoad(value){
		this.SegmentManager.LoadSettings(value)
	}
	
	UseCurrentClicked(){
		value := UCR.Libraries.StickOps.AHKToInternal(this.IOControls.IA1.Get())
		if (this.GuiControls.Invert.Get()){
			value := UCR.Libraries.StickOps.Invert(value)
		}
		value := UCR.Libraries.StickOps.InternalToAHK(value)
		this.SegmentManager.SetInputBox(value)
	}
	
	; The user changed options - store stick and axis selected for fast retreival
	MyOutputChangedValue(value){
		this.vAxis := value.Binding[1]
		this.vDevice := value.DeviceID
		this.OutputBound := value.IsBound()
	}
	
	; The user moved the selected input axis. Manipulate the output axis accordingly
	MyInputChangedState(value){
		value := UCR.Libraries.StickOps.AHKToInternal(value)
		if (this.OutputBound){
			if (this.GuiControls.Invert.Get()){
				value := UCR.Libraries.StickOps.Invert(value)
			}
			value := UCR.Libraries.StickOps.InternalToAHK(value)
			
			value := this.SegmentManager.GetValue(value)
			
			this.IOControls.OA1.Set(value)
		}
	}
	
	class SegmentControl {
		Segments := []
		Points := []
		
		__New(callback, parent, options := ""){
			this.parent := parent
			this.callback := callback
			Gui, Add, ListView, % "hwndhwnd w110 h75 section " options, Input|Output
			LV_ModifyCol(1, 50)
			LV_ModifyCol(2, 50)
			this.hLV := hwnd
			Gui, Add, Button, hwndhwnd x+5 yp w20 h75, -
			fn := this.DeleteClicked.Bind(this)
			GuiControl, +g, % hwnd, % fn
			Gui, Add, Edit, xs y+5 hwndhwnd w50
			this.hEditInput := hwnd
			Gui, Add, Edit, x+10 yp hwndhwnd w50
			this.hEditOutput := hwnd
			Gui, Add, Button, hwndhwnd x+5 yp w20, +
			fn := this.AddClicked.Bind(this)
			GuiControl, +g, % hwnd, % fn
		}
		
		; Set save to false when loading settings, to avoid triggering save on load
		_AddPoint(i, o){
			if (!this.IsNumeric(i) || !this.IsNumeric(o)){
				return false
			}
			inserted := false
			for index, obj in this.Points {
				if (obj[1] == i)
					return false
				if (obj[1] > i){
					this.Points.Insert(index, [round(i, 2), round(o, 2)])
					inserted := true
					break
				}
			}
			if (!inserted){
				this.Points.push([round(i, 2), round(o, 2)])
			}
			return true
		}
		
		_RemovePoint(index){
			this.Points.RemoveAt(index)
			this.BuildSegments()
			this.SaveSettings()
		}
		
		LoadSettings(str){
			this.Points := []
			chunks := StrSplit(str, "|")
			for i, pt in chunks {
				p := StrSplit(pt, ",")
				res := this._AddPoint(p[1], p[2], false)
			}
			this.BuildSegments()
		}
		
		SaveSettings(){
			str := ""
			for i, chunk in this.Points {
				if (i > 1){
					str .= "|"
				}
				str .= chunk[1] "," chunk[2]
			}
			this.callback.Call(str)
		}
		
		SetInputBox(value){
			GuiControl, , % this.hEditInput, % round(value, 2)
		}
		
		BuildSegments(){
			gui, % this.parent.hwnd ":default"
			Gui, ListView, % this.hLV
			LV_Delete()
			for i, p in this.Points {
				LV_Add(, p[1], p[2])
			}
			pts := this.Points.clone()
			;~ pts.Insert(1, [0,0])
			pts.Push([100,100])
			;~ p0 := pts.removeat(1)
			p0 := [0,0]
			this.Segments := []
			for i, p1 in pts {
				this.Segments.push( {k : (p1.2-p0.2) / (p1.1-p0.1) , m : ( p1.1*p0.2 - p0.1*p1.2 ) / (p1.1-p0.1), end : p1.1 } ), p0 := p1
			}
		}
		
		AddClicked(){
			GuiControlGet, i, , % this.hEditInput
			GuiControlGet, o, , % this.hEditOutput
			if (!this._AddPoint(i, o)){
				SoundBeep, 200, 500
				return
			}
			this.BuildSegments()
			this.SaveSettings()
		}
		
		DeleteClicked(){
			Gui, ListView, % this.hLV
			row := LV_GetNext()
			this._RemovePoint(row)
		}
		
		IsNumeric(str){
			if str is number
				return true
			return false
		}
		
		GetValue(x){
			for i, seg in this.Segments
				if (x <= seg.end)
					return x*seg.k+seg.m
		}
	}
	
}

Return to “Gaming Scripts (v1)”

Who is online

Users browsing this forum: No registered users and 34 guests