Easy User Interface with KXGUI [WIP]

So, I’ve spent the past 3 months doing researches, and trying to build a Graphical User Interface (GUI) for our beloved game engine :smiley:
After building it (It is called PGUI btw, see in my signature) I realised that it was too complicated.

Then KXGUI came up, it’s easier and based on some fragments of the original source code of PGUI. It’s supposed to be a simpler version of it.
This project is a WIP, so here you can see the current supported (feel free to suggest something!):

Features:

  • Multi-resolution: You can get the same widget dimensions on every screen resolution, this was a missing feature on PGUI and you could clearly see that the widgets were too tiny if you played Super RC Boat Racing. Everything now is scaled according to your screen resolution.
  • Custom cursors: Another missing feature on PGUI. You can use this if you don’t want to use the hacky “textured plane and logic-bricks” approach. It’s pretty easy to use! See some examples at the end of this post.

Current Screenshot:

Examples:

from kxgui import *
from bge import logic as g

def main(cont):
    o = cont.owner
    sce = g.getCurrentScene()


    if "init" not in o:
        o["gui"] = GUI()
        
        o["gui"].addWidget("play"   , Button.new(text="Play"   , height=0.05), group="menu")
        o["gui"].addWidget("options", Button.new(text="Options", height=0.05), group="menu")
        o["gui"].addWidget("credits", Button.new(text="Credits", height=0.05), group="menu")
        o["gui"].addWidget("exit"   , Button.new(text="Exit"   , height=0.05), group="menu")
        
        o["gui"].groups["menu"].position = [0.39, 0.35]
        
        o["gui"].applyToScene()


        o["init"] = 1
    else:
        o["gui"].update()
        
        if o["gui"].widgets["exit"].events.clicked:
            g.endGame()
  • Custom Cursor: http://i.imgur.com/RQWn0ES.png
from kxgui import *
from bge import logic as g

def main(cont):
    o = cont.owner
    sce = g.getCurrentScene()


    if "init" not in o:
        o["gui"] = GUI()
        
        o["gui"].cursor = Cursor.new(g.expandPath("//cursor1.png"))
        
        o["gui"].addWidget("btn", Button.new(x=0.02, y=0.3))
        
        o["gui"].applyToScene()


        o["init"] = 1
    else:
        o["gui"].update()

You can also change the cursor’s hotspot!
http://i.imgur.com/ktx7qXf.png


o["gui"].cursor.hotSpot = [0.5, 0.5]
# The "Debug" mode shows the bounds and the hotSpot location of the cursor.
o["gui"].cursor.debug = True

GitHub: https://github.com/DCubix/kxgui

That’s all, I’ll leave a .zip file (containing the blend and some cursors) there for you to test it out! Thanks in advance :smiley: :smiley:

Attachments

KXGUI_v0.75.zip (391 KB)KXGUI_v0.75b.zip (695 KB)KXGUI_v0.8.zip (716 KB)

Hi TwisterGE,

Have you tried BGUI? It’s another UI for the BGE, written by moguri. That’s the general solution I’ve used up to now.

I looked at your UI, it worked, and it was relatively simple to use. The code looks well written, but I have some points:

  • I dislike camelCase. There I said it! Jokes aside, it’s fine that you’re consistent. I just needed to voice my opinion :wink:
  • It might be useful to enable nested widgets. That way, a more advanced UI can be developed.
  • That said, be careful that the transform code is efficient. In BGUI that was a bit of a sore point.
  • It’s advisable to hold weak references to your widgets so they don’t hog memory / you can catch bugs when things are holding references wrongly.
  • In my experience, BGL is pretty slow when you ask it to do many operations. I would advise considering a manager which can perform basic filtering of unnecessary draw operations (e.g setup and teardown operations when nothing was done in between). This helped speed things up for me, with BGUI (I disabled frame drawing so that frames could just be used for organisation).
  • I am glad you’ve added JSON support. That’s sensible. It might also be useful to add a CSS-like styler, or if you don’t want to go to such lengths, (because Qt probably invokes the HTML renderer for that), a style-sheet of some other, restricted form.

Thanks for posting the resource. It’s simple enough that novice coders can read through it and slowly understand what it’s doing, without being without utility!

Regards,
Angus.

That is a very cool idea… using a css like code for gui… it would really helpfull

Hello, @agoose77

Yes, I’ve tried BGUI before (it didn’t work, and that’s one of the reasons why I’m making my own), and I use the texture handling code from it.

  • I used to dislike camelCase as well, but I think that it fits Python just perfectly.
  • I’ll try to make nested widgets, but I’m not sure…
  • About the weak references, well, I never heard of them before, I need to study more :stuck_out_tongue:
  • That’s true, BGL is very slow, but I only use simple drawing and you can disable them and just use the Buttons as clickable areas.
  • I’m going to start designing a kind of style sheet, using JSON (I’m not crazy enough to write my own parser lol), and maybe some nine-patch textures (these are tricky to make, and there’s almost nothing about them on Google, just how to use them on Android).

Thanks for your comment! :slight_smile:

Wow. Looks great. I never had much luck with BGUI either but I’ll give this a try.
thanks!

Hey, today I worked on the event system. It’s based on callbacks, and are very simple to make :smiley:

First, you can register a callback or use an existing one:


# Using an existing one
o["gui"].widgets["myButton"].events.callbacks["on_click"] = myButtonClicked

# Registering a callback
# NOTE: This only works if you are extending the Widget class to create custom widgets!
o["gui"].widgets["myButton"].events.registerCallback("myCallback", myFunction)

# And then raise the event.
o["gui"].widgets["myButton"].events.raiseEvent("myCallback", args=[3.14159, "blah"])

On the top of your script, you should declare your callbacks:


def myFunction(sender, pinumber, blahString):
    print(pinumber, blahString)

def myButtonClicked(sender):
    sender.owner.text = "Blah"
    print("Clicked myButton")

NOTE: Sender is the event object that has raised the event. You can access its owner, which is the Widget that contains the event manager.

I updated the ZIP on the main post with the new version :slight_smile:

GUI Skinning
http://i.imgur.com/O9zT4bT.gif

Small suggestion - perhaps rename raise_event to “raise” or “publish”, and subscribeCallback to “subscribe” or “accept”

@agoose77
“raise” is a reserved word in Python. I’ll see what I can do. :wink:

Today I added a TextBox to the GUI system.
It’s single and multi-line, you can mask the text (for passwords), can be numeric-only and etc…
http://i.imgur.com/xW7KgXo.gif
EDIT: The ZIP in the main post was updated :wink:

Thank you for doing this!

now we need a way to render these to textures and accept input as a face of a object. then Wrectifieds UI will be complete!

Text box thingy looks amazing. Does it also support managing the design of it? For example, if I want it to be something like black background and green text etc.
Or even adding texture to it?

I hope I can find

Sent from my SM-G920F using Tapatalk

@adriansnetlis: I think it support some management:

“TextBox”: { “normal”: {
“image”: “//imgs/textbox.png”,
“padding”: [6, 6, 6, 6]
},
“textColor”: [0, 0, 0, 1],
“backColor”: [1, 1, 1, 1],
“borderColor”: [0, 0, 0, 1],
“borderWidth”: 1,
“borderRadius”: 0
}
}

@@TwisterGE: Your GUI looks quite easy and understandable to use. Great work!
Can you make scrollbars on that textbox :slight_smile: . Scrollbars are essential for many games but I’m not sure masking objects is supported in BGE.

Also if you try and add drop down menus,tab menus, radio buttons, check lists, progress bars, hint boxes(on roll-over),yes/no dialogs(pop-ups), I promise you, your GUI will be legendary here :wink:

There is a GUI called NGUI for Unity, also made by one person…I think it was a russian. He is using scaling down/up the content(buttons/items) to imitate drop down menu functionality. I think you can use scaling up/down of items for many cases in order to imitate specific interface functionalities.

This looks nice!
I’ve been using BGUI for a while for my projects. It works fine (mostly), but it is a bit cumbersome and hard to understand at first (at least it was for me), even setting up a simple pre-game menu is a bit of a chore.

I second the inclusion of drop-down and scrolling menus. This is something BGUI does not do out of the box. A generic tool-tip function would be neat too (widgets could have a tooltip attribute?).

Also, full text alignment would be very nice. BGUI can do centered text (mostly), but no right alignment, which is annoying.

:smiley: :smiley: Thanks @@haidme
Yes, I’ve made some scroll bars :smiley: but now I need to add them to the TextBox.

Also if you try and add drop down menus,tab menus, radio buttons, check lists, progress bars, hint boxes(on roll-over) I promise you, your GUI will be legendary here

Maybe Progress bars, radio buttons, or dropdowns, i’ll see what I can do, because I don’t want to make this turn into a mess like I did before…
For now, I want it to be as simple as possible :wink:

@@Nines
You can align text left, center or right, vertically and horizontally.

Just to be contrary, this is provided via a patch, and pretty quick to add support for in most toolkits :slight_smile:

I’m impressed with this… Still need to look at it all but from screen shots and user fear back it looks and sounds very nice.

Today’s feature is: Scrolled TextBox :smiley: !!
http://i.imgur.com/EBkREZN.gif

Yay!
nice work :slight_smile: