You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
290 lines
9.0 KiB
C
290 lines
9.0 KiB
C
#include <unistd.h>
|
|
#include "demo.h"
|
|
|
|
static void
|
|
grow_rgb8(uint32_t* rgb){
|
|
int r = ncchannel_r(*rgb);
|
|
int g = ncchannel_g(*rgb);
|
|
int b = ncchannel_b(*rgb);
|
|
int delta = (*rgb & 0x80000000ul) ? -1 : 1;
|
|
if(b == r){
|
|
b += delta;
|
|
}else if(g == r){
|
|
g += delta;
|
|
}else{
|
|
r += delta;
|
|
}
|
|
if(b == 256 || r == 256 || g == 256){
|
|
b = r = g = 255;
|
|
*rgb |= 0x80000000ul;
|
|
}else if(b == -1 || r == -1 || g == -1){
|
|
b = r = g = 0;
|
|
*rgb &= ~0x80000000ul;
|
|
}
|
|
*rgb = (*rgb & 0xff000000ul) | (r * 65536 + g * 256 + b);
|
|
}
|
|
|
|
static struct ncplane*
|
|
legend(struct notcurses* nc, const char* msg){
|
|
int dimx, dimy;
|
|
notcurses_term_dim_yx(nc, &dimy, &dimx);
|
|
ncplane_options nopts = {
|
|
.rows = 3,
|
|
.cols = strlen(msg) + 4,
|
|
.y = 3,
|
|
.x = NCALIGN_CENTER,
|
|
.flags = NCPLANE_OPTION_HORALIGNED,
|
|
};
|
|
struct ncplane* n = ncplane_create(notcurses_stdplane(nc), &nopts);
|
|
if(n == NULL){
|
|
return NULL;
|
|
}
|
|
nccell c = CELL_TRIVIAL_INITIALIZER;
|
|
nccell_set_fg_rgb8(&c, 0, 0, 0); // darken surrounding characters by half
|
|
nccell_set_fg_alpha(&c, NCALPHA_BLEND);
|
|
nccell_set_bg_alpha(&c, NCALPHA_TRANSPARENT); // don't touch background
|
|
if(ncplane_set_base_cell(n, &c)){
|
|
ncplane_destroy(n);
|
|
return NULL;
|
|
}
|
|
if(ncplane_set_fg_rgb(n, 0xd78700) || ncplane_set_bg_rgb(n, 0)){
|
|
ncplane_destroy(n);
|
|
return NULL;
|
|
}
|
|
ncplane_on_styles(n, NCSTYLE_BOLD | NCSTYLE_ITALIC);
|
|
if(ncplane_printf_aligned(n, 1, NCALIGN_CENTER, " %s ", msg) < 0){
|
|
ncplane_destroy(n);
|
|
return NULL;
|
|
}
|
|
return n;
|
|
}
|
|
|
|
static int
|
|
slideitslideit(struct notcurses* nc, struct ncplane* n, uint64_t deadline,
|
|
int* vely, int* velx){
|
|
int dimy, dimx;
|
|
int yoff, xoff;
|
|
int ny, nx;
|
|
notcurses_term_dim_yx(nc, &dimy, &dimx);
|
|
ncplane_dim_yx(n, &ny, &nx);
|
|
ncplane_yx(n, &yoff, &xoff);
|
|
struct timespec iterdelay;
|
|
timespec_div(&demodelay, 60, &iterdelay);
|
|
struct timespec cur;
|
|
do{
|
|
DEMO_RENDER(nc);
|
|
yoff += *vely;
|
|
xoff += *velx;
|
|
if(xoff <= 1){
|
|
xoff = 1;
|
|
*velx = -*velx;
|
|
}else if(xoff >= dimx - nx){
|
|
xoff = dimx - nx - 1;
|
|
*velx = -*velx;
|
|
}
|
|
if(yoff <= 2){
|
|
yoff = 2;
|
|
*vely = -*vely;
|
|
}else if(yoff >= dimy - ny){
|
|
yoff = dimy - ny - 1;
|
|
*vely = -*vely;
|
|
}
|
|
ncplane_move_yx(n, yoff, xoff);
|
|
demo_nanosleep(nc, &iterdelay);
|
|
clock_gettime(CLOCK_MONOTONIC, &cur);
|
|
}while(timespec_to_ns(&cur) < deadline);
|
|
return 0;
|
|
}
|
|
|
|
// run panels atop the display in an exploration of transparency
|
|
static int
|
|
slidepanel(struct notcurses* nc, struct ncplane* stdn){
|
|
int dimy, dimx;
|
|
notcurses_term_dim_yx(nc, &dimy, &dimx);
|
|
int ny = dimy / 4;
|
|
int nx = dimx / 3;
|
|
int yoff = random() % (dimy - ny - 2) + 1; // don't start atop a border
|
|
int xoff = random() % (dimx - nx - 2) + 1;
|
|
struct ncplane* l;
|
|
|
|
// First we just create a plane with no styling and no glyphs.
|
|
struct ncplane_options nopts = {
|
|
.y = yoff,
|
|
.x = xoff,
|
|
.rows = ny,
|
|
.cols = nx,
|
|
};
|
|
struct ncplane* n = ncplane_create(stdn, &nopts);
|
|
|
|
// Zero-initialized channels use the default color, opaquely. Since we have
|
|
// no glyph, we should show underlying glyphs in the default colors. The
|
|
// background default might be transparent, at the window level (i.e. a copy
|
|
// of the underlying desktop).
|
|
nccell c = CELL_CHAR_INITIALIZER(' ');
|
|
struct timespec cur;
|
|
ncplane_set_base_cell(n, &c);
|
|
clock_gettime(CLOCK_MONOTONIC, &cur);
|
|
uint64_t deadlinens = timespec_to_ns(&cur) + timespec_to_ns(&demodelay);
|
|
int velx = random() % 4 + 1;
|
|
int vely = random() % 4 + 1;
|
|
l = legend(nc, "default background, all opaque, whitespace glyph");
|
|
int err = slideitslideit(nc, n, deadlinens, &vely, &velx);
|
|
if(err){
|
|
ncplane_destroy(n);
|
|
ncplane_destroy(l);
|
|
return err;
|
|
}
|
|
ncplane_destroy(l);
|
|
|
|
nccell_load_char(n, &c, '\0');
|
|
ncplane_set_base_cell(n, &c);
|
|
clock_gettime(CLOCK_MONOTONIC, &cur);
|
|
deadlinens = timespec_to_ns(&cur) + timespec_to_ns(&demodelay);
|
|
l = legend(nc, "default background, all opaque, no glyph");
|
|
if( (err = slideitslideit(nc, n, deadlinens, &vely, &velx)) ){
|
|
ncplane_destroy(n);
|
|
ncplane_destroy(l);
|
|
return err;
|
|
}
|
|
ncplane_destroy(l);
|
|
|
|
// Next, we set our foreground transparent, allowing characters underneath to
|
|
// be seen in their natural colors. Our background remains opaque+default.
|
|
nccell_set_fg_alpha(&c, NCALPHA_TRANSPARENT);
|
|
ncplane_set_base_cell(n, &c);
|
|
clock_gettime(CLOCK_MONOTONIC, &cur);
|
|
deadlinens = timespec_to_ns(&cur) + timespec_to_ns(&demodelay);
|
|
l = legend(nc, "default background, fg transparent, no glyph");
|
|
if( (err = slideitslideit(nc, n, deadlinens, &vely, &velx)) ){
|
|
ncplane_destroy(n);
|
|
ncplane_destroy(l);
|
|
return err;
|
|
}
|
|
ncplane_destroy(l);
|
|
|
|
// Set the foreground color, setting it to blend. We should get the underlying
|
|
// glyphs in a blended color, with the default background color.
|
|
nccell_set_fg_rgb(&c, 0x80c080);
|
|
nccell_set_fg_alpha(&c, NCALPHA_BLEND);
|
|
ncplane_set_base_cell(n, &c);
|
|
clock_gettime(CLOCK_MONOTONIC, &cur);
|
|
l = legend(nc, "default background, fg blended, no glyph");
|
|
deadlinens = timespec_to_ns(&cur) + timespec_to_ns(&demodelay);
|
|
if( (err = slideitslideit(nc, n, deadlinens, &vely, &velx)) ){
|
|
ncplane_destroy(n);
|
|
ncplane_destroy(l);
|
|
return err;
|
|
}
|
|
ncplane_destroy(l);
|
|
|
|
// Opaque foreground color. This produces underlying glyphs in the specified,
|
|
// fixed color, with the default background color.
|
|
nccell_set_fg_rgb(&c, 0x80c080);
|
|
nccell_set_fg_alpha(&c, NCALPHA_OPAQUE);
|
|
ncplane_set_base_cell(n, &c);
|
|
clock_gettime(CLOCK_MONOTONIC, &cur);
|
|
l = legend(nc, "default background, fg colored opaque, no glyph");
|
|
deadlinens = timespec_to_ns(&cur) + timespec_to_ns(&demodelay);
|
|
if( (err = slideitslideit(nc, n, deadlinens, &vely, &velx)) ){
|
|
ncplane_destroy(n);
|
|
ncplane_destroy(l);
|
|
return err;
|
|
}
|
|
ncplane_destroy(l);
|
|
|
|
// Now we replace the characters with X's, colored as underneath us.
|
|
// Our background color remains opaque default.
|
|
nccell_load_char(n, &c, 'X');
|
|
nccell_set_fg_default(&c);
|
|
nccell_set_fg_alpha(&c, NCALPHA_TRANSPARENT);
|
|
nccell_set_bg_alpha(&c, NCALPHA_OPAQUE);
|
|
ncplane_set_base_cell(n, &c);
|
|
clock_gettime(CLOCK_MONOTONIC, &cur);
|
|
l = legend(nc, "default colors, fg transparent, print glyph");
|
|
deadlinens = timespec_to_ns(&cur) + timespec_to_ns(&demodelay);
|
|
if( (err = slideitslideit(nc, n, deadlinens, &vely, &velx)) ){
|
|
ncplane_destroy(n);
|
|
ncplane_destroy(l);
|
|
return err;
|
|
}
|
|
ncplane_destroy(l);
|
|
|
|
// Now we replace the characters with X's, but draw the foreground and
|
|
// background color from below us.
|
|
nccell_set_fg_alpha(&c, NCALPHA_TRANSPARENT);
|
|
nccell_set_bg_alpha(&c, NCALPHA_TRANSPARENT);
|
|
ncplane_set_base_cell(n, &c);
|
|
clock_gettime(CLOCK_MONOTONIC, &cur);
|
|
l = legend(nc, "all transparent, print glyph");
|
|
deadlinens = timespec_to_ns(&cur) + timespec_to_ns(&demodelay);
|
|
if( (err = slideitslideit(nc, n, deadlinens, &vely, &velx)) ){
|
|
ncplane_destroy(n);
|
|
ncplane_destroy(l);
|
|
return err;
|
|
}
|
|
ncplane_destroy(l);
|
|
|
|
// Finally, we populate the plane for the first time with non-transparent
|
|
// characters. We blend, however, to show the underlying color in our glyphs.
|
|
nccell_set_fg_alpha(&c, NCALPHA_BLEND);
|
|
nccell_set_bg_alpha(&c, NCALPHA_BLEND);
|
|
nccell_set_fg_rgb(&c, 0x80c080);
|
|
nccell_set_bg_rgb(&c, 0x204080);
|
|
ncplane_set_base_cell(n, &c);
|
|
clock_gettime(CLOCK_MONOTONIC, &cur);
|
|
l = legend(nc, "all blended, print glyph");
|
|
deadlinens = timespec_to_ns(&cur) + timespec_to_ns(&demodelay);
|
|
if( (err = slideitslideit(nc, n, deadlinens, &vely, &velx)) ){
|
|
ncplane_destroy(n);
|
|
ncplane_destroy(l);
|
|
return err;
|
|
}
|
|
ncplane_destroy(l);
|
|
|
|
return ncplane_destroy(n);
|
|
}
|
|
|
|
// draws a border along the perimeter, then fills the inside with position
|
|
// markers, each a slightly different color. the goal is to make sure we can
|
|
// have a great many colors, that they progress reasonably through the space,
|
|
// and that we can write to every coordinate.
|
|
int trans_demo(struct notcurses* nc){
|
|
int maxx, maxy;
|
|
struct ncplane* n = notcurses_stddim_yx(nc, &maxy, &maxx);
|
|
ncplane_set_fg_rgb8(n, 255, 255, 255);
|
|
uint64_t channels = 0;
|
|
ncchannels_set_fg_rgb8(&channels, 0, 128, 128);
|
|
ncchannels_set_bg_rgb8(&channels, 90, 0, 90);
|
|
int y = 1, x = 0;
|
|
ncplane_cursor_move_yx(n, y, x);
|
|
if(ncplane_rounded_box_sized(n, 0, channels, maxy - 1, maxx, 0)){
|
|
return -1;
|
|
}
|
|
uint32_t rgb = 0;
|
|
while(++y < maxy - 1){
|
|
x = 1;
|
|
if(ncplane_cursor_move_yx(n, y, x)){
|
|
return -1;
|
|
}
|
|
while(x < maxx - 1){
|
|
ncplane_set_fg_rgb8(n, (rgb & 0xff0000) >> 16u, (rgb & 0xff00) >> 8u, rgb & 0xff);
|
|
ncplane_set_bg_rgb8(n, 0, 10, 0);
|
|
ncplane_putchar(n, x % 10 + '0');
|
|
grow_rgb8(&rgb);
|
|
++x;
|
|
}
|
|
}
|
|
if(notcurses_canfade(nc)){
|
|
struct ncplane* l = legend(nc, "what say we explore transparency together?");
|
|
DEMO_RENDER(nc);
|
|
struct timespec now;
|
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
|
int err;
|
|
if( (err = ncplane_pulse(l, &demodelay, pulser, &now)) != 2){
|
|
return err;
|
|
}
|
|
ncplane_destroy(l);
|
|
}
|
|
return slidepanel(nc, n);
|
|
}
|