Myra - UI Library for the MonoGame

Hi Roman…

I tried your suggestion and several variations on it, including testing for a left-mouse button. However, I could not seem to prevent the Update\Draw Events from firing when selecting a menu option.

If you look at the extracted image from my map-board shown below you sill see that the master menu option (TEST FUNCTIONS & CLEAR SELECTED HEXAGONS) have both been selected. Under the word, HEXAGONS, you will note that the hexagon underneath the displayed menu options is highlighted in yellow\orange. This is because when selecting from the menu, the mouse point selected on the actual map-board is still being processed by the selected-hexagon routines.

This is what I am trying to avoid so that when the menu options are selected only the processing for the menu is being run…

Thank you again for all your help… :slight_smile:

Steve Naidamast

Hi Steve!
Well, my suggestion wasnt about preventing Update/Draw Events, but about changing its handlers logic so if mouse pointer is over Myra menu than the event processing is interrupted by calling return.

Frankly I still dont understand what are those Update/Draw Events. As MonoGame framework doesnt have it, but it has Game.Update and Game.Draw methods. Which are called every game tick.

Hi Roman…

Thank you for your reply…

Just to clarify, I learned events as being any routine that is called by a timer or a user action. Since MonoGame’s Update and Draw routines are fired with every “tick” of an internal clock, to me they would be considered timer-events.

However, we are simply talking about semantics here. Nonetheless, it appears that we have no control over the firing of any of the MonoGame events\methods as they are designed to process on their own making them the cyclic aspect of the MonoGame processing infrastructure. I believe this the way all such game engines process their major level tasks.

Simply forcing a return within either the Update and\or Draw events\methods will not do anything to prevent the testing for a mouse-click within these events\methods. This is due to the following code I implemented in the Update routine…

            if (coMouseState.LeftButton == Microsoft.Xna.Framework.Input.ButtonState.Pressed)
            {
                Find_MouseSelectedHex(ref loHexTile);

                coSelectedHexTile = new HexMapEngine.Structures.HexTile();   
                coSelectedHexTile = loHexTile;

                coSelectedHexTile.HEX_TILE_SELECTED = true;
            }

In this case, the state of the left mouse-button is being maintained until it changes through another user action (ie: release). As a result, no matter whether the Myra component event fires first or the Update\Draw events fire, the state of the mouse-button is being maintained and will eventually be processed for at least one cycle.

Since your menu-component allows for a user click to be passed through to the underlying screen, my code above will always process the mouse-button state as the last one created.

The optimum solution is to find a way in which a mouse-click on an overlaying menu item is compartmentalized from the rest of the MonoGame infrastructure. However, given the nature of how the Myra events are being processed as secondary in this situation, I am not sure if this is possible.

Is there a way in which the Myra components can be self-contained? In other words, separate them from the MonoGame internal infrastructure so that whatever happens on the Myra components as it regards user-actions have no effect on the underlying screen.

Steve Naidamast

Hi Steve!
Thanks for the clarification. I thought you were talking about some sort of C# events, which caused some confusion.
Well, I still think that you simply need to prevent processing mouse input if the mouse pointer is over Myra menu-component.
To make that first of all add following method:

private bool IsMouseOverGUI()
{
        var isMouseOverGUI = false;
	foreach(var widget in _desktop.Widgets)
	{
		if (widget.IsMouseOver)
		{
			isMouseOverGUI = true;
                        break;
		}
	}

        return isMouseOverGUI;
}

Where _desktop is Myra’s Desktop (it is named _host in some samples).
Then add call to the above method to your code:

	if (coMouseState.LeftButton == Microsoft.Xna.Framework.Input.ButtonState.Pressed && !IsMouseOverGUI())
	{
		Find_MouseSelectedHex(ref loHexTile);
		coSelectedHexTile = new HexMapEngine.Structures.HexTile();
		coSelectedHexTile = loHexTile;
		coSelectedHexTile.HEX_TILE_SELECTED = true;
	}

As for separating Myra’s input processing from the rest of MonoGame infrastructure. Well, current Myra versions doesnt allow that. In future prob I could hack into Mouse object and erase mouse’s state if mouse click had been processed by Myra. Though I am unsure if it’s correct approach for such problem.It definitely requires more research.

Myra 0.7.2 is out!
UI Form Serialization format had been changed to the human readable xml.
Now Myra UI Editor could be used in conjunction with a text editor(click on the below animated gif to see it):

Also I’ve wrote wiki entry describing Myra UI Form Serialization:

Link to the latest binary release distribution: https://github.com/rds1983/Myra/releases/download/0.7.2.142/Myra.0.7.2.142.zip

Myra Project Site: https://github.com/rds1983/Myra

2 Likes

Hi Roman…

I have been trying multiple variations on your recommended coding suggestion with no success. I believe I have found the reasons why, which has to do with the way your internal object structures for the menu reflect their information.

The top-most structure that is used as the container for your menu is the Desktop structure. As my code shows below, the attributes and properties of this structure are fairly generic…

>>>
?coMyraUIDesktop
{Myra.Graphics2D.UI.Desktop}
Bounds: 0 0 0 0
ContextMenu: null
FocusedWidget: null
KeyboardState: {Microsoft.Xna.Framework.Input.KeyboardState}
ModalWidget: null
MousePosition: 0 0
MouseState: {Microsoft.Xna.Framework.Input.MouseState}
MouseWheel: 0
Widgets: Count = 1
_widgets: Count = 1
<<<

The next structure, which actually defines the container for the menu is the Grid structure as shown below…

>>> (At generation of menu components)
?coMyraUIDesktop.Widgets[0]
{Myra.Graphics2D.UI.Grid}
AbsoluteBounds: 0 0 0 0
AbsoluteLocation: 0 0
AcceptsTab: false
Background: null
Border: null
Bounds: 0 0 0 0
CanFocus: false
ChildCount: 1
Children: Count = 1
ClipToBounds: false
ColumnSpacing: 1
ColumnsProportions: Count = 1
Desktop: {Myra.Graphics2D.UI.Desktop}
DisabledBackground: null
DisabledBorder: null
DisabledOverBackground: null
DrawLines: false
DrawLinesColor: 255 255 255 255
Enabled: true
GridPositionX: 0
GridPositionY: 0
GridSpanX: 1
GridSpanY: 1
HeightHint: null
HorizontalAlignment: Stretch
Id: null
IsFocused: false
IsMouseOver: false
LayoutBounds: 0 0 0 0
Location: 0 0
MouseButtonsDown: null
OverBackground: null
OverBorder: null
PaddingBottom: 0
PaddingHeight: 0
PaddingLeft: 0
PaddingRight: 0
PaddingTop: 0
PaddingWidth: 0
Parent: null
RenderBounds: 0 0 0 0
RowSpacing: 1
RowsProportions: Count = 1
Size: 0 0
Tag: null
TotalColumnsPart: null
TotalRowsPart: null
VerticalAlignment: Stretch
Visible: true
Widgets: Count = 1
WidthHint: null
XHint: 0
YHint: 0
_widgets: Count = 1
<<<

>>> (at runtime when menu is displayed)
?coMyraUIDesktop.Widgets[0]
{Myra.Graphics2D.UI.Grid}
AbsoluteBounds: 0 0 1200 1000
AbsoluteLocation: 0 0
AcceptsTab: false
Background: null
Border: null
Bounds: 0 0 1200 1000
CanFocus: false
ChildCount: 1
Children: Count = 1
ClipToBounds: false
ColumnSpacing: 1
ColumnsProportions: Count = 1
Desktop: {Myra.Graphics2D.UI.Desktop}
DisabledBackground: null
DisabledBorder: null
DisabledOverBackground: null
DrawLines: false
DrawLinesColor: 255 255 255 255
Enabled: true
GridPositionX: 0
GridPositionY: 0
GridSpanX: 1
GridSpanY: 1
HeightHint: null
HorizontalAlignment: Stretch
Id: null
IsFocused: false
IsMouseOver: true
LayoutBounds: 0 0 1200 1000
Location: 0 0
MouseButtonsDown: null
OverBackground: null
OverBorder: null
PaddingBottom: 0
PaddingHeight: 0
PaddingLeft: 0
PaddingRight: 0
PaddingTop: 0
PaddingWidth: 0
Parent: null
RenderBounds: 0 0 1200 1000
RowSpacing: 1
RowsProportions: Count = 1
Size: 1200 1000
Tag: null
TotalColumnsPart: null
TotalRowsPart: null
VerticalAlignment: Stretch
Visible: true
Widgets: Count = 1
WidthHint: null
XHint: 0
YHint: 0
_widgets: Count = 1
<<<

If you notice the RenderBounds between the when the grid structure is created and when it is finally displayed, you will note that the dimensions change from “0,0,0,0” to that of “0,0,1200,1000”. This appears to mean that the display grid will cover a much larger area of the screen than the actual displayed components take. This also appears to mean that the capturing of mouse-over events can be trapped at the much larger grid-level than should be. I have been able to test this by selecting a point on the displayed screen outside the bounds of the actually displayed menu and yet the function that validates for a mouse-over test for the menu returns “true” when it should be false.

In addition, I have not been able to easily drill down further into the menu’s internal structure to be able to test the actual, individual menu component structures for similar properties. And yet, even if I can, these similar properties appear to be unaffected by any mouse-over events.

For example the structure for the actual “Horizontal Menu” has the following attributes and properties…

>>>
?coMyraUIDesktop.Widgets[0].FindWidgetById(“MyraMasterMenu”)
{Myra.Graphics2D.UI.HorizontalMenu}
AbsoluteBounds: 0 0 0 0
AbsoluteLocation: 0 0
AcceptsTab: false
Background: {button {X:309 Y:162 Width:12 Height:20}}
Border: null
Bounds: 0 0 0 0
CanFocus: false
ChildCount: 1
Children: Count = 1
ClipToBounds: false
ColumnSpacing: 0
ColumnsProportions: Count = 1
Desktop: {Myra.Graphics2D.UI.Desktop}
DisabledBackground: null
DisabledBorder: null
DisabledOverBackground: null
DrawLines: false
DrawLinesColor: 255 255 255 255
Enabled: true
GridPositionX: 0
GridPositionY: 0
GridSpanX: 1
GridSpanY: 1
HeightHint: null
HorizontalAlignment: Stretch
Id: “MyraMasterMenu”
IsFocused: false
IsMouseOver: false
Items: Count = 1
LayoutBounds: 0 0 0 0
Location: 0 0
MenuItemStyle: {Myra.Graphics2D.UI.Styles.MenuItemStyle}
MouseButtonsDown: null
OpenMenuItem: null
Orientation: Horizontal
OverBackground: null
OverBorder: null
PaddingBottom: 0
PaddingHeight: 0
PaddingLeft: 0
PaddingRight: 0
PaddingTop: 0
PaddingWidth: 0
Parent: {Myra.Graphics2D.UI.Grid}
RenderBounds: 0 0 0 0
RowSpacing: 0
RowsProportions: Count = 0
SeparatorStyle: {Myra.Graphics2D.UI.Styles.MenuSeparatorStyle}
Size: 0 0
Tag: null
TotalColumnsPart: null
TotalRowsPart: null
VerticalAlignment: Stretch
Visible: true
Widgets: Count = 1
WidthHint: 1200
XHint: 0
YHint: 0
_widgets: Count = 1
<<<

If you notice, the “IsMouseOver” boolean property is “false” for the “Horizontal Menu” structure even if one were to place the mouse directly over the main menu strip that is stretched across the entire top part of the screen.

If I have done my analysis correctly, these disparities are why your suggested code is not yielding the expected results.

This would be fine if such interfaces were to be defined on completely separate screens as is often shown for beginning game tutorials for 2D games. However, I am attempting to develop a rather complex simulation and to date the Myra UI is the top interface library I can find for MonoGame. And I have researched such libraries quite extensively.

I am hoping that with the information have provided you can provide a resolution to this issue as I really do not want to start looking for another interface library since I feel that the Myra UI has great potential for the MonoGame Development Community… :relaxed:

Steve Naidamast

Hi Steve,
So the Grid stretches over the whole screen, that is why it always returns IsMouseOver=true and my suggestion fails.
Well, in that case IsMouseGUI method should look like following:

private bool IsMouseOverGUI()
{
  if (_horizontalMenu.IsMouseOver)
  {
    return true;
  }

  if (_desktop.ContextMenu != null && _desktop.ContextMenu.IsMouseOver)
  {
    return true;
  }

  return false;
}

I realize that above code is not obvious, therefore I’ve created new ticket related to the discussed issue: #40

Thanks for bringing it!

Hi Roman…

I just sent you an email with the notes I posted yesterday and then noticed that you had responded in the forums here.

I will give your suggestions a try in a little while.

Thank you again for all your wonderful assistance in this… :relaxed:

Hi Roman…

I was just able to implement your newly recommended code for the testing of a mouse over in my menu system.

It appears to be working now as needed.

I have noticed only what appears to be a minor “bug” but that appears to be in my own hex highlight clearing code and has nothing to do with the menu system.

Thank you so much for your excellent help… :slight_smile:

1 Like

Myra 0.7.5 is out!
Now it is possible to apply a custom stylesheet in the UI Editor(click on the below animated gif to see it action):

Also issue #40 had been fixed, @SNaidamast.

Link to the latest binary release(it contains ui and stylesheets demonstrated at the above gif): https://github.com/rds1983/Myra/releases/download/0.7.5.146/Myra.0.7.5.146.zip

NuGet had been updated as well.

1 Like

Myra 0.7.6 is out.
This version contains refactoring and bug fixes based on the feedback I got.
Right now, functionality wise Myra is close to what I’ve planned originally.
Though a few essential features will be added eventually(like support of the mobiles and maybe version for Xenko engine).
For now I am going to concentrate on better documentation & samples.

Link to the binary distribution: https://github.com/rds1983/Myra/releases/download/0.7.6.147/Myra.0.7.6.147.zip
NuGet had been updated as well.

Myra Project Site: https://github.com/rds1983/Myra

1 Like

Myra 0.8.0 is out.
The new version has following changes:

  1. Support for the .Net Core. Now Myra can be used in conjunction with the MonoGame.Framework.DesktopGL.Core.
  2. Revamp of the Myra Project Site. Updated screenshots, added NuGet/AppVeyor badges and restructured the text.
  3. Fixes for #47 and #48.
  4. Refactoring of the input system events.

Link to the new binary release: https://github.com/rds1983/Myra/releases/download/0.8.0.154/Myra.0.8.0.154.zip

NuGet had been updated too.

3 Likes

Hi Roman…

I just tried out your latest version of your Myra-UI.

It seems that the Myra Editor keeps on crashing\closing no matter what option I select.

I went back to the version I am currently using and tested the editor out and everything worked fine doing the same tasks I attempted with the latest version.

If I may suggest; you should consider how you initiate a new project. In the version of Myra I am currently using, you left-double click on the project pane, which creates a base grid for the project and then select “New” from the drop-down menu in order to initialize a new project. At least that is the way I have been doing it.

From here you can begin building your interface by adding the individual components.

If you do the same exact set of tasks in your recent version of Myra, no base grid is created in the project pane. And if you attempt to add any available component, the application simply closes out.

My recommendation would be to have an option in the drop-down menu system that provides for “New Project”, will do all of the project initializations for you. This will be much more intuitive…

I am looking forward to upgrading my Myra SDK as soon as these apparent issues are fixed…

:relaxed:

Hi Steve,
There is major difference beetween new and old Myras - new Myra has many different containers: Grid, Panel, ScrollPane, SplitPane, Window, Dialog. Therefore I removed creation of the Grid as root container as a user may want to have, say, Dialog as root container.
Now root container is added to the project same way as any other widget:

Though now I see that adding root container isn’t intuitive. So I’ll add some kind of New Project Wizard that pop ups after pressing “New” button where one could select the root container type.
I’ve created corresponding issue: https://github.com/rds1983/Myra/issues/51

Also as you can see from that animaged gif, I couldn’t reproduce crash as well.
Though I found another crash related to the “Reset Stylesheet” menu button.
Anyway in the next version UI Editor wouldn’t quietly close but show MessageBox with error text.
Again issue had been created: https://github.com/rds1983/Myra/issues/52

Thanks for the feedback!

Roman…

I have figured out the use of your new Myra Editor but every time I try to save the project, the editor simply closes out.

In addition, I cannot export any generated C# code. What I have been able to export is simply a directory path…

:disappointed_relieved:

Myra 0.8.1 is out.
It contains multiple fixes and refactorings. Most notable update is addition of the new widget - RadioButton:

@SNaidamast
Another update is that now if it crashes, MessageBox with error text should show like this:

So I’d recommend trying out new version.
Which binary release is located here:
https://github.com/rds1983/Myra/releases/download/0.8.1.156/Myra.0.8.1.155.zip
https://github.com/rds1983/Myra/releases/download/0.8.1.156/Myra.0.8.1.156.zip
https://github.com/rds1983/Myra/releases/download/0.8.1.156/Myra.0.8.1.159.zip

NuGet had been updated too.

Perhaps depends on the operating system.
The editor well works at Win8.
On Win7 differently: on one computer it is closed in attempt of preservation or export, on another - it is not started.
I did preparation on Win8, then transferred and finished on Win7 manually, by code. It is not difficult to write everything the code.

Tried the new version on Win7:


System.IO.IOException: Устройство не готово.

в System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
в System.IO.DriveInfo.get_VolumeLabel()
в Myra.Graphics2D.UI.File.FileDialog…ctor(FileDialogMode mode)
в Myra.UIEditor.Studio.Save(Boolean setFileName)
в Myra.Graphics2D.UI.ListItem.FireSelected()
в Myra.Graphics2D.UI.Menu.ButtonOnClick(Object sender, EventArgs eventArgs)
в Myra.Graphics2D.UI.ButtonBase`1.OnTouchUp()
в Myra.Graphics2D.UI.Desktop.HandleButton(ButtonState buttonState, ButtonState lastState, MouseButtons buttons)
в Myra.Graphics2D.UI.Desktop.UpdateInput()
в Myra.Graphics2D.UI.Desktop.Render()
в Myra.UIEditor.Studio.Draw(GameTime gameTime)
в Microsoft.Xna.Framework.Game.DoDraw(GameTime gameTime)
в Microsoft.Xna.Framework.Game.Tick()
в Microsoft.Xna.Framework.SdlGamePlatform.RunLoop()
в Microsoft.Xna.Framework.Game.Run(GameRunBehavior runBehavior)
в Myra.UIEditor.Program.Main()


I’ve win7 and it works ok.
Anyway, I’ve enclosed that DriveInfo.VolumeLabel section(which was mentioned in the exception stack trace) with try/catch and build the new version.
Could you try it?

Here’s link: https://github.com/rds1983/Myra/releases/download/0.8.1.156/Myra.0.8.1.156.zip
https://github.com/rds1983/Myra/releases/download/0.8.1.156/Myra.0.8.1.159.zip

Now export works. The .xml file is normal.
Save works too, but files of .cs are not completed:
“Resources\ExportCSDesigner.cstemplate;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8”
There is no code of widgets in the text.

Thank you very much for the help.
I’ve managed to reproduce issue with export on my local env.
Corresponding ticket had been created: https://github.com/rds1983/Myra/issues/53

It would be fixed in the next version.