working demo
This commit is contained in:
commit
ee48872cc8
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
*.out
|
BIN
documentation/reference.jpg
Normal file
BIN
documentation/reference.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 141 KiB |
51
examples/ncurses_columns.c
Normal file
51
examples/ncurses_columns.c
Normal file
@ -0,0 +1,51 @@
|
||||
// @BAKE gcc $@ -o $*.out -I../ $(pkg-config --cflags --libs ncurses) -lm
|
||||
#include <stdio.h>
|
||||
#include <ncurses.h>
|
||||
#include "rect_layouts.h"
|
||||
|
||||
WINDOW * windows[5] = { NULL, NULL, NULL, NULL, NULL };
|
||||
|
||||
void do_resize(void) {
|
||||
rect_t parent = center(get_screen_rect(), scale(get_screen_rect(), 0.8));
|
||||
for (int i = 0; i < 5; i++) {
|
||||
delwin(windows[i]);
|
||||
// NOTE: we are actually redundantly recalculating,
|
||||
// both for scaling and in the expansion of UNPACK;
|
||||
// a temp var should be deployed;
|
||||
// now, this is generally bad and should be avoided,
|
||||
// however it *does work* and developer comfort is a top priority
|
||||
windows[i] = newwin(UNPACK(next(rfloor(scalex(parent, 0.2)), i)));
|
||||
refresh();
|
||||
}
|
||||
|
||||
clear();
|
||||
wrefresh(stdscr);
|
||||
}
|
||||
|
||||
signed main(void) {
|
||||
initscr();
|
||||
noecho();
|
||||
curs_set(0);
|
||||
halfdelay(1);
|
||||
|
||||
do_resize();
|
||||
|
||||
while(1) {
|
||||
switch (wgetch(stdscr)) {
|
||||
case KEY_RESIZE: do_resize();
|
||||
}
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
int maxy, maxx;
|
||||
getmaxyx(windows[i], maxy, maxx);
|
||||
for (int h = 0; h < (maxy * maxx); h++) {
|
||||
waddch(windows[i], '0' + i);
|
||||
}
|
||||
box(windows[i], ACS_VLINE, ACS_HLINE);
|
||||
wrefresh(windows[i]);
|
||||
}
|
||||
}
|
||||
|
||||
endwin();
|
||||
return 0;
|
||||
}
|
60
examples/raylib_diablo_like.c
Normal file
60
examples/raylib_diablo_like.c
Normal file
@ -0,0 +1,60 @@
|
||||
// @BAKE gcc $@ -o $*.out -I../ -lraylib -lGL -lm -lpthread -ldl -lrt -lX11
|
||||
#include <raylib.h>
|
||||
#include "rect_layouts.h"
|
||||
|
||||
rect_t hotbar;
|
||||
rect_t healt;
|
||||
rect_t manna;
|
||||
rect_t inventory;
|
||||
rect_t inventory_inner;
|
||||
rect_t inventory_slot;
|
||||
|
||||
void do_resize(void) {
|
||||
hotbar = ride(after(get_screen_rect(), 1), scaley(get_screen_rect(), 0.17f));
|
||||
healt = ride(after(get_screen_rect(), 1), scale(get_unit_rect(), hotbar.height * 1.2f));
|
||||
manna = paper(hotbar, healt);
|
||||
inventory = stretchy(hotbar, paper(get_screen_rect(), scalex(get_screen_rect(), 0.5f)));
|
||||
inventory_inner = buoyance(inventory, scale(inventory, 0.8f));
|
||||
inventory_slot = rock(inventory_inner, hang(inventory_inner, scale(get_unit_rect(), inventory_inner.width / 9)));
|
||||
}
|
||||
|
||||
signed main(void) {
|
||||
SetConfigFlags(FLAG_WINDOW_RESIZABLE);
|
||||
InitWindow(600, 600, "");
|
||||
|
||||
do_resize();
|
||||
|
||||
while (!WindowShouldClose()) {
|
||||
if (IsWindowResized()) {
|
||||
do_resize();
|
||||
}
|
||||
|
||||
BeginDrawing();
|
||||
DrawRectangleRec(get_screen_rect(), RAYWHITE);
|
||||
DrawRectangleRec(inventory, BLACK);
|
||||
DrawRectangleRec(inventory_inner, GRAY);
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
for (int h = 0; h < 9; h++) {
|
||||
DrawRectangleRec(
|
||||
after(next(inventory_slot, h), i),
|
||||
(Color) {
|
||||
(unsigned char)(0 + ((i + h) * 10)),
|
||||
(unsigned char)(0 + ((i + h) * 10)),
|
||||
(unsigned char)(0 + ((i + h) * 10)),
|
||||
255,
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
DrawRectangleRec(hotbar, GRAY);
|
||||
DrawRectangleRec(healt, RED);
|
||||
DrawRectangleRec(manna, BLUE);
|
||||
EndDrawing();
|
||||
}
|
||||
|
||||
CloseWindow();
|
||||
|
||||
return 0;
|
||||
}
|
404
rect_layouts.h
Normal file
404
rect_layouts.h
Normal file
@ -0,0 +1,404 @@
|
||||
#ifndef RECT_LAYOUTS_H
|
||||
#define RECT_LAYOUTS_H
|
||||
/* This header file defines with intuitive rectangle transformations.
|
||||
*
|
||||
* The intended purpose is to ease defining single screen interfaces.
|
||||
* Layout engines are great, but very complex to implement and master.
|
||||
* Static layouts on the otherhand tend to get very ugly, verbose and bug prone.
|
||||
* The idea is to have a very minimalistic abstraction layer,
|
||||
* with easy to visualize operations.
|
||||
* This solves readability and typo-ing x to y, while being widely usable,
|
||||
* adaptable or even reimplementable within just a few minutes.
|
||||
*
|
||||
* No doubt someone somewhere has adapted a similar approach before,
|
||||
* however to the best of my knowledge this is the first attempt
|
||||
* to normalize it into a library.
|
||||
* In case I'm wrong, please throw me and email.
|
||||
*/
|
||||
|
||||
// TODO: further macro hell x, y, width and height so they can be user overwritten too
|
||||
// TODO: stretch(x|y) naming is meh
|
||||
// TODO: theres a logical inconsistency between ride-hang and rock-paper; either justify it or normalize it
|
||||
|
||||
|
||||
// ### --------------- ###
|
||||
// ### SPECIALIZATIONS ###
|
||||
// ### --------------- ###
|
||||
/* This has to go on top, because macros. Please read on.
|
||||
*/
|
||||
|
||||
#ifdef RAYLIB_H
|
||||
# define rect_t Rectangle
|
||||
static inline
|
||||
rect_t get_screen_rect(void) {
|
||||
return (rect_t) {
|
||||
.x = 0,
|
||||
.y = 0,
|
||||
.width = (float)GetScreenWidth(),
|
||||
.height = (float)GetScreenHeight(),
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// ### ------- ###
|
||||
// ### General ###
|
||||
// ### ------- ###
|
||||
|
||||
/* Our internal rectangle representation.
|
||||
* Feel free to overwrite it with whatever suits you,
|
||||
* just #define alias it to `rect_t`.
|
||||
*/
|
||||
#ifndef rect_t
|
||||
typedef struct rect_t {
|
||||
float x, y, width, height;
|
||||
} rect_t;
|
||||
#endif
|
||||
|
||||
#ifdef __NCURSES_H
|
||||
# define UNPACK(r) (int)r.height, (int)r.width, (int)r.y, (int)r.x
|
||||
static inline
|
||||
rect_t get_screen_rect(void) {
|
||||
return (rect_t) {
|
||||
.x = 0,
|
||||
.y = 0,
|
||||
.width = (float)COLS,
|
||||
.height = (float)LINES,
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
// tl;dr
|
||||
static inline rect_t rfloor(rect_t r);
|
||||
static inline rect_t get_unit_rect(void);
|
||||
static inline rect_t scaley(rect_t a, float f);
|
||||
static inline rect_t scalex(rect_t a, float f);
|
||||
static inline rect_t scale(rect_t a, float f);
|
||||
static inline rect_t balance(rect_t dest, rect_t source);
|
||||
static inline rect_t buoyance(rect_t dest, rect_t source);
|
||||
static inline rect_t center(rect_t dest, rect_t source);
|
||||
static inline rect_t hang(rect_t dest, rect_t source);
|
||||
static inline rect_t ride(rect_t dest, rect_t source);
|
||||
static inline rect_t rock(rect_t dest, rect_t source);
|
||||
static inline rect_t paper(rect_t dest, rect_t source);
|
||||
static inline rect_t next(rect_t source, int n);
|
||||
static inline rect_t after(rect_t source, int n);
|
||||
static inline rect_t stretchy(rect_t dest, rect_t source);
|
||||
static inline rect_t stretchx(rect_t dest, rect_t source);
|
||||
|
||||
|
||||
|
||||
/* Floor every field of a rect.
|
||||
* Useful if next() or after() create visible gaps.
|
||||
* NOTE: we are not actually floaring so we dont depend on <math.h>,
|
||||
* for our ends and purposes it should just werk™
|
||||
*/
|
||||
static inline
|
||||
rect_t rfloor(rect_t r) {
|
||||
return (rect_t) {
|
||||
.x = (long long)r.x,
|
||||
.y = (long long)r.y,
|
||||
.width = (long long)r.width,
|
||||
.height = (long long)r.height,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/* Return the easiest rect to transform.
|
||||
* Coordinates (0, 0) are easy to shift.
|
||||
* Size 1x1 is easy to scale.
|
||||
*
|
||||
* +-+
|
||||
* +-+
|
||||
*/
|
||||
static inline
|
||||
rect_t get_unit_rect(void) {
|
||||
return (rect_t) {
|
||||
.x = 0,
|
||||
.y = 0,
|
||||
.width = 1,
|
||||
.height = 1,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/* Modify the width by a factor.
|
||||
*
|
||||
* +-+ __\ +---+
|
||||
* +-+ / +---+
|
||||
*/
|
||||
static inline
|
||||
rect_t scalex(rect_t a, float f) {
|
||||
return (rect_t) {
|
||||
.x = a.x,
|
||||
.y = a.y,
|
||||
.width = a.width * f,
|
||||
.height = a.height,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/* Modify the height by a factor.
|
||||
*
|
||||
* +-+ __\ +-+
|
||||
* +-+ / | |
|
||||
* +-+
|
||||
*/
|
||||
static inline
|
||||
rect_t scaley(rect_t a, float f) {
|
||||
return (rect_t) {
|
||||
.x = a.x,
|
||||
.y = a.y,
|
||||
.width = a.width,
|
||||
.height = a.height * f,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/* Modify the height and width by a factor.
|
||||
* Exists because its judged to be a common operation.
|
||||
*
|
||||
* +-+ __\ +---+
|
||||
* +-+ / | |
|
||||
* +---+
|
||||
*/
|
||||
static inline
|
||||
rect_t scale(rect_t a, float f) {
|
||||
return (rect_t) {
|
||||
.x = a.x,
|
||||
.y = a.y,
|
||||
.width = a.width * f,
|
||||
.height = a.height * f,
|
||||
};
|
||||
}
|
||||
|
||||
/* Align to the middle horiontally
|
||||
*
|
||||
* +---+---+---+
|
||||
* | : |
|
||||
* +---+ |
|
||||
* | | |
|
||||
* | | |
|
||||
* +---+ |
|
||||
* | : |
|
||||
* +---+---+---+
|
||||
*/
|
||||
static inline
|
||||
rect_t balance(rect_t dest, rect_t source) {
|
||||
return (rect_t) {
|
||||
.x = dest.x + ((dest.width - source.width) / 2),
|
||||
.y = source.y,
|
||||
.width = source.width,
|
||||
.height = source.height,
|
||||
};
|
||||
}
|
||||
|
||||
/* Align to the middle vertically
|
||||
*
|
||||
* +---+---+---+
|
||||
* | | | |
|
||||
* | - | | - |
|
||||
* | +---+ |
|
||||
* | |
|
||||
* | |
|
||||
* | |
|
||||
* +---+---+---+
|
||||
*/
|
||||
static inline
|
||||
rect_t buoyance(rect_t dest, rect_t source) {
|
||||
return (rect_t) {
|
||||
.x = source.x,
|
||||
.y = dest.y + ((dest.height - source.height) / 2),
|
||||
.width = source.width,
|
||||
.height = source.height,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/* Blance and Buoyance. Align to the middle vertically and horizontally.
|
||||
* Exists because its judged to be a common operation.
|
||||
*
|
||||
* +-----------+
|
||||
* | : |
|
||||
* | +---+ |
|
||||
* | - | | - |
|
||||
* | | | |
|
||||
* | +---+ |
|
||||
* | : |
|
||||
* +-----------+
|
||||
*/
|
||||
static inline
|
||||
rect_t center(rect_t dest, rect_t source) {
|
||||
return balance(dest, buoyance(dest, source));
|
||||
}
|
||||
|
||||
|
||||
/* Dangles from the top.
|
||||
*
|
||||
* +---+-------+
|
||||
* | | |
|
||||
* | | |
|
||||
* +---+ |
|
||||
* | |
|
||||
* | |
|
||||
* | |
|
||||
* +-----------+
|
||||
*/
|
||||
static inline
|
||||
rect_t hang(rect_t dest, rect_t source) {
|
||||
return (rect_t) {
|
||||
.x = source.x,
|
||||
.y = dest.y,
|
||||
.width = source.width,
|
||||
.height = source.height,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/* Places on the top.
|
||||
*
|
||||
* +---+
|
||||
* | |
|
||||
* | |
|
||||
* +---+-------+
|
||||
* | |
|
||||
* | |
|
||||
* | |
|
||||
* | |
|
||||
* | |
|
||||
* | |
|
||||
* +-----------+
|
||||
*/
|
||||
static inline
|
||||
rect_t ride(rect_t dest, rect_t source) {
|
||||
return (rect_t) {
|
||||
.x = source.x,
|
||||
.y = dest.y - source.height,
|
||||
.width = source.width,
|
||||
.height = source.height,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/* Moves to the left.
|
||||
* NOTE: this is a reference to the political compas, for easy memorization.
|
||||
*
|
||||
* +---+-------+
|
||||
* | | |
|
||||
* | | |
|
||||
* +---+ |
|
||||
* | |
|
||||
* | |
|
||||
* | |
|
||||
* +-----------+
|
||||
*/
|
||||
static inline
|
||||
rect_t rock(rect_t dest, rect_t source) {
|
||||
return (rect_t) {
|
||||
.x = dest.x,
|
||||
.y = source.y,
|
||||
.width = source.width,
|
||||
.height = source.height,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/* Moves to the right.
|
||||
* NOTE: this is a reference to the political compas, for easy memorization.
|
||||
*
|
||||
* +-------+---+
|
||||
* | | |
|
||||
* | | |
|
||||
* | +---+
|
||||
* | |
|
||||
* | |
|
||||
* | |
|
||||
* +-----------+
|
||||
*/
|
||||
static inline
|
||||
rect_t paper(rect_t dest, rect_t source) {
|
||||
return (rect_t) {
|
||||
.x = (dest.x + dest.width) - source.width,
|
||||
.y = source.y,
|
||||
.width = source.width,
|
||||
.height = source.height,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/* Gets the N-th horiontal neighbour.
|
||||
*
|
||||
* +---+---+
|
||||
* | | |
|
||||
* | | |
|
||||
* +---+---+
|
||||
*/
|
||||
static inline
|
||||
rect_t next(rect_t source, int n) {
|
||||
return (rect_t) {
|
||||
.x = source.x + (source.width * n),
|
||||
.y = source.y,
|
||||
.width = source.width,
|
||||
.height = source.height,
|
||||
};
|
||||
}
|
||||
|
||||
/* Gets the N-th vectical neighbour.
|
||||
*
|
||||
* +---+
|
||||
* | |
|
||||
* | |
|
||||
* +---+
|
||||
* | |
|
||||
* | |
|
||||
* +---+
|
||||
*/
|
||||
static inline
|
||||
rect_t after(rect_t source, int n) {
|
||||
return (rect_t) {
|
||||
.x = source.x,
|
||||
.y = source.y + (source.height * n),
|
||||
.width = source.width,
|
||||
.height = source.height,
|
||||
};
|
||||
}
|
||||
|
||||
static inline
|
||||
rect_t stretchy(rect_t dest, rect_t source) {
|
||||
return (dest.y > source.y) ?
|
||||
(rect_t) {
|
||||
.x = source.x,
|
||||
.y = source.y,
|
||||
.width = source.width,
|
||||
.height = dest.y - source.y,
|
||||
}
|
||||
:
|
||||
(rect_t) {
|
||||
.x = source.x,
|
||||
.y = dest.y + dest.height,
|
||||
.width = source.width,
|
||||
.height = source.height + (source.y - (dest.y + dest.height)),
|
||||
}
|
||||
;
|
||||
}
|
||||
|
||||
static inline
|
||||
rect_t stretchx(rect_t dest, rect_t source) {
|
||||
return (dest.x > source.x) ?
|
||||
(rect_t) {
|
||||
.x = source.x,
|
||||
.y = source.y,
|
||||
.width = dest.x - source.x,
|
||||
.height = source.height,
|
||||
}
|
||||
:
|
||||
(rect_t) {
|
||||
.x = dest.x + dest.width,
|
||||
.y = source.y,
|
||||
.width = source.width + (source.x - (dest.x + dest.width)),
|
||||
.height = source.height,
|
||||
}
|
||||
;
|
||||
}
|
||||
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user