Geyser VBox add and remove [solved]

takilara
Posts: 26
Joined: Tue Jul 28, 2020 10:23 pm

Geyser VBox add and remove [solved]

Post by takilara »

I am trying to make a set of gauges that shows effects on my character, these will be created with a duration, and slowly "shrink".
There are many simultanous effects, and they will keep changing. Aka the effect "Major Cold Resistance" might be active with a remaining duration, or not active. If it is not active, then i don't want it to show.

I was hoping i could use the VBox for this.
Indeed, i can successfully add my Gauges to the VBox, and update them when needed.
My challenge comes when i want to remove a no longer active effect.
  • I dont know how to actually remove it.
  • I have tested with Geyser:remove(gaugeobj) but this doesnt seem to have any effect on the visuals
  • I have utilized gaugeobj:hide() with partial success, then the gauge hides, but leaves a "hole" in the VBox
  • I have tried to VBoxContainerObj:organize() to force redraw (after hidden or removed) with no success. I also tried to resize the gauge to 0x0, and organize, but then it resizes back :)
  • The closest i have gotten is to remove everything in the VBox, then remove the VBox itself, then recreate the entire thing whenever i need to remove one effect. this is too slow though.
So i guess my questions:
  • Is this even the correct use of the VBox (dynamic updates)? Or is it primarily designed to layout during creation phase?
  • I have been trying to remove the objects from a VBox, if that is wrong, is there other ways that will have the Vbox disregard e.g. a hidden child? (im thinking something like moving the object i would have prefered destroyed to another container, hide it, then "organize" on the vbox?
  • alternatively, maybe there is a completely different way to handle this. Any suggestions? (at this point im thinking maybe a user window, and no vbox at all...)
Attached picture of how i would like it to be

Thanks and regards
effect_gauges.png
Last edited by takilara on Sun Nov 01, 2020 11:10 pm, edited 1 time in total.

User avatar
demonnic
Posts: 884
Joined: Sat Dec 05, 2009 3:19 pm

Re: Geyser VBox add and remove

Post by demonnic »

What you're trying to do isn't necessarily wrong, but can be a bit finicky.

I wrote a class to handle things like this which can be either a V or H box and will provide the behaviour you are looking for:

https://github.com/demonnic/MDK/wiki/SortBox

It's part of the MDK I'm maintaining, which you can read more about here: https://github.com/demonnic/MDK

takilara
Posts: 26
Joined: Tue Jul 28, 2020 10:23 pm

Re: Geyser VBox add and remove

Post by takilara »

Thanks! this looks like just what i'm looking for!

Thanks also to the pointer to the MDK, I scanned through, and there are several nice items in there i can use for other things:)

I havent had a chance to try to implement yet, but I took a quick look at the SortBox wiki and api docs.
I think i grasp how to use it, however one thing is still not clear to me from the docs:
  • How do i correctly remove "the no longer relevant" gagues?
I can see you doing this in the animated example, so it is obviously possible :) Is this just using Geyser:remove as i try to above? (but that it works in SorBox? or some other mechanics?)
Nevermind, found this in the source: function SortBox:remove(window) :)

I'll give it a stab :)

User avatar
demonnic
Posts: 884
Joined: Sat Dec 05, 2009 3:19 pm

Re: Geyser VBox add and remove

Post by demonnic »

I believe for that example the timer gauges are removing themselves, but yeah it should just be :remove(myGauge) to pull myGauge out when it's done.

takilara
Posts: 26
Joined: Tue Jul 28, 2020 10:23 pm

Re: Geyser VBox add and remove

Post by takilara »

I have gotten some progress!

First, the SortBox seems to work very well. Nice work! Now im tempted to look into the timer gauges also :)

Second, I think the main issue was how i was using remove.
I was trying to either use Geyser:remove(<fullreferencetogauge>), or <fullreferencetogauge>:remove()

However, after some experimentation, i now realize i have to call :remove on the container object that should remove its child. So in my case that would now be:
<referenceToSortedVBox>:remove(<fullreferencetogauge>)

At least my initial experimentations work using this approach and i am able to remove objects :) Still some way to go to get this to fully work though.

Btw, how does the elasticity work?

User avatar
demonnic
Posts: 884
Joined: Sat Dec 05, 2009 3:19 pm

Re: Geyser VBox add and remove

Post by demonnic »

Elasticity sort of flips the script on v/hboxes in terms of resizing. Normally items will resize themselves to fill up the box and fit all the items in.

With elasticity, if all your items are set to static sizes (myGeyserObject.v_policy = Geyser.Fixed for vboxes, h_policy for hboxes) then the box will grow to fit its contents instead of the other way around.

takilara
Posts: 26
Joined: Tue Jul 28, 2020 10:23 pm

Re: Geyser VBox add and remove

Post by takilara »

Sounds like the Elasticity is exactly what i want :)

However, i am still not able to remove the gauges, it seems i am leaving references alive somehow. E.g. after removal of the gauge, it will still show, but show/hide on the container will no longer affect the "removed" gauge. (e.g. if i use the code below to add TEST1, TEST2, TEST3, then remove TEST2, these will all still show. Then if i do EffectGaugeGui.EffectContainer:hide() TEST1 and TEST3 will get hidden, but not TEST2..)

How do you normally keep references to gui objects? I might be confused by pass by reference vs pass by value in Lua...

After i call :remove(gauge ref) on the parent container, the object is gone from the parent container.windowList, but stays on the gui. Traversing windowList in Geyser, seem to indicate that there are still references to the gauges alive, even after removing them from the parent container.
Also, are there significance to the "name" property of the Gui objects?

I have been doing the following, I suspect this is not following some best practice here...

Code: Select all

EffectGaugesGui = EffectGaugesGui or {}
EffectGaugesGui.Gauges = EffectGaugesGui.Gauges or {}
EffectGaugeGui.UserWindow = EffectGaugeGui.UserWindow or Geyser.UserWindow:new({
  name = "Effects",
  titleText ="Effects",
  x = "20%", y="20%",
  width="30%", height ="40%"
})
EffectGaugeGui.EffectContainer= EffectGaugeGui.EffectContainer or Geyser.SortBox:new({
  name = "dyn_eff_container",
  x = 0,
  y = 0,
  height = "100%",
  width = "100%",
},EffectGaugeGui.UserWindow)

function EffectGaugeGui:create_gauge(effect,duration)
    EffectGaugeGui.Gauges[effect] = EffectGaugeGui.Gauges[effect] or Geyser.Gauge:new({
      name="gauge_"..effect,
      --height="2%",
      --v_policy=Geyser.Fixed
      --x="0%", y="4%",
      width="100%", height=10,
      fgColor = "black"
    }, EffectGaugeGui.EffectContainer)
end

function EffectGaugeGui:remove_gauge(effect)
  --EffectGaugeGui.Gauges[effect]:remove()
  EffectGaugeGui.EffectContainer:remove(EffectGaugeGui.Gauges[effect])
end

User avatar
demonnic
Posts: 884
Joined: Sat Dec 05, 2009 3:19 pm

Re: Geyser VBox add and remove

Post by demonnic »

You still have to :hide() the gauge itself. so add an EffectGaugeGui.Gauges[effect]:hide() to remove it from being visible.

takilara
Posts: 26
Joined: Tue Jul 28, 2020 10:23 pm

Re: Geyser VBox add and remove

Post by takilara »

oh, so hide first, then :remove?

I hope i wont cause a memory leak this way though, if i keep holding endless amounts of gauges. I guess i might want to try to reuse before create new then?
possibly not even remove them, only hide....?

User avatar
demonnic
Posts: 884
Joined: Sat Dec 05, 2009 3:19 pm

Re: Geyser VBox add and remove

Post by demonnic »

If you don't remove them, they will create a hole in your vbox. I do recommend reusing gauges where possible, it's just good form, but you'd have to get to a great number of labels before you started seeing issues due to memory leaking, I'd think.

Post Reply