added ninesliced and text rendering commands
parent
70d6ca6571
commit
dd40766fca
|
@ -6,6 +6,8 @@
|
|||
#include "inttypes.h"
|
||||
#include "SDL2/SDL_blendmode.h"
|
||||
#include "SDL2/SDL_render.h"
|
||||
#include "SDL2/SDL_surface.h"
|
||||
#include "string.h"
|
||||
|
||||
#define NUM_DRAWCMDS 2048
|
||||
|
||||
|
@ -56,6 +58,22 @@ void get_scaling_factors(float* width, float* height,
|
|||
(*height) = (*width)*aspectr;
|
||||
}
|
||||
|
||||
SDL_FRect get_dest_with_size(SDL_FRect untransformed, int ui) {
|
||||
float fw, fh, fwm, fhm;
|
||||
get_scaling_factors(&fw, &fh, &fwm, &fhm, ui);
|
||||
SDL_FRect r = (SDL_FRect) {
|
||||
.x=((-g_active_view.x)+(fw*0.5f)+untransformed.x)*fwm,
|
||||
.y=((-g_active_view.y)+(fh*0.5f)+untransformed.y)*fwm,
|
||||
.w=untransformed.w*fwm,
|
||||
.h=untransformed.h*fwm
|
||||
};
|
||||
if(ui) {
|
||||
r.x = untransformed.x * fwm;
|
||||
r.y = untransformed.y * fhm;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
void exec_sprite_cmd(const drawcmd_t* cmd) {
|
||||
const sprite_t* sprite = &cmd->sprite;
|
||||
float fw, fh, fwm, fhm;
|
||||
|
@ -115,11 +133,132 @@ void exec_rect_cmd(const drawcmd_t* cmd) {
|
|||
SDL_RenderFillRectF(g_context.renderer, &r);
|
||||
}
|
||||
|
||||
void exec_sliced_cmd(const drawcmd_t* cmd) {
|
||||
const nineslice_t* sliced = &cmd->sliced;
|
||||
|
||||
// target rect in world space
|
||||
SDL_FRect rect = sliced->rect;
|
||||
// sliced texture
|
||||
SDL_Texture* t = sliced->texture;
|
||||
|
||||
// width and height of sliced texture
|
||||
int tw, th;
|
||||
SDL_QueryTexture(t, NULL, NULL, &tw, &th);
|
||||
|
||||
// top-left
|
||||
SDL_Rect srcr = {
|
||||
0, 0, sliced->corner_size, sliced->corner_size
|
||||
};
|
||||
SDL_FRect dstr = get_dest_with_size((SDL_FRect){
|
||||
rect.x, rect.y, sliced->radius, sliced->radius
|
||||
}, cmd->ui);
|
||||
SDL_RenderCopyF(g_context.renderer, t, &srcr, &dstr);
|
||||
|
||||
// top - centre
|
||||
srcr = (SDL_Rect) {
|
||||
sliced->corner_size, 0,
|
||||
tw - sliced->corner_size*2, sliced->corner_size
|
||||
};
|
||||
dstr = get_dest_with_size((SDL_FRect){
|
||||
rect.x + sliced->radius, 0.0, sliced->rect.w - sliced->radius * 2, sliced->radius
|
||||
}, cmd->ui);
|
||||
SDL_RenderCopyF(g_context.renderer, t, &srcr, &dstr);
|
||||
|
||||
// top-right
|
||||
srcr = (SDL_Rect) {
|
||||
tw - sliced->corner_size, 0, sliced->corner_size, sliced->corner_size
|
||||
};
|
||||
dstr = get_dest_with_size((SDL_FRect){
|
||||
rect.w - sliced->radius, 0, sliced->radius, sliced->radius
|
||||
}, cmd->ui);
|
||||
SDL_RenderCopyF(g_context.renderer, t, &srcr, &dstr);
|
||||
|
||||
// centre-left
|
||||
srcr = (SDL_Rect) {
|
||||
0, sliced->corner_size, sliced->corner_size, th - sliced->corner_size * 2
|
||||
};
|
||||
dstr = get_dest_with_size((SDL_FRect) {
|
||||
0, sliced->radius, sliced->radius, rect.h - sliced->radius * 2
|
||||
}, cmd->ui);
|
||||
SDL_RenderCopyF(g_context.renderer, t, &srcr, &dstr);
|
||||
|
||||
// centre-centre
|
||||
srcr = (SDL_Rect) {
|
||||
sliced->corner_size, sliced->corner_size, tw - sliced->corner_size * 2, th - sliced->corner_size * 2
|
||||
};
|
||||
dstr = get_dest_with_size((SDL_FRect) {
|
||||
sliced->radius, sliced->radius, rect.w - sliced->radius * 2, rect.h - sliced->radius * 2
|
||||
}, cmd->ui);
|
||||
SDL_RenderCopyF(g_context.renderer, t, &srcr, &dstr);
|
||||
|
||||
// centre-right
|
||||
srcr = (SDL_Rect) {
|
||||
tw - sliced->corner_size, sliced->corner_size, sliced->corner_size, th - sliced->corner_size * 2
|
||||
};
|
||||
dstr = get_dest_with_size((SDL_FRect) {
|
||||
rect.w - sliced->radius, sliced->radius, sliced->radius, rect.h - sliced->radius * 2
|
||||
}, cmd->ui);
|
||||
SDL_RenderCopyF(g_context.renderer, t, &srcr, &dstr);
|
||||
|
||||
// bottom-left
|
||||
srcr = (SDL_Rect) {
|
||||
0, th - sliced->corner_size,
|
||||
sliced->corner_size, sliced->corner_size
|
||||
};
|
||||
dstr = get_dest_with_size((SDL_FRect){
|
||||
0, rect.h - sliced->radius,
|
||||
sliced->radius, sliced->radius
|
||||
}, cmd->ui);
|
||||
SDL_RenderCopyF(g_context.renderer, t, &srcr, &dstr);
|
||||
|
||||
// bottom-centre
|
||||
srcr = (SDL_Rect) {
|
||||
sliced->corner_size, th - sliced->corner_size, tw - sliced->corner_size * 2, sliced->corner_size
|
||||
};
|
||||
dstr = get_dest_with_size((SDL_FRect) {
|
||||
sliced->radius, rect.h - sliced->radius, rect.w - sliced->radius * 2, sliced->radius
|
||||
}, cmd->ui);
|
||||
SDL_RenderCopyF(g_context.renderer, t, &srcr, &dstr);
|
||||
|
||||
// bottom-right
|
||||
srcr = (SDL_Rect) {
|
||||
tw - sliced->corner_size, th - sliced->corner_size, sliced->corner_size, sliced->corner_size
|
||||
};
|
||||
dstr = get_dest_with_size((SDL_FRect) {
|
||||
rect.w - sliced->radius, rect.h - sliced->radius, sliced->radius, sliced->radius
|
||||
}, cmd->ui);
|
||||
SDL_RenderCopyF(g_context.renderer, t, &srcr, &dstr);
|
||||
}
|
||||
|
||||
void exec_text_cmd(const drawcmd_t* cmd) {
|
||||
SDL_FRect r = get_dest_with_size(cmd->text.area, cmd->ui);
|
||||
SDL_FRect rt = {r.x*100, r.y*100, r.w*100, r.h*100};
|
||||
SDL_Surface* s = TTF_RenderText_Solid_Wrapped(cmd->text.font, cmd->text.text, cmd->text.fg, floor(cmd->text.area.y * 100));
|
||||
if(s != NULL) {
|
||||
SDL_FreeSurface(s);
|
||||
SDL_Texture* t = SDL_CreateTextureFromSurface(g_context.renderer, s);
|
||||
float ar = r.w / r.h;
|
||||
float ar2 = (float)s->w / (float)s->h;
|
||||
SDL_Rect srcr = {0, 0, s->w, s->h};
|
||||
if(ar > ar2) {
|
||||
srcr.h = srcr.w * ar;
|
||||
} else if(ar < ar2) {
|
||||
r.h = r.w * ar2;
|
||||
}
|
||||
SDL_RenderCopyF(g_context.renderer, t, &srcr, &r);
|
||||
SDL_DestroyTexture(t);
|
||||
}
|
||||
free(cmd->text.text);
|
||||
}
|
||||
|
||||
typedef void(*drawcmd_delegate)(const drawcmd_t*);
|
||||
drawcmd_delegate const drawcmd_funcs[] = {
|
||||
&exec_sprite_cmd,
|
||||
&exec_rect_cmd
|
||||
&exec_rect_cmd,
|
||||
&exec_sliced_cmd,
|
||||
&exec_text_cmd,
|
||||
};
|
||||
|
||||
void exec_buffer() {
|
||||
if(d_debug_next_frame) printf("debug capture of draw buffer\ncount: %zu\n", (size_t)(g_drawdata_endptr - g_drawdata));
|
||||
for(const drawcmd_t* cmd = g_drawdata; cmd != g_drawdata_endptr; ++cmd) {
|
||||
|
@ -206,6 +345,32 @@ void draw_rect(const rectshape_t* rect) {
|
|||
draw(&d);
|
||||
}
|
||||
|
||||
void draw_sliced(const nineslice_t *sliced) {
|
||||
drawcmd_t d = {
|
||||
.type=DRAWCMDTYPE_SLICED,
|
||||
.depth=sliced->depth,
|
||||
.sliced=*sliced
|
||||
};
|
||||
draw(&d);
|
||||
}
|
||||
|
||||
void draw_text(const char *str, SDL_FRect area, TTF_Font *font, SDL_Color font_color, depth_t depth) {
|
||||
int len = strlen(str);
|
||||
textarea_t t = {
|
||||
.text = calloc(len+1, sizeof(char)),
|
||||
.area = area,
|
||||
.fg = font_color,
|
||||
.font = font,
|
||||
};
|
||||
strcpy(t.text, str);
|
||||
drawcmd_t d = {
|
||||
.type=DRAWCMDTYPE_TEXT,
|
||||
.text=t,
|
||||
.depth=depth,
|
||||
};
|
||||
draw(&d);
|
||||
}
|
||||
|
||||
spritesheet_t make_spritesheet(const char *file, int tile_width, int tile_height) {
|
||||
spritesheet_t sheet=(spritesheet_t){
|
||||
.texture=get_texture(file),
|
||||
|
@ -217,6 +382,17 @@ spritesheet_t make_spritesheet(const char *file, int tile_width, int tile_height
|
|||
return sheet;
|
||||
}
|
||||
|
||||
nineslice_t make_nineslice(const char *file, int corner_px, float radius) {
|
||||
nineslice_t sliced = {
|
||||
.depth = RLAYER_UI,
|
||||
.corner_size = corner_px,
|
||||
.radius = radius,
|
||||
.rect= {0.0, 0.0, 1.0, 1.0},
|
||||
.texture=get_texture(file)
|
||||
};
|
||||
return sliced;
|
||||
}
|
||||
|
||||
sprite_t make_sprite(const char* file, float x, float y) {
|
||||
sprite_t sprite=(sprite_t){
|
||||
.texture=get_texture(file),
|
||||
|
|
|
@ -6,6 +6,7 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
#include "context.h"
|
||||
#include "SDL2/SDL_ttf.h"
|
||||
|
||||
typedef int depth_t;
|
||||
|
||||
|
@ -15,6 +16,8 @@ typedef enum drawcmdtype_t {
|
|||
DRAWCMDTYPE_MIN = -1,
|
||||
DRAWCMDTYPE_SPRITE = 0,
|
||||
DRAWCMDTYPE_RECT = 1,
|
||||
DRAWCMDTYPE_SLICED = 2,
|
||||
DRAWCMDTYPE_TEXT = 3,
|
||||
DRAWCMDTYPE_MAX
|
||||
} drawcmdtype_t;
|
||||
|
||||
|
@ -26,9 +29,19 @@ typedef struct spritesheet_t {
|
|||
|
||||
typedef struct nineslice_t {
|
||||
SDL_Texture* texture;
|
||||
float corner_height, corner_width; // the width and height of the corners
|
||||
SDL_FRect rect; // the rectangle to fit into
|
||||
depth_t depth;
|
||||
float radius;
|
||||
int corner_size;
|
||||
} nineslice_t; // nine-sliced texture for ui
|
||||
|
||||
typedef struct textarea_t {
|
||||
char* text;
|
||||
TTF_Font* font;
|
||||
SDL_Color fg;
|
||||
SDL_FRect area;
|
||||
} textarea_t;
|
||||
|
||||
typedef struct sprite_t {
|
||||
SDL_Texture* texture;
|
||||
float x, y; // positions of x,y
|
||||
|
@ -54,6 +67,8 @@ typedef struct drawcmd_t {
|
|||
union {
|
||||
sprite_t sprite; // if type is sprite, render this
|
||||
rectshape_t rect; // if type is rect, render this
|
||||
nineslice_t sliced;
|
||||
textarea_t text;
|
||||
};
|
||||
} drawcmd_t; // an orderable command to render, should not be directly used, use draw_* functions instead
|
||||
|
||||
|
@ -73,12 +88,19 @@ extern void draw(const drawcmd_t* cmd);
|
|||
|
||||
extern void draw_sprite(const sprite_t* sprite);
|
||||
extern void draw_rect(const rectshape_t* rect);
|
||||
extern void draw_sliced(const nineslice_t* sliced);
|
||||
extern void draw_text(const char* str, SDL_FRect area, TTF_Font* font, SDL_Color font_color, depth_t depth);
|
||||
extern spritesheet_t make_spritesheet(const char* file, int tile_width, int tile_height);
|
||||
extern nineslice_t make_nineslice(const char* file, int corner_px, float radius);
|
||||
extern sprite_t make_sprite(const char* file, float x, float y);
|
||||
extern sprite_t sprite_from_spritesheet(spritesheet_t* sheet, int index);
|
||||
extern SDL_Rect get_srcrect_from(spritesheet_t* sheet, int index);
|
||||
extern void set_active_view(const view_t* view);
|
||||
|
||||
inline sprite_t no_sprite() {
|
||||
return (sprite_t){NULL, 0.0, 0.0, {0.0, 0.0}, 0.0, 0.0, 0.0, 0, {0, 0, 0, 0}};
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue