ronenness / geonbit.ui Goto Github PK
View Code? Open in Web Editor NEWUI system for MonoGame projects.
License: MIT License
UI system for MonoGame projects.
License: MIT License
It looks as if the assembly is 32 bit and from a quick search around it looks like that means it can't be loaded into a 64 bit program.
Everything works fine if I build the assembly myself as x64, so I'm guessing the fix is including x86 and x64 binaries in the NuGet package? I don't really know much about NuGet, so that's the best I can do, sorry!
Here's the detail from the exception:
System.BadImageFormatException was unhandled
FileName=GeonBit.UI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
FusionLog==== Pre-bind state information ===
LOG: DisplayName = GeonBit.UI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
(Fully-specified)
LOG: Appbase = file:///E:/Projects/Game1/bin/DesktopGL/x86/Debug/
LOG: Initial PrivatePath = NULL
Calling assembly : Game1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null.
===
LOG: This bind starts in default load context.
LOG: No application configuration file found.
LOG: Using host configuration file:
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework64\v4.0.30319\config\machine.config.
LOG: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind).
LOG: Attempting download of new URL file:///E:/Projects/Game1/bin/DesktopGL/x86/Debug/GeonBit.UI.DLL.
ERR: Failed to complete setup of assembly (hr = 0x8007000b). Probing terminated.
P.S. this library is really nice so far.
Hey, i just installed GeonBit today through Nugget. Everything went smoothly and i had your examples up and running with no noticable issues.
After trying to use a custom theme with another font it became clear that the font rendering was fuzzy no matter the size or the font description settings (tried also multiple different fonts). As you can see on the image bellow the same font rendered through spriteBatch (the one on top) appears correctly, while the text of the paragraph, header and button attached to the panel seem to have the wrong scale - thus appearing blurry. The scale setting on the style files of all the visible widgets is 1.0 . Is there a hidden global scale property somewhere?
I thought this might be fixed in the recent release but it wasn't so reporting it now, I'm pretty sure it showed up in 3.0.2 though.
As you can see, the selection for the item in the list is too wide. The same issue is showing up in dropdown as they use the same select list entity.
The only thing I can think off the top of my head why this might be showing up is I do scale the UI globally by a factor of .5, but that's purely a guess.
Two dll problems, one with MonoGame.Framework in DataTypes references and one NVorbis in GeonBit.UI references. Window.Position is throwing an error it says that GameWindow does not contain a definition for Position. Game.Exit() is obsolete and this platform policy does not allow programmatically closing.
Hello again,
For my project UI scaling is not some thing I really desire. Is there a way built in to disable the scaling of the UI entities upon window resizes?
Hello,
I've been experimenting with Panels Opacity and this is what happens:
With full Opacity:
Panel panel= new Panel(new Vector2(500, 200)); panel.Opacity = 255;
With no Opacity:
Panel panel= new Panel(new Vector2(500, 200)); panel.Opacity = 0;
Shouldn't the panel be invisible?
Also this comes with another wierd problem:
The first screenshot is without any Panel displayed and the second is with panel.Opacity = 125;
, notice how the colors are now different between the triangles and the background. The only thing different is that the background is Monogame's clear color ( GraphicsDevice.Clear(new Color(199, 148, 100, 0));
) and the triangles are textures.
This is an enchancement/feature request. I know you're busy so this is kind of just when you can get to it (if you agree!) or I could do a PR sometime and you could look at that.
It'd be handy if entities could have these extra sizing options:
FitParent
and it would be expanded to Parent.Size.Y-button.Size.Y
. If there's more than one entity with this option set, they'll share the remaining space, so 2 entities get 50% each, 3 get ~33% each, etc.. I was also thinking that this could probably replace Vector2.Zero
(i.e. parent size), since this is the more intuitive outcome when you're trying to fit to parent.Also, I was thinking the rule with these could be that they can't be stacked both ways, e.g. a panel with FitChildren
containing a panel with FitParent
. If they're stacked, the child with FitParent
sizing gets set to default. Either that or you could just throw an exception (which might be a better idea, then you don't have the annoying instance where the layout just isn't looking right but you can't figure out why).
Lastly, because there would be more sizing options, it would probably be a good idea to make a static class, e.g. something like:
public static class Sizing {
public static float Default = -1;
public static float FitToParent = 0;
public static float FitToChildren = -2;
}
So then you can do
new Panel(new Vector2(Sizing.FitToParent, Sizing.FitToChildren), ...)
and it's explicit what sizing method you're using, and you can add more in the future just by expanding them into the negatives (-3, -4, etc.).
There's quite a lot in this issue, it could probably be split up, but I just wanted to kind of gauge what you thought about it and get some feedback!
Hey, thanks for your work on this nice library, it does pretty much everything I needed a GUI to do for my next project.
I was wondering if a table component could be added. Working similarly to a SelectList but with support for columns. I don't really need each cell to be it's own individual entity, rows would be perfectly fine (and, i assume, much easier to implement).
If not, I might have a go at it, but there's a chance it will be terrible, terrible hacky code.
Hello everybody,
the past week I worked on gamepad support for GeonBit.UI. If someone is interested in taking a look then please do: https://github.com/sqrMin1/GeonBit.UI/tree/gamepad
Included is a sample project (GeonBit.UI.Gamepad). You should start it first to get a clue how it works (of course with your Xbox 360 controller plugged in).
Everything should be self-explaining, because I described everything in the sample and in the code.
I didn't make a pull request so far, because I used MonoGame 3.6 Windows DX (through NuGet) and the main GeonBit.UI-repo is using MonoGame 3.5 DesktopGL. But in case you are interested in having this in the main repo @RonenNess then you could create a seperate branch for it (eg. gamepad36) and I will make a PR on this then.
I hope this is helpful.
Cheers,
Marcel
By the way: GeonBit.UI is very awesome! I had a lot of fun using it and I will use it in my main project. Thanks for your hard work!
There was an older version of Monogame that was referenced in DataTypes. When using the newer version it conflicts. Error in VS2017 says that Monogame.Framework.dll could not load something im not sure exactly. But opening up the DataTypes sln and fixing the reference then rebuilding and re referencing DataTypes.dll in your pipeline and project fixed it for me.
I think it'd be a good idea to have a SelectList<T>
class which SelectList
inherits from (so it'd be SelectList : SelectList<string>
, although maybe the naming could be a bit different so there's no confusion).
The SelectList<T>
constructor would take two extra parameters:
itemEntitySize (Vector2)
: the size of the entities the select list will containitemEntityConstructor (Func<T, Entity>)
: a delegate which takes an item and creates an entity to represent that item.Instead of creating Paragraph
objects, itemEntityConstructor
is called for each item in the list.
The existing SelectList
would pass a delegate through of type Func<string, Paragraph>
which would build paragraphs in the same way as they're done now.
I'll put a working proof-of-concept in a comment after this, but I'll give a usage example here.
Example class to be shown in the list:
public class MyClass {
public string Name;
public IconType Icon;
public static Entity EntityConstructor(MyClass instance) {
Panel panel = new Panel(Vector2.Zero);
panel.AddChild(new Icon(instance.Icon, Anchor.AutoInline));
panel.AddChild(new Paragraph(instance.Name, Anchor.AutoInline, new Vector2(0.5f, 0)));
return panel;
}
}
And setting up the list:
SelectList<MyClass> selectList = new SelectList<MyClass>(new Vector2(400, 400),
new Vector2(0, 100), MyClass.EntityConstructor);
MyClass[] items = new [] {
new MyClass { Name = "Myclass1", Icon = IconType.Apple },
new MyClass { Name = "Myclass2", Icon = IconType.Sword },
new MyClass { Name = "Myclass3", Icon = IconType.Feather },
new MyClass { Name = "Myclass4", Icon = IconType.MagicBook },
new MyClass { Name = "Myclass5", Icon = IconType.Map },
new MyClass { Name = "Myclass6", Icon = IconType.OrbBlue },
new MyClass { Name = "Myclass7", Icon = IconType.OrbGreen },
new MyClass { Name = "Myclass8", Icon = IconType.Pistol }
};
selectList.AddRange(items);
UserInterface.AddEntity(selectList);
I'm thinking this could be useful for creating lists with more information in them. If LockSelection
(not implemented in the following mockup) is set, it could be used for a list of items that are interactable themselves (so with buttons, etc.) and could potentially be extended to allow for drag and drop reordering, etc.
I want to create a TextInput as a PasswordInput so when i write a password into this box the characters returns the sign ***** back instead showing the password. Sadly i cannot find anything in the documentation. Is there a workaround for that?
Mouse interaction does not work as expected in Panel
s contained within a Panel
with the VerticalScroll
behavior. The mouse appears to be interpreted as offset by some amount related to the Panel
s distance from the top-left corner of the window.
TopLeft | Auto |
---|---|
![]() |
![]() |
As seen in the "TopLeft" screenshot, the mouse interaction works but is incorrectly offset on the vertical axis. Interaction does not work at all when the panel is centered, as seen in the "Auto" screenshot. The "Option 4" Checkbox
residing outside of the inner Panel
works as expected.
This was tested with a resolution of 1280x720. On sufficiently low resolutions, a centered panel will exhibit behavior similar to that of "TopLeft", probably due to the shorter distance to the top-left window corner.
This issue also affects SelectList
s contained within a Panel
with VerticalScroll
.
Example code:
{
Panel panel = new Panel(new Vector2(400, 400), anchor: Anchor.TopLeft);
panel.PanelOverflowBehavior = PanelOverflowBehavior.VerticalScroll;
panel.Scrollbar.AdjustMaxAutomatically = true;
UserInterface.Active.AddEntity(panel);
Panel inner = new Panel(new Vector2(0, 200));
inner.AddChild(new CheckBox("Option 1"));
inner.AddChild(new CheckBox("Option 2"));
inner.AddChild(new CheckBox("Option 3"));
panel.AddChild(inner);
panel.AddChild(new CheckBox("Option 4"));
}
{
Panel panel = new Panel(new Vector2(400, 400));
panel.PanelOverflowBehavior = PanelOverflowBehavior.VerticalScroll;
panel.Scrollbar.AdjustMaxAutomatically = true;
UserInterface.Active.AddEntity(panel);
Panel inner = new Panel(new Vector2(0, 200));
inner.AddChild(new CheckBox("Option 1"));
inner.AddChild(new CheckBox("Option 2"));
inner.AddChild(new CheckBox("Option 3"));
panel.AddChild(inner);
panel.AddChild(new CheckBox("Option 4"));
}
Thanks for creating GeonBit.UI, it's absolutely amazing so far!
Is there a reason why Entity.Update() and InputHelper has no support for right mouse button actions (click, down, pressed & released) ?
GetCharacterActualSize() returns the size of the space character, which is generally narrower than other characters.
Using this width to calculate the caret position when clicking on a text input element is inaccurate for any fonts that aren't monospace. Generally the solution used is to loop through each character and calculate the width of the string as you go until you get close enough to the position. For multiline, calculate height first, then loop through characters in the relevant line.
If I initialise a SelectList
with new Vector2(400, 0)
(for example), it will render the box at full height, but won't show any of the items. If I manually set the height, it works fine. Not sure if I'm using the size wrong, or if this is a bug, but just thought I'd report it.
So I tried out the texture change for the default button. I have a 300x100 texture with a 3pixel wide edge. So in the xml form I put 0.01 for FrameWidth and 0.03 for FrameHeight. But its making the edge much bigger than that. Am I doing this right?
Hi, I just tried the GeonbitUI for the first time but I have a small problem and the cursor appear in the upper left corner of the screen but it does not move.
How can I solve that?
I think a method like UserInterface.IsMouseHover() would be great ! I have try to resolve the problem with MouseEnter and MouseLeave but i have some issue when a entity(like a panel) is removed.
Btw, your library is awesome,
Thank you, Arno.
Here's a quick example:
Panel panel = new Panel(new Vector2(300, 400));
SelectList selectList = new SelectList();
panel.AddChild(selectList);
selectList.AddItem("Example item");
The "Example item"
paragraph doesn't show up at all. Obviously it's fine if you know the items beforehand, but if you're wanting to dynamically add/remove and reuse the same SelectList it doesn't really work.
Hello again.
I was working with panels and PanelOverflowBehavior.VerticalScroll and it seems that while the scrollbar appears, it's not usable as there's no 'nob' to scroll with. Mouse wheel or arrow keys do not seem to work either.
UserInterface.Active.UseRenderTarget is set to true during initialization.
Here's a sample code :
Menu building (run once)
var lolpan = new Panel(new Vector2(300, 300), PanelSkin.Default, Anchor.Center);
lolpan.PanelOverflowBehavior = PanelOverflowBehavior.VerticalScroll;
for (int i = 0; i < 1000; i++)
{
var txt = new Paragraph("test text");
lolpan.AddChild(txt);
}
UserInterface.Active.AddEntity(lolpan);
My rendering code looks like this, following the documentation
protected override void Draw(GameTime gameTime)
{
UserInterface.Active.Draw(spriteBatch);
MyGame.Draw(SpriteSortMode.FrontToBack);
UserInterface.Active.DrawMainRenderTarget(spriteBatch);
base.Draw(gameTime);
}
Resulting in the following thing:
As you can see, there's a scrollbar but it's not functional.
It would be great if you could look it up.
Thank you.
Edit: Also, i dunno if it's related or not, elements out of the view (here, the ~990 following lines) are still apparently being drawn/processed. The above example decreased my FPS massively. While it's not really something that would happen with real code, that information might be relevant.
When installing the framework with help of the NuGet Manager one will have to manually open up Content.mcgb with a text editor and add the reference to the DataType.dll. Otherwise the xmlimporter will throw an error when trying to build the assets.
Under the reference category you will need to add
"/reference:../../packages/GeonBit.UI.3.0.2.2/lib/geonbitui/DataTypes.dll"
of course depending on both your relevant file path etc.
Compiling with the Mono C# compiler version 5.0.1.1 prints the following warning:
GeonBit.UI/Source/Entities/Entity.cs(371,17): warning CS0162: Unreachable code detected
The code in question is:
// should never get here
throw new System.Exception("Internal error in getting default size.");
Obviously, this code is deliberately unreachable. However, based on the compiler's assertion that it is indeed entirely unreachable, it also seems entirely unnecessary.
Personally, I would have removed it in favor of a compilation process free of warnings. But of course, the decision is entirely up to you, the maintainer(s).
When setting a new UserInterface
in an OnClick
event, the mouse jumps to the top left corner of the game window for a single frame before returning to its previous location. The offending code as below:
button.OnClick += (args) =>
{
Active = new UserInterface();
}
_rightPanel = new Panel(new Vector2(Convert.ToInt32(ScreenManager.ScreenArea.Width * .3), Convert.ToInt32(ScreenManager.ScreenArea.Height)), PanelSkin.Default, Anchor.TopRight);
_tabs = new PanelTabs();
_invTab = _tabs.AddTab("Inventory");
_statTab = _tabs.AddTab("Skills");
DrawInv();
_rightPanel.AddChild(_tabs);
UserInterface.AddEntity(_rightPanel);
DrawInv()(Removed non-relevent code):
var width = _rightPanel.Size.X;
var rowSize = (float)Math.Floor(width / 65);
_invTab.panel.ClearChildren();
for (var i = 0; i < Player.Inventory.Items.Length; i++)
{
var item = Player.Inventory.Items[i];
if (item == null) continue;
var icon = new IconI(i, _icons[item.EntityName], Anchor.TopLeft, 1.2f, true, new Vector2(10, 10))
{
//Event handlers
};
if(i == 0)
icon.SetPosition(Anchor.TopCenter, new Vector2(0));
else if (i - 1 < rowSize)
icon.SetPosition(Anchor.TopLeft, new Vector2(65 * (i - 1), 65));
else if (i - (1 + rowSize) < rowSize)
icon.SetPosition(Anchor.TopLeft, new Vector2(65 * (i - (1 + rowSize)), 65 * 2));
_invTab.panel.AddChild(icon);
}
IconI is just derived from Icon with an addition int added.
Result is as follows:
This occurs with the update to 2.0.2.0
Hopefully its not another obvious error on my part :)
If you're dragging an entity and move the mouse quickly, the dragging stops. If you drag the entity around slowly it works fine, but as soon as you move too quickly the entity gets dropped.
Here's some quick example code, the whole game class just in case there's some setup I'm missing or something I have in the wrong order.
public class DragTestGame : Game {
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
public DragTestGame() {
graphics = new GraphicsDeviceManager(this);
graphics.PreferredBackBufferWidth = 1280;
graphics.PreferredBackBufferHeight = 720;
Content.RootDirectory = "Content";
}
protected override void Initialize() {
UserInterface.Initialize(Content);
Panel panel = new Panel(new Vector2(300));
panel.Draggable = true;
UserInterface.AddEntity(panel);
base.Initialize();
}
protected override void LoadContent() {
spriteBatch = new SpriteBatch(GraphicsDevice);
}
protected override void Update(GameTime gameTime) {
UserInterface.Update(gameTime);
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime) {
GraphicsDevice.Clear(Color.CornflowerBlue);
UserInterface.Draw(spriteBatch);
base.Draw(gameTime);
}
}
See the following screenshot:
This happens when you draw MultiColor paragraph with color instructions and outline, which uses a non-monospace font.
Original discussion on this bug:
#22 (comment)
I've been scratching my head at this for 2 days, So i'm going to reach out and ask if you have any insights.
Im working on a loading screen that will display while the world is generated. Generation runs in a thread and reports progress back which then gets applied to the progress bar.
Here's the relevent code:
var prog = new ProgressBar
{
Min = 0,
Max = 500000,
Draggable = false,
StepsCount = 500000
};
_panel.AddChild(prog);
var progressHandler = new Progress<int>(value =>
{
prog.Value = value;
});
var progress = (IProgress<int>) progressHandler;
_result = Task.Run(() =>
{
var world = WorldTools.GenerateWorld(0, 500, 500, tileSet, "World", 24, tilesPath, progress);
return world;
});
Heres what happens: https://youtu.be/tbUQu9LLsjI
If I add the values to my log file, They are being applied to the progress bar:
2017-05-09 12:15:05 - Loading - INFO: value = 50000
2017-05-09 12:15:05 - Loading - INFO: prog.value = 50000
2017-05-09 12:15:05 - Loading - INFO: value = 100000
2017-05-09 12:15:05 - Loading - INFO: prog.value = 100000
2017-05-09 12:15:05 - Loading - INFO: value = 150000
2017-05-09 12:15:05 - Loading - INFO: prog.value = 150000
2017-05-09 12:15:05 - Loading - INFO: value = 200000
2017-05-09 12:15:05 - Loading - INFO: prog.value = 200000
2017-05-09 12:15:05 - Loading - INFO: value = 250000
2017-05-09 12:15:05 - Loading - INFO: prog.value = 250000
The UI does remain responsive this whole time, so yeah. I'm stuck. Not sure if this is a bug with the progress bar, or in my code but as you can see it's pretty bare bones and the value is being added to the progress bar. Any thoughts?
I noticed that if I set a panel to PanelOverflowBehavior.VerticalScroll that if I then clear the children at some later point, it will crash due to an 'Object reference not set to an instance of an object.' in the GeonBit.UI.Entities.Entity.BringToFront() method.
I figured I'd be able to remove entities via ClearChildren() and add them as needed. I have found a work-around by just removing entities and adding entities explicitly which seems to work fine.
Users reported they need the ability to override DrawUtils functionality, specifically to control the Draw() / End() calls. Since its static, its currently impossible.
It should be a regular class they can inherit from and replace with their own, or a similar design pattern that would make it more flexible.
In addition, the UserInterface should be turned into a proper singleton, since now its somewhere in between.
If you create and add a new button to the UI on mousedown (e.g. clicking the game world and opening a popup info window there), and the button is positioned where the mouse cursor currently is, the button is immediately clicked (i.e. on the same frame as the initial mouseclick).
This seems like it could be unintended, so maybe instead entities could wait a frame before registering any interaction?
It could just be checking for and unsetting an isFirstFrame
flag and then short-circuiting the update method.
Apologies if i'm missing something obvious, But I am trying to add tabs to a panel and while the code compiles and runs fine, There are no tabs. Heres what I am trying to do:
Panel rightPanel = new Panel(new Vector2(x,y), PanelSkin.Default, Anchor.TopRight);
PanelTabs tabs = new PanelTabs();
PanelTabs.TabData invTab = tabs.AddTab("Inventory");
PanelTabs.TabData statTab = tabs.AddTab("Skills");
invTab.panel.AddChild(new Header("Hello inventory!"));
statTab.panel.AddChild(new Header("Hello stats!"));
rightPanel.AddChild(tabs);
UserInterface.AddEntity(rightPanel);
The result I am getting is the empty panel with the "Hello inventory!" header, but no tab buttons.
This used to work so I suspect something broke in one of the last couple of updates. Anyway the OnClick/OnMouseEnter/OnMouseLeave events aren't firing correctly when an entity is AutoCenter, TopRight, etc. It's offset, it seems to work from the center of the entity to the right of it (where it doesn't exist) but not from where it starts to it's center.
The code below will only change the label text when the mouse enters or leaves the area from the center of the label to the far right, but not in the first half of the label, as if something is offset. This will work if Anchor.Left is chosen, but also breaks if it's Anchor.Right, I suspect other situations probably behave incorrectly as well.
Label oLabel = new Label("Broken", Anchor.AutoCenter);
oLabel.OnMouseEnter = (Entity label) =>
{
label.FillColor = Color.Red;
};
oLabel.OnMouseLeave = (Entity label) =>
{
label.FillColor = Color.White;
};
It'd be handy to have a method to insert a child element at a certain index. I've gone ahead and written an implementation of this by taking most of the Entity.AddChild()
method and just changing it a bit.
I've also just made AddChild()
call InsertChild(child, _children.Count)
since that seemed the most straightforward way to do it.
I haven't got time right now, but I can do a PR in the next couple of days.
/// <summary>
/// Add a child entity.
/// </summary>
/// <param name="child">Entity to add as child.</param>
/// <param name="inheritParentState">If true, this entity will inherit the parent's state (set InheritParentState property).</param>
public void AddChild(Entity child, bool inheritParentState = false)
{
InsertChild(child, _children.Count, inheritParentState);
}
/// <summary>
/// Insert a child entity at a specific index.
/// </summary>
/// <param name="child">Entity to add as child.</param>
/// <param name="index">The zero-based index at which <paramref name="child"/> should be inserted.</param>
/// <param name="inheritParentState">If true, this entity will inherit the parent's state (set InheritParentState property).</param>
public void InsertChild(Entity child, int index, bool inheritParentState = false)
{
// make sure don't already have a parent
if (child._parent != null)
{
throw new System.Exception("Child element to add already got a parent!");
}
// do this first, so that any exceptions short-circuit this method
// before we update any values on child
_children.Insert(index, child);
// set inherit parent mode
child.InheritParentState = inheritParentState;
// set parent
child._parent = this;
child._indexInParent = index;
// update any siblings which need their index updating
for (int i = index + 1; i < _children.Count; i++)
{
_children[i]._indexInParent += 1;
}
// reset child parent dest rect version
child._parentLastDestRectVersion = _destRectVersion - 1;
// mark child as dirty
child.MarkAsDirty();
MarkAsDirty();
}
I've already got this code and much of the explanation in my pull request #20 but I have a feeling I'll need to probably redo that as it contains a multiple enhancements and that wasn't intended and I'm still learning. This allows the enhancement to receive some better discussion as well I think.
Overview
What I'm after is the ability for the Paragraph entity to support different colored text, defined by the programmer as needed. I want to retain the current way it works and just use the FillColor without issue and then extend it so that if desired the programmer can place inline the various colors they want various bits of text to be colored all the way down to single characters. The scheme would follow a convention like the following:
Examples
string sText = "Hi, my name is {{blue}}Jonah{{default}} what is your name?";
This would simply render 'Hi, my name is' as the default FillColor, 'Jonah' in blue and the text after Jonah back to the default FillColor. Here's another example for clarity:
string sText = "My favorite colors are {{red}}red{{default}},{{blue}}blue{{default}}, and {{orange}}orange{{default}}.
This would render the words red, blue and orange in their respective colors and everything else as the default FillColor.
Implementation
The way I've implemented this in my pull request is a simple scheme where if any of these 'color instructions' are encountered in a Paragraph entity, we pull out all the instructions with a simple regular expression, then we store in a dictionary of instructions the index in the parsed text where the color begins. This is only done at time of instantiation or whenever the .Text property changes for efficiency.
Later when actual rendering of the Paragraph takes place, if any color instructions are found, the text is processed character by character using the current color, starting with the default FillColor, as the index in the text is processed, the current color changes and that character is rendered in that color. This is done until all the text is rendered. This takes into account character spacing and wrapping and all that logic that is done as part of the Paragraph class. Additionally I've tested with anchors and offsets as well and everything looks good. Lastly I ensured this worked well with styles for things like headers, etc so it doesn't interfere with those styles, simply overrides where desired.
I've tested this on various entities, buttons, dropdowns, headers, panels, etc. The only place I found an issue is with the TextInput entity, due to the way it is implemented. It breaks up the text on the input for purposes of using the scrollbar so with my changes, this entity does not support the coloring of text. I don't think it's a huge deal as most of the time it's the player inputting text so there's no need for multiple colors I wouldn't expect. However the trick where if you lock it and it can scroll through text, admittedly that would be useful to allow the text to be colored as desired. With the changes making use of the RenderTargets, I think this would again be possible. Ideally I'd like to see all uses of Paragraph simply work with this enhancement.
Efficiency
As stated, the parsing of the text is a one time operation that occurs on instantiation or whenever the .Text property changes. The actual rendering however is done character by character to ensure the programmer has full control down to the character of what bits of text receive different colors. This is obviously less efficient than drawing a single string but I haven't noticed it to be an issue. If it is, if there is a better way we should explore that.
Colors
Currently I've added support for a variety of standard basic named colors. It wouldn't take much more work to allow for RGB values in a designation like {{255 0 255}}, that would open up the entire color spectrum to the programmer, however tedious it may be. Ideally if we could import System.Drawing, we could access a lot more named color options. I didn't do this because I figured there was a good reason it hasn't been included in the library to begin with, but if there isn't it would open a lot of things up in terms of colors. Regardless, with a little time, we could include all the named colors in XNA into this system, would just require a pretty large switch statement :)
RenderTarget2D
allocates unmanaged resources (GPU memory) and thus Dispose()
must be called at appropriate an time. I can find at least two classes that uses RenderTarget2D
: UserInterface
and Panel
. I suggest that these two classes implement IDisposable
so that the user can free/dispose the unmanaged resources.
I create multiple UserInterface
instances and currently I do x.RenderTarget?.Dispose()
, however, the RenderTarget2D
of the Panel
is protected and there is no getter for it.
Furthermore, there are at least two cases where _renderTarget
is set to null
without first calling Dispose()
.
UserInterface.cs:141:
set { _useRenderTarget = value; _renderTarget = null; }
Panel.cs:163:
if (_overflowMode == PanelOverflowBehavior.Overflow)
{
_renderTarget = null;
return;
}
Good morning.
Trying to use Geonbit, but cannot get it setup on my system.
Using Visual Studio 2015. With Monogame 3.6
This is where my issues start coming in:
When I try and rebuild the contents inside my Content Manager,
Im presented with a couple of errors:
"Importer (XmlImporter) had unexpected failure!"
They are for any XML files inside the "GeonBit" folder.
I found that I can bypass these errors, by browsing through the Content Manager,
and then setting all the XML files' "Build Action" to "Copy"
Unfortunately, when I try and run my project,
it will then start complaining about "cursor.xnb" not being in the compiled Content folder.
What am I doing wrong?
Kind regards
Hello
Through the MonoGame Community forum I have seen your post and your library. At this point, I would like to say thank you to you. Overall, it already works. I have some issues though.
I have done following things:
First, I have added your complete Source-Code to my MonoGame-Project with all folders and files. After that I had to insert the reference. Here I ran into problems. To compile this project I could not use the Visual Studio sln file. So I created another solution in my MonoGame solution. So in my solution I got 2 subsolutions. One is my game and one is your DLL-Library-Solution. In the DLL-Library solution I added the 4 files in your DLL-project and compiled it. What I got was an executable file. (*.exe). After that I could add the reference in my Game solution.
Next I added your Content folder to my Content pipeline. Also, I added the reference (exe file in this case) in the content pipeline. This reduced many errors, especially XML errors when compiling the resources.
But still. When i compile your resources in the content manager pipeline I get several interessting errors. Mostly spritefonts and fx files.
/GeonBit/themes/hd/effects/disabled.fx
.../sillouette.fx
.../fonts/Italic.spritefont
.../fonts/Bold.spritefont
.../fonts/Regular.spritefont
and the exact same errors in the lowres folder where Bold.spritefont is not existing. the name there starts with a small b. bold.spritefont. I don't know if this matters.
I did 'solve' these errors by kicking out all the fonts and replacing them by adding just a new spritefont with the same name. This is of course not a desired solution, because now, everything is the same.
Also I just deleted the *.fx files. In your code, please forgive me, I deleted the silouette and disabled effect with null.
Now I compiled everything and I could do some nice GUI. Thank you for that.
But I would like to know what is going wrong there. And how could I solve this issue. The error message in detail for fx files is:
Processor 'EffectProcessor' han unexpected error.
System.NotImplementedException: the method or operation is not implemented at XNA.Framework. Content.pipeline. Processors.effectprocessor.process
with the spritefont I got
Bitstream vera Sans mono oblique not found
Thank you
Andru
This is a simple enhancement I did originally for pull request #20, unfortunately I'm still learning pull requests and it has changes when I merged dev branch changes into it as well as my other enhancement, which I doubt is how I should be doing pull requests.
For purposes of discussion if any is needed this is pretty simple. I just added a Label entity to the progress bar that is positioned in the center of a ProgressBar to serve as an optional caption to inform the user what is happening for example when a game is loading or some other longer process is happening. That's really it!
Would be nice to have an OnRightClick or OnAltClick on entities.
OnMouseDown doesn't register rightclicks.
It turns out that if you mousedown over an entity, then move your mouse away and back again (while keeping the button down) the Entity.OnMouseDown
event is called every time.
I'll see if I can do a PR for this in a little bit!
I've noticed that when you have multiple draggable entities like a draggable panel with a draggable button as a child. When you hold down the mouse button to drag the panel if the cursor happens to go over the button, the button becomes the focused entity and starts to move while the panel stops. Im sorry if thats not a good explanation, please let me know if you need more clarity on what I mean.
To simplify the installation process.
If people wish to change the themes they should just download the XMLs / spritefont sources and edit them instead of making it editable by default which requires them to install fonts and set dll reference to Content manager.
I noticed that I am able to click in other applications and a button in the game window will be pressed if the button in the game window is behind where i clicked on the top most application.
Would be great to apply a ViewMatrix to the spriteBatch.
I noticed with the latest release 2.0.1 that the DropDown behavior for me anyway has some breaking changes, namely:
Details
I notice there is now a DropDown.SelectList which you can attach OnValueChanged event but that seems counter-intuitive to me since the whole thing is a DropDown, am I missing something intended here with the recent changes? I have a situation where one value in on DropDown refreshes the options in another DropDown upon being changed, this no longer works.
Previously I was able to set the SelectedValue or SelectedIndex as long as the value was already added which makes sense, now I can't do it unless it's added to it's parent and the parent is actually being rendered.
Code
// SelectedValue/SelectedIndex issue
DropDown drop = new DropDown(new Vector2(0, 240));
drop.AddItem("Warrior");
drop.AddItem("Mage");
drop.SelectedValue = "Mage"; // breaks on CalcDestRect() as _parent is null
panel.AddChild(drop);
drop.SelectedValue = "Mage"; // does not break
// OnValueChanged issue
drop.OnValueChange = (Entity odropdown) =>
{
System.Diagnostics.Debug.WriteLine("Test"); // Never fires now but it used to
};
Hi, I think I found a weird but minor bug. And given i just read you were about to push another official update, you might want to look it up beforehand.
Simply put, if you make a checkbox, when the UI scale is something different than 1, the label part will move right per a few pixels each frame until it gets out of the screen. The checkbox bitmap itself stays in place and is still functional. Changing back the UI scale to 1.0 will reset the label at its correct position and scrolling will stop.
I'm sorta assuming it's a rounding error or a = that become a += somewhere in your scaling stuff. As far as i know it's the only component doing that.
A code as simple as this is enough to trigger it (same thing happen if the checkbox is contained in a panel)
{
var newButton = new CheckBox("Build");
UserInterface.Active.AddEntity(newButton);
}
Weirdly enough, I have an instance of a complex settings menu with sub panels, and plenty of anchors where it's not the case. If it helps i can post the code.
Cheers! (sorry for always bringing weird bug reports)
edit: I'm on the main branch. just close if it's something you fixed in the dev one.
I tried to build Content few times, but it stops on one file time after time.
What is wrong?
Project archive
It would be cool if a Panel could calculate what the maximum height of all child entities is, so it can set the scrollbar "Max" automatically.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.