diff --git a/BizHawk.MultiClient/Global.cs b/BizHawk.MultiClient/Global.cs
index bb157e8f88..2d1eb19978 100644
--- a/BizHawk.MultiClient/Global.cs
+++ b/BizHawk.MultiClient/Global.cs
@@ -236,6 +236,11 @@ namespace BizHawk.MultiClient
public static AutoFireStickyXORAdapter AutofireStickyXORAdapter = new AutoFireStickyXORAdapter();
+ ///
+ /// Forces any controller button to Off, useful for things like Joypad.Set
+ ///
+ public static ForceOffAdaptor ForceOffAdaptor = new ForceOffAdaptor();
+
///
/// will OR together two IControllers
///
diff --git a/BizHawk.MultiClient/LuaImplementation.cs b/BizHawk.MultiClient/LuaImplementation.cs
index 3659e2694a..243b989ca5 100644
--- a/BizHawk.MultiClient/LuaImplementation.cs
+++ b/BizHawk.MultiClient/LuaImplementation.cs
@@ -2117,15 +2117,82 @@ namespace BizHawk.MultiClient
{
foreach (var button in buttons.Keys)
{
- if (Convert.ToBoolean(buttons[button]) == true)
+ bool invert = false;
+ bool? theValue = null;
+ string theValueStr = buttons[button].ToString();
+
+ if (!String.IsNullOrWhiteSpace(theValueStr))
{
- if (controller == null)
+ if (theValueStr.ToLower() == "false")
{
- Global.ClickyVirtualPadController.Click(button.ToString());
+ theValue = false;
+ }
+ else if (theValueStr.ToLower() == "true")
+ {
+ theValue = true;
}
else
{
- Global.ClickyVirtualPadController.Click("P" + controller.ToString() + " " + button.ToString());
+ invert = true;
+ theValue = null;
+ }
+ }
+ else
+ {
+ theValue = null;
+ }
+
+
+ if (!invert)
+ {
+ if (theValue == true)
+ {
+ if (controller == null) //Force On
+ {
+ Global.ClickyVirtualPadController.Click(button.ToString());
+ Global.ForceOffAdaptor.SetSticky(button.ToString(), false);
+ }
+ else
+ {
+ Global.ClickyVirtualPadController.Click("P" + controller.ToString() + " " + button.ToString());
+ Global.ForceOffAdaptor.SetSticky("P" + controller.ToString() + " " + button.ToString(), false);
+ }
+ }
+ else if (theValue == false) //Force off
+ {
+ if (controller == null)
+ {
+ Global.ForceOffAdaptor.SetSticky(button.ToString(), true);
+ }
+ else
+ {
+ Global.ForceOffAdaptor.SetSticky("P" + controller.ToString() + " " + button.ToString(), true);
+ }
+ }
+ else if (theValue == null)
+ {
+ //Turn everything off
+ if (controller == null)
+ {
+ Global.ForceOffAdaptor.SetSticky(button.ToString(), false);
+ }
+ else
+ {
+ Global.ForceOffAdaptor.SetSticky("P" + controller.ToString() + " " + button.ToString(), false);
+ }
+ }
+ }
+ else //Inverse
+ {
+ if (controller == null)
+ {
+ Global.StickyXORAdapter.SetSticky(button.ToString(), true);
+ Global.ForceOffAdaptor.SetSticky(button.ToString(), false);
+ }
+ else
+ {
+ Global.StickyXORAdapter.SetSticky("P" + controller.ToString() + " " + button.ToString(), true);
+ Global.ForceOffAdaptor.SetSticky("P" + controller.ToString() + " " + button.ToString(), false);
}
}
}
diff --git a/BizHawk.MultiClient/MainForm.cs b/BizHawk.MultiClient/MainForm.cs
index 2aefe4f756..f231f64338 100644
--- a/BizHawk.MultiClient/MainForm.cs
+++ b/BizHawk.MultiClient/MainForm.cs
@@ -1780,7 +1780,9 @@ namespace BizHawk.MultiClient
Global.AutofireStickyXORAdapter.Source = Global.StickyXORAdapter;
Global.MultitrackRewiringControllerAdapter.Source = Global.AutofireStickyXORAdapter;
- Global.MovieInputSourceAdapter.Source = Global.MultitrackRewiringControllerAdapter;
+ Global.ForceOffAdaptor.Source = Global.MultitrackRewiringControllerAdapter;
+
+ Global.MovieInputSourceAdapter.Source = Global.ForceOffAdaptor;
Global.ControllerOutput.Source = Global.MovieOutputHardpoint;
Global.Emulator.Controller = Global.ControllerOutput;
diff --git a/BizHawk.MultiClient/movie/InputAdapters.cs b/BizHawk.MultiClient/movie/InputAdapters.cs
index 86c645906b..0ef72c6cde 100644
--- a/BizHawk.MultiClient/movie/InputAdapters.cs
+++ b/BizHawk.MultiClient/movie/InputAdapters.cs
@@ -34,6 +34,23 @@ namespace BizHawk.MultiClient
Pressed.Add(button);
}
+ public void Unclick(string button)
+ {
+ Pressed.Remove(button);
+ }
+
+ public void Toggle(string button)
+ {
+ if (IsPressed(button))
+ {
+ Pressed.Remove(button);
+ }
+ else
+ {
+ Pressed.Add(button);
+ }
+ }
+
HashSet Pressed = new HashSet();
}
@@ -118,9 +135,45 @@ namespace BizHawk.MultiClient
}
+ public class ForceOffAdaptor : IController
+ {
+ public bool IsPressed(string button) { return this[button]; }
+ public float GetFloat(string name) { return 0.0f; } //TODO
+ public void UpdateControls(int frame) { }
+
+ protected HashSet stickySet = new HashSet();
+ public IController Source;
+ public IController SourceOr;
+ public ControllerDefinition Type { get { return Source.Type; } set { throw new InvalidOperationException(); } }
+
+ public bool this[string button]
+ {
+ get
+ {
+ bool source = Source[button];
+ if (stickySet.Contains(button))
+ {
+ return false;
+ }
+ else
+ {
+ return Source[button];
+ }
+ }
+ set { throw new InvalidOperationException(); }
+ }
+
+ public void SetSticky(string button, bool isSticky)
+ {
+ if (isSticky)
+ stickySet.Add(button);
+ else stickySet.Remove(button);
+ }
+ }
+
public class StickyXORAdapter : IController
{
- private HashSet stickySet = new HashSet();
+ protected HashSet stickySet = new HashSet();
public IController Source;
public ControllerDefinition Type { get { return Source.Type; } set { throw new InvalidOperationException(); } }