Log In  

Cart #pgui-6 | 2024-05-15 | Embed ▽ | License: CC4-BY-NC-SA
35

A GUI library for Picotron!

It includes basic components: boxes, text boxes, text input, buttons, sliders, radio and multiple selection buttons, and color selecter. And layout components: vertical and horizontal stacks, dropdowns, a topbar and a scrollable container.

It can be useful to test game mechanics or to build app interfaces.

You can use this cart and see how it works or check the documentation on the github repository.

(I'll try to make a video on how to use it and post it here too :))

Here's one simple example:

include "pgui.lua"

function _init()
  -- Define the initial value of the slider
    slidervalue = 10
end

function _update()
  -- Refresh pgui each frame
    pgui:refresh()

  -- Create a slider and set its value back from its return value
    slidervalue = pgui:component("hslider",{pos=vec(190,20),value=slidervalue})
end

function _draw()
    cls(5)

  -- Draw the circle, its size is based on the return value of the slider
    circfill(240,140,slidervalue,8)

   -- Draw all pgui components  
    pgui:draw()
end

Let me know if you use it for any projects or if you have improvement ideas!

Note: keyboard text input is not currently working on the online version

Changelog:

1.0.1:

  • Added layers option
  • Improved dropdown (now the content is shown one layer on top)
  • Minor performance improvements

1.0.2:

  • Fixed offset error in scrollable and fixed button response miscalculations inside scrollable
  • Added flr option to hslider
  • Fixed minor layout adjustments
  • Added sprite_box component based on @MaddoScientisto's suggestion
  • Fixed color palette not being passed to children components

1.0.3

  • Performance update, now components consume less cpu
  • Refactored codebase to make it cleaner and easier to expand
  • Minor display improvements in hslider
  • Fixed color palette change function

P#147208 2024-04-23 20:47 ( Edited 2024-05-15 00:21)

That looks great and I'll definitely use it for my game, if I get to a point where UI is needed, which will be a while

P#147233 2024-04-24 08:37

@MaddoScientisto Great! Let me know when you use it and if you have any questions or feedback

P#147254 2024-04-24 13:57

This is great!
One thing I noticed is there's no way mentioned in the docs to close a dropdown on a button press, so I'm doing something like this, based on source code:

    local topbar_options = {
    {"button",{text="File",stroke=false}},
    {"dropdown",{label="top_tools",text="Tools",stroke=false,contents={
            {"button",{text="Level Editor",stroke=false}},
            {"button",{text="Soundscape Editor",stroke=false}},
    }}},
    {"button",{text="About",stroke=false}}
    }

    local topbar = pgui:component("topbar",{contents=topbar_options})

    if topbar[2][1] then
        pgui:set_store("top_tools",false,true)
        include "devtools/leveleditor.lua"
    elseif topbar[2][2] then
        pgui:set_store("top_tools",false,true)
        include "devtools/soundscape.lua"
    end

It works, but does that look right?
Thanks for the awesome work

P#147316 2024-04-25 17:52

hi @x_k, you're absolutely right!

Just so other people understand what is happening:

pgui:set_store("top_tools",false,true)

Sets to false the internal store that keeps track of opening/closing the dropdown with the "top_tools" label. (The last argument of the function is used to choose between the internal store of pgui or a user's store that can also be used, true is for pgui's store, false for user's store).

Thank you for pointing this out, I might create a function to close or open the dropdown to facilitate the process, but you figured it out perfectly. Maybe I can just explain this method in the docs.

P#147333 2024-04-25 21:40 ( Edited 2024-04-25 21:40)

Good to hear, thanks again! I'll be testing it thoroughly through the weekend :p

P#147336 2024-04-25 22:18

I just started using this to start making my childhood dream: a debug menu

Very easy to implement, I'm glad usage of camera() does not mess up the positioning of the UI interactions, I just have to make sure that I draw the UI after I reset camera and not while it's shifted, but since most of the logic is happening in update this is really easy to do

P#147439 2024-04-27 15:50 ( Edited 2024-04-27 15:51)

@MaddoScientisto Nice! And I like the design of the character

P#147547 2024-04-29 12:48

Everything is pretty much temp sprites, the character was randomly made by a friend of mine.

By the way, I tried to make the background of the GUI transparent by using color= {0,18,12,0,7,6} but nothing changed, any idea why?

pgui:component("vstack",{stroke=true,pos=vec(0,0),color={0,18,12,0,7,6},height=0,margin=3,gap=3,contents={
    {"text_box",{text=string.format("x: %.2f y: %.2f", cirnoInstance.x, cirnoInstance.y),margin=2,stroke=true,active=false,hover=false},color={0,18,12,0,7,6}},
    {"text_box",{text=string.format("mx: %.2f my: %.2f", cirnoInstance.move_x, cirnoInstance.move_y),margin=2,stroke=true,active=false,hover=false}},
    {"text_box",{text=string.format("Actors: %d", count(actors)),margin=2,stroke=true,active=false,hover=false}},
    {"text_box",{text=string.format("%.4f %dfps",stat(1),stat(7)),margin=2,stroke=true,active=false,hover=false}},
    {"text_box",{text=string.format("Bullets: %d", count(bullets)),margin=2,stroke=true,active=false,hover=false}},
    {"text_box",{text=string.format("Particles: %d", count(particles)),margin=2,stroke=true,active=false,hover=false}},
    {"text_box",{text=string.format("Weapon: %s", cirnoInstance.weapon.data.name),margin=2,stroke=true,active=false,hover=false}},
    {"text_box",{text=string.format("Weapon timer: %d", cirnoInstance.weapon.timer),margin=2,stroke=true,active=false,hover=false}},
    {"sprite_box",{sprite=cirnoInstance.weapon.data.spriteIndex,margin=2,stroke=true,active=false,hover=false}},
  }})

This is what the debug hud looks like now

P#147559 2024-04-29 13:55
1

@MaddoScientisto The main reason is that, when you draw shapes, 0 is actually not transparent but black (in the default palette). On the contrary, 0 is transparent on sprites unless you use the palt function to make the color visible.

However, I did miss to implement the part where color palettes are passed from one component onto its children components, I'll have to add that. In the meantime, you can change the general palette with the function: pgui:set_palette(YOUR_PALETTE_TABLE), you can put it inside the _init function.

And if you don't want to draw the background box in the vstack, you can comment out the part of the component that draws it:

pgui_components.vstack.fns.update = function(self,offset)
    self.size = vec(0,self.margin*2)
    local y = self.margin

  -- comment out the function that creates the background box like this:
    -- pgui:component("box",{offset=offset,clip=self.clip,layer=self.layer,color=self.color,size=self.size,stroke=self.stroke})

  ...Here comes the rest of the function
end

It will keep the structure (margins, gaps, etc., but without the box behind).

Btw, if you're happy with the default options for a component (like margins, stroke, etc.), you can omit them when you create it, this can make the code more readable. For instance, in your example:

pgui:component("vstack",{color={0,18,12,0,7,6},contents={
  {"text_box",{text=string.format("x: %.2f y: %.2f", cirnoInstance.x, cirnoInstance.y)}},
  {"text_box",{text=string.format("mx: %.2f my: %.2f", cirnoInstance.move_x, cirnoInstance.move_y)}},
  {"text_box",{text=string.format("Actors: %d", count(actors))}},
  {"text_box",{text=string.format("%.4f %dfps",stat(1),stat(7))}},
  {"text_box",{text=string.format("Bullets: %d", count(bullets))}},
  {"text_box",{text=string.format("Particles: %d", count(particles))}},
  {"text_box",{text=string.format("Weapon: %s", cirnoInstance.weapon.data.name)}},
  {"text_box",{text=string.format("Weapon timer: %d", cirnoInstance.weapon.timer)}},
  {"sprite_box",{sprite=cirnoInstance.weapon.data.spriteIndex}},
}})

P#147637 2024-04-30 12:45

This is so useful! Is there a way to create a dialog box or something that acts like one? I cant seem to figure out how to close/hide an hstack once it is open.

P#148385 2024-05-14 13:43 ( Edited 2024-05-14 13:56)
1

Hi @TheGarrett, thanks! There's a text_box component that you can use to display a simple dialog, and you can use vstacks to compose a dialog box with buttons. Yo can even put hstacks inside vstacks and so on, so there are many posibilities for layouts. In the future, I would like to do a text_box with a typewriter effect, so it can be used for characters dialog or story.

Because this GUI library is based on the immediate mode pattern, all components are rendered each frame, so you can hide them or show them whenever you want. Say you want to show an hstack only if a condition is true, you can just use an if statement, that would be equivalent to hiding it:

if condition then
  pgui:component("hstack",{pos=vec(0,0),contents={
    {"text_box",{text="content"}},
  }})
end

Now, if you want to close a dropdown that was opened by clicking it, you can use this function: pgui:close_dropdown(LABEL_OF_YOUR_DROPDOWN). Because the dropdown keeps track of its internal state.

Hope that helps!

P#148453 2024-05-16 02:01 ( Edited 2024-05-16 02:01)

[Please log in to post a comment]