texed: image stacking ops
parent
88f77b709f
commit
9284086a3d
BIN
art/demo.ecotex
BIN
art/demo.ecotex
Binary file not shown.
1234
art/gen/demo.h
1234
art/gen/demo.h
File diff suppressed because it is too large
Load Diff
BIN
art/gen/demo.png
BIN
art/gen/demo.png
Binary file not shown.
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.1 KiB |
BIN
art/test.ecotex
BIN
art/test.ecotex
Binary file not shown.
|
@ -21,6 +21,7 @@
|
||||||
#define TD_UI_PADDING 5.0f
|
#define TD_UI_PADDING 5.0f
|
||||||
#define TD_UI_PREVIEW_BORDER 4.0f
|
#define TD_UI_PREVIEW_BORDER 4.0f
|
||||||
#define TD_UI_DEFAULT_ZOOM 4.0f
|
#define TD_UI_DEFAULT_ZOOM 4.0f
|
||||||
|
#define TD_IMAGES_MAX_STACK 128
|
||||||
|
|
||||||
static uint16_t screenWidth = 1280;
|
static uint16_t screenWidth = 1280;
|
||||||
static uint16_t screenHeight = 720;
|
static uint16_t screenHeight = 720;
|
||||||
|
@ -71,6 +72,9 @@ typedef enum {
|
||||||
TOP_FLIP_IMAGE,
|
TOP_FLIP_IMAGE,
|
||||||
TOP_ROTATE_IMAGE,
|
TOP_ROTATE_IMAGE,
|
||||||
|
|
||||||
|
TOP_PUSH_IMAGE,
|
||||||
|
TOP_POP_IMAGE,
|
||||||
|
|
||||||
TOP_FORCE_UINT8 = UINT8_MAX
|
TOP_FORCE_UINT8 = UINT8_MAX
|
||||||
} td_op_kind;
|
} td_op_kind;
|
||||||
|
|
||||||
|
@ -96,7 +100,8 @@ typedef struct {
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char *filepath;
|
char *filepath;
|
||||||
Image img;
|
int32_t img_pos;
|
||||||
|
Image img[TD_IMAGES_MAX_STACK];
|
||||||
Texture2D tex;
|
Texture2D tex;
|
||||||
GuiFileDialogState fileDialog;
|
GuiFileDialogState fileDialog;
|
||||||
td_msgbox msgbox;
|
td_msgbox msgbox;
|
||||||
|
@ -112,7 +117,8 @@ static char filename[200];
|
||||||
|
|
||||||
#include "texed_ops_list.c"
|
#include "texed_ops_list.c"
|
||||||
|
|
||||||
void texed_new(int32_t w, int32_t h);
|
void texed_new(int w, int h);
|
||||||
|
void texed_clear(void);
|
||||||
void texed_destroy(void);
|
void texed_destroy(void);
|
||||||
void texed_load(void);
|
void texed_load(void);
|
||||||
void texed_save(void);
|
void texed_save(void);
|
||||||
|
@ -124,6 +130,9 @@ void texed_msgbox_init(char const *title, char const *message, char const *butto
|
||||||
void texed_process_ops(void);
|
void texed_process_ops(void);
|
||||||
void texed_process_params(void);
|
void texed_process_params(void);
|
||||||
|
|
||||||
|
void texed_img_push(int w, int h, Color color);
|
||||||
|
void texed_img_pop(int x, int y, int w, int h, Color tint);
|
||||||
|
|
||||||
void texed_add_op(int kind);
|
void texed_add_op(int kind);
|
||||||
void texed_rem_op(int idx);
|
void texed_rem_op(int idx);
|
||||||
void texed_swp_op(int idx, int idx2);
|
void texed_swp_op(int idx, int idx2);
|
||||||
|
@ -310,7 +319,9 @@ void texed_run(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void texed_new(int32_t w, int32_t h) {
|
void texed_new(int32_t w, int32_t h) {
|
||||||
ctx.img = GenImageColor(w, h, WHITE);
|
ctx.img_pos = -1;
|
||||||
|
zpl_memset(ctx.img, 0, sizeof(Image)*TD_IMAGES_MAX_STACK);
|
||||||
|
texed_img_push(w, h, WHITE);
|
||||||
ctx.filepath = NULL;
|
ctx.filepath = NULL;
|
||||||
ctx.selected_op = 0;
|
ctx.selected_op = 0;
|
||||||
ctx.msgbox.result = -1;
|
ctx.msgbox.result = -1;
|
||||||
|
@ -327,21 +338,59 @@ void texed_new(int32_t w, int32_t h) {
|
||||||
ctx.is_saved = true;
|
ctx.is_saved = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void texed_clear(void) {
|
||||||
|
zpl_array_clear(ctx.ops);
|
||||||
|
for (int i = 0; i <= ctx.img_pos; i+=1)
|
||||||
|
UnloadImage(ctx.img[i]);
|
||||||
|
ctx.img_pos = -1;
|
||||||
|
}
|
||||||
|
|
||||||
void texed_destroy(void) {
|
void texed_destroy(void) {
|
||||||
UnloadTexture(ctx.tex);
|
texed_clear();
|
||||||
UnloadImage(ctx.img);
|
|
||||||
CloseWindow();
|
CloseWindow();
|
||||||
zpl_array_free(ctx.ops);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void texed_export_cc(char const *path) {
|
void texed_export_cc(char const *path) {
|
||||||
zpl_printf("Building texture %s.h ...\n", path);
|
zpl_printf("Building texture %s.h ...\n", path);
|
||||||
ExportImageAsCode(ctx.img, zpl_bprintf("art/gen/%s.h", GetFileNameWithoutExt(path)));
|
ExportImageAsCode(ctx.img[ctx.img_pos], zpl_bprintf("art/gen/%s.h", GetFileNameWithoutExt(path)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void texed_export_png(char const *path) {
|
void texed_export_png(char const *path) {
|
||||||
zpl_printf("Exporting texture %s.png ...\n", path);
|
zpl_printf("Exporting texture %s.png ...\n", path);
|
||||||
ExportImage(ctx.img, zpl_bprintf("art/gen/%s.png", GetFileNameWithoutExt(path)));
|
ExportImage(ctx.img[ctx.img_pos], zpl_bprintf("art/gen/%s.png", GetFileNameWithoutExt(path)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void texed_img_push(int w, int h, Color color) {
|
||||||
|
if (ctx.img_pos == TD_IMAGES_MAX_STACK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ctx.img_pos += 1;
|
||||||
|
ctx.img[ctx.img_pos] = GenImageColor(w, h, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
void texed_img_pop(int x, int y, int w, int h, Color tint) {
|
||||||
|
if (ctx.img_pos == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Image *oi = &ctx.img[ctx.img_pos];
|
||||||
|
Image *di = &ctx.img[ctx.img_pos-1];
|
||||||
|
|
||||||
|
Rectangle src = {
|
||||||
|
0, 0,
|
||||||
|
oi->width, oi->height
|
||||||
|
};
|
||||||
|
|
||||||
|
w = (w == 0) ? di->width : w;
|
||||||
|
h = (h == 0) ? di->height : h;
|
||||||
|
|
||||||
|
Rectangle dst = {
|
||||||
|
x, y,
|
||||||
|
w, h,
|
||||||
|
};
|
||||||
|
|
||||||
|
ImageDraw(di, *oi, src, dst, tint);
|
||||||
|
UnloadImage(ctx.img[ctx.img_pos]);
|
||||||
|
ctx.img_pos -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void texed_repaint_preview(void) {
|
void texed_repaint_preview(void) {
|
||||||
|
@ -350,7 +399,7 @@ void texed_repaint_preview(void) {
|
||||||
|
|
||||||
if (!IsWindowReady()) return;
|
if (!IsWindowReady()) return;
|
||||||
UnloadTexture(ctx.tex);
|
UnloadTexture(ctx.tex);
|
||||||
ctx.tex = LoadTextureFromImage(ctx.img);
|
ctx.tex = LoadTextureFromImage(ctx.img[ctx.img_pos]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void texed_compose_image(void) {
|
void texed_compose_image(void) {
|
||||||
|
@ -369,7 +418,6 @@ void texed_msgbox_init(char const *title, char const *message, char const *butto
|
||||||
}
|
}
|
||||||
|
|
||||||
int texed_find_op(int kind) {
|
int texed_find_op(int kind) {
|
||||||
assert(kind >= 0 && kind < DEF_OPS_LEN);
|
|
||||||
for (int i = 0; i < DEF_OPS_LEN; i += 1) {
|
for (int i = 0; i < DEF_OPS_LEN; i += 1) {
|
||||||
if (default_ops[i].kind == kind) {
|
if (default_ops[i].kind == kind) {
|
||||||
return i;
|
return i;
|
||||||
|
@ -379,8 +427,9 @@ int texed_find_op(int kind) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void texed_add_op(int kind) {
|
void texed_add_op(int kind) {
|
||||||
assert(kind >= 0 && kind < DEF_OPS_LEN);
|
int idx = texed_find_op(kind);
|
||||||
td_op *dop = &default_ops[texed_find_op(kind)];
|
assert(idx >= 0);
|
||||||
|
td_op *dop = &default_ops[idx];
|
||||||
|
|
||||||
td_op op = {
|
td_op op = {
|
||||||
.kind = dop->kind,
|
.kind = dop->kind,
|
||||||
|
|
|
@ -2,18 +2,29 @@ static inline
|
||||||
float texed_map_value(float v, float min, float max);
|
float texed_map_value(float v, float min, float max);
|
||||||
|
|
||||||
void texed_process_ops(void) {
|
void texed_process_ops(void) {
|
||||||
|
for (int i = 0; i <= ctx.img_pos; i+=1)
|
||||||
|
UnloadImage(ctx.img[i]);
|
||||||
|
ctx.img_pos = -1;
|
||||||
|
|
||||||
for (int i = 0; i < zpl_array_count(ctx.ops); i += 1) {
|
for (int i = 0; i < zpl_array_count(ctx.ops); i += 1) {
|
||||||
td_op *op = &ctx.ops[i];
|
td_op *op = &ctx.ops[i];
|
||||||
if (op->is_hidden) continue;
|
if (op->is_hidden) continue;
|
||||||
zpl_printf("processing op: %s ... \n", op->name);
|
zpl_printf("processing op: %s ... \n", op->name);
|
||||||
|
|
||||||
switch (op->kind) {
|
switch (op->kind) {
|
||||||
|
case TOP_PUSH_IMAGE:
|
||||||
case TOP_NEW_IMAGE: {
|
case TOP_NEW_IMAGE: {
|
||||||
UnloadImage(ctx.img);
|
texed_img_push(op->params[0].i32, op->params[1].i32, op->params[2].color);
|
||||||
ctx.img = GenImageColor(op->params[0].i32, op->params[1].i32, op->params[2].color);
|
}break;
|
||||||
|
case TOP_POP_IMAGE: {
|
||||||
|
texed_img_pop(op->params[0].i32,
|
||||||
|
op->params[1].i32,
|
||||||
|
op->params[2].i32,
|
||||||
|
op->params[3].i32,
|
||||||
|
op->params[4].color);
|
||||||
}break;
|
}break;
|
||||||
case TOP_DRAW_RECT: {
|
case TOP_DRAW_RECT: {
|
||||||
ImageDrawRectangle(&ctx.img,
|
ImageDrawRectangle(&ctx.img[ctx.img_pos],
|
||||||
op->params[0].i32,
|
op->params[0].i32,
|
||||||
op->params[1].i32,
|
op->params[1].i32,
|
||||||
op->params[2].i32,
|
op->params[2].i32,
|
||||||
|
@ -21,7 +32,7 @@ void texed_process_ops(void) {
|
||||||
op->params[4].color);
|
op->params[4].color);
|
||||||
}break;
|
}break;
|
||||||
case TOP_DRAW_LINE: {
|
case TOP_DRAW_LINE: {
|
||||||
ImageDrawLine(&ctx.img,
|
ImageDrawLine(&ctx.img[ctx.img_pos],
|
||||||
op->params[0].i32,
|
op->params[0].i32,
|
||||||
op->params[1].i32,
|
op->params[1].i32,
|
||||||
op->params[2].i32,
|
op->params[2].i32,
|
||||||
|
@ -29,7 +40,7 @@ void texed_process_ops(void) {
|
||||||
op->params[4].color);
|
op->params[4].color);
|
||||||
}break;
|
}break;
|
||||||
case TOP_DITHER: {
|
case TOP_DITHER: {
|
||||||
ImageDither(&ctx.img,
|
ImageDither(&ctx.img[ctx.img_pos],
|
||||||
op->params[0].i32,
|
op->params[0].i32,
|
||||||
op->params[1].i32,
|
op->params[1].i32,
|
||||||
op->params[2].i32,
|
op->params[2].i32,
|
||||||
|
@ -46,8 +57,8 @@ void texed_process_ops(void) {
|
||||||
int flip = op->params[5].i32;
|
int flip = op->params[5].i32;
|
||||||
int rotate = op->params[6].i32;
|
int rotate = op->params[6].i32;
|
||||||
|
|
||||||
if (w != -1 || h != -1) {
|
if (w != 0 || h != 0) {
|
||||||
ImageResize(&img, w != -1 ? w : img.width, h != -1 ? h : img.height);
|
ImageResize(&img, w != 0 ? w : img.width, h != 0 ? h : img.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flip == 1) {
|
if (flip == 1) {
|
||||||
|
@ -62,7 +73,7 @@ void texed_process_ops(void) {
|
||||||
ImageRotateCCW(&img);
|
ImageRotateCCW(&img);
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageDraw(&ctx.img, img,
|
ImageDraw(&ctx.img[ctx.img_pos], img,
|
||||||
(Rectangle){0.0f, 0.0f, img.width, img.height},
|
(Rectangle){0.0f, 0.0f, img.width, img.height},
|
||||||
(Rectangle){x, y, img.width, img.height},
|
(Rectangle){x, y, img.width, img.height},
|
||||||
op->params[5].color);
|
op->params[5].color);
|
||||||
|
@ -78,29 +89,29 @@ void texed_process_ops(void) {
|
||||||
int y = op->params[2].i32;
|
int y = op->params[2].i32;
|
||||||
int size = op->params[3].i32;
|
int size = op->params[3].i32;
|
||||||
Color color = op->params[4].color;
|
Color color = op->params[4].color;
|
||||||
ImageDrawText(&ctx.img, str, x, y, size, color);
|
ImageDrawText(&ctx.img[ctx.img_pos], str, x, y, size, color);
|
||||||
}break;
|
}break;
|
||||||
case TOP_RESIZE_IMAGE: {
|
case TOP_RESIZE_IMAGE: {
|
||||||
if (ctx.img.width == 0) break;
|
if (ctx.img[ctx.img_pos].width == 0) break;
|
||||||
int w = op->params[0].i32;
|
int w = op->params[0].i32;
|
||||||
int h = op->params[1].i32;
|
int h = op->params[1].i32;
|
||||||
int mode = op->params[2].i32;
|
int mode = op->params[2].i32;
|
||||||
if (mode) {
|
if (mode) {
|
||||||
ImageResize(&ctx.img, w, h);
|
ImageResize(&ctx.img[ctx.img_pos], w, h);
|
||||||
} else {
|
} else {
|
||||||
ImageResizeNN(&ctx.img, w, h);
|
ImageResizeNN(&ctx.img[ctx.img_pos], w, h);
|
||||||
}
|
}
|
||||||
}break;
|
}break;
|
||||||
case TOP_COLOR_TWEAKS: {
|
case TOP_COLOR_TWEAKS: {
|
||||||
ImageColorContrast(&ctx.img, texed_map_value(op->params[0].flt, -100.0f, 100.0f));
|
ImageColorContrast(&ctx.img[ctx.img_pos], texed_map_value(op->params[0].flt, -100.0f, 100.0f));
|
||||||
ImageColorBrightness(&ctx.img, (int)texed_map_value(op->params[1].flt, -255.0f, 255.0f));
|
ImageColorBrightness(&ctx.img[ctx.img_pos], (int)texed_map_value(op->params[1].flt, -255.0f, 255.0f));
|
||||||
ImageColorTint(&ctx.img, op->params[2].color);
|
ImageColorTint(&ctx.img[ctx.img_pos], op->params[2].color);
|
||||||
|
|
||||||
if (op->params[3].i32) {
|
if (op->params[3].i32) {
|
||||||
ImageColorInvert(&ctx.img);
|
ImageColorInvert(&ctx.img[ctx.img_pos]);
|
||||||
}
|
}
|
||||||
if (op->params[4].i32) {
|
if (op->params[4].i32) {
|
||||||
ImageColorGrayscale(&ctx.img);
|
ImageColorGrayscale(&ctx.img[ctx.img_pos]);
|
||||||
}
|
}
|
||||||
}break;
|
}break;
|
||||||
default: {
|
default: {
|
||||||
|
|
|
@ -12,6 +12,22 @@ static td_op default_ops[] = {
|
||||||
PARAM(TPARAM_COORD, "h", "64"),
|
PARAM(TPARAM_COORD, "h", "64"),
|
||||||
PARAM(TPARAM_COLOR, "color", "ffffffff"),
|
PARAM(TPARAM_COLOR, "color", "ffffffff"),
|
||||||
}
|
}
|
||||||
|
},{
|
||||||
|
OP(TOP_PUSH_IMAGE),
|
||||||
|
PARAMS(3) {
|
||||||
|
PARAM(TPARAM_COORD, "w", "64"),
|
||||||
|
PARAM(TPARAM_COORD, "h", "64"),
|
||||||
|
PARAM(TPARAM_COLOR, "color", "ffffffff"),
|
||||||
|
}
|
||||||
|
},{
|
||||||
|
OP(TOP_POP_IMAGE),
|
||||||
|
PARAMS(5) {
|
||||||
|
PARAM(TPARAM_COORD, "x", "0"),
|
||||||
|
PARAM(TPARAM_COORD, "y", "0"),
|
||||||
|
PARAM(TPARAM_COORD, "w", "0"),
|
||||||
|
PARAM(TPARAM_COORD, "h", "0"),
|
||||||
|
PARAM(TPARAM_COLOR, "tint", "ffffffff"),
|
||||||
|
}
|
||||||
},{
|
},{
|
||||||
OP(TOP_DRAW_RECT),
|
OP(TOP_DRAW_RECT),
|
||||||
PARAMS(5) {
|
PARAMS(5) {
|
||||||
|
@ -36,8 +52,8 @@ static td_op default_ops[] = {
|
||||||
PARAM(TPARAM_STRING, "src", "samples/test.png"),
|
PARAM(TPARAM_STRING, "src", "samples/test.png"),
|
||||||
PARAM(TPARAM_COORD, "x", "0"),
|
PARAM(TPARAM_COORD, "x", "0"),
|
||||||
PARAM(TPARAM_COORD, "y", "0"),
|
PARAM(TPARAM_COORD, "y", "0"),
|
||||||
PARAM(TPARAM_COORD, "w", "-1"),
|
PARAM(TPARAM_COORD, "w", "0"),
|
||||||
PARAM(TPARAM_COORD, "h", "-1"),
|
PARAM(TPARAM_COORD, "h", "0"),
|
||||||
PARAM(TPARAM_COLOR, "tint", "ffffffff"),
|
PARAM(TPARAM_COLOR, "tint", "ffffffff"),
|
||||||
PARAM(TPARAM_INT, "flip?", "0"),
|
PARAM(TPARAM_INT, "flip?", "0"),
|
||||||
PARAM(TPARAM_INT, "rotate?", "0"),
|
PARAM(TPARAM_INT, "rotate?", "0"),
|
||||||
|
@ -54,10 +70,10 @@ static td_op default_ops[] = {
|
||||||
},{
|
},{
|
||||||
OP(TOP_DITHER),
|
OP(TOP_DITHER),
|
||||||
PARAMS(4) {
|
PARAMS(4) {
|
||||||
PARAM(TPARAM_INT, "r_bpp", "8"),
|
PARAM(TPARAM_INT, "r_bpp", "4"),
|
||||||
PARAM(TPARAM_INT, "g_bpp", "8"),
|
PARAM(TPARAM_INT, "g_bpp", "4"),
|
||||||
PARAM(TPARAM_INT, "b_bpp", "8"),
|
PARAM(TPARAM_INT, "b_bpp", "4"),
|
||||||
PARAM(TPARAM_INT, "a_bpp", "8"),
|
PARAM(TPARAM_INT, "a_bpp", "4"),
|
||||||
}
|
}
|
||||||
},{
|
},{
|
||||||
OP(TOP_RESIZE_IMAGE),
|
OP(TOP_RESIZE_IMAGE),
|
||||||
|
|
|
@ -9,8 +9,7 @@ void texed_load(void) {
|
||||||
assert(ctx.filepath);
|
assert(ctx.filepath);
|
||||||
zpl_printf("Loading %s ...\n", ctx.filepath);
|
zpl_printf("Loading %s ...\n", ctx.filepath);
|
||||||
is_repaint_locked = true;
|
is_repaint_locked = true;
|
||||||
zpl_array_clear(ctx.ops);
|
texed_clear();
|
||||||
|
|
||||||
uint32_t size = 0;
|
uint32_t size = 0;
|
||||||
uint8_t *databuf = LoadFileData(zpl_bprintf("art/%s", ctx.filepath), &size);
|
uint8_t *databuf = LoadFileData(zpl_bprintf("art/%s", ctx.filepath), &size);
|
||||||
|
|
||||||
|
@ -24,7 +23,7 @@ void texed_load(void) {
|
||||||
int selected_op = (int)uc.item.as.u64;
|
int selected_op = (int)uc.item.as.u64;
|
||||||
|
|
||||||
UNPACK(CWP_ITEM_FLOAT);
|
UNPACK(CWP_ITEM_FLOAT);
|
||||||
zoom = uc.item.as.real;
|
old_zoom = zoom = uc.item.as.real;
|
||||||
|
|
||||||
UNPACK(CWP_ITEM_ARRAY);
|
UNPACK(CWP_ITEM_ARRAY);
|
||||||
int arrsize = (int)uc.item.as.array.size;
|
int arrsize = (int)uc.item.as.array.size;
|
||||||
|
|
|
@ -2,6 +2,8 @@ static inline
|
||||||
void int_to_hex_color(uint32_t color, char *text);
|
void int_to_hex_color(uint32_t color, char *text);
|
||||||
static inline
|
static inline
|
||||||
int GuiDropdownBoxEco(Rectangle bounds, char const *text, char const *caption, int *active, bool editMode);
|
int GuiDropdownBoxEco(Rectangle bounds, char const *text, char const *caption, int *active, bool editMode);
|
||||||
|
static inline
|
||||||
|
bool GuiValueBoxEco(Rectangle bounds, const char *text, int *value, int minValue, int maxValue, bool editMode);
|
||||||
|
|
||||||
static inline
|
static inline
|
||||||
bool IsCtrlAcceleratorPressed(char key);
|
bool IsCtrlAcceleratorPressed(char key);
|
||||||
|
@ -22,7 +24,7 @@ void texed_draw_topbar(zpl_aabb2 r) {
|
||||||
|
|
||||||
if (GuiButton(aabb2_ray(new_prj_r), "NEW") || IsCtrlAcceleratorPressed('n')) {
|
if (GuiButton(aabb2_ray(new_prj_r), "NEW") || IsCtrlAcceleratorPressed('n')) {
|
||||||
if (ctx.is_saved) {
|
if (ctx.is_saved) {
|
||||||
texed_destroy();
|
texed_clear();
|
||||||
texed_new(TD_DEFAULT_IMG_WIDTH, TD_DEFAULT_IMG_HEIGHT);
|
texed_new(TD_DEFAULT_IMG_WIDTH, TD_DEFAULT_IMG_HEIGHT);
|
||||||
} else {
|
} else {
|
||||||
new_pending = true;
|
new_pending = true;
|
||||||
|
@ -33,7 +35,7 @@ void texed_draw_topbar(zpl_aabb2 r) {
|
||||||
if (new_pending && ctx.msgbox.result != -1) {
|
if (new_pending && ctx.msgbox.result != -1) {
|
||||||
new_pending = false;
|
new_pending = false;
|
||||||
if (ctx.msgbox.result == 1) {
|
if (ctx.msgbox.result == 1) {
|
||||||
texed_destroy();
|
texed_clear();
|
||||||
texed_new(TD_DEFAULT_IMG_WIDTH, TD_DEFAULT_IMG_HEIGHT);
|
texed_new(TD_DEFAULT_IMG_WIDTH, TD_DEFAULT_IMG_HEIGHT);
|
||||||
}
|
}
|
||||||
ctx.msgbox.result = -1; // NOTE(zaklaus): ensure we don't re-trigger this branch next frame
|
ctx.msgbox.result = -1; // NOTE(zaklaus): ensure we don't re-trigger this branch next frame
|
||||||
|
@ -293,12 +295,14 @@ void texed_draw_props_pane(zpl_aabb2 r) {
|
||||||
}break;
|
}break;
|
||||||
case TPARAM_INT:
|
case TPARAM_INT:
|
||||||
case TPARAM_COORD: {
|
case TPARAM_COORD: {
|
||||||
if (GuiValueBox(aabb2_ray(tbox_r), NULL, &p->i32, INT32_MIN, INT32_MAX, p->edit_mode)) {
|
if (GuiValueBoxEco(aabb2_ray(tbox_r), NULL, &p->i32, INT32_MIN, INT32_MAX, p->edit_mode)) {
|
||||||
p->edit_mode = !p->edit_mode;
|
p->edit_mode = !p->edit_mode;
|
||||||
|
|
||||||
if (!p->edit_mode) {
|
if (!p->edit_mode) {
|
||||||
sprintf(p->str, "%d", p->i32);
|
sprintf(p->str, "%d", p->i32);
|
||||||
texed_repaint_preview();
|
texed_repaint_preview();
|
||||||
|
} else if (IsKeyDown(KEY_LEFT_SHIFT)) {
|
||||||
|
p->i32 = 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}break;
|
}break;
|
||||||
|
@ -485,4 +489,124 @@ void texed_draw_msgbox(zpl_aabb2 r) {
|
||||||
static inline
|
static inline
|
||||||
bool IsCtrlAcceleratorPressed(char key) {
|
bool IsCtrlAcceleratorPressed(char key) {
|
||||||
return (IsKeyDown(KEY_LEFT_CONTROL) || IsKeyDown(KEY_RIGHT_CONTROL)) && (char)GetKeyPressed() == key;
|
return (IsKeyDown(KEY_LEFT_CONTROL) || IsKeyDown(KEY_RIGHT_CONTROL)) && (char)GetKeyPressed() == key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline
|
||||||
|
bool GuiValueBoxEco(Rectangle bounds, const char *text, int *value, int minValue, int maxValue, bool editMode) {
|
||||||
|
#if !defined(VALUEBOX_MAX_CHARS)
|
||||||
|
#define VALUEBOX_MAX_CHARS 32
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int framesCounter = 0; // Required for blinking cursor
|
||||||
|
|
||||||
|
GuiControlState state = guiState;
|
||||||
|
bool pressed = false;
|
||||||
|
|
||||||
|
char textValue[VALUEBOX_MAX_CHARS + 1] = "\0";
|
||||||
|
sprintf(textValue, "%i", *value);
|
||||||
|
|
||||||
|
Rectangle textBounds = { 0 };
|
||||||
|
if (text != NULL)
|
||||||
|
{
|
||||||
|
textBounds.width = (float)GetTextWidth(text);
|
||||||
|
textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE);
|
||||||
|
textBounds.x = bounds.x + bounds.width + GuiGetStyle(VALUEBOX, TEXT_PADDING);
|
||||||
|
textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2;
|
||||||
|
if (GuiGetStyle(VALUEBOX, TEXT_ALIGNMENT) == GUI_TEXT_ALIGN_LEFT) textBounds.x = bounds.x - textBounds.width - GuiGetStyle(VALUEBOX, TEXT_PADDING);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update control
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
if ((state != GUI_STATE_DISABLED) && !guiLocked)
|
||||||
|
{
|
||||||
|
Vector2 mousePoint = GetMousePosition();
|
||||||
|
|
||||||
|
bool valueHasChanged = false;
|
||||||
|
|
||||||
|
if (editMode)
|
||||||
|
{
|
||||||
|
state = GUI_STATE_PRESSED;
|
||||||
|
|
||||||
|
framesCounter++;
|
||||||
|
|
||||||
|
int keyCount = (int)strlen(textValue);
|
||||||
|
|
||||||
|
// Only allow keys in range [48..57]
|
||||||
|
if (keyCount < VALUEBOX_MAX_CHARS)
|
||||||
|
{
|
||||||
|
if (GetTextWidth(textValue) < bounds.width)
|
||||||
|
{
|
||||||
|
int key = GetCharPressed();
|
||||||
|
if ((key >= 48) && (key <= 57))
|
||||||
|
{
|
||||||
|
textValue[keyCount] = (char)key;
|
||||||
|
keyCount++;
|
||||||
|
valueHasChanged = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete text
|
||||||
|
if (keyCount > 0)
|
||||||
|
{
|
||||||
|
if (IsKeyPressed(KEY_BACKSPACE))
|
||||||
|
{
|
||||||
|
keyCount--;
|
||||||
|
textValue[keyCount] = '\0';
|
||||||
|
framesCounter = 0;
|
||||||
|
if (keyCount < 0) keyCount = 0;
|
||||||
|
valueHasChanged = true;
|
||||||
|
}
|
||||||
|
else if (IsKeyDown(KEY_BACKSPACE))
|
||||||
|
{
|
||||||
|
if ((framesCounter > TEXTEDIT_CURSOR_BLINK_FRAMES) && (framesCounter%2) == 0) keyCount--;
|
||||||
|
textValue[keyCount] = '\0';
|
||||||
|
if (keyCount < 0) keyCount = 0;
|
||||||
|
valueHasChanged = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (valueHasChanged) *value = TextToInteger(textValue);
|
||||||
|
|
||||||
|
if (IsKeyPressed(KEY_ENTER) || (!CheckCollisionPointRec(mousePoint, bounds) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON))) pressed = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (*value > maxValue) *value = maxValue;
|
||||||
|
else if (*value < minValue) *value = minValue;
|
||||||
|
|
||||||
|
if (CheckCollisionPointRec(mousePoint, bounds))
|
||||||
|
{
|
||||||
|
state = GUI_STATE_FOCUSED;
|
||||||
|
if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) pressed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pressed) framesCounter = 0;
|
||||||
|
}
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Draw control
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
Color baseColor = BLANK;
|
||||||
|
if (state == GUI_STATE_PRESSED) baseColor = GetColor(GuiGetStyle(VALUEBOX, BASE_COLOR_PRESSED));
|
||||||
|
else if (state == GUI_STATE_DISABLED) baseColor = GetColor(GuiGetStyle(VALUEBOX, BASE_COLOR_DISABLED));
|
||||||
|
|
||||||
|
// WARNING: BLANK color does not work properly with Fade()
|
||||||
|
GuiDrawRectangle(bounds, GuiGetStyle(VALUEBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(VALUEBOX, BORDER + (state*3))), guiAlpha), baseColor);
|
||||||
|
GuiDrawText(textValue, GetTextBounds(VALUEBOX, bounds), GUI_TEXT_ALIGN_CENTER, Fade(GetColor(GuiGetStyle(VALUEBOX, TEXT + (state*3))), guiAlpha));
|
||||||
|
|
||||||
|
// Draw blinking cursor
|
||||||
|
if ((state == GUI_STATE_PRESSED) && (editMode && ((framesCounter/20)%2 == 0)))
|
||||||
|
{
|
||||||
|
// NOTE: ValueBox internal text is always centered
|
||||||
|
Rectangle cursor = { bounds.x + GetTextWidth(textValue)/2 + bounds.width/2 + 2, bounds.y + 2*GuiGetStyle(VALUEBOX, BORDER_WIDTH), 1, bounds.height - 4*GuiGetStyle(VALUEBOX, BORDER_WIDTH) };
|
||||||
|
GuiDrawRectangle(cursor, 0, BLANK, Fade(GetColor(GuiGetStyle(VALUEBOX, BORDER_COLOR_PRESSED)), guiAlpha));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw text label if provided
|
||||||
|
if (text != NULL) GuiDrawText(text, textBounds, (GuiGetStyle(VALUEBOX, TEXT_ALIGNMENT) == GUI_TEXT_ALIGN_RIGHT)? GUI_TEXT_ALIGN_LEFT : GUI_TEXT_ALIGN_RIGHT, Fade(GetColor(GuiGetStyle(LABEL, TEXT + (state*3))), guiAlpha));
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
return pressed;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue