246 lines
6.3 KiB
C
246 lines
6.3 KiB
C
#define ZPL_NO_WINDOWS_H
|
|
#include "zpl.h"
|
|
|
|
#include "editors/texed.h"
|
|
#include "raylib.h"
|
|
#include "utils/raylib_helpers.h"
|
|
#include "cwpack/cwpack.h"
|
|
|
|
#define RAYGUI_IMPLEMENTATION
|
|
#define RAYGUI_SUPPORT_ICONS
|
|
#include "raygui.h"
|
|
|
|
#define GUI_FILE_DIALOG_IMPLEMENTATION
|
|
#include "gui_file_dialog.h"
|
|
|
|
#define GUI_TEXTBOX_EXTENDED_IMPLEMENTATION
|
|
#include "gui_textbox_extended.h"
|
|
|
|
static uint16_t screenWidth = 1280;
|
|
static uint16_t screenHeight = 720;
|
|
static float zoom = 4.0f;
|
|
|
|
#define TD_DEFAULT_IMG_WIDTH 64
|
|
#define TD_DEFAULT_IMG_HEIGHT 64
|
|
#define TD_UI_PADDING 5.0f
|
|
#define TD_UI_PREVIEW_BORDER 4.0f
|
|
|
|
typedef enum {
|
|
TPARAM_FLOAT,
|
|
TPARAM_COORD,
|
|
TPARAM_INT,
|
|
TPARAM_COLOR,
|
|
TPARAM_STRING,
|
|
|
|
TPARAM_FORCE_UINT8 = UINT8_MAX
|
|
} td_param_kind;
|
|
|
|
typedef struct {
|
|
td_param_kind kind;
|
|
char const *name;
|
|
char str[1000];
|
|
bool edit_mode;
|
|
|
|
union {
|
|
float flt;
|
|
uint32_t u32;
|
|
int32_t i32;
|
|
Color color;
|
|
char copy[4];
|
|
};
|
|
} td_param;
|
|
|
|
typedef enum {
|
|
TOP_NEW_IMAGE,
|
|
TOP_DRAW_RECT,
|
|
TOP_DRAW_LINE,
|
|
TOP_DITHER,
|
|
TOP_LOAD_IMAGE,
|
|
TOP_DRAW_TEXT,
|
|
TOP_RESIZE_IMAGE,
|
|
|
|
TOP_FORCE_UINT8 = UINT8_MAX
|
|
} td_op_kind;
|
|
|
|
typedef struct {
|
|
td_op_kind kind;
|
|
char const *name;
|
|
bool is_hidden;
|
|
|
|
uint8_t num_params;
|
|
td_param *params;
|
|
} td_op;
|
|
|
|
#define OP(n) .kind = n, .name = #n
|
|
|
|
typedef struct {
|
|
char *filepath;
|
|
Image img;
|
|
Texture2D tex;
|
|
GuiFileDialogState fileDialog;
|
|
|
|
td_op *ops; //< zpl_array
|
|
int selected_op;
|
|
} td_ctx;
|
|
|
|
static td_ctx ctx = {0};
|
|
|
|
static char filename[200];
|
|
|
|
#include "texed_ops_list.c"
|
|
|
|
void texed_new(int32_t w, int32_t h);
|
|
void texed_destroy(void);
|
|
void texed_load(void);
|
|
void texed_save(void);
|
|
void texed_repaint_preview(void);
|
|
void texed_process_ops(void);
|
|
void texed_process_params(void);
|
|
void texed_add_op(int idx);
|
|
void texed_rem_op(int idx);
|
|
void texed_swp_op(int idx, int idx2);
|
|
|
|
void texed_draw_oplist_pane(zpl_aabb2 r);
|
|
void texed_draw_props_pane(zpl_aabb2 r);
|
|
void texed_draw_topbar(zpl_aabb2 r);
|
|
|
|
static inline
|
|
void DrawAABB(zpl_aabb2 rect, Color color) {
|
|
DrawRectangleEco(rect.min.x, rect.min.y,
|
|
rect.max.x-rect.min.x,
|
|
rect.max.y-rect.min.y,
|
|
color);
|
|
}
|
|
|
|
static inline
|
|
Rectangle aabb2_ray(zpl_aabb2 r) {
|
|
return (Rectangle) {
|
|
.x = r.min.x,
|
|
.y = r.min.y,
|
|
.width = r.max.x-r.min.x,
|
|
.height = r.max.y-r.min.y
|
|
};
|
|
}
|
|
|
|
#include "texed_ops.c"
|
|
#include "texed_prj.c"
|
|
#include "texed_widgets.c"
|
|
|
|
void texed_run(void) {
|
|
InitWindow(screenWidth, screenHeight, "eco2d - texture editor");
|
|
SetTargetFPS(60);
|
|
|
|
texed_new(TD_DEFAULT_IMG_WIDTH, TD_DEFAULT_IMG_HEIGHT);
|
|
|
|
GuiSetStyle(TEXTBOX, TEXT_COLOR_NORMAL, ColorToInt(RAYWHITE));
|
|
|
|
zpl_aabb2 screen = {
|
|
.min = (zpl_vec2) {.x = 0.0f, .y = 0.0f},
|
|
.max = (zpl_vec2) {.x = screenWidth, .y = screenHeight},
|
|
};
|
|
|
|
zpl_aabb2 topbar = zpl_aabb2_cut_top(&screen, 25.0f);
|
|
zpl_aabb2 oplist_pane = zpl_aabb2_cut_right(&screen, screenWidth / 2.0f);
|
|
zpl_aabb2 preview_window = zpl_aabb2_cut_top(&screen, (screen.max.y-screen.min.y) / 2.0f);
|
|
zpl_aabb2 property_pane = screen;
|
|
|
|
// NOTE(zaklaus): contract all panes for a clean UI separation
|
|
oplist_pane = zpl_aabb2_contract(&oplist_pane, TD_UI_PADDING);
|
|
preview_window = zpl_aabb2_contract(&preview_window, TD_UI_PADDING);
|
|
property_pane = zpl_aabb2_contract(&property_pane, TD_UI_PADDING);
|
|
|
|
Rectangle preview_rect = aabb2_ray(preview_window);
|
|
Image checkerboard = GenImageChecked(preview_rect.width, preview_rect.height, 16, 16, BLACK, ColorAlpha(GRAY, 0.2f));
|
|
Texture2D checker_tex = LoadTextureFromImage(checkerboard);
|
|
UnloadImage(checkerboard);
|
|
|
|
while (!WindowShouldClose()) {
|
|
BeginDrawing();
|
|
ClearBackground(GetColor(0x222034));
|
|
{
|
|
if (ctx.fileDialog.fileDialogActive) GuiLock();
|
|
DrawTextureEx(checker_tex, (Vector2){ preview_window.min.x, preview_window.min.y}, 0.0f, 1.0f, WHITE);
|
|
DrawTextureEx(ctx.tex, (Vector2){ preview_window.min.x, preview_window.min.y}, 0.0f, zoom, WHITE);
|
|
|
|
DrawAABB(topbar, RAYWHITE);
|
|
DrawAABB(property_pane, GetColor(0x422060));
|
|
DrawAABB(oplist_pane, GetColor(0x425060));
|
|
|
|
texed_draw_topbar(topbar);
|
|
texed_draw_props_pane(property_pane);
|
|
texed_draw_oplist_pane(oplist_pane);
|
|
|
|
if (ctx.fileDialog.fileDialogActive) GuiUnlock();
|
|
GuiFileDialog(&ctx.fileDialog);
|
|
}
|
|
EndDrawing();
|
|
}
|
|
|
|
UnloadTexture(checker_tex);
|
|
texed_destroy();
|
|
}
|
|
|
|
void texed_new(int32_t w, int32_t h) {
|
|
ctx.img = GenImageColor(w, h, WHITE);
|
|
ctx.filepath = NULL;
|
|
ctx.selected_op = 0;
|
|
zpl_array_init(ctx.ops, zpl_heap());
|
|
texed_add_op(TOP_NEW_IMAGE);
|
|
|
|
ctx.fileDialog = InitGuiFileDialog(420, 310, zpl_bprintf("%s/art", GetWorkingDirectory()), false);
|
|
}
|
|
|
|
void texed_destroy(void) {
|
|
UnloadTexture(ctx.tex);
|
|
UnloadImage(ctx.img);
|
|
zpl_array_free(ctx.ops);
|
|
}
|
|
|
|
void texed_repaint_preview(void) {
|
|
UnloadTexture(ctx.tex);
|
|
texed_process_params();
|
|
texed_process_ops();
|
|
ctx.tex = LoadTextureFromImage(ctx.img);
|
|
}
|
|
|
|
void texed_add_op(int idx) {
|
|
assert(idx >= 0 && idx < DEF_OPS_LEN);
|
|
td_op *dop = &default_ops[idx];
|
|
|
|
td_op op = {
|
|
.kind = dop->kind,
|
|
.name = dop->name,
|
|
.num_params = dop->num_params,
|
|
.params = (td_param*)zpl_malloc(sizeof(td_param)*dop->num_params)
|
|
};
|
|
|
|
zpl_memcopy(op.params, dop->params, sizeof(td_param)*dop->num_params);
|
|
|
|
zpl_array_append(ctx.ops, op);
|
|
ctx.selected_op = zpl_array_count(ctx.ops)-1;
|
|
|
|
texed_repaint_preview();
|
|
}
|
|
|
|
void texed_swp_op(int idx, int idx2) {
|
|
assert(idx >= 0 && idx < (int)zpl_array_count(ctx.ops));
|
|
assert(idx2 >= 0 && idx2 < (int)zpl_array_count(ctx.ops));
|
|
|
|
td_op tmp = ctx.ops[idx2];
|
|
ctx.ops[idx2] = ctx.ops[idx];
|
|
ctx.ops[idx] = tmp;
|
|
ctx.selected_op = idx2;
|
|
texed_repaint_preview();
|
|
}
|
|
|
|
void texed_rem_op(int idx) {
|
|
assert(idx >= 0 && idx < (int)zpl_array_count(ctx.ops));
|
|
zpl_mfree(ctx.ops[idx].params);
|
|
zpl_array_remove_at(ctx.ops, idx);
|
|
|
|
if (idx == ctx.selected_op) {
|
|
if (idx > 0) ctx.selected_op -= 1;
|
|
}
|
|
texed_repaint_preview();
|
|
}
|