ArthurSonzogni / FTXUI

:computer: C++ Functional Terminal User Interface. :heart:
MIT License
6.64k stars 399 forks source link

Allow Canvas re-use for optimization #836

Closed WildRackoon closed 4 months ago

WildRackoon commented 4 months ago

My current workflow requires to incrementally draw a few dots on a canvas alongside the ones drawn in the previous frames, to this end, my program has to redraw everything each frame and keep track of previously drawn primitives/pixels separately (outside the Canvas).

Unless another solution that I am not aware of exists, this issue focuses on the following things:

Currently there is no way to re-use a ftxui::Canvas accross frames using the available dom canvas(...) overloads: See (https://github.com/ArthurSonzogni/FTXUI/blob/main/src/ftxui/dom/canvas.cpp#L852C1-L895C1)

I think one of the following solutions could be appropriate:

Slightly off-topic note: having the ability to override ComputeRequirement() in the std::function<void(Canvas&)> fn overload would be a nice addition to dynamically change the Canvas size without changing the dom entirely.

Epixu commented 4 months ago

I have just proposed a pull-request that probably fixes part of your problem I've asked for a bit more time to bulletproof it, but I think it is mergable atm, if Arthur decides so. I'm a bit busy currently, so I can do another PR later down the line.

ArthurSonzogni commented 4 months ago

Hello!

What makes you believe a Canvas can't be reused?

The API uses a Ref/ConstRef. It represent a owned or referenced instance.

Element canvas(ConstRef<Canvas>);

So, it is up to you to decide to move/copy/reference it:

Move

Canvas c;
auto from_copy = canvas(std::move(c));

Reference

Canvas c;
auto from_reference = canvas(&c);

Copy

Canvas c;
auto from_copy = canvas(c);
WildRackoon commented 4 months ago

Oh I see, I did not look too deeply to discover that this from_reference syntax existed, this definitely solves this issue of using a Canvas as a proper framebuffer object.

As for #834, its definitely going in the right direction to get something similar to ImGui::Image().

Will later if I really need a dynamic ComputeRequirement() or not though.

Many thanks.