Log In  


Cart #pgui-7 | 2024-07-06 | Embed ▽ | License: CC4-BY-NC-SA
49

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

1.0.4:

  • Sprite component now returns if it was clicked so it can act like a button
  • Fixed set_palette function
  • Added close_dropdown function
  • Minor ajustments on multiselect and radio buttons
  • Added better support for special characters, based on @VinnyRules's suggestion

49


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


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


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


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.


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


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


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


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


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}},
}})


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.


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!


This looks really useful thank you.


hey! i found a solution to typing special characters. I modded your pgui.lua and got it up and running. Let me know if you want the code!


@VinnyRules Wow, cool! Of course, please share it!
You could post the fragment here or the whole code in GitHub


@ssergiorodriguezz i've made a pull request on git!


Thank you, @VinnyRules, I added support for special characters in 1.0.4 based on your idea. It is attributed in the changelog.



[Please log in to post a comment]