#export a few nodes on screen as png

1 messages · Page 1 of 1 (latest)

timber carbon
#

i'm trying to make a tool that recreates dialogue from a certain game so people can make fake dialogue for that game. i've gotten the visuals themselves mostly working, and the customizability, but now i want to figure out how to take a few of the nodes in the scene and export them together as a png

this is what my scene tree looks like. i want to export the dialogue box, its children, and the portrait nodes to a png with a transparent background

(i'm a beginner at godot but this seems like a more advanced problem, so putting it here)

#

<@&1349109171240439858>

wicked gorge
#

uhhhhhh

left flume
#

You want to use a viewportcontainer with a viewport

wicked gorge
left flume
#

And then you can grab an image from the Viewport container

timber carbon
#

how do i do that? ^^"

left flume
#

They are nodes

#

You want to add the Viewport container first

#

Then viewport

timber carbon
#

subviewport?

left flume
#

Oops yeah

#

Keep forgetting it got changed

timber carbon
#

alright

#

do i put the stuff in the subviewport container or subviewport?

left flume
#

And then a Camera 2D to the viewport

#

All Control nodes should be children

#

That you want to export

timber carbon
#

children of what specifically?

left flume
#

The subviewport

timber carbon
#

alright

left flume
#

And the 2D nodes should be fine. I think it uses global world by default?

timber carbon
#

like this?

left flume
#

That looks good

timber carbon
#

okay cool

#

how do i do the exporting?

left flume
#

The function is in viewport (and inherited by subviewport)

#

get_texture()

#

Then you .get_image() that texture

#

Then finally you can use .save_png(...) on that image

timber carbon
#

nods okay

#

is there a way i can do that using a file dialog?

left flume
#

Yeah, you need to use the signals of the file dialog to handle that

#

So when someone selects a file location you pass that into the function extracting the image.

#

You should add a button or keyboard shortcut that just shows the file dialog

timber carbon
#

so i can have a button that tells a file dialog to open, and then when a location is chosen, that tells the subviewport to save the image to that location

left flume
#

You want two functions

#

Well the button technically can be bound from pressed to the file dialog's builtin show function

#

You don't need additional logic to set it up unless you want to use the file dialog for anything else

timber carbon
#

okay i think i got it

#

okay i think i did the code right, but the image it's exporting is blank and the stuff i want to export isn't showing up on screen anymore
i think i just don't know how subviewports work

#

@left flume ?

left flume
#

It might have messed with other sizing anchors too

timber carbon
#

i'm pretty sure it's filling up the whole screen?

left flume
#

Is the Viewport set to stretch?

timber carbon
#

viewport container or viewport? container no, viewport i don't know

left flume
#

Found it in Viewport container

timber carbon
#

?

left flume
#

Stretch

#

It will make the size of the subscene match

timber carbon
#

okay, did that, it doesn't seem to have changed anything though

left flume
#

Can you show me the Viewport container options?

timber carbon
left flume
#

Expand to true

#

Both of them

timber carbon
#

alright

#

still doesn't seem to have done anything

left flume
#

That's strange

#

The exported image is blank at the correct size?

#

Or has no size?

timber carbon
#

correct size yeah

#

i changed the subviewport size to match the window size manually

left flume
#

Camera is set to current?

timber carbon
#

how do i check?

left flume
#

It's an option of camera

timber carbon
#

i don't see it and nothing shows up when i search for current

left flume
#

Oh it's called enabled in 2D, sorry

timber carbon
#

yep, that's on

left flume
#

Can you show me dialog box options?

timber carbon
left flume
#

The camera options seem fine

#

Can you show me your dialog box options?

#

Wanna check the anchors

timber carbon
#

okay hold on it shouldn't be anchored in the top left lol

left flume
#

Lol

#

Yeah sometimes it gets messed up when reparenting

timber carbon
#

okay it's anchored correctly now

#

also i've discovered something

#

the camera outline thing is half the size of the window and is in the top left corner
zooming it out to 0.5 shows the stuff i want to see on screen but half the size it should be and in the bottom right corner

left flume
#

Ah strange

#

It should be controlled by the viewportcontainer

#

Maybe force the resolution in subviewport as well

timber carbon
#

alright i can do that in a few minutes

#

looks like i've already done that

left flume
#

That looks fine

#

Also I can see the dialog box in the preview

timber carbon
#

yeah

left flume
#

Does it show like that in the test?

timber carbon
#

that's been a thing, the camera just isn't capturing it

left flume
#

Yeah the Control nodes don't even need the camera, which makes it weird

#

Only your sprites do

timber carbon
#

this is what the scene preview looks like, the pink border is the camera

left flume
#

Oh it's tiny

timber carbon
#

yeah

left flume
#

No options seem wrong though

#

Maybe turn off stretch in the container for now

#

And manually resize the subviewport

#

See if that at least works

timber carbon
#

the subviewport is the right size regardless of whether or not the container has stretch

#

it's just the camera that's wrong

#

???

left flume
#

Oh

timber carbon
#

oH wait okay i think changing the camera's anchor mode from drag center to fixed top left fixed it

left flume
#

Sweet.

timber carbon
#

exceeept now the portrait isn't showing

left flume
#

What are the anchors of portrait?

timber carbon
#

the portrait has no texture by default and is changed through code

#

but even after changing it it doesn't show anymore

left flume
#

Those offsets are correct?

timber carbon
#

they have been, yeah

left flume
#

And the anchor points look like bottom left aligned

timber carbon
#

yep

#

oh, wait, hold on, i might know what it is

#

yep okay that fixed it

#

i renamed the file dialog which messed up the signal, so it just wasn't setting the image

left flume
#

Oh yeah the paths

#

Makes sense

#

That's why I usually use unique names for nodes

timber carbon
#

mhm, it was just something i'd made a while ago and i've been learning as i go along so i hadn't been uniquely naming everything yet

#

alright i think that's it, thank you :D

left flume
#

No problem glad it works now

timber carbon
#

@left flume hihelo it's been a while but i'm coming back to this now, is there a way to get it to crop the transparency out of the image?

left flume
#

Oh hello. I don't think there is an automatic way.

timber carbon
#

hmm alright

left flume
#

Oh

#

get_used_rect on image

timber carbon
#

the thing i have is

func _on_export_png_dialog_file_selected(path):
  get_texture().get_image().save_png(path)

so where would i put that?

left flume
#

Get image returns an image object

#

So make that line into 2 lines first

#

Then image.get_region(image.get_used_rect()) will return a new image

#

And then save the png of the new image instead

timber carbon
#

doesn't seem to work

#

it saves the image but doesn't crop it

#

maybe it's considering all of it used for some reason?

#

oh, wait, it's exporting the background too, how did i make it not do that before

#

okay there

#

alright that made it work :D cool, ty :>

#

dooo you happen to know if there's a way to get it to export a short gif? ^^"

left flume
#

I see one named gdgifexporter

timber carbon
#

alright, i'll look into it, ty

timber carbon
left flume
#

The example only exports 1 frame for 1 second

timber carbon
#

ah okay hold on so is it just like, exporter.add_frame() adds a new frame

#

ohhhkay

#

okay, update, i'm able to capture each frame, but it takes a few seconds to add each frame to the exporter, hm

#

oh yeah, and then it exports this, which isn't what i'm aiming for ahgjkdf

#
func get_image():
    var image = get_texture().get_image()
    if trim_transparency:
        image = image.get_region(image.get_used_rect())
    return image


func _on_export_gif_dialog_file_selected(path):
    var image = get_image()
    image.convert(Image.FORMAT_RGBA8)
    var exporter = GIFExporter.new(image.get_width(), image.get_height())
    
    var frames = []
    for i in range(30):
        image = get_image()
        image.convert(Image.FORMAT_RGBA8)
        frames.append(image)
        print("got frame ", i+1)
        await get_tree().create_timer(1/30).timeout
    for i in range(30):
        print("adding frame ", i+1)
        exporter.add_frame(frames[i], 1/30, MedianCutQuantization)
        
    var file: FileAccess = FileAccess.open(path, FileAccess.WRITE)
    file.store_buffer(exporter.export_file_data())
    file.close()
#

@left flume ^^"?

left flume
#

I think the easiest way is to have a node that takes frames into a queue and set that nodes process thread to not the main thread.

#

You'll have to use a mutex around the queue array

#

It's a little complicated to explain

timber carbon
#

iii have never worked with threads before

#

hm

#

and that still leaves the issue of the gif not exporting correctly

#

and i don't know why that's happening

left flume
#

Maybe there is an issue when the width and height changes between frames.

#

Since you are doing an automatic trim on the image every frame.

timber carbon
#

it doesn't