notcurses icon indicating copy to clipboard operation
notcurses copied to clipboard

How to hide an ncvisual object

Open lokxii opened this issue 2 years ago • 12 comments

ncplanes can be hidden by rendering off screen. But when you blit an ncvisual object to an ncplane, and move the ncplane off screen, the ncvisual object stays on the screen. Is there anyway to properly hide an ncvisual object

lokxii avatar Apr 15 '24 18:04 lokxii

And I observe that calling notcurses_refresh() after notcurses_render() causes the ncvisual object to disappear

lokxii avatar Apr 15 '24 18:04 lokxii

I think I can just detect and destroy out of bounds ncplanes. But this seems inefficient

lokxii avatar Apr 15 '24 18:04 lokxii

you can just hide the plane on which the ncvisual has been blitted, unless i'm misunderstanding you?

dankamongmen avatar Apr 15 '24 22:04 dankamongmen

an ncvisual is not a drawn object. it's just memory holding an image.

until you blit it, it's not visible. after you blit it, the ncvisual itself has nothing to do with what is seen. you can freely change it if you want; what's visible remains the same unless you reblit it.

so to hide what's been drawn, you hide the ncplane. to destroy what's been drawn, you destroy the ncplane. etc.

dankamongmen avatar Apr 15 '24 22:04 dankamongmen

and know you can freely reblit the ncvisual onto the plane (if it's transparent, you'll want to clear the plane first). like to play multiple frames of an animation, it's:

blit render clear plane blit next frame render clear plane blit next frame render

let me know if this isn't clear!

dankamongmen avatar Apr 15 '24 22:04 dankamongmen

I forgot to mention that I blited ncvisual to a child plane (using NCVISUAL_OPTION_CHILDPLANE and setting .n = parent_plane), and then I moved the parent plane. The ncvisual stays on screen even when the parent plane is moved off screen completely

lokxii avatar Apr 16 '24 02:04 lokxii

i also tried to call ncplane_erase() and then reblit the ncvisual on an off screen plane, the image stays on screen.

lokxii avatar Apr 16 '24 02:04 lokxii

I forgot to mention that I blited ncvisual to a child plane (using NCVISUAL_OPTION_CHILDPLANE and setting .n = parent_plane), and then I moved the parent plane. The ncvisual stays on screen even when the parent plane is moved off screen completely

hrmmmm, that seems like an error. if you can put together a minimum example, i'll look into it.

this is strange. does e.g. ncplayer work like you'd expect on your setup?

dankamongmen avatar Apr 16 '24 04:04 dankamongmen

int main() {
    const char* path = "some_picture.png";
    setlocale(LC_ALL, "");
    notcurses* nc = NULL;
    notcurses_options opt = {
        .loglevel = NCLOGLEVEL_INFO,
        .flags = NCOPTION_NO_QUIT_SIGHANDLERS | NCOPTION_SUPPRESS_BANNERS
    };
    if ((nc = notcurses_init(&opt, NULL)) == NULL) {
        exit(EXIT_FAILURE);
    }

    ncplane* stdplane = notcurses_stdplane(nc);

    ncplane_options plane_opt = {
        .y = 0, .x = 0,
        .rows = 2, .cols = 4,
    };
    ncplane* plane = ncplane_create(stdplane, &plane_opt);

    ncvisual* ncv = ncvisual_from_file(path);
    if (!ncv) {
        exit(EXIT_FAILURE);
    }

    ncvisual_options vopts = {
        .n = plane,
        .blitter = NCBLIT_PIXEL,
        // .flags = NCVISUAL_OPTION_CHILDPLANE,
    };

    ncvgeom geom;
    ncvisual_geom(nc, ncv, &vopts, &geom);
    ncvisual_resize(ncv, 2 * 2 * geom.cdimx, 4 * geom.cdimx);

    ncvisual_blit(nc, ncv, &vopts);

    auto in_range = [=](int y, int x) {
        unsigned int h, w;
        notcurses_stddim_yx(nc, &h, &w);
        return y >= 0 && y <= h && x >= 0 && x <= w;
    };

    ncinput ni;
    bool flag = true;
    while (flag) {
        notcurses_render(nc);
        if (notcurses_get_blocking(nc, &ni) == -1) {
            continue;
        }
        if (ni.evtype != NCTYPE_PRESS) {
            continue;
        }
        switch (ni.id) {
            case 'q': flag = false; break;
            case 'j': ncplane_move_rel(plane, 5, 0); break;
            case 'k': ncplane_move_rel(plane, -5, 0); break;
            case 'l': ncplane_move_rel(plane, 0, 10); break;
            case 'h': ncplane_move_rel(plane, 0, -10); break;
        }
        ncplane_erase(plane);
        ncvisual_blit(nc, ncv, &vopts);
    }

    notcurses_stop(nc);
}

It's the same if I blit on a child plane or blit on the parent plane.

lokxii avatar Apr 16 '24 05:04 lokxii

My solution now is to check if the child plane with ncvisual is off screen, destroy or recreate the plane accordingly. But this adds significant complexity to my project that will handle a lot of images.

lokxii avatar Apr 16 '24 05:04 lokxii

yeah that shouldn't be necessary. btw what terminal are you running in? it'll be important to know whether you're using the sixel protocol or kitty. the code here is kinda fragile and you may well be hitting a bug.

dankamongmen avatar Apr 16 '24 05:04 dankamongmen

kitty

lokxii avatar Apr 16 '24 05:04 lokxii