#debugging a label/line array

262 messages · Page 1 of 1 (latest)

rugged crypt
#

have an issue with my 'label array' that cycles through 3 label's text in a VBoxContainer with 3 labels in it ```swift
#region Line Inner Class
class Line:
var text:String
var lifetime:float
var label:Label

func set_label(new_label:Label, label_alpha_animation:Curve) -> void:
    label = new_label
    label.text = text
    label.modulate.a = label_alpha_animation.sample(lifetime)

func process(delta:float, label_alpha_animation:Curve) -> void:
    lifetime += LABEL_ANIM_RATE * delta
    label.modulate.a = label_alpha_animation.sample(lifetime)

func finished() -> bool:
    return lifetime >= LABEL_LIFETIME

#endregion

var lines:Array[Line]

#

and then this ```swift
func on_item_picked_up(pickup:String, type:String, ammo_item:String) -> void:
# Create a new line
var new_line := Line.new()
match type:
"":
print("void line???")
"Health":
if pickup == "200":
new_line.text = "You picked up the Prime Healing Coil."
else:
new_line.text = "You gained " + pickup + " health."
"Armor":
new_line.text = "You gained " + pickup + " armor."

new_line.lifetime = 0.0
lines.push_front(new_line) # Add to BEGINNING of array

# Update the label of each line
for i in range(0, mini(lines.size(), labels.size())):
    labels[i].visible = true
    lines[i].set_label(labels[i], label_alpha_animation)
    
 #    Remove excess lines
 print(lines)
 print(labels)
 while lines.size() > labels.size():
    lines.remove_at(lines.size() - 1)
 print(lines)```
#

and then this

#

func _process(delta:float) -> void:
    # Iterate backwards so we can erase from the array without breaking the for loop
    for i in range(lines.size() - 1, -1, -1):
        lines[i].process(delta, label_alpha_animation)
        if lines[i].finished():
            lines[i].label.visible = false
            lines.remove_at(i)
lunar lava
#

is this 4.3?

#

also what's the exact issue, the order they're rendering in? sorry it's not immediately obvious

rugged crypt
#

4.3

#

you can see it happen at the end of this clip

#

although for some reason i'm having a hard time reproducing it

#

bottom left

#

they normally render as seen in this video

#
You got the Rocket Launcher.
[<RefCounted#-9223371114007230836>]
[first_label:<Label#382151431418>, second_label:<Label#382117876984>, third_label:<Label#382084322550>]
[<RefCounted#-9223371114007230836>]

You gained 100 armor.

[<RefCounted#-9223365573180645062>, <RefCounted#-9223371114007230836>]
[first_label:<Label#382151431418>, second_label:<Label#382117876984>, third_label:<Label#382084322550>]
[<RefCounted#-9223365573180645062>, <RefCounted#-9223371114007230836>]

You gained 10 armor.

[<RefCounted#-9223364077273738692>, <RefCounted#-9223365573180645062>, <RefCounted#-9223371114007230836>]
[first_label:<Label#382151431418>, second_label:<Label#382117876984>, third_label:<Label#382084322550>]
[<RefCounted#-9223364077273738692>, <RefCounted#-9223365573180645062>, <RefCounted#-9223371114007230836>]

You gained 21 health.

[<RefCounted#-9223361043802093942>, <RefCounted#-9223364077273738692>, <RefCounted#-9223365573180645062>, <RefCounted#-9223371114007230836>]
[first_label:<Label#382151431418>, second_label:<Label#382117876984>, third_label:<Label#382084322550>]
[<RefCounted#-9223361043802093942>, <RefCounted#-9223364077273738692>, <RefCounted#-9223365573180645062>]

You picked up the Prime Healing Coil.

[<RefCounted#-9223358947019189117>, <RefCounted#-9223361043802093942>, <RefCounted#-9223364077273738692>, <RefCounted#-9223365573180645062>]
[first_label:<Label#382151431418>, second_label:<Label#382117876984>, third_label:<Label#382084322550>]
[<RefCounted#-9223358947019189117>, <RefCounted#-9223361043802093942>, <RefCounted#-9223364077273738692>]

You gained 10 health.
[<RefCounted#-9223350980425280983>, <RefCounted#-9223358947019189117>, <RefCounted#-9223361043802093942>]
[first_label:<Label#382151431418>, second_label:<Label#382117876984>, third_label:<Label#382084322550>]
[<RefCounted#-9223350980425280983>, <RefCounted#-9223358947019189117>, <RefCounted#-9223361043802093942>]
10```
#

heres a bug report showing the line size

#

notice how when the 'bug' happens

#

it's no longer 'clipping' a fourth line

#

it's instead just staying at 3

#

@lunar lava

lunar lava
#

hmmm

rugged crypt
#

it should be 'oh this is four lines, i'm snipping it to three'

#

but its not

lunar lava
#

this might be above my skill level, i'm having a hard time figuring out why the problem would even be inconsistent in the first place, let alone what's causing it

rugged crypt
#

the firs tline in those groups of 3 is the line size the second you pick it up

#

the third line is 'after' the snipping

#

that's all right man

#

ive just been wrestling

lunar lava
#

any time i run into a sporadic issue that's hard to consistently replicate, the first thing that comes to mind is an editor setting or engine bug

rugged crypt
#

well

#

i can replicate it a lot

#

just not 100% of the time

#

a manual push and pop and print line for every step of the labels stack...maybe?

lunar lava
#

yeah, that's whats puzzling

#

sorry i'm not much help i just have zero clue here

rugged crypt
#

dw about it

#

its appreciated nonetheless

rugged crypt
#

i'll replicate it rn

marble crane
#

It's not to do with picking up the same type of thing, right?

rugged crypt
#

see, i'm not entirely sure

#

i THOUGHT it was

#

it could still be

rugged crypt
#

now that i bug test it

#

but i need to figure out how to deal with that if so, and not everything that does pickup has this issue

rugged crypt
#

it's just this particular use case

#

all right - rocket launcher pickup, going straight for the 200 hp healing super thing, decay down to like 120 hp, and taking damage to get 89 - to pick up 25 with only that, the bug doesnt happen

#

rocket launcher, going for an armor + 50, then the super thing, and then decay down to like 120 hp, and taking damage to get 89 - and picking up 25, the bug happens, but it is slightly delayed by like half a second

#

that's four pickups

#

picking up like five guns in a row, no bug

#

all the armor pieces (like five) no bug

#

just super healing and 25 hp pack, no bug

#

shard launcher, going for 2 armors, then super thing, then decaying down to 120, and taking damage to get 89, and picking up 25, bug happens

#

1 armor, same thing as above, bug happens

#

but it does DOUBLE lines if i pick up 2 armors

#

picked up all the starting ammo and weapons, went to the 200 overheal, and damage until i was 90 hp, and then +25

#

bug happened too

#

after the overheal, tried a 5 armor piece and it did the same thing

#

i feel like all this stuff is ONLY happening after the overheal + decay

#

completely reproducible

#

you can see it moving up after a bit

marble crane
#

So what series of actions is required to cause it?

rugged crypt
#

Touching things so you pick them up in the order listed a couple posts above

fresh ledge
#

do you have a summary of the current state of the problem?

jagged vale
#

I'm trying to get a handle on the exact bug, but is the objective to just show the latest 3 messages?

rugged crypt
#

yeah, basically - as seen in the video, normally, the 3-line array "cycles" through the three lines of text and pushes the 'newest' line to the bottom, while pushing the next two upwards

#

then it snips off the 'fourth' so it always remains 3 lines

#

but in this bug seen at the end of the video, it pushes the line upwards for some reason

fresh ledge
#

i'm not quite sure what all those arrays are even doing, why don't you just make a new label when something happens and fade them out over time / delete the front while there's more than 3?

#

that's just a HBoxLayout with some Labels after all, right?

rugged crypt
#

yes

#

well, vbox

fresh ledge
#

oh yeah ofc

rugged crypt
#

it basically just does this

#
[3]
[2]
[1]```
#

and then [2] [1] [new]

fresh ledge
#

then just make a Line extends label that fades out over time and queue_frees itself when done, and when you pick something up just add one of those to the vbox and remove the first one if there were too many

rugged crypt
#

and it keeps cycling likem that

fresh ledge
#

yeah but that's what a vbox already does if you remove its first child and add a new one at the end.

rugged crypt
#

i will most likely just do that in the end if i can't salvage this implementation

#

but it's appreciated

#

it makes perfect sense

#

all right, i think i'll just do that

jagged vale
#

My first thought, before going into all the logic of the label code is to consolidate these things, for example:

class_name timed_label extends Label
var lifetime:float
func _init(life_time_in_seconds:float = 1): #// 1 Second life by default
  lifetime = life_time_in_seconds

func _enter_tree() -> void:
  get_tree().create_timer(lifetime).timeout.connect(expire)

func expire() -> void:
  queue_free()

then you would just need to monitor the the children of the vbox, you could attach a script to the VBox to handle that or manage it from some other node

rugged crypt
#

makes sense

jagged vale
#

now if you want fading etc, you would adjust the code above

rugged crypt
#

will try to do it this way, thanks

rugged crypt
#

@jagged vale i'm home and i'm almost there i think

#
class_name timed_label extends Label

const LABEL_LIFETIME := 5
const LABEL_ANIM_RATE := 1.0 / LABEL_LIFETIME

@export var label_alpha_animation:Curve # How alpha should be animated over a labels lifetime

var lifetime:float

func _enter_tree() -> void:
    get_tree().create_timer(LABEL_LIFETIME).timeout.connect(expire)
    
func expire() -> void:
    self.modulate.a = label_alpha_animation.sample(lifetime)
    queue_free()
    
func process(delta:float) -> void:
    lifetime += LABEL_ANIM_RATE * delta
    self.modulate.a = label_alpha_animation.sample(lifetime)
``` i'm just trying to figure out how to get the fadeout to work
#

home stretch i think

jagged vale
#

do you want the fade out and fade in to have the same time?

rugged crypt
#

no

#

i hav ea curve

#

just a sec

#

like this

jagged vale
#

might want to use _process

rugged crypt
#

oh did i type process

#

LOL

#

shit

#

just a sec

rugged crypt
#

oh my fucking god

#

thanks

jagged vale
#

if you want to help me, I think I'm doing something stupid with fades as well

rugged crypt
#

sure

jagged vale
#

huh it won't let me paste the code..

rugged crypt
#

as a side note

#

i have a question

#

how do i force it to only have 3 labels at a time

#

the vboxcontainer

#

it SORT of does it

rugged crypt
#

but it's adding a fourth label

jagged vale
#

hmmm

#

well how are you handling the vbox when you add a child

#

ideally you would have a function akin to add_child_max_three()

rugged crypt
#
func on_item_picked_up(pickup:String, type:String, ammo_item:String) -> void:
    var E : LabelNew = LABEL_NEW.instantiate()
    pickup_labels.add_child(E)
    E.text = "TestPickup"```
#

literally this

#

as a test thing

#

just add child

#

and then when the top one fades out

#

the vbox properly 'trims' it to three

#

instead of four

#

but i dont want it to wait that long lol

#

i want it to be instant

#

yes, i commented out my previous text changing match statemnt

jagged vale
#

if you do a simple pickup_labels.get_children().size() => 3 then you just either remove the first or last

#

make sure to do it same frame for seamless

rugged crypt
#

oh, so like pickup_labels.remove_child(2)

#

because size is 0,1,2

#

for 3 i think

jagged vale
#

size is 1 indexed

#

so ["test"].size() is 1

rugged crypt
#

oh

#

okay, i see

jagged vale
#

don't forget to q free the removed child

rugged crypt
#

yeah

#

uhhhh lets see

#

that's not an assignment!!

#

i just wanna know if the value is greater than or equal to 3

#

lamo

#

oh, i it won't let me remove child via int

#

oh ok

#
if pickup_labels.get_child_count() > 3:
  pickup_labels.remove_child(1)```
jagged vale
#
func add_child_max(source:Node,add:Node,max:float = 3)
  var children = source.get_children()
  while children.size() >= max:
    children[0].queue_free()
    source.remove_node(children[0])
    children = source.get_children()
  source.add_child(add)
rugged crypt
#

won't work but

#

oh, you made a whole function for it

#

lemme see

jagged vale
#

this removes first

#

I can adjust it for last

rugged crypt
#

yeah, this should remove last

jagged vale
#
func add_child_max(parent:Node,add:Node,max:float = 3)
  var children = source.get_children()
  while children.size() >= max:
    children[-1].queue_free()
    source.remove_child(children[-1])
    children = source.get_children()
  parent.add_child(add)
#

for last lol

rugged crypt
#

why is it bool

#

jsut a sec

#

alright lemme see

#

wym non existent function

jagged vale
#

uh change to child instead of node

#

ugh

#

I guess I didn't know the godot API as well as I thought.

#

I corrected it

rugged crypt
#

i made it, it's right there

marble crane
#

The function is in a script that's attached to the container?

rugged crypt
#

no

jagged vale
#

instead of pickup_labels.add_child_max(...) do add_child_max(pickup_labels,E)

rugged crypt
#

ohhhh

#

i see what you mean

#

never mind LMOA

#

yeah sorry

#

kind of tipsy tn

jagged vale
#

oh no

#

leave comments!

rugged crypt
#

alright i think this works

#

moment of truth

#

we got it

#

thanks all

#

big thanks to BlackShift

#

:))))))))))))

#

alright

#

@jagged vale before i close this as answered

#

what did u wanna ask me

jagged vale
#

uh nvm, if you are tipsy

#

XD

rugged crypt
#

dw about it

#

it aint that bad

#

just ask

jagged vale
#

Just look over my code in the gist I posted, see if anything seems wrong with the logic flow

#

it has issues if the it loads too quickly

rugged crypt
#
func _process(delta: float) -> void:
    if is_loading:
        var status_percentage:Array
        var status := ResourceLoader.load_threaded_get_status(current_load_path,status_percentage)
        if status == ResourceLoader.THREAD_LOAD_LOADED:
            var packed_level:PackedScene = ResourceLoader.load_threaded_get(current_load_path)
            loaded_level = packed_level.instantiate()
            replace_level(loaded_level)
            is_loading = false
            get_tree().process_frame.connect(remove_splash,CONNECT_ONE_SHOT)
        elif status != ResourceLoader.THREAD_LOAD_IN_PROGRESS:
            remove_splash()
    pass``` ok the first thing that jumps out at me
#

is nested if

#

so like

#

i would write it like this

#
func _process(delta: float) -> void:
    if not is_loading:
          return
     var status_percentage:Array
     var status := ResourceLoader.load_threaded_get_status(current_load_path,status_percentage)
    ```
#

saee what i mean

#

oyu dont need to have it in a big ass if statement indentation

jagged vale
#

yea..

rugged crypt
#

oh wait

#

this is process

#

LMOA

#

okay just a second

marble crane
#

Guard clauses my beloved

rugged crypt
#

yeah

#

i would do guard clauses whenever i can

rugged crypt
jagged vale
#

hmm, I'm thinking of actually turning the entire tween chain in a step_advance state machine

rugged crypt
#

ok so thats not a bad idea

#

but like jsut remember

#

state machines are cool but for most things

jagged vale
#

that's what that enum is for

rugged crypt
#

they're overkill

#

if it makes it easier for you

#

go ahead

#

but its really not a game ender if you dont use one for something like that

jagged vale
#

well I've got issues, of too many states right now, like the 2 different screens and a load state, so what's that, like 2*2*2 states (6)

rugged crypt
#

oh

#

well in that case that's a different story

#

i might as well mention

#
        elif status != ResourceLoader.THREAD_LOAD_IN_PROGRESS:
            remove_splash()``` this looks kinda gross because i have an inherent revulsion towards elif
#

hmm

jagged vale
#

would you rather use match on two expected values?

rugged crypt
#

if it were me, yes

marble crane
#

Match is great, but probably not suited to this case

rugged crypt
#

but you're not me

#

i mean its binary right

#

why not just make it a bool

#

and be like if bool is true = then this

#

and if not true then this

jagged vale
#

THREAD_LOAD_IN_PROGRESS is one of 4 possible enums

rugged crypt
#

oh, i get it now

jagged vale
#

I'm surprised you didn't mention the recursive signal bind

func handle_black_fade_complete(graphic:bool = false):
    if graphic:
        start_splash_fade()
    else:
        clear_level()
        get_tree().create_timer(fade_time).timeout.connect(handle_black_fade_complete.bind(true))
    pass
rugged crypt
#

is that such a huge problem

jagged vale
#

I think that might be problem

rugged crypt
#

hmm

jagged vale
#

as I can't await that unless I store it

rugged crypt
#

i mean you should be storing it regardless right?

jagged vale
#

I'll remove it for now

#

hmm, now its just broken

#

I'll just refactor the entire thing 🙂

rugged crypt
#

lmao

rugged crypt
#

instead of making a new timer every time

#

since timers don't have to delete themselves or end forever when youre done using them

#

you could just have a timer that isn't in that function

#

that is cycling through the timer

#

and every time it 'ends' it calls that function

#

see what i mean?

jagged vale
#

well I'm basically leverging the tween as a timer, I think the issue is that I'm not disconecting them

rugged crypt
#

i see

jagged vale
#

I think .kill() is causing finish() to fire

rugged crypt
jagged vale
#

its tween's kill

rugged crypt
#

i see, yeah

rugged crypt
#

lord knows im doing suboptimal stuff rn

#

what really matters is it works and isn't a hit on perf

#

just a time management question i think

#

sorry i can't be more help, i'm no pro yet