I'm having trouble in developing my windows phone app. It's a game and I'm using XNA.
Here one of the Navigation Page:
The problem is that in the top left the "back" button is at the same place on the page before this one. So when I tap the back button, it doesn't lead me to the previous page but to the first one. (sometimes if I click fast enought it leads me to the previous one). As it works sometimes, I think the error doesn't come from my code. I think as the back_button is at the same place on both pages, it update too fast and the "touch_event" stay for too long maybe. I don't know how to solve this.
There is how I catch the button click:
TouchPanelCapabilities touchCap = TouchPanel.GetCapabilities();
if (touchCap.IsConnected)
{
TouchCollection touches = TouchPanel.GetState();
if (touches.Count >= 1)
{
Vector2 PositionTouch = touches[0].Position;
return (Mouseclik((int)PositionTouch.X, (int)PositionTouch.Y));
}
}
return (Screen.ChooseLevelScreen);
You need something like this:
if (touches.Count >= 1)
if (touches[0].State == TouchLocationState.Released)
{
Vector2 PositionTouch = touches[0].Position;
return (Mouseclik((int)PositionTouch.X, (int)PositionTouch.Y));
}
Usually, a tap is detected when you release the touch, not while you are pressing it, in this way you are sure that you detect it only once.
Poll for when your finger is released as opposed to clicked. That way when you remove your finger from the touch button it will only be registered once and not the x amount of times your finger was still on the button and the loop was carried out.
see TouchLocationState.Released at
http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.input.touch.touchlocationstate.aspx
you need TouchLocationState.Released
http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.input.touch.touchlocationstate.aspx
Related
Do you see how, after editing a value on -say- an image asset and then clicking anywhere outside without first clicking on apply, makes a window appear to ask you if you want to save or discard changes?
So, I wanted to do pretty much that from an OnGUI() or OnSceneGUI(), and right after starting to write the MyClassEditor : Editor realized that I not only knew how to accomplish such a thing; but apparently I didn't even know where to start searching on how to detect the mouse "entering" or "leaving" anything in the UI... if even possible.
This is what i found first when googling "detect mouse leaving inspector unity", and well as far as i understood, it is about detecting the edge of the screen boundaries, and the game window boundaries. So I went over the next result, which now looks promising at the beggining since it seems to describe my issue, but that is misleading since that solution applies to detect the mouse inside the scene view without loosing focus of the UI.. and i want to detect the focus lost so i head back to google only to stumble with a couple (more like several tbh) more of similar cases (like the unity reference to Monobehaviour.OnMouseEnter/Exit).
Which probably shows how lost I am, and I don't mean to ask for anything solved, but maybe a little push in the right direction will do? I appreciate every little help.
Edit:
So I tried this inside a [CustomEditor(typeof(MyClass))] public class MyClassEditor : Editor:
public override void OnInspectorGUI()
{
Event e = Event.current;
switch (e.type)
{
case EventType.MouseDown:
Debug.Log("mouse down");
break;
case EventType.MouseEnterWindow:
Debug.Log("mouse left a window");
break;
case EventType.MouseLeaveWindow:
Debug.Log("mouse entered a window");
break;
default:
break;
}
base.OnInspectorGUI();
var click = GUILayout.Button("Quick Fill");
if (click)
{
MyClassEditorWindow.Open((MyClass)target);
}
}
and even when the button works and the [mouse down] fires (only when clicking on top of what i think would be UIElements(?), tho -but not outside them, on the empty inspector area-),the other two ones don't seem to be firing... pretty sure im doing more than one thing wrong, not a clue of what of all.
There is a property in EditowWindow called wantsMouseEnterLeaveWindow.
If you set it to true, you will receive EventType.MouseLeaveWindow/EventType.MouseEnterWindow events.
Normally, I enable it in OnEnable function like this:
private void OnEnable() { wantsMouseEnterLeaveWindow = true; }
bool clickingGuiElement = false;
if (UnityEngine.EventSystems.EventSystem.current.IsPointerOverGameObject())
{
if (UnityEngine.EventSystems.EventSystem.current.currentSelectedGameObject != null)
{
if (UnityEngine.EventSystems.EventSystem.current.currentSelectedGameObject
.GetComponent<CanvasRenderer>() != null)
{
// user is clicking on a UI element (button)
clickingGuiElement = true;
}
else
clickingGuiElement = false;
}
else
clickingGuiElement = false;
}
else
clickingGuiElement = false;
The code above is utilizing Unity's EventSystem. This small control structure serves the purpose of handling objects being currently clicked on. It accomplishes the task of setting a boolean to inform the program whether the user is clicking on an UI element or not. In my case it is primarily utilized on buttons. Using this boolean output one can block UI clicks from propagating through the UI and interacting with any gameObjects that may be behind the UI.
Running through the code above on the HoloLens with breakpoints and/or printouts the result is always the same - false. The program never makes it into the first if statement on the HoloLens.
I need to be able to detect if the users airtap/clicker input, when they click, is on a UI element. If I know when a user clicks on an UI element, I can block it from propagating through the UI (as is done above, but, again, it works in the Editor and not on the HoloLens).
So, what substitutes the same EventSystem functionality achieved here (in the Editor) on the HoloLens?
P.S. I am using IPointerClickerHandler from UnityEngine.EventSystems in other parts of my code and it works fine, so I am not sure why this implementation utilizing the EventSystems isn't working. My best guess (from implementing features in the Editor vs the HoloLens) is that the 'Pointer' used in IsPointerOverGameObject isn't utilizing airtap input akin to mouse click input.
if(GazeManager.Instance.IsGazingAtObject && GazeManager.Instance.HitObject != null)
{
Debug.Log("guiElementName: " + GazeManager.Instance.HitObject.transform.name);
}
Did not find an EventSystem code equivalent in the end, however there is an easy solution in the 'GazeManager' script provided in the HoloToolkit provided by Microsoft.
Utilizing a simple check like this one above, one is able to determine if the users gaze is on a GUI element. Like so,
// Object assignment
GameObject cursor;
// If on GUI menu control structure
if (GazeManager.Instance.IsGazingAtObject && GazeManager.Instance.HitObject != null &&
(GazeManager.Instance.HitObject.transform.name == "icon" ||
GazeManager.Instance.HitObject.transform.name == "guiManager"))
{
// Scale
cursor.transform.localScale = halfScale;
// Move the cursor to the point where the raycast hit
// to display it on the gui element
cursor.transform.position = GazeManager.Instance.HitInfo.point;
// Enable the cursor mesh
cursor.GetComponent<MeshRenderer>().enabled = true;
}
Self-explanatory really, the code above scales, moves, and displays a cursor gameObject on an GUI when the users gaze is on it.
In my case [I used] the boolean output [from the EventSystem code attempting to] block UI clicks from propagating through the UI and interacting with any gameObjects that may be behind the UI.
Rather then blocking the clicks, one can handle a users gaze input, when gazing at UI elements, properly using the GazeManager.
Your UI Element needs to have a collider, and you need to use the raycast to detect if your ui element is being hit by the raycast. In the hololens the only way that I know of to detect that an element or game object has been hit is using gaze.
Edit: Upon clarification of the problem, you need to make sure that the layer that the raycast is able to hit is only the layer your button is on.
The question asks about detecting if a button is clicked, and the comments bring more understanding of the full problem, but the nature of the question is asked from the perspective of the person asking the questions's experience with other systems not from the understanding of how Hololens and Unity work together, to give the answer you are looking for is not possible because it's the wrong question. Everything in unity is essentially a game object, but they all can sit on different and multiple layers at the same time in the scene, you can see the layers in the top right in unity. The answer to resolve the problem is to specify the layer that the button is on, and that layer is not shared with other game objects which is not default behavior in Unity. When you are doing the raycast, you need to ignore all of the other layers, then you will no longer interact with the background objects behind the button. The link I included tells you how to do that. Once you have done that you would use the airtap event wired to the button like any other game object.
Here is a link on how to work with layers in Unity.
https://answers.unity.com/questions/416919/making-raycast-ignore-multiple-layers.html
I'm writing a complex GUI for my game's main menu. I have already created a ButtonGUI class with it's own constructor with the parameters of button text, text color etc. I have a background texture drawn behind the text for every button, to make it look pretty. So I implemented a simple mouse input system:
void DetectBtnInput(ButtonGUI btn)
{
if (mouseRect.Intersects(btn.SourceRect))
{
btn.IsHovered = true;
if (mouseState.LeftButton == ButtonState.Pressed) settingsWindow.isOpen = true;
}
}
This method is called in Update(GameTime gameTime) for each instance of the ButtonGUI class. So mouseRect = new Rectangle(mouseState.X, mouseState.Y, 1, 1);
each instance of the ButtonGUI class has a Rectangle SourceRect property, which is equal to the position of the button passed to the constructor (obviously the button's size is the same every time). The logic behind the above code is simple, if the mouse is hovering the button instance's SourceRect, btn.IsHovered is set to true, it changes text color. When clicked, my WindowGUI class instance opens with additional settings.
So my aim is at making these buttons look nice and have the Windows styled button mechanics. So I am looking for a code to check for mouse hold-like event and have for example a bool that changes the button texture or whatever I can do myself. But the problem is that I tried incorporating the solution people give about the previousMouseState and the newMouseState, but I am not certain as if it works in Monogame as it worked in XNA... Or was my implementation wrong? Can I have a clearer example on how you handle mouse-hold in your games? Thanks in advance!
If you mean the player can click and hold (as per question title), and nothing happens until they then release. previous and current state should work fine as an implementation such as.
Forgive any incorrections in syntax, hopefully you can take this as pseudo code enough to make your own.
MouseState prev, curr;
curr = GetMouseState();
update()
{
prev = curr;
curr = GetMouseState();
// Simple check for a mouse click (from being held down)
if (curr == MouseState.Up && prev == MouseState.Down)
{
// Do mouse stuff here
}
}
I've attached some MouseMove and MouseClick events to my program and next up is one of these:
Get "global" mouse movement, so that I can read the mouse location even outside the form.
Prevent my mouse from leaving the form in the first place.
My project is a game so it'd be awesome to prevent the mouse leaving my form like most other games do (ofc. you can move it out if you switch focus with alt+tab fe.) and taking a look at answers to other questions asking for global mosue movement, they seem pretty messy for my needs.
Is there an easy way to prevent my mouse from going outside my form's borders? Or actually to prevent it from going OVER the borders in the first place, I want the mouse to stay inside the client area.
Additional info about the game:
The game is a short, 5-30 seconds long survival game (it gets too hard after 30 seconds for you to stay alive) where you have to dodge bullets with your mouse. It's really annoying when you move your mouse out of the form and then the player (System.Windows.Forms.Panel attached to mouse) stops moving and instantly gets hit by a bullet. This is why preventing mouse from leaving the area would be good.
Late answer but might come in handy. You could subscribe the form to MouseLeave and MouseMove events and handle them like this :
private int X = 0;
private int Y = 0;
private void Form1_MouseLeave(object sender, EventArgs e)
{
Cursor.Position = new Point(X, Y);
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
if (Cursor.Position.X < this.Bounds.X + 50 )
X = Cursor.Position.X + 20;
else
X = Cursor.Position.X - 20;
if (Cursor.Position.Y < this.Bounds.Y + 50)
Y = Cursor.Position.Y + 20;
else
Y = Cursor.Position.Y - 20;
}
The above will make sure the mouse cursor never leaves the bounds of the form. Make sure you unsubscribe the events when the game is finished.
Edit :
Hans Passants's answer makes more sense than my answer. Use Cursor.Clip on MouseEnter :
private void Form1_MouseEnter(object sender, EventArgs e)
{
Cursor.Clip = this.Bounds;
}
You could free the cursor in case of any error/crash (I'm sure you could catch'em) :
Cursor.Clip = Rectangle.Empty;
You cannot trap the mouse, that would prevent the user from, say, operating the Start menu. Closest you can get is assigning the Cursor.Clip property. But it is easily defeated by the user pressing Ctrl+Esc for example, there is no notification for this.
Best thing to do is to subscribe the form's Deactivated event, it reliably tells you that the user switched to another program. The Activated event tells you when the user moved back. Of course the user will have few reasons to actually do this when the game score depends on keeping a game object moving. So don't forget to give the user an easy way to pause the game with, say, the Escape key.
I don't know a solution for your exact problem, but I have a completely different idea for you. I don't know how your game works, but based on what you told me, why not make it a step harder: Add borders to the game-area, for example 4 pixels wide rectangles, which you are not allowed to touch. If you touch them, you die and the mouse gets released.
You can use the Cursor class. For example:
int X = Cursor.Position.X;
int Y = Cursor.Position.Y;
As for preventing the user to move the mouse outside the form, the best approach would probably be if you had someway to know what is the coordinates of your form on the screen and attach a MouseMove event, and check if the mouse is inside the form rectangle.
To know the form position on the screen take a look at this question.
I wouldn't recommend the global mouse movement control for two reasons.
It's bad design, you should respect the bounds of the operating system. Make the application full screen if you want this kind of behaviour. The only applications that should perform these kind of operations are "kiosk" mode applications which lock down the entire OS (to prevent operator abuse).
Global key hooks are messy, aren't guaranteed to work and are dangerous because they affect a key part of the operating system (all controls). A bug in your code could result in requiring a reboot on the machine.
That said, last time I checked (a while ago, on Vista) SetWindowsHookEx still works (but its not officially supported IIRC), it's an unmanaged call so you'll have to pinvoke but with it you can refuse to pass on messages that would move the mouse outside of the bounds of your application. I'm not 100% sure if the OS will let you beat it to the cursor control (I've only blocked keyboards before on desktop boxes) but its probably your best shot.
I am writing a silly little program (as we all do from time to time) to work on some basic C# coding. As I'm sure you can see, the mouse is clicked, the picture moves until it's at the place where the mouse was clicked. This bit works fine. I then want the picturebox to move randomly, which I have also managed! The next problem I have is that when I click, instead of moving to the new mouse coordinates, the picturebox continues to move randomly. Any help on this would be much appreciated! Here is the code I think is the problem.
Many Thanks!
John
protected override void OnMouseClick(MouseEventArgs e)
{
base.OnMouseClick(e);
int destX = e.X;
int destY = e.Y;
HasArrived = false;
while (HasArrived == false)
{
moveImage(destX, destY, pictureBox1);
if (pictureBox1.Left == destX && pictureBox1.Top == destY)
{
HasArrived = true;
while (HasArrived == true)
{
randomMove(pictureBox1);
hungry1 += 1;
}
}
}
}
You are stucked in your inner loop!
Try to put the loop in a backgroundworker,
so you can recognize the new mouseclick to set HasArrived to true.
And using the negative while statement in the positive while statemant seems very bad to me,
ive never seen that before.
I dont think thiss will work fine..
It's probably because HasArrived never gets set to false anywhere? But that will also mean you will be stuck in your Move loop as well.
EDIT: If you want to only move randomly once after you move to the position you clicked at, then remove the while around the random bit, else you'll need some other variable to know when to break out of the while.
Your inner loop seems to have a problem.
HasArrived = true;
while (HasArrived == true)
{
randomMove(pictureBox1);
hungry1 += 1;
}
Unless randomMove() can modify HasArrived, your loop never set HasArrived to false, so the while condition is always true, and you will never get out of the loop.
I looks like its because once the picture moves to its destination your program is stuck in a tight while loop from which it never escapes
First of all, you should never test equality of variables with boolean expressions. This means HasArrived == false is bad and it is better to write it like this:
while (!HasArrived)
{
// ...
while (HasArrived)
{
}
}
The problem is that your program does not give back control to the form, after the mouse has been clicked once.
Let me illustrate, what your program does as soon as the mouse has been clicked:
remember new x and y coords
while the picture has not arrived, move the image
in case the picture has arrived it's destination - move it around randomly
But it ends up moving the picture around until you kill the program, because your form does still handle the "OnMouseClicked"-event. And as long as the program does not return from your event handling method, the form is unable to record any other event (typically it should freeze, ending with "Application not responding").
So from what I think your code is supposed to do you should code your program like this:
1. Create a parallel thread to move around your image randomly
2. Pause the thread as long as your mouse-click event has not yet been handled
Also your question is wrong at all. Realtime means that your program is able to give any result in a predefined time-limit. Your method does not fit this at all, beacause the time your method takes for execution depends on how fast your image moves and which distance it should move.