Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
The ClickNoSlideThreshold value is measured in pixels which determines if a releasing the mouse or touch screen should be treated as a ClickNoSlide. If the distance moved since the last push is less than ClickNoSlideThreshold, then the PrimaryClickNoSlide property is true for that frame. Otherwise, only the Click property is true.
If this value is increased, then the Cursor reports clicks even if the user has moved the cursor slightly since pushing the cursor (or touching the screen). If this value is reduced, then clicks will not register as often if the cursor has moved slightly since touch. This value primarily exists to help distinguish between actual push/release vs. push+slide. Since this value is in pixels it may need to be increased for high-resolution touch screens.
The IWindow interface is an interface that enables objects to be added to the GuiManager. Once an object is added to the GuiManager it will automatically be tested for Cursor events. The IWindow interface can be used to simplify the implementation of buttons, check boxes, and any other types of UI elements which may need to interact with the cursor.
Although IWindow can be implemented manually in code, the IWindow interface is most typically implemented by Glue in generated code. For more information on IWindow in Glue, see this page.
The WindowOver returns the Window (or any object inheriting from Window such as Button, TextBox, etc.) that the Cursor is currently over. This will return the top-most window, so if the Cursor is over a Button which is contained inside a Window, the WindowOver property will contain a reference to the Button.
Speicifcally WindowOver considers:
Gum objects
FlatRedBall.Forms objects (since they use Gum as their visuals)
Any Entity or code-only object which inherits from IWindow and has been added to the GuiManager.
The following code performs "ClickLogic" when the user performs a primary click (left click on the mouse or a release on a touch screen) if the Cursor is not over any window. This is a common way to check if the cursor is over any UI.
One very common bug is related to having multiple IWindows overlapping. In this case events may not be raising even though it appears they should be graphically. You can use the Cursor's WindowOver property in combination with the FlatRedBall.Debugging.Debugger to help identify the problem:
If the wrong window is being returned by WindowOver, you can diagnose/correct this by doing the following:
Verify that the two IWindows have different Z values if they are on the same layer or verify that the desired IWindows are on separate Layers
Call GuiManager.SortZAndLayerBased() to sort the IWindows in the GuiManager so that tests are performed in the right order.
See if the Window you are expecting to be over has its Enabled property set to true.
All Gum objects implement the IWindow interface, so all are (at least by interface) eligible for Cursor interaction. However, not all Gum objects will interact with the cursor. For more information, see the Events on Gum Objects tutorial.
The IInputReceiver interface provides methods and properties common to all UI elements which can receive input from devices such as the Keyboard or Xbox360GamePads. Any object which implements the IInputReceiver can be assigned to the InputManager's InputReceiver.
Only one instance can be assigned as the InputManager.InputReceiver property. If assigned, this instance has a number of methods called upon being assigned as well as in response to input. Its OnFocusUpdate is also called every frame automatically.
FlatRedBall.Forms elements typically receive input in one of two ways:
In response to Cursor clicks. These events are ultimately raised by the underlying Gum objects (GraphicalUiElement)
In response to changes in a keyboard state or Xbox360GamePad which is polled every-frame.
Forms elements which need to poll input every frame should do so by implementing IInputReceiver and checking input in the OnFocusUpdate.
For example, the following code could be used to perform custom actions whenever the A button is pressed on a Forms control which implements IInputReceiver:
For a full example of implementation, see the ListBox implementation:
The IInputReceiver interface is designed to prevent multiple objects from receiving input. The most common way to do this is to have the IInputReceiver process input in its ReceiveInput method, then clear the input. For example, the following code can be used to move an object and clear the input.
This method is especially effective because ReceiveInput is called prior to the game's activity. For more information, see the ReceiveInput page.
IInputReceivers automatically receive input from the keyboard when they have focus. To prevent this from occurring the TakingInput property can be set to false:
The Cursor class represents the moving cursor (on desktop) or the touch screen (on touch screens). The Cursor class is similar to the Mouse class in its interface, but provides a few additional features:
The Cursor is a more abstract class supporting a variety of input sources such as Mouse, Xbox360Gamepad, and TouchScreen
The Cursor works very well with the Window class and IWindow interface. The cursor is automatically used with Gum and FlatRedBall.Forms objects
We recommend using the Cursor class unless you specifically need to inspect the Mouse hardware.
The Cursor can handle both mouse and touch screen input. Many games can use the exact same Cursor class whether written for the mouse or touch screen. Games needing more control over touch screen input can use the TouchScreen class.
The Cursor class can be accessed through the GuiManager's Cursor property as follows:
The Cursor is a general-purpose class for handling cross-platform input. It can represent a mouse, touch screen, or visible cursor controlled by the Xbox 360 Gamepad.
Property
Mouse
Touch Screen
PrimaryPush
The user just pressed the left mouse button down (was not down last frame)
The user just touched the touch screen (was not touched last frame)
PrimaryDown
The user has the left mouse button down
The user is touching the touch screen
PrimaryClick
The user has just released the left mouse button (was down last frame, not down this frame)
The user has just lifted off of the touch screen (was touched last frame, not this frame)
By default the cursor is invisible when moving over a FlatRedBall game. The following code makes the cursor visible when over the game window:
The following code creates a Circle wherever the Cursor is pushed:
The GetRay method can be used to get a Ray representing objects which the Cursor is over. This Ray can be used for complex object picking, and will work even when the Camera is rotated, unlike the WorldXAt and WorldYAt methods.
The following code shows how the GetRay function can be used to get a Ray representing the Cursor's current position and direction of the camera. The following code is implemented in the CustomInitialize and CustomActivity of an otherwise empty screen.
Mouse world coordinates for a rotated Camera by Scott Dancer
The IgnoreInputThisFrame will result in input values being ignored for the remainder of this frame. This can be used if two independent systems rely on cursor input (such as a click) and clicks (or other input) should be ignored for all objects if one responds to it.
IsOn returns whether the calling Cursor is over a given object. This function will not behave properly if the Camera is not viewing down the Z axis (default). If you have a rotated Camera, then you should use IsOn3D. This function does a position check - it does not consider if anything is covering the argument, or if the Cursor is over any other UI component. For more information on checking of the Cursor is over UI (as a test before performing IsOn checks), see the WindowOver page.
The IsOn overload which takes a Layer will check if the Cursor is over the argument Layer in screen coordinates. In other words, this function will behave properly even if the Camera is rotated. This function will simply do a check of the Cursor's screen position against the bounds of the Layer. If a Layer occupies the full screen, then this function will return true.
Every Cursor in FlatRedBall belongs to a specific Camera. Since multiple Cameras can exist at a given time, Cursors must know which Camera to use to convert screen space to world space for collision against game objects including UI.
By default the Cursor which can be accessed through GuiManager.Cursor uses the default Camera which FlatRedBall creates for you (which can be accessed through SpriteManager.Camera).
The Cursor's Camera property can be changed. To do this simply set the Camera property to the desired Camera instance:
The Cursor uses the Camera property internally when performing checks. Methods which use the Camera include:
The Camera property can be changed at any point, and it can be changed multiple times per frame if the Cursor is going to be used to check for whether it is over objects on multiple Cameras.
The CustomUpdate delegate allows for customizing the Cursor's behavior. Specifically this allows setting the Cursor's position and primary/secondary/middle values.
CustomUpdate is used if you would like to use the FRB Cursor class, but would like to provide custom input logic. The most common scenario for this is when using input devices which are not natively supported by FRB. For example, the Cursor could be used with the Wii's Remote hardware (which can be paired with a computer through bluetooth).
If a non-null CustomUpdate delegate is specified then the regular input logic for the Cursor no longer applies. In other words, the Cursor no longer responds to Mouse input if CustomUpdate is used.
The following code shows how to control the cursor with the keyboard.
SecondaryClick determines whether the secondary button (right mouse button on a mouse) was pushed last frame but released this frame.
The SecondaryClick property can be used to detect whether a UI element, such as a Gum GraphicalUiElement, was clicked with the right mouse button.
The ScreenX and ScreenY properties return the X and Y coordinates of the Cursor in pixel coordinates. These values represent the location of the cursor relative to the top-left of the game screen. These values will not be impacted by properties set on the Camera. These values can be used if you are manually handling gestures or if you are converting screen coordinates to world coordinates instead of using the FlatRedBall methods.
The following code uses the Debugger class to display the Cursor's screen coordinates in real time:
The IsOn3D method is a very powerful method that can be used to test if the cursor is over an object. IsOn3D is used by Glue generated code to test if the Cursor is over an Entity if the Entity implements IClickable or IWindow. The IsOn3D method is very powerful and flexible. It considers:
Object position
Camera position
Object orientation
Camera orientation
Camera perspective settings
Layers
It can be used to check if the cursor is over any of the following objects:
Sprite
Text
AxisAlignedCube
Sphere
Any other object implementing IPositionable, IScalable, IRotatable
The following code creates a group of Sprites which turn invisible when the cursor moves over them. Add the following at class scope:
Add the following in Initialize after initializing FlatRedBall:
Add the following to Update:
The IsOn3D method can be used to detect if the Cursor has clicked on an object. For example, the following code shows how to check if the user has clicked on a Sprite:
For more information on PrimaryClick, see the PrimaryClick page.
The IsOn3D method supports Layers as well. For example, assuming mySprite is a valid Sprite and myLayer is valid Layer:
The PrimaryClick property returns whether the Cursor has been clicked this frame. A click is defined as:
PrimaryDown was true last frame and...
PrimaryDown is false this frame
This occurs if the user pushes and releases the left moue button or touches and lifts on the touch screen. If developing games which may use a touch screen, you should consider PrimaryClickNoSlide to differentiate between when the user touches and releases in the same spot vs. when the user touches, slides, then releases.
The cursor can be checked to see if a click occurred in any CustomActivity code. The following code creates a Circle wherever the user clicks:
The PrimaryPushTime property returns the amount of time since the Cursor's PrimaryPush was last set to true. This value will return 0 if the PrimaryPush was just set, or if the Cursor's PrimaryDown is false. Otherwise, this value will be greater than 0. This value can be used to detect how long the mouse button has been pressed or the touch screen touched.
The WorldX property returns the X coordinate of the cursor in world units (impacted by zooming and camera position). WorldX is typically used on 2D games, or 3D games where the Z=0 plane contains the entities. For 3D games, see the .
The following code shows how to move an entity instance with the cursor.
The following code shows how to move an entity instance towards the cursor.
The PrimaryClickNoSlide property returns whether the Cursor has clicked (the primary button was down last frame, not this frame) and if the cursor has not moved more than during the time the button was down. This property is often used on touch screens so that the game can differentiate between when the user intended to touch and release a UI element versus when a slide-release was performed.
The Cursor's TransformationMatrix value provides additional control for transforming the screen's coordinates as reported by the mouse to screen and world coordinates used by the game. This property defaults to the identity matrix and is typically used if your game renders to a RenderTarget which is being scaled up, such as for pixel perfect 2D games.
Typically the TransformationMatrix is only set if you need to scale or offset your cursor for games which use render targets. For example, if a game is rendering to a render target with resolution of 480x360, but is being rendered at 300% zoom with render targets, then the following code would be used to scale down the larger resolution to the 480x360 resolution:
This code is not necessary if you are performing zoom through the FlatRedBall editor, since that automatically handles Cursor position scaling and offset - it is only necessary if you intend to perform additional screen scaling and offsets outside of the built-in code generation.
The FlatRedBall Cursor object uses mouse or touch screen input by default. This default behavior can be changed with the SetControllingGamepad method, which switches a Cursor to be used by an Xbox360GamePad instance. When using an Xbox360GamePad for cursor control, the following input is applied:
Cursor position is controlled by the left analog stick and d-pad. Position is kept inside of the screen automatically.
The primary action (usually left mouse button) is controlled by the A button
The secondary action (usually the right mouse button) is controlled by the X button
Scrolling is controlled by the right analog stick’s Y (vertical) position
When using an Xbox360GamePad, the native (Windows) cursor will not move in response to gamepad controls, so a visual representation must be manually added.
The following code assumes a Circle has been added to the current Screen:
WorldPosition returns a Vector2 of the cursor's world position (as opposed to screen position). WorldPosition can be used to place objects or perform manual detection of whether the cursor is over an object.
The following code moves an object according to the cursor's position. Note that the ToVector3 extension method is used to convert a Vector2 to a Vector3
The WindowPushed property returns the IWindow that the Cursor was over when a push last occurred. This property will remain valid while the cursor is down, and will continue to remain valid the frame when the cursor is clicked (released). After the frame where a click has occurred, the property is returned to null until the next push. WindowPushed is often used to push+drag off of a UI element.
The following code example shows how to create Circle and AxisAlignedRectangle instances by push+dragging off of two IWindows. These can be Glue entities implementing IWindow, Gum components, or hand-written IWindow-implementing objects. The following code assumes that the screen contains two IWindow-implementing objects:
RectangleButton
CircleButton
Note that this code creates circles and rectangles, but does not add them to any list. In a real game these shapes would need to be added to some list (probably a list created in Glue for the screen) so that they would get properly disposed when the screen is destroyed. This additional code has been omitted for this sample.
The WorldXAt and WorldYAt methods are useful for finding the position of the Cursor at a given Z value. These methods should generally be used only when dealing with an unrotated . For more information on limitations see below. If you are dealing with a (the default) then you can use a Z value of 0 in the WorldXAt and WorldYAt functions.
The following code creates a which moves with the Cursor.
Add the following using statements:
Add the following at class scope:
Add the following to Initialize after initializing FlatRedBall:
Add the following to Update:
The WorldXAt and WorldYAt methods can also be passed Cameras and Layers if the default is not being used. Most commonly when working with HUD in Glue, you may add the HUD element to a 2D Layer, and this 2D Layer may have a settings that differ from your default Camera. In this case, you should use these available overrides. Specifically, if you are working in an Entity, you can use the following:
The WorldXAt and WorldYAt methods can be combined with Sprites and Layers to create a custom cursor. The following code shows how to create a custom cursor using the redball.bmp graphic. This code assumes a 2D coordinate system. You will need to adjust the Sprite size appropriately if using 3D coordinates instead:
Add the following at class scope:
Add the following to your game or Screen's Initialize/CustomInitialize:
Add the following to your game or Screen's Update/CustomActivity:
The XForUI and YForUI members provide a coordinate system that can be used to interact with the default FlatRedBall GUI. There are a few things to keep in mind with the UI:
The values reported by XForUI and YForUI are rarely needed. Most interaction with the default FRB UI can be done through events and properties.
The default FlatRedBall UI is not intended to be used in final games. It is not cross-platform, not skinnable, and lacks flexibility in areas that a full game may need. Instead, we recommend using and creating a custom UI.
The FlatRedBall UI was written in the very early days of FlatRedBall; therefore, the interface is not as clear as we would like to see it. Due to its rare use in shipped games and the amount of legacy code in the FRBDK, the interface has gone mostly unchanged for a long time.
The following code shows how to create a and have it move with the Cursor: Add the following using statement:
Add the following at class scope:
Add the following in Initialize after initializing FlatRedBall:
Add the following to Update:
The XForUI and YForUI properties return a coordinate system which is centered at the center of the screen with positive Y pointing up. The GUI coordinate system is centered at the top left with positive Y pointing down. The modifications using GuiManager.XEdge and YEdge are necessary to convert the Cursor's GUI coordinates to the FRB Gui's coordinate system. This confusing requirement is a result of very old FlatRedBall code which cannot be changed for legacy reasons.
The GuiManager is a static object responsible for common UI element management as well as some UI creation. There are two categories of UI elements:
Default FlatRedBall GUI objects which are usually used for debugging and tools (these are used in all FRB graphical tools like the SpriteEditor, PolygonEditor, etc)
Entities inheriting from
For a Default FlatRedBall UI element to be visible and functional it must either belong to the GuiManager or another UI element. Entities are drawn by the engine like normal Entities - the GuiManager simply handles the cursor-based activity (like clicks).
When a is created and added to the GuiManager, it can be added to one of three internal lists. These lists define the three categories. These categories are:
Regular
Dominant
Perishable
The following sections define the characteristics of each category.
Adding a by calling its constructor then passing it to the GuiManager's AddWindow method will add the as a regular . Regular remain in memory until they are removed using the GuiManager's RemoveWindow method. Making a regular invisible will not remove it from the GuiManager.
Dominant are which consume interaction while they are visible. In other words, if a dominant is present, no other will receive input. Any can be made dominant through the method. Dominant are often used when the users attention is required on a particular . Examples include a asking if the program should really exit after clicking the close button or a for selecting a file to load in an application. Dominant can be removed by either calling the GuiManager's RemoveWindow method or by setting the dominant Visible property to false. Setting the Visible property to false will result in the GuiManager automatically removing the if is set to true.
The WorldXAt and WorldYAt methods are useful for finding the absolute world position of the Cursor at a given Z value. These methods should generally be used only when dealing with an unrotated . For more information on limitations see below. If you are dealing with a (the default) then you can use a Z value of 0 in the WorldXAt and WorldYAt functions.
The following code creates a which moves with the Cursor.
Add the following using statements:
Add the following at class scope:
Add the following to Initialize after initializing FlatRedBall:
Add the following to Update:
The WorldXAt and WorldYAt methods can also be passed Cameras and Layers if the default is not being used. Most commonly when working with HUD in Glue, you may add the HUD element to a 2D Layer, and this 2D Layer may have a settings that differ from your default Camera. In this case, you should use these available overrides. Specifically, if you are working in an Entity, you can use the following:
The WorldXAt and WorldYAt methods can be combined with Sprites and Layers to create a custom cursor. The following code shows how to create a custom cursor using the redball.bmp graphic. This code assumes a 2D coordinate system. You will need to adjust the Sprite size appropriately if using 3D coordinates instead:
Add the following at class scope:
Add the following to your game or Screen's Initialize/CustomInitialize:
Add the following to your game or Screen's Update/CustomActivity:
The WorldXAt and WorldYAt methods may giave unexpected results if the Camera is rotated. These methods should only be used when the Camera is facing down the Z axis (default orientation). For a rotated , the method should be used. If interested in object picking, you can use the or the or interfaces for Entities in Glue.
Perishable are which will automatically be removed by the GuiManager when the user clicks and the Cursor is not over the perishable . Perishable Windows are most commonly used for Windows which have a short life span. Examples include the drop-down ListBoxes that appear when clicking the on or menus appearing when right-clicking on an object. If the user clicks on a perishable , the will not automatically remove itself. The removal is usually handled in one of the events in this case.
Did this article leave any questions unanswered? Post any question in our for a rapid response.
The WorldXAt and WorldYAt methods may giave unexpected results if the Camera is rotated. These methods should only be used when the Camera is facing down the Z axis (default orientation). For a rotated , the method should be used. If interested in object picking, you can use the or the or interfaces for Entities in Glue.
The BringsClickedWindowsToFront property controls whether the GuiManager brings any clicked Window to the front of its internal list. The internal GuiManager list does not control rendering, just the order that clicks are tested. Windows at the front of the list are prioritized regarding Cursor input. This is desired behavior if the GuiManager controls the rendering order of these windows (as is the case with the default FRB GUI found in the FRB tools) but it is not desirable behavior if the GuiManager does not control the rendering order (as is the case for Glue Entities implementing IWindow.
In summary:
If using default FlatRedBall Gui for a tool or debugging, leave BringsClickedWindowsToFront to its default BringsClickedWindowsToFront value.
If using Glue IWindow Entities, you should set BringsClickedWindowsToFront to false and control ordering through the BringToFront method)
Dominant Windows are IWindows which have higher priority over regular IWindows. If the GuiManager contains any dominant IWindows then any non-dominant IWindows will not receive any input from the Cursor. Dominant IWindows are a good way to prevent the user from interacting with regular (non-dominant) IWindows when UI such as a pause screen or exit confirmation screen is visible. Multiple IWindows can be marked as dominant windows using AddDominantWindow. AddDominantWindow can be called on a regular IWindow to convert it to a dominant window. Dominant windows can be converted back to non-dominant windows using the MakeRegularWindow method.
This example shows how to use AddDominantWindow to change whether a popup is the dominant window in response to UI events. This example uses a Gum screen with two objects - UserControlInstance and PopupInstance as shown in the following treeview:
Visually, the layout is shown in the following image:
The hiding and showing of the popup is controlled as shown in the following code:
The IClickable interface requires implementation to specify a HasCursorOver method, which is typically used for clicking or grabbing an object. Since the IClickable interface works with the Cursor object, it can be used with a physical mouse, touch screen, or any other input device which maps to the Cursor object. Although GUI elements are the most common type of IClickables, other objects such as clickable elements can implement IClickable. Examples include board pieces in a match-three game or units in a real time strategy game. IClickable is a base interface for . IWindow extends IClickable by adding input-based events.
Glue entities can be marked as IClickable, which results in Glue generating IClickable-implementing code. For more information, see the page.
The MakeRegularWindow function can be used to convert an IWindow which has been made a dominant window through no longer act dominant and make it instead a regular window.
The GamePadsForUiControl list specifies which game pads can be used to control FlatRedBall.Forms controls. By default this list is empty, but it can be populated with gamepads to enable navigation and selection of UI with the DPad, AnalogSticks, and Buttons. For more information see the page.
The RemoveWindow method can be used to remove a Window from the GuiManager. The pattern for addition and removal for the GuiManager matches the other managers. In other words, you call AddWindow to add a Window to the GuiManager, and RemoveWindow to remove it.
Windows are added to the GuiManager through the AddWindow method:
Windows can be removed from the GuiManager through the RemoveWindow method:
The SortZAndLayerBased function is a function which can be called to sort the GuiManager's by their Z value and Layer membership. Layers take first priority, then IWindows which are on the same Layer will be sorted by their Z. The higher the Z value of an IWindow, or the further in-front a Layer is, the later in the list the IWindow will appear.
The following can be called to update the order:
The GuiManager keeps track of the order of IWindows that it is storing. For default-drawn Windows, this ordering is reflected in the draw order. However, for Entities, the ordering of the Entities in the GuiManager may not match the ordering that the Entities are drawn. The order of IWindow Entities only matters if Entities overlap. In this case, you will need to manually control the order of Entities by using BringToFront. The GuiManager will also automatically bring clicked windows to the front. This is desirable when using default-drawn Windows, but usually not desirable when working with Entities. Therefore, if you are using IWindow Entities in you will want to set the property to false in your game's initialization.
If you have IWindow Entities which are overlapping, you will want to control the order of your Entities using the BringToFront method. For example, consider an Entity called ButtonFrame which contains three Buttons. To bring the three Buttons to the front so that they are clickable, you might want to add the following code:
The Windows IEnumerable contains all regular (non-dominant) windows in the GuiManager. By default IWindow-implementing Entities created in Glue will add themselves to the GuiManager and appear in this list. The order of IWindows in this list determines the order in which the Cursor performs UI checks.
By default, FlatRedBall.Forms objects created through Gum screens add themselves to the GuiManager and appear in this list. Note that the GuiManager does not hold a direct reference to the FlatRedBall.Forms objects, but rather the Visual for each of the forms. Furthermore, only the top-level objects are added to the GuiManager. Therefore, if a StackLayout instance contains multiple buttons, only the StackLayout's Visual will appear in the Window list. For example, the following image shows a Gum screen with four buttons. Since all of the buttons are not contained by any other Forms objects, all four will appear in the Windows list.
The ReceiveInput function is called every frame by the FlatRedBall Engine on the current IInputReceiver. This function can be used by objects implementing the IIputReceiver interface to handle input and to clear it after processing it.
ReceiveInput is ultimately called when the Keyboard's state is updated inside the FlatRedBall Engine. This means that this method is called *before* any Screen or Entity activity if using Glue. If not using Glue, and if all of your custom code is written *after* FlatRedBallServices.Update (which is called in your Game class) then the ReceiveInput will also be called before any of your custom code. This is useful because it allows the current IInputReceiver to receive and clear input before any other custom game logic is performed. In other words, no game code will need to be modified to prevent double-input from happening if the IInputReceiver calls the Keyboard's Clear function after processing input.
The Enabled property determines whether a UI element will react to input events, such as being clicked. IWindow instances which have their Enabled value set to false will be skipped over by the Cursor when performing UI checks; these instances will never be assigned to the Cursor.WindowOver property.