My monogame game has stopped responding to mouse clicks. Prior to version 3.5, this was working fine. Here's how I'm currently getting the input:
protected override void Update (GameTime game_time)
{
Mouse_Input (game_time);
}
void Mouse_Input(GameTime game_time)
{
mouse_current = Mouse.GetState();
if (mouse_current.LeftButton == ButtonState.Pressed)
{
// click
}
}
Setting breakpoints in the function reveals all the code is being hit, but LeftButton is always ButtonState.Released.
I've tried with both a wired mouse and the trackpad. Keyboard input is working fine. Anyone else running into this?
I always use this way.
MouseState currentMouseState;
MouseState oldMouseState;
public bool checkClick()
{
oldMouseState = currentMouseState;
currentMouseState = Mouse.GetState();
if (Visible)
{
if (currentMouseState.LeftButton == ButtonState.Pressed && oldMouseState.LeftButton == ButtonState.Released)
{
return true;
}
}
}
If you want to check if the Mouse clicks on a Rectangle (Hud elements for example)
public bool checkClickRectangle(Rectangle rec)
{
oldMouseState = currentMouseState;
currentMouseState = Mouse.GetState();
if (Visible)
{
if (rec.Contains(new Vector2(Mouse.GetState().X, Mouse.GetState().Y)) && currentMouseState.LeftButton == ButtonState.Pressed && oldMouseState.LeftButton == ButtonState.Released)
{
return true;
}
}
}
This was actually a not a problem with Monogame, but a problem in my game logic that was very difficult to track down.
After upgrading to 3.5, I had to reconfigure how my Texture2D's were being loaded, which also meant refactoring some classes. I ended up with a class within a class which were both inheriting from Game.
public class Brush_Control : Game
{
public class Tile : Game
{
Process of elimination narrowed the search to this class. I believe this caused an infinite loop that interfered with the input somehow, but without throwing an error or causing an obvious freeze.
Removing the inner Game reference as a parent fixed the problem, and it turns out I no longer need to have it there anyway.
Related
I'm using MRTK 2.3.0 trying to catch a "Grip Press" event from the Mixed Reality motion controller.
I've setup the Input Action in the MRTK Toolkit in the Hierarchy of Unity. I've also assigned the action to the controller's grip button in the Controller Definitions. I'm using the following code and made sure the Grip variable is assigned to the Grip Press event. Nothing happens... I'm able to catch touchpad and joystick, menu button press, but not Grip? Why?
According to this documentation: https://microsoft.github.io/MixedRealityToolkit-Unity/Documentation/MixedRealityConfigurationGuide.html the Grip should be a "float" as it's designed as single axis (I wonder why, since it's a button and not a trigger...). However, I'm trying to catch the event where I can... not working...
Anyone understand what the heck I'm trying to say here? (sorry, the code below also includes other events that I can catch without a hickup).
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Microsoft.MixedReality.Toolkit.Input;
using Microsoft.MixedReality.Toolkit;
public class TestInput : MonoBehaviour, IMixedRealityBaseInputHandler,
IMixedRealityInputHandler<Vector2>, IMixedRealityInputHandler
{
public MixedRealityInputAction Trigger, Grip, Scroll, Swipe, Joystick, DPad, TouchPadClicked, TouchPadTouched, MenuPressed;
public MixedRealityInputAction DPadUp, DPadDown, DPadLeft, DPadRight, JoystickUp, JoystickDown, JoystickLeft, JoystickRight;
private bool TouchpadPressed, MenuButtonPressed, GrabPressed, TouchDialogPadPressed, TouchpadClicked, Thouchpadtouched,
ThumbstickActive, ThumbstickPressed, VRManipulationStarted, ScrubStarted, PlayPause = false;
private void OnEnable()
{
IMixedRealityInputSystem inputSystem;
if (MixedRealityServiceRegistry.TryGetService<IMixedRealityInputSystem>(out inputSystem))
{
inputSystem?.RegisterHandler<IMixedRealityBaseInputHandler>(this);
inputSystem?.RegisterHandler<IMixedRealityInputHandler<Vector2>>(this);
inputSystem?.RegisterHandler<IMixedRealityInputHandler>(this);
inputSystem?.RegisterHandler<IMixedRealityInputHandler<float>>(this);
}
}
private void OnDisable()
{
IMixedRealityInputSystem inputSystem;
if (MixedRealityServiceRegistry.TryGetService<IMixedRealityInputSystem>(out inputSystem))
{
inputSystem?.UnregisterHandler<IMixedRealityBaseInputHandler>(this);
inputSystem?.UnregisterHandler<IMixedRealityInputHandler<Vector2>>(this);
inputSystem?.UnregisterHandler<IMixedRealityInputHandler>(this);
inputSystem?.UnregisterHandler<IMixedRealityInputHandler<float>>(this);
}
}
public void OnInputChanged(InputEventData<Vector2> ed)
{
Debug.Log("InputChanged");
if (ed.MixedRealityInputAction == DPad)
{
Debug.Log("Touched Touchpad at:" + ed.InputData.x.ToString() + "," + ed.InputData.y.ToString());
}
if (ed.MixedRealityInputAction == Joystick)
{
Debug.Log("Touched Joystick at:" + ed.InputData.x.ToString() + "," + ed.InputData.y.ToString());
}
}
public void OnInputChanged(InputEventData ed)
{
if (ed.MixedRealityInputAction == MenuPressed)
{
Debug.Log("Menu button pressed");
//ActionText.text = "Grab pressed";
}
}
public void OnInputChanged(InputEventData<float> ed)
{
Debug.Log("Float Changed");
if (ed.MixedRealityInputAction == Grip)
Debug.Log("Grab Pressed");
}
Ok... I got this..... It's a BUG in MRTK.
I have 18 actions defined (when you have DPad left, up, down etc it goes by fast!).
When I try to assign my MixedRealityInputAction to an InputAction in the Inspector, when I try to select GrabPressed (which is the 18th action), I get
IndexOutOfRangeException: Index was outside the bounds of the array.
Microsoft.MixedReality.Toolkit.Input.Editor.InputActionPropertyDrawer.OnGUI
Therefore the action does not work....
I tried to use another InputAction instead and assign it to the grab button (I used Select in this case) and it works like a charm....
Beware....
Try
Input.GetAxisRaw(ControllerMappingLibrary.AXIS_11) > 0 || Input.GetAxisRaw(ControllerMappingLibrary.AXIS_12) > 0;
AXIS_11 is grip press for the left controller while 12 is for the right controller
This might be a simple question but I can't figure it out.
I have a form called in my main function:
void Main() {
Mem = new MemoryManager();
Console::WriteLine("Thread Started");
Application::EnableVisualStyles();
Application::SetCompatibleTextRenderingDefault(false);
FinalSolution::ControlPanel form;
Thread^ cLoop = gcnew Thread(gcnew ThreadStart(loop));
cLoop->Start();
Application::Run(%form);
}
All I want to do is, if someone presses a key in general (not just when the program is in focus), it changes the background to a different color.
I have tried a few things but nothing has worked so far. Here is the loop and I have indicated where I want it to happen.
void loop() {
while (true) {
if (GetAsyncKeyState(key)) {
//Here
form.button->BackColor = System::Drawing::Color::ForestGreen;
}
}
}
Of course the issue is that this function doesn't know what form is, but I don't know how to tell it.
Ended up just putting the loop directly in the form header and that solved the problem.
I am working on disabling copy/paste option menus on xamarin forms Entry, I am able to disable copy option using IsPassword=true attribute but this attribute also converts the normal input field to password field, which is not a requirement.
<Entry IsPassword="true" Placeholder="Password" TextColor="Green" BackgroundColor="#2c3e50" />
Thanks in advance.
This has to do with how Forms functions. Using iOS as the example here, the CanPerform override referred to in the other answer's Bugzilla issue is using the UIMenuController as the withSender and not the UITextField itself that might otherwise be expected. This is because the EntryRenderer class is a ViewRenderer<TView, TNativeView> type and subsequently is using whatever TNativeView (in this case, the UITextView) has in its CanPerform. Because nothing is going to be overridden by default, one still sees all of the cut/copy/paste options in the UIMenuController.
As a result, there would be a couple options. You could first make the modification where if you don't want copy/paste but are fine with getting rid of everything else, you can use UIMenuController.SharedMenuController.SetMenuVisible(false, false) in a custom renderer inheriting from EntryRenderer. If you look around on SO, there are similar questions where this is a possible route.
Alternatively, you can create a "true" custom renderer inheriting from ViewRenderer<TView, TNativeView> as ViewRenderer<Entry, YourNoCopyPasteUITextFieldClassName>. The class inheriting from UITextField can then override CanPerform as something like follows:
public override bool CanPerform(Selector action, NSObject withSender)
{
if(action.Name == "paste:" || action.Name == "copy:" || action.Name == "cut:")
return false;
return base.CanPerform(action, withSender);
}
This will require more effort because the custom renderer will not have the same behavior as the EntryRenderer, but as Xamarin.Forms is now open source, you could look to it for some ideas as to how the EntryRenderer functions normally. Something similar would likely have to be done for Android.
Edit: For Android, you can probably use this SO answer as a starting point: How to disable copy/paste from/to EditText
Another custom renderer, this time inheriting from ViewRenderer<Entry, EditText>, and create a class inside of it like this (in the most basic form):
class Callback : Java.Lang.Object, ActionMode.ICallback
{
public bool OnActionItemClicked(ActionMode mode, IMenuItem item)
{
return false;
}
public bool OnCreateActionMode(ActionMode mode, IMenu menu)
{
return false;
}
public void OnDestroyActionMode(ActionMode mode)
{
}
public bool OnPrepareActionMode(ActionMode mode, IMenu menu)
{
return false;
}
}
Then, in your OnElementChanged method, you can set the native control and the CustomSelectionActionModeCallback value:
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
if (Control != null)
{
Control.CustomSelectionActionModeCallback = new Callback();
}
}
Doing something like the following appears to disable all of the copy/paste/cut functionality on the custom entry as far as the toolbar goes. However, you can still long click to show the paste button, to which I've poked around a bit hadn't found an answer yet beyond setting LongClickable to false. If I do find anything else in that regard, I'd make sure to update this.
I have a strange problem with an AlphaAnimation. It is supposed to run repeatedly when an AsyncTask handler is called.
However, the first time the handler is called in the Activity, the animation won't start unless I touch the screen or if the UI is updated (by pressing the phone's menu button for example).
The strange part is that once the animation has run at least once, it will start without problem if the handler is called again.
Here's what the code looks like:
// AsyncTask handler
public void onNetworkEvent()
{
this.runOnUiThread(new Runnable() {
#Override
public void run()
{
flashScreen(Animation.INFINITE);
}
});
}
// Called method
private void flashScreen(int repeatCount)
{
final View flashView = this.findViewById(R.id.mainMenuFlashView);
AlphaAnimation alphaAnimation = new AlphaAnimation(1, 0);
alphaAnimation.setRepeatCount(repeatCount);
alphaAnimation.setRepeatMode(Animation.RESTART);
alphaAnimation.setDuration(300);
alphaAnimation.setInterpolator(new DecelerateInterpolator());
alphaAnimation.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation)
{
flashView.setVisibility(View.VISIBLE);
}
#Override
public void onAnimationEnd(Animation animation)
{
flashView.setVisibility(View.GONE);
}
#Override
public void onAnimationRepeat(Animation animation) { }
});
flashView.startAnimation(alphaAnimation);
}
I have noticed that runOnUIThread isn't necessary (same results occur if I don't use it), but I prefer keeping it as I'm not on the UI thread.
Any ideas on what could cause this?
A little more research showed that my problem was the same a this question:
Layout animation not working on first run
The flashView's visibility was set to GONE by default (causing the Animation not to start immediately as the View had never been rendered), so I just need to set it to INVISIBLE before calling flashView.startAnimation()
If setting the View to VISIBLE won't work, as was in my case, it helped for me to call requestLayout() before starting the Animation, like so:
Animation an = new Animation() {
...
view.requestLayout();
view.startAnimation(an);
In my case, my View was 0dip high which prevented onAnimationStart from being called, this helped me around that problem.
This worked for me:
view.setVisibility(View.VISIBLE);
view.startAnimation(animation);
I had to set the view to VISIBLE (not INVISIBLE, neither GONE), causing the view renderization needed to animate it.
That's not an easy one. Till you got a real answer : The animation start is triggered by onNetworkEvent. As we don't know the rest of the code, you should look there, try to change onNetworkEvent by an other event that you can easily identify, just to debug if the rest of the code is ok or if it's just the trigger that is responsible for it.
May be it will help someone, because previous answers not helped me.
My animation was changing height of view (from 0 to it's real height and back) on click - expand and collapse animations.
Nothing worked until i added listener and set visibility to GONE, when animation ends:
collapseAnim.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
view.setVisibility(View.GONE);
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
And when expand just set it to VISIBLE before animation:
view.setVisibility(View.VISIBLE);
view.startAnimation(expandAnim);
I'm playing around with editing java.lang.Object for the Java Runtime Environment. I realize that there are probably better ways to do what I want, but that is not what my question is about.
Basically I've added a constructor to java.lang.Object which gets called everytime an object is created. I'm waiting for a certain class to load like so:
public Object() {
if (hookEnabled) {
hookEnabled = false;
objectCount++;
if (objectCount > objectStartCount) {
if (this.getClass() != null) {
String name = this.getClass().getName();
if ((!name.startsWith("java.")) && (!name.startsWith("javax.")) && (!name.startsWith("launcher.")) && (!name.startsWith("sunw.")) && (!name.startsWith("com.sun.")) && (!name.startsWith("sun.")) && (!name.startsWith("org.xml.")) && (!name.startsWith("org.w3c.")) && (!name.startsWith("org.omg.")) && (!name.startsWith("org.ietf."))) {
if (!hasHooked) {
hasHooked = true;
//startup beep
java.awt.Toolkit.getDefaultToolkit().beep();
//load interface
javax.swing.JFrame frame = new javax.swing.JFrame("");
frame.setBounds(0, 0, 400, 400);
frame.setAlwaysOnTop(true);
frame.setVisible(true);
}
}
}
}
hookEnabled = true;
}
}
This works fine. It adds a window to whatever application is being run by the JVM.
However, when making a simple change by moving the JFrame code into a separate class, and calling that call the JVM simply crashes:
public Object() {
if (hookEnabled) {
hookEnabled = false;
objectCount++;
if (objectCount > objectStartCount) {
if (this.getClass() != null) {
String name = this.getClass().getName();
if ((!name.startsWith("java.")) && (!name.startsWith("javax.")) && (!name.startsWith("launcher.")) && (!name.startsWith("sunw.")) && (!name.startsWith("com.sun.")) && (!name.startsWith("sun.")) && (!name.startsWith("org.xml.")) && (!name.startsWith("org.w3c.")) && (!name.startsWith("org.omg.")) && (!name.startsWith("org.ietf."))) {
if (!hasHooked) {
hasHooked = true;
(new tvmh.DFVMH()).setup();
}
}
}
}
hookEnabled = true;
}
}
--
package tvmh;
public class DFVMH {
public void setup() {
//startup beep
java.awt.Toolkit.getDefaultToolkit().beep();
//load interface
javax.swing.JFrame frame = new javax.swing.JFrame("");
frame.setBounds(0, 0, 400, 400);
frame.setAlwaysOnTop(true);
frame.setVisible(true);
}
}
The same happens when I try to create a java.util.Timer object.
Interestingly enough, the above does work if I make DFVMH an inline class (internal class) of java.lang.Object itself.
Could anyone tell me why such behaviour would happen? And is there any way to safely call such custom class?
Tinkering with the innards of the JVM like this is very risky. There are all sorts of hidden dependencies at the low levels of the JVM that can break. JVM bootstrap is a very delicate process.
For instance, the most likely reason you are seeing a crash rather a StackOverflowError is that your change has broken all object construction ... including construction of the error object.
And I suspect that your guard code is ineffective because this.getClass().getName() may be causing a String object to be created. So the fatal recursion happens before you get to your guard.
(Incidentally, your hasHooked flag introduces a race condition.)
My advice is "Don't do it!".
What do you mean by 'it crashes'?.
Isn't it StackOverflowException? Your new tvmh.DFVMH() is actually a constructor all too. So it runs through your 'overriden' Object constructor.
If you already play like this, how about adding the tvmh.DFVMH to stop list of packages/classes?
Just a quick thought: new tvmh.DFVHM() becomes a new object, which also derives from java.lang.Object, meaning your custom constructor code will be run again before the first one has finished. I'm guessing "hasHooked" should guard against that, but how is that variable defined? If that guard doesn't work, this sequence it will recurse infinitely.
If you make DFVMH an inline class it's name will probably start with "java.lang[...]" (it's in java.lang.Object, after all) and will thus not get through the long if statement with all the name.startsWith.