aseprite importer
This commit is contained in:
parent
0256f4cd15
commit
d52b15e1be
12
Makefile
12
Makefile
|
@ -17,6 +17,9 @@ LD = $(CC)
|
|||
ifeq ($(CC), clang)
|
||||
AR = llvm-ar
|
||||
endif
|
||||
ifeq ($(CC), x86_64-w64-mingw32-gcc)
|
||||
AR = x86_64-w64-mingw32-ar
|
||||
endif
|
||||
|
||||
ifdef NEDITOR
|
||||
CFLAGS += -DNO_EDITOR
|
||||
|
@ -72,6 +75,7 @@ ifeq ($(OS), Windows_NT)
|
|||
LDFLAGS += -mwin32 -static
|
||||
CFLAGS += -mwin32
|
||||
LDLIBS += mingw32 kernel32 d3d11 user32 shell32 dxgi gdi32 ws2_32 ole32 winmm setupapi m
|
||||
# LDLIBS += mingw32 kernel32 gdi32 user32 shell32 ws2_32 ole32 winmm setupapi m
|
||||
EXT = .exe
|
||||
PLAT = w64
|
||||
PKGCMD = cd $(BIN); zip -q -r $(MAKEDIR)/$(DISTDIR)/$(DIST) . -x \*.a ./obj/\*
|
||||
|
@ -144,7 +148,7 @@ SHADERS := $(patsubst %.sglsl, %.sglsl.h, $(SHADERS))
|
|||
install: $(BIN)/$(NAME)
|
||||
cp -f $(BIN)/$(NAME) $(DESTDIR)
|
||||
|
||||
$(BIN)/$(NAME): $(BIN)/libengine.a $(BIN)/libquickjs.a $(BIN)/libcdb.a
|
||||
$(BIN)/$(NAME): $(BIN)/libengine.a $(BIN)/libquickjs.a
|
||||
@echo Linking $(NAME)
|
||||
$(LD) $^ $(LDFLAGS) -L$(BIN) $(LDLIBS) -o $@
|
||||
cp $(BIN)/$(NAME) .
|
||||
|
@ -155,13 +159,13 @@ $(DISTDIR)/$(DIST): $(BIN)/$(NAME)
|
|||
@mkdir -p $(DISTDIR)
|
||||
@$(PKGCMD)
|
||||
|
||||
$(BIN)/libengine.a: $(SHADERS) source/engine/core.cdb.h .WAIT $(OBJS)
|
||||
$(BIN)/libengine.a: $(SHADERS) source/engine/core.cdb.h $(OBJS)
|
||||
@$(AR) rcs $@ $(OBJS)
|
||||
|
||||
$(BIN)/libcdb.a:
|
||||
mkdir -p $(BIN)
|
||||
rm -f $(CDB)/libcdb.a
|
||||
make -C $(CDB) libcdb.a
|
||||
make -C $(CDB) CC=$(CC) AR=$(AR) libcdb.a
|
||||
cp $(CDB)/libcdb.a $(BIN)
|
||||
|
||||
$(BIN)/libquickjs.a:
|
||||
|
@ -211,7 +215,7 @@ jso: tools/jso.c $(BIN)/libquickjs.a
|
|||
WINCC = x86_64-w64-mingw32-gcc
|
||||
.PHONY: crosswin
|
||||
crosswin:
|
||||
make CC=$(WINCC) OS=Windows_NT
|
||||
gmake CC=$(WINCC) OS=Windows_NT
|
||||
|
||||
clean:
|
||||
@echo Cleaning project
|
||||
|
|
|
@ -87,6 +87,52 @@ sprite.inputs.kp2 = function() { this.pos = [-0.5,-1]; };
|
|||
sprite.inputs.kp1 = function() { this.pos = [-1,-1]; };
|
||||
Object.seal(sprite);
|
||||
|
||||
var aseframeset2anim = function(frameset, meta)
|
||||
{
|
||||
var anim = {};
|
||||
anim.frames = [];
|
||||
anim.path = meta.image;
|
||||
var dim = meta.size;
|
||||
|
||||
var ase_make_frame = function(ase_frame,i) {
|
||||
var f = ase_frame.frame;
|
||||
var frame = {};
|
||||
frame.rect = {
|
||||
s0: f.x/dim.w,
|
||||
s1: (f.x+f.w)/dim.w,
|
||||
t0: f.y/dim.h,
|
||||
t1: (f.y+f.h)/dim.h
|
||||
};
|
||||
frame.time = ase_frame.duration / 1000;
|
||||
anim.frames.push(frame);
|
||||
};
|
||||
|
||||
frameset.forEach(ase_make_frame);
|
||||
|
||||
anim.loop = true;
|
||||
return anim;
|
||||
}
|
||||
|
||||
var ase2anim = function(ase)
|
||||
{
|
||||
var json = IO.slurp(ase);
|
||||
json = JSON.parse(json);
|
||||
var frames = Array.isArray(json.frames) ? json.frames : Object.values(json.frames);
|
||||
return aseframeset2anim(json.frames, json.meta);
|
||||
}
|
||||
|
||||
var ase2anims = function(ase)
|
||||
{
|
||||
var json = IO.slurp(ase);
|
||||
json = JSON.parse(json);
|
||||
var anims = {};
|
||||
var frames = Array.isArray(json.frames) ? json.frames : Object.values(json.frames);
|
||||
for (var tag of json.meta.frameTags)
|
||||
anims[tag.name] = aseframeset2anim(frames.slice(tag.from, tag.to+1), json.meta);
|
||||
|
||||
return anims;
|
||||
}
|
||||
|
||||
var gif2anim = function(gif)
|
||||
{
|
||||
var anim = {};
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
#define SOKOL_TRACE_HOOKS
|
||||
#define SOKOL_IMPL
|
||||
#include "sokol/sokol_glue.h"
|
||||
#include "sokol/sokol_audio.h"
|
||||
#include "sokol/sokol_time.h"
|
||||
#include "sokol/sokol_args.h"
|
||||
|
|
|
@ -93,5 +93,5 @@ void log_cat(FILE *f) {
|
|||
}
|
||||
|
||||
void sg_logging(const char *tag, uint32_t lvl, uint32_t id, const char *msg, uint32_t line, const char *file, void *data) {
|
||||
mYughLog(lvl, 1, line, file, "tag: %d, msg: %s", tag, msg);
|
||||
mYughLog(lvl, 1, line, file, "tag: %s, msg: %s", tag, msg);
|
||||
}
|
||||
|
|
|
@ -1,529 +0,0 @@
|
|||
#include "gifdec.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#ifdef _WIN32
|
||||
#include <io.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#define MIN(A, B) ((A) < (B) ? (A) : (B))
|
||||
#define MAX(A, B) ((A) > (B) ? (A) : (B))
|
||||
|
||||
typedef struct Entry {
|
||||
uint16_t length;
|
||||
uint16_t prefix;
|
||||
uint8_t suffix;
|
||||
} Entry;
|
||||
|
||||
typedef struct Table {
|
||||
int bulk;
|
||||
int nentries;
|
||||
Entry *entries;
|
||||
} Table;
|
||||
|
||||
static uint16_t
|
||||
read_num(FILE *f)
|
||||
{
|
||||
uint8_t bytes[2];
|
||||
|
||||
fread(bytes, 2, 1, f);
|
||||
return bytes[0] + (((uint16_t) bytes[1]) << 8);
|
||||
}
|
||||
|
||||
gd_GIF *gd_open_gif_f(FILE *f)
|
||||
{
|
||||
uint8_t sigver[3];
|
||||
uint16_t width, height, depth;
|
||||
uint8_t fdsz, bgidx, aspect;
|
||||
int i;
|
||||
uint8_t *bgcolor;
|
||||
int gct_sz;
|
||||
gd_GIF *gif;
|
||||
|
||||
/* Header */
|
||||
fread(sigver, 1, 3, f);
|
||||
if (memcmp(sigver, "GIF", 3) != 0) {
|
||||
fprintf(stderr, "invalid signature\n");
|
||||
goto fail;
|
||||
}
|
||||
/* Version */
|
||||
fread(sigver, 1,3,f);
|
||||
if (memcmp(sigver, "89a", 3) != 0) {
|
||||
fprintf(stderr, "invalid version\n");
|
||||
goto fail;
|
||||
}
|
||||
/* Width x Height */
|
||||
width = read_num(f);
|
||||
height = read_num(f);
|
||||
/* FDSZ */
|
||||
fread(&fdsz, 1, 1, f);
|
||||
/* Presence of GCT */
|
||||
if (!(fdsz & 0x80)) {
|
||||
fprintf(stderr, "no global color table\n");
|
||||
goto fail;
|
||||
}
|
||||
/* Color Space's Depth */
|
||||
depth = ((fdsz >> 4) & 7) + 1;
|
||||
/* Ignore Sort Flag. */
|
||||
/* GCT Size */
|
||||
gct_sz = 1 << ((fdsz & 0x07) + 1);
|
||||
/* Background Color Index */
|
||||
fread(&bgidx, 1, 1, f);
|
||||
/* Aspect Ratio */
|
||||
fread(&aspect, 1, 1, f);
|
||||
/* Create gd_GIF Structure. */
|
||||
gif = calloc(1, sizeof(*gif));
|
||||
if (!gif) goto fail;
|
||||
gif->fd = f;
|
||||
gif->width = width;
|
||||
gif->height = height;
|
||||
gif->depth = depth;
|
||||
/* Read GCT */
|
||||
gif->gct.size = gct_sz;
|
||||
fread(gif->gct.colors, gif->gct.size, 3, f);
|
||||
gif->palette = &gif->gct;
|
||||
gif->bgindex = bgidx;
|
||||
gif->frame = calloc(4, width * height);
|
||||
if (!gif->frame) {
|
||||
free(gif);
|
||||
goto fail;
|
||||
}
|
||||
gif->canvas = &gif->frame[width * height];
|
||||
if (gif->bgindex)
|
||||
memset(gif->frame, gif->bgindex, gif->width * gif->height);
|
||||
bgcolor = &gif->palette->colors[gif->bgindex*3];
|
||||
if (bgcolor[0] || bgcolor[1] || bgcolor [2])
|
||||
for (i = 0; i < gif->width * gif->height; i++)
|
||||
memcpy(&gif->canvas[i*3], bgcolor, 3);
|
||||
gif->anim_start = ftell(f);
|
||||
goto ok;
|
||||
fail:
|
||||
return NULL;
|
||||
ok:
|
||||
return gif;
|
||||
}
|
||||
|
||||
gd_GIF *
|
||||
gd_open_gif(const char *fname)
|
||||
{
|
||||
FILE *f = fopen(fname, "rb");
|
||||
if (!f) return NULL;
|
||||
return gd_open_gif_f(f);
|
||||
}
|
||||
|
||||
static void
|
||||
discard_sub_blocks(gd_GIF *gif)
|
||||
{
|
||||
uint8_t size;
|
||||
|
||||
do {
|
||||
fread(&size, 1, 1, gif->fd);
|
||||
fseek(gif->fd, size, SEEK_CUR);
|
||||
} while (size);
|
||||
}
|
||||
|
||||
static void
|
||||
read_plain_text_ext(gd_GIF *gif)
|
||||
{
|
||||
if (gif->plain_text) {
|
||||
uint16_t tx, ty, tw, th;
|
||||
uint8_t cw, ch, fg, bg;
|
||||
off_t sub_block;
|
||||
fseek(gif->fd, 1, SEEK_CUR); /* block size = 12 */
|
||||
tx = read_num(gif->fd);
|
||||
ty = read_num(gif->fd);
|
||||
tw = read_num(gif->fd);
|
||||
th = read_num(gif->fd);
|
||||
fread(&cw, 1, 1, gif->fd);
|
||||
fread(&ch, 1, 1, gif->fd);
|
||||
fread(&fg, 1, 1, gif->fd);
|
||||
fread(&bg, 1, 1, gif->fd);
|
||||
sub_block = ftell(gif->fd);
|
||||
gif->plain_text(gif, tx, ty, tw, th, cw, ch, fg, bg);
|
||||
fseek(gif->fd, sub_block, SEEK_SET);
|
||||
} else {
|
||||
/* Discard plain text metadata. */
|
||||
fseek(gif->fd, 13, SEEK_CUR);
|
||||
}
|
||||
/* Discard plain text sub-blocks. */
|
||||
discard_sub_blocks(gif);
|
||||
}
|
||||
|
||||
static void
|
||||
read_graphic_control_ext(gd_GIF *gif)
|
||||
{
|
||||
uint8_t rdit;
|
||||
|
||||
/* Discard block size (always 0x04). */
|
||||
fseek(gif->fd, 1, SEEK_CUR);
|
||||
fread(&rdit, 1, 1, gif->fd);
|
||||
gif->gce.disposal = (rdit >> 2) & 3;
|
||||
gif->gce.input = rdit & 2;
|
||||
gif->gce.transparency = rdit & 1;
|
||||
gif->gce.delay = read_num(gif->fd);
|
||||
fread(&gif->gce.tindex, 1, 1, gif->fd);
|
||||
/* Skip block terminator. */
|
||||
fseek(gif->fd, 1, SEEK_CUR);
|
||||
}
|
||||
|
||||
static void
|
||||
read_comment_ext(gd_GIF *gif)
|
||||
{
|
||||
if (gif->comment) {
|
||||
off_t sub_block = ftell(gif->fd);
|
||||
gif->comment(gif);
|
||||
fseek(gif->fd, sub_block, SEEK_SET);
|
||||
}
|
||||
/* Discard comment sub-blocks. */
|
||||
discard_sub_blocks(gif);
|
||||
}
|
||||
|
||||
static void
|
||||
read_application_ext(gd_GIF *gif)
|
||||
{
|
||||
char app_id[8];
|
||||
char app_auth_code[3];
|
||||
|
||||
/* Discard block size (always 0x0B). */
|
||||
fseek(gif->fd, 1, SEEK_CUR);
|
||||
/* Application Identifier. */
|
||||
fread(app_id, 8, 1, gif->fd);
|
||||
/* Application Authentication Code. */
|
||||
fread(app_auth_code, 3, 1, gif->fd);
|
||||
if (!strncmp(app_id, "NETSCAPE", sizeof(app_id))) {
|
||||
/* Discard block size (0x03) and constant byte (0x01). */
|
||||
fseek(gif->fd, 2, SEEK_CUR);
|
||||
gif->loop_count = read_num(gif->fd);
|
||||
/* Skip block terminator. */
|
||||
fseek(gif->fd, 1, SEEK_CUR);
|
||||
} else if (gif->application) {
|
||||
off_t sub_block = ftell(gif->fd);
|
||||
gif->application(gif, app_id, app_auth_code);
|
||||
fseek(gif->fd, sub_block, SEEK_SET);
|
||||
discard_sub_blocks(gif);
|
||||
} else {
|
||||
discard_sub_blocks(gif);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
read_ext(gd_GIF *gif)
|
||||
{
|
||||
uint8_t label;
|
||||
|
||||
fread(&label, 1, 1, gif->fd);
|
||||
switch (label) {
|
||||
case 0x01:
|
||||
read_plain_text_ext(gif);
|
||||
break;
|
||||
case 0xF9:
|
||||
read_graphic_control_ext(gif);
|
||||
break;
|
||||
case 0xFE:
|
||||
read_comment_ext(gif);
|
||||
break;
|
||||
case 0xFF:
|
||||
read_application_ext(gif);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "unknown extension: %02X\n", label);
|
||||
}
|
||||
}
|
||||
|
||||
static Table *
|
||||
new_table(int key_size)
|
||||
{
|
||||
int key;
|
||||
int init_bulk = MAX(1 << (key_size + 1), 0x100);
|
||||
Table *table = malloc(sizeof(*table) + sizeof(Entry) * init_bulk);
|
||||
if (table) {
|
||||
table->bulk = init_bulk;
|
||||
table->nentries = (1 << key_size) + 2;
|
||||
table->entries = (Entry *) &table[1];
|
||||
for (key = 0; key < (1 << key_size); key++)
|
||||
table->entries[key] = (Entry) {1, 0xFFF, key};
|
||||
}
|
||||
return table;
|
||||
}
|
||||
|
||||
/* Add table entry. Return value:
|
||||
* 0 on success
|
||||
* +1 if key size must be incremented after this addition
|
||||
* -1 if could not realloc table */
|
||||
static int
|
||||
add_entry(Table **tablep, uint16_t length, uint16_t prefix, uint8_t suffix)
|
||||
{
|
||||
Table *table = *tablep;
|
||||
if (table->nentries == table->bulk) {
|
||||
table->bulk *= 2;
|
||||
table = realloc(table, sizeof(*table) + sizeof(Entry) * table->bulk);
|
||||
if (!table) return -1;
|
||||
table->entries = (Entry *) &table[1];
|
||||
*tablep = table;
|
||||
}
|
||||
table->entries[table->nentries] = (Entry) {length, prefix, suffix};
|
||||
table->nentries++;
|
||||
if ((table->nentries & (table->nentries - 1)) == 0)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint16_t
|
||||
get_key(gd_GIF *gif, int key_size, uint8_t *sub_len, uint8_t *shift, uint8_t *byte)
|
||||
{
|
||||
int bits_read;
|
||||
int rpad;
|
||||
int frag_size;
|
||||
uint16_t key;
|
||||
|
||||
key = 0;
|
||||
for (bits_read = 0; bits_read < key_size; bits_read += frag_size) {
|
||||
rpad = (*shift + bits_read) % 8;
|
||||
if (rpad == 0) {
|
||||
/* Update byte. */
|
||||
if (*sub_len == 0) {
|
||||
fread(sub_len, 1, 1, gif->fd); /* Must be nonzero! */
|
||||
if (*sub_len == 0)
|
||||
return 0x1000;
|
||||
}
|
||||
fread(byte, 1, 1, gif->fd);
|
||||
(*sub_len)--;
|
||||
}
|
||||
frag_size = MIN(key_size - bits_read, 8 - rpad);
|
||||
key |= ((uint16_t) ((*byte) >> rpad)) << bits_read;
|
||||
}
|
||||
/* Clear extra bits to the left. */
|
||||
key &= (1 << key_size) - 1;
|
||||
*shift = (*shift + key_size) % 8;
|
||||
return key;
|
||||
}
|
||||
|
||||
/* Compute output index of y-th input line, in frame of height h. */
|
||||
static int
|
||||
interlaced_line_index(int h, int y)
|
||||
{
|
||||
int p; /* number of lines in current pass */
|
||||
|
||||
p = (h - 1) / 8 + 1;
|
||||
if (y < p) /* pass 1 */
|
||||
return y * 8;
|
||||
y -= p;
|
||||
p = (h - 5) / 8 + 1;
|
||||
if (y < p) /* pass 2 */
|
||||
return y * 8 + 4;
|
||||
y -= p;
|
||||
p = (h - 3) / 4 + 1;
|
||||
if (y < p) /* pass 3 */
|
||||
return y * 4 + 2;
|
||||
y -= p;
|
||||
/* pass 4 */
|
||||
return y * 2 + 1;
|
||||
}
|
||||
|
||||
/* Decompress image pixels.
|
||||
* Return 0 on success or -1 on out-of-memory (w.r.t. LZW code table). */
|
||||
static int
|
||||
read_image_data(gd_GIF *gif, int interlace)
|
||||
{
|
||||
uint8_t sub_len, shift, byte;
|
||||
int init_key_size, key_size, table_is_full;
|
||||
int frm_off, frm_size, str_len, i, p, x, y;
|
||||
uint16_t key, clear, stop;
|
||||
int ret;
|
||||
Table *table;
|
||||
Entry entry;
|
||||
off_t start, end;
|
||||
|
||||
fread(&byte, 1, 1, gif->fd);
|
||||
key_size = (int) byte;
|
||||
if (key_size < 2 || key_size > 8)
|
||||
return -1;
|
||||
|
||||
start = ftell(gif->fd);
|
||||
discard_sub_blocks(gif);
|
||||
end = ftell(gif->fd);
|
||||
fseek(gif->fd, start, SEEK_SET);
|
||||
clear = 1 << key_size;
|
||||
stop = clear + 1;
|
||||
table = new_table(key_size);
|
||||
key_size++;
|
||||
init_key_size = key_size;
|
||||
sub_len = shift = 0;
|
||||
key = get_key(gif, key_size, &sub_len, &shift, &byte); /* clear code */
|
||||
frm_off = 0;
|
||||
ret = 0;
|
||||
frm_size = gif->fw*gif->fh;
|
||||
while (frm_off < frm_size) {
|
||||
if (key == clear) {
|
||||
key_size = init_key_size;
|
||||
table->nentries = (1 << (key_size - 1)) + 2;
|
||||
table_is_full = 0;
|
||||
} else if (!table_is_full) {
|
||||
ret = add_entry(&table, str_len + 1, key, entry.suffix);
|
||||
if (ret == -1) {
|
||||
free(table);
|
||||
return -1;
|
||||
}
|
||||
if (table->nentries == 0x1000) {
|
||||
ret = 0;
|
||||
table_is_full = 1;
|
||||
}
|
||||
}
|
||||
key = get_key(gif, key_size, &sub_len, &shift, &byte);
|
||||
if (key == clear) continue;
|
||||
if (key == stop || key == 0x1000) break;
|
||||
if (ret == 1) key_size++;
|
||||
entry = table->entries[key];
|
||||
str_len = entry.length;
|
||||
for (i = 0; i < str_len; i++) {
|
||||
p = frm_off + entry.length - 1;
|
||||
x = p % gif->fw;
|
||||
y = p / gif->fw;
|
||||
if (interlace)
|
||||
y = interlaced_line_index((int) gif->fh, y);
|
||||
gif->frame[(gif->fy + y) * gif->width + gif->fx + x] = entry.suffix;
|
||||
if (entry.prefix == 0xFFF)
|
||||
break;
|
||||
else
|
||||
entry = table->entries[entry.prefix];
|
||||
}
|
||||
frm_off += str_len;
|
||||
if (key < table->nentries - 1 && !table_is_full)
|
||||
table->entries[table->nentries - 1].suffix = entry.suffix;
|
||||
}
|
||||
free(table);
|
||||
if (key == stop)
|
||||
fread(&sub_len, 1, 1, gif->fd); /* Must be zero! */
|
||||
fseek(gif->fd, end, SEEK_SET);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read image.
|
||||
* Return 0 on success or -1 on out-of-memory (w.r.t. LZW code table). */
|
||||
static int
|
||||
read_image(gd_GIF *gif)
|
||||
{
|
||||
uint8_t fisrz;
|
||||
int interlace;
|
||||
|
||||
/* Image Descriptor. */
|
||||
gif->fx = read_num(gif->fd);
|
||||
gif->fy = read_num(gif->fd);
|
||||
|
||||
if (gif->fx >= gif->width || gif->fy >= gif->height)
|
||||
return -1;
|
||||
|
||||
gif->fw = read_num(gif->fd);
|
||||
gif->fh = read_num(gif->fd);
|
||||
|
||||
gif->fw = MIN(gif->fw, gif->width - gif->fx);
|
||||
gif->fh = MIN(gif->fh, gif->height - gif->fy);
|
||||
|
||||
fread(&fisrz, 1, 1, gif->fd);
|
||||
interlace = fisrz & 0x40;
|
||||
/* Ignore Sort Flag. */
|
||||
/* Local Color Table? */
|
||||
if (fisrz & 0x80) {
|
||||
/* Read LCT */
|
||||
gif->lct.size = 1 << ((fisrz & 0x07) + 1);
|
||||
fread(gif->lct.colors, 3, 1, gif->fd);
|
||||
gif->palette = &gif->lct;
|
||||
} else
|
||||
gif->palette = &gif->gct;
|
||||
/* Image Data. */
|
||||
return read_image_data(gif, interlace);
|
||||
}
|
||||
|
||||
static void
|
||||
render_frame_rect(gd_GIF *gif, uint8_t *buffer)
|
||||
{
|
||||
int i, j, k;
|
||||
uint8_t index, *color;
|
||||
i = gif->fy * gif->width + gif->fx;
|
||||
for (j = 0; j < gif->fh; j++) {
|
||||
for (k = 0; k < gif->fw; k++) {
|
||||
index = gif->frame[(gif->fy + j) * gif->width + gif->fx + k];
|
||||
color = &gif->palette->colors[index*3];
|
||||
if (!gif->gce.transparency || index != gif->gce.tindex)
|
||||
memcpy(&buffer[(i+k)*3], color, 3);
|
||||
}
|
||||
i += gif->width;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dispose(gd_GIF *gif)
|
||||
{
|
||||
int i, j, k;
|
||||
uint8_t *bgcolor;
|
||||
switch (gif->gce.disposal) {
|
||||
case 2: /* Restore to background color. */
|
||||
bgcolor = &gif->palette->colors[gif->bgindex*3];
|
||||
i = gif->fy * gif->width + gif->fx;
|
||||
for (j = 0; j < gif->fh; j++) {
|
||||
for (k = 0; k < gif->fw; k++)
|
||||
memcpy(&gif->canvas[(i+k)*3], bgcolor, 3);
|
||||
i += gif->width;
|
||||
}
|
||||
break;
|
||||
case 3: /* Restore to previous, i.e., don't update canvas.*/
|
||||
break;
|
||||
default:
|
||||
/* Add frame non-transparent pixels to canvas. */
|
||||
render_frame_rect(gif, gif->canvas);
|
||||
}
|
||||
}
|
||||
|
||||
/* Return 1 if got a frame; 0 if got GIF trailer; -1 if error. */
|
||||
int
|
||||
gd_get_frame(gd_GIF *gif)
|
||||
{
|
||||
char sep;
|
||||
|
||||
dispose(gif);
|
||||
fread(&sep, 1, 1, gif->fd);
|
||||
while (sep != ',') {
|
||||
if (sep == ';')
|
||||
return 0;
|
||||
if (sep == '!')
|
||||
read_ext(gif);
|
||||
else return -1;
|
||||
fread(&sep, 1, 1, gif->fd);
|
||||
}
|
||||
if (read_image(gif) == -1)
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
gd_render_frame(gd_GIF *gif, uint8_t *buffer)
|
||||
{
|
||||
memcpy(buffer, gif->canvas, gif->width * gif->height * 3);
|
||||
render_frame_rect(gif, buffer);
|
||||
}
|
||||
|
||||
int
|
||||
gd_is_bgcolor(gd_GIF *gif, uint8_t color[3])
|
||||
{
|
||||
return !memcmp(&gif->palette->colors[gif->bgindex*3], color, 3);
|
||||
}
|
||||
|
||||
void
|
||||
gd_rewind(gd_GIF *gif)
|
||||
{
|
||||
fseek(gif->fd, gif->anim_start, SEEK_SET);
|
||||
}
|
||||
|
||||
void
|
||||
gd_close_gif(gd_GIF *gif)
|
||||
{
|
||||
free(gif->frame);
|
||||
free(gif);
|
||||
}
|
|
@ -1,322 +0,0 @@
|
|||
/*
|
||||
GIF decoder
|
||||
===========
|
||||
|
||||
This is a small C library that can be used to read GIF files.
|
||||
|
||||
Features
|
||||
--------
|
||||
|
||||
* support for all standard GIF features
|
||||
* support for Netscape Application Extension (looping information)
|
||||
* other extensions may be easily supported via user hooks
|
||||
* small and portable: less than 500 lines of C99
|
||||
* public domain
|
||||
|
||||
|
||||
Limitations
|
||||
-----------
|
||||
|
||||
* no support for GIF files that don't have a global color table
|
||||
* no direct support for the plain text extension (rarely used)
|
||||
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
0. Essential GIF concepts
|
||||
|
||||
GIF animations are stored in files as a series of palette-based
|
||||
compressed frames.
|
||||
|
||||
In order to display the animation, a program must lay the frames on top
|
||||
of a fixed-size canvas, one after the other. Each frame has a size,
|
||||
position and duration. Each frame can have its own palette or use a
|
||||
global palette defined in the beginning of the file.
|
||||
|
||||
In order to properly use extension hooks, it's necessary to understand
|
||||
how GIF files store variable-sized data. A GIF block of variable size is
|
||||
a sequence of sub-blocks. The first byte in a sub-block indicates the
|
||||
number of data bytes to follow. The end of the block is indicated by an
|
||||
empty sub-block: one byte of value 0x00. For instance, a data block of
|
||||
600 bytes is stored as 4 sub-blocks:
|
||||
|
||||
255, <255 data bytes>, 255, <255 data bytes>, 90, <90 data bytes>, 0
|
||||
|
||||
1. Opening and closing a GIF file
|
||||
|
||||
The function `gd_open_gif()` tries to open a GIF file for reading.
|
||||
|
||||
gd_GIF *gd_open_gif(const char *fname);
|
||||
|
||||
If this function fails, it returns NULL.
|
||||
|
||||
If `gd_open_gif()` succeeds, it returns a GIF handler (`gd_GIF *`). The
|
||||
GIF handler can be passed to the other gifdec functions to decode GIF
|
||||
metadata and frames.
|
||||
|
||||
To close the GIF file and free memory after it has been decoded, the
|
||||
function `gd_close_gif()` must be called.
|
||||
|
||||
void gd_close_gif(gd_GIF *gif);
|
||||
|
||||
2. Reading GIF attributes
|
||||
|
||||
Once a GIF file has been successfully opened, some basic information can
|
||||
be read directly from the GIF handler:
|
||||
|
||||
gd_GIF *gif = gd_open_gif("animation.gif");
|
||||
printf("canvas size: %ux%u\n", gif->width, gif->height);
|
||||
printf("number of colors: %d\n", gif->palette->size);
|
||||
|
||||
3. Reading frames
|
||||
|
||||
The function `gd_get_frame()` decodes one frame from the GIF file.
|
||||
|
||||
int gd_get_frame(gd_GIF *gif);
|
||||
|
||||
This function returns 0 if there are no more frames to read.
|
||||
|
||||
The decoded frame is stored in `gif->frame`, which is a buffer of size
|
||||
`gif->width * gif->height`, in bytes. Each byte value is an index to the
|
||||
palette at `gif->palette`.
|
||||
|
||||
Since GIF files often only store the rectangular region of a frame that
|
||||
changed from the previous frame, this function will only update the
|
||||
bytes in `gif->frame` that are in that region. For GIF files that only
|
||||
use the global palette, the whole state of the canvas is stored in
|
||||
`gif->frame` at all times, in the form of an indexed color image.
|
||||
However, when local palettes are used, it's not enough to keep color
|
||||
indices from previous frames. The color RGB values themselves need to be
|
||||
stored.
|
||||
|
||||
For this reason, in order to get the whole state of the canvas after
|
||||
a new frame has been read, it's necessary to call the function
|
||||
`gd_render_frame()`, which writes all pixels to a given buffer.
|
||||
|
||||
void gd_render_frame(gd_GIF *gif, uint8_t *buffer);
|
||||
|
||||
The buffer size must be at least `gif->width * gif->height * 3`, in
|
||||
bytes. The function `gd_render_frame()` writes the 24-bit RGB values of
|
||||
all canvas pixels in it.
|
||||
|
||||
4. Frame duration
|
||||
|
||||
GIF animations are not required to have a constant frame rate. Each
|
||||
frame can have a different duration, which is stored right before the
|
||||
frame in a Graphic Control Extension (GCE) block. This type of block is
|
||||
read by gifdec into a `gd_GCE` struct that is a member of the GIF
|
||||
handler. Specifically, the unsigned integer `gif->gce.delay` holds the
|
||||
current frame duration, in hundreths of a second. That means that, for
|
||||
instance, if `gif->gce.delay` is `50`, then the current frame must be
|
||||
displayed for half a second.
|
||||
|
||||
5. Looping
|
||||
|
||||
Most GIF animations are supposed to loop automatically, going back to
|
||||
the first frame after the last one is displayed. GIF files may contain
|
||||
looping instruction in the form of a non-negative number. If this number
|
||||
is zero, the animation must loop forever. Otherwise, this number
|
||||
indicates how many times the animation must be played. When `gifdec` is
|
||||
decoding a GIF file, this number is stored in `gif->loop_count`.
|
||||
|
||||
The function `gd_rewind()` must be called to go back to the start of the
|
||||
GIF file without closing and reopening it.
|
||||
|
||||
void gd_rewind(gd_GIF *gif);
|
||||
|
||||
6. Putting it all together
|
||||
|
||||
A simplified skeleton of a GIF viewer may look like this:
|
||||
|
||||
gd_GIF *gif = gd_open_gif("some_animation.gif");
|
||||
char *buffer = malloc(gif->width * gif->height * 3);
|
||||
for (unsigned looped = 1;; looped++) {
|
||||
while (gd_get_frame(gif)) {
|
||||
gd_render_frame(gif, buffer);
|
||||
// insert code to render buffer to screen
|
||||
// and wait for delay time to pass here
|
||||
}
|
||||
if (looped == gif->loop_count)
|
||||
break;
|
||||
gd_rewind(gif);
|
||||
}
|
||||
free(buffer);
|
||||
gd_close_gif(gif);
|
||||
|
||||
7. Transparent Background
|
||||
|
||||
GIFs can mark a certain color in the palette as the "Background Color".
|
||||
Pixels having this color are usually treated as transparent pixels by
|
||||
applications.
|
||||
|
||||
The function `gd_is_bgcolor()` can be used to check whether a pixel in
|
||||
the canvas currently has background color.
|
||||
|
||||
int gd_is_bgcolor(gd_GIF *gif, uint8_t color[3]);
|
||||
|
||||
Here's an example of how to use it:
|
||||
|
||||
gd_render_frame(gif, buffer);
|
||||
color = buffer;
|
||||
for (y = 0; y < gif->height; y++) {
|
||||
for (x = 0; x < gif->width; x++) {
|
||||
if (gd_is_bgcolor(gif, color))
|
||||
transparent_pixel(x, y);
|
||||
else
|
||||
opaque_pixel(x, y, color);
|
||||
color += 3;
|
||||
}
|
||||
}
|
||||
|
||||
8. Reading streamed metadata with extension hooks
|
||||
|
||||
Some metadata blocks may occur any number of times in GIF files in
|
||||
between frames. By default, gifdec ignore these blocks. However, it's
|
||||
possible to setup callback functions to handle each type of extension
|
||||
block, by changing some GIF handler members.
|
||||
|
||||
Whenever a Comment Extension block is found, `gif->comment()` is called.
|
||||
|
||||
void (*comment)(struct gd_GIF *gif);
|
||||
|
||||
As defined in the GIF specification, "[t]he Comment Extension contains
|
||||
textual information which is not part of the actual graphics in the GIF
|
||||
Data Stream." Encoders are recommended to only include "text using the
|
||||
7-bit ASCII character set" in GIF comments.
|
||||
|
||||
The actual comment is stored as a variable-sized block and must be read
|
||||
from the file (using the file descriptor `gif->fd`) by the callback
|
||||
function. Here's an example, printing the comment to stdout:
|
||||
|
||||
void
|
||||
comment(gd_GIF *gif)
|
||||
{
|
||||
uint8_t sub_len, byte, i;
|
||||
do {
|
||||
read(gif->fd, &sub_len, 1);
|
||||
for (i = 0; i < sub_len; i++) {
|
||||
read(gif->fd, &byte, 1);
|
||||
printf("%c", byte);
|
||||
}
|
||||
} while (sub_len);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
// Somewhere on the main path of execution.
|
||||
gif->comment = comment;
|
||||
|
||||
|
||||
Whenever a Plain Text Extension block is found, `gif->plain_text()` is
|
||||
called.
|
||||
|
||||
void (*plain_text)(
|
||||
struct gd_GIF *gif, uint16_t tx, uint16_t ty,
|
||||
uint16_t tw, uint16_t th, uint8_t cw, uint8_t ch,
|
||||
uint8_t fg, uint8_t bg
|
||||
);
|
||||
|
||||
According to the GIF specification, "[t]he Plain Text Extension contains
|
||||
textual data and the parameters necessary to render that data as a
|
||||
graphic [...]". This is a rarely used extension that requires the
|
||||
decoder to actually render text on the canvas. In order to support this,
|
||||
one must read the relevant specification and implement a suitable
|
||||
callback function to setup as `gif->plain_text`.
|
||||
|
||||
The actual plain text is stored as a variable-sized block and must be
|
||||
read from the file by the callback function.
|
||||
|
||||
|
||||
Whenever an unknown Application Extension block is found,
|
||||
`gif->application()` is called.
|
||||
|
||||
void (*application)(struct gd_GIF *gif, char id[8], char auth[3]);
|
||||
|
||||
Application Extensions are used to extend GIF with extraofficial
|
||||
features. Currently, gifdec only supports the so-called "Netscape
|
||||
Application Extension", which is commonly used to specify looping
|
||||
behavior. Other Application Extensions may be supported via this hook.
|
||||
|
||||
The application data is stored as a variable-sized block and must be
|
||||
read from the file by the callback function.
|
||||
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
The file "example.c" is a demo GIF player based on gifdec and SDL2. It
|
||||
can be tested like this:
|
||||
|
||||
$ cc `pkg-config --cflags --libs sdl2` -o gifplay gifdec.c example.c
|
||||
$ ./gifplay animation.gif
|
||||
|
||||
That should display the animation. Press SPACE to pause and Q to quit.
|
||||
|
||||
Copying
|
||||
-------
|
||||
|
||||
All of the source code and documentation for gifdec is released into the
|
||||
public domain and provided without warranty of any kind.
|
||||
*/
|
||||
|
||||
#ifndef GIFDEC_H
|
||||
#define GIFDEC_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct gd_Palette {
|
||||
int size;
|
||||
uint8_t colors[0x100 * 3];
|
||||
} gd_Palette;
|
||||
|
||||
typedef struct gd_GCE {
|
||||
uint16_t delay;
|
||||
uint8_t tindex;
|
||||
uint8_t disposal;
|
||||
int input;
|
||||
int transparency;
|
||||
} gd_GCE;
|
||||
|
||||
typedef struct gd_GIF {
|
||||
FILE *fd;
|
||||
off_t anim_start;
|
||||
uint16_t width, height;
|
||||
uint16_t depth;
|
||||
uint16_t loop_count;
|
||||
gd_GCE gce;
|
||||
gd_Palette *palette;
|
||||
gd_Palette lct, gct;
|
||||
void (*plain_text)(
|
||||
struct gd_GIF *gif, uint16_t tx, uint16_t ty,
|
||||
uint16_t tw, uint16_t th, uint8_t cw, uint8_t ch,
|
||||
uint8_t fg, uint8_t bg
|
||||
);
|
||||
void (*comment)(struct gd_GIF *gif);
|
||||
void (*application)(struct gd_GIF *gif, char id[8], char auth[3]);
|
||||
uint16_t fx, fy, fw, fh;
|
||||
uint8_t bgindex;
|
||||
uint8_t *canvas, *frame;
|
||||
} gd_GIF;
|
||||
|
||||
gd_GIF *gd_open_gif(const char *fname);
|
||||
gd_GIF *gd_open_gif_f(FILE *f);
|
||||
int gd_get_frame(gd_GIF *gif);
|
||||
void gd_render_frame(gd_GIF *gif, uint8_t *buffer);
|
||||
int gd_is_bgcolor(gd_GIF *gif, uint8_t color[3]);
|
||||
void gd_rewind(gd_GIF *gif);
|
||||
void gd_close_gif(gd_GIF *gif);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* GIFDEC_H */
|
|
@ -16,7 +16,6 @@
|
|||
#include "resources.h"
|
||||
#include "yugine.h"
|
||||
#include "sokol/sokol_app.h"
|
||||
#include "sokol/sokol_glue.h"
|
||||
|
||||
#include "crt.sglsl.h"
|
||||
#include "box.sglsl.h"
|
||||
|
@ -70,14 +69,16 @@ void gif_rec_start(int w, int h, int cpf, int bitdepth)
|
|||
.render_target = true,
|
||||
.width = gif.w,
|
||||
.height = gif.h,
|
||||
.pixel_format = SG_PIXELFORMAT_RGBA8
|
||||
// .pixel_format = SG_PIXELFORMAT_RGBA8
|
||||
.label = "gif rt",
|
||||
});
|
||||
|
||||
sg_gif.depth = sg_make_image(&(sg_image_desc){
|
||||
.render_target = true,
|
||||
.width = gif.w,
|
||||
.height = gif.h,
|
||||
.pixel_format = SG_PIXELFORMAT_DEPTH_STENCIL
|
||||
.pixel_format = SG_PIXELFORMAT_DEPTH,
|
||||
.label = "gif depth",
|
||||
});
|
||||
|
||||
sg_gif.pass = sg_make_pass(&(sg_pass_desc){
|
||||
|
@ -196,6 +197,13 @@ void trace_destroy_shader(sg_shader shd, void *data)
|
|||
YughWarn("DESTROYED SHADER");
|
||||
}
|
||||
|
||||
void trace_fail_image(sg_image id, void *data)
|
||||
{
|
||||
sg_image_desc desc = sg_query_image_desc(id);
|
||||
YughWarn("Failed to make image %s", desc.label);
|
||||
|
||||
}
|
||||
|
||||
static sg_trace_hooks hooks = {
|
||||
.fail_shader = trace_fail_shader,
|
||||
.make_shader = trace_make_shader,
|
||||
|
@ -207,9 +215,22 @@ void render_init() {
|
|||
mainwin.height = sapp_height();
|
||||
|
||||
sg_setup(&(sg_desc){
|
||||
.context = sapp_sgcontext(),
|
||||
.context.d3d11.device = sapp_d3d11_get_device(),
|
||||
.context.d3d11.device_context = sapp_d3d11_get_device_context(),
|
||||
.context.d3d11.render_target_view_cb = sapp_d3d11_get_render_target_view,
|
||||
.context.d3d11.depth_stencil_view_cb = sapp_d3d11_get_depth_stencil_view,
|
||||
/* .context.metal.device = sapp_metal_get_device(),
|
||||
.context.metal.renderpass_descriptor_cb = sapp_metal_get_renderpass_descriptor,
|
||||
.context.metal.drawable_cb = sapp_metal_get_drawable,
|
||||
.context.color_format = (sg_pixel_format) sapp_color_format(),
|
||||
.context.depth_format = (sg_pixel_format) sapp_depth_format(),
|
||||
.context.sample_count = sapp_sample_count(),
|
||||
.context.wgpu.device = sapp_wgpu_get_device(),
|
||||
.context.wgpu.render_view_cb = sapp_wgpu_get_render_view,
|
||||
.context.wgpu.resolve_view_cb = sapp_wgpu_get_resolve_view,
|
||||
.context.wgpu.depth_stencil_view_cb = sapp_wgpu_get_depth_stencil_view,
|
||||
.mtl_force_managed_storage_mode = 1,
|
||||
.logger = {
|
||||
*/ .logger = {
|
||||
.func = sg_logging,
|
||||
.user_data = NULL,
|
||||
},
|
||||
|
@ -263,13 +284,15 @@ void render_init() {
|
|||
.render_target = true,
|
||||
.width = mainwin.width,
|
||||
.height = mainwin.height,
|
||||
.label = "crt rt",
|
||||
});
|
||||
|
||||
crt_post.depth_img = sg_make_image(&(sg_image_desc){
|
||||
.render_target = true,
|
||||
.width = mainwin.width,
|
||||
.height = mainwin.height,
|
||||
.pixel_format = SG_PIXELFORMAT_DEPTH_STENCIL
|
||||
.pixel_format = SG_PIXELFORMAT_DEPTH,
|
||||
.label = "crt depth",
|
||||
});
|
||||
|
||||
crt_post.pass = sg_make_pass(&(sg_pass_desc){
|
||||
|
@ -370,14 +393,14 @@ void render_winsize()
|
|||
crt_post.img = sg_make_image(&(sg_image_desc){
|
||||
.render_target = true,
|
||||
.width = mainwin.width,
|
||||
.height = mainwin.height
|
||||
.height = mainwin.height,
|
||||
});
|
||||
|
||||
crt_post.depth_img = sg_make_image(&(sg_image_desc){
|
||||
.render_target = true,
|
||||
.width = mainwin.width,
|
||||
.height = mainwin.height,
|
||||
.pixel_format = SG_PIXELFORMAT_DEPTH_STENCIL
|
||||
.pixel_format = SG_PIXELFORMAT_DEPTH,
|
||||
});
|
||||
|
||||
crt_post.pass = sg_make_pass(&(sg_pass_desc){
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
#include <math.h>
|
||||
#include <stb_ds.h>
|
||||
#include <stb_image.h>
|
||||
#include "gifdec.h"
|
||||
|
||||
#include "resources.h"
|
||||
|
||||
|
@ -72,22 +71,8 @@ int mip_wh(int w, int h, int *mw, int *mh, int lvl)
|
|||
|
||||
int gif_nframes(const char *path)
|
||||
{
|
||||
long rawlen;
|
||||
unsigned char *raw = slurp_file(path, &rawlen);
|
||||
char *ext = strrchr(path,'.');
|
||||
int frames = 0; /* default here is also the error code */
|
||||
|
||||
FILE *f = fmemopen(raw, rawlen, "r");
|
||||
gd_GIF *gif = gd_open_gif_f(f);
|
||||
|
||||
if (!gif) goto fin;
|
||||
|
||||
while (gd_get_frame(gif)) frames++;
|
||||
|
||||
fin:
|
||||
gd_close_gif(gif);
|
||||
free(raw);
|
||||
return frames;
|
||||
struct Texture *t = texture_pullfromfile(path);
|
||||
return t->frames;
|
||||
}
|
||||
|
||||
/* If an empty string or null is put for path, loads default texture */
|
||||
|
@ -122,43 +107,9 @@ struct Texture *texture_pullfromfile(const char *path) {
|
|||
tex->height = qoi.height;
|
||||
n = qoi.channels;
|
||||
} else if (!strcmp(ext, ".gif")) {
|
||||
FILE *f = fmemopen(raw, rawlen, "r");
|
||||
gd_GIF *gif = gd_open_gif_f(f);
|
||||
int frames = 0;
|
||||
while (gd_get_frame(gif))
|
||||
frames++;
|
||||
|
||||
gd_rewind(gif);
|
||||
|
||||
int frame = 0;
|
||||
uint8_t gifbuf[gif->width*gif->height*3];
|
||||
data = malloc(gif->width*gif->height*4*frames);
|
||||
|
||||
while (gd_get_frame(gif)) {
|
||||
gd_render_frame(gif, gifbuf);
|
||||
uint8_t black[4] = {0,0,0,0};
|
||||
for (int p = 0; p < gif->height*gif->width; p++) {
|
||||
int offset = (p*4)+(frame*gif->width*gif->height*4);
|
||||
if (gd_is_bgcolor(gif, gifbuf+(p*3)))
|
||||
memcpy(data+offset, black, 4*sizeof(uint8_t));
|
||||
else {
|
||||
memcpy(data+offset, gifbuf+(p*3), 3*sizeof(uint8_t));
|
||||
data[offset+3] = 255;
|
||||
}
|
||||
}
|
||||
|
||||
frame++;
|
||||
}
|
||||
tex->width = gif->width;
|
||||
tex->height = gif->height*frames;
|
||||
gd_close_gif(gif);
|
||||
fclose(f);
|
||||
|
||||
/*
|
||||
int *delays;
|
||||
int frames;
|
||||
data = stbi_load_gif_from_memory(raw, rawlen, &delays, &tex->width, &tex->height, &frames, &n, 4);
|
||||
*/
|
||||
data = stbi_load_gif_from_memory(raw, rawlen, &delays, &tex->width, &tex->height, &tex->frames, &n, 4);
|
||||
tex->height *= tex->frames;
|
||||
} else {
|
||||
data = stbi_load_from_memory(raw, rawlen, &tex->width, &tex->height, &n, 4);
|
||||
}
|
||||
|
|
|
@ -58,6 +58,7 @@ struct TextureOptions {
|
|||
int animation;
|
||||
int wrapx;
|
||||
int wrapy;
|
||||
|
||||
};
|
||||
|
||||
/* Represents an actual texture on the GPU */
|
||||
|
@ -68,6 +69,7 @@ struct Texture {
|
|||
unsigned char *data;
|
||||
struct TextureOptions opts;
|
||||
struct TexAnim anim;
|
||||
int frames;
|
||||
};
|
||||
|
||||
struct Image {
|
||||
|
|
136
source/engine/thirdparty/sokol/sokol_glue.h
vendored
136
source/engine/thirdparty/sokol/sokol_glue.h
vendored
|
@ -1,136 +0,0 @@
|
|||
#if defined(SOKOL_IMPL) && !defined(SOKOL_GLUE_IMPL)
|
||||
#define SOKOL_GLUE_IMPL
|
||||
#endif
|
||||
#ifndef SOKOL_GLUE_INCLUDED
|
||||
/*
|
||||
sokol_glue.h -- glue helper functions for sokol headers
|
||||
|
||||
Project URL: https://github.com/floooh/sokol
|
||||
|
||||
Do this:
|
||||
#define SOKOL_IMPL or
|
||||
#define SOKOL_GLUE_IMPL
|
||||
before you include this file in *one* C or C++ file to create the
|
||||
implementation.
|
||||
|
||||
...optionally provide the following macros to override defaults:
|
||||
|
||||
SOKOL_ASSERT(c) - your own assert macro (default: assert(c))
|
||||
SOKOL_GLUE_API_DECL - public function declaration prefix (default: extern)
|
||||
SOKOL_API_DECL - same as SOKOL_GLUE_API_DECL
|
||||
SOKOL_API_IMPL - public function implementation prefix (default: -)
|
||||
|
||||
If sokol_glue.h is compiled as a DLL, define the following before
|
||||
including the declaration or implementation:
|
||||
|
||||
SOKOL_DLL
|
||||
|
||||
On Windows, SOKOL_DLL will define SOKOL_GLUE_API_DECL as __declspec(dllexport)
|
||||
or __declspec(dllimport) as needed.
|
||||
|
||||
OVERVIEW
|
||||
========
|
||||
The sokol core headers should not depend on each other, but sometimes
|
||||
it's useful to have a set of helper functions as "glue" between
|
||||
two or more sokol headers.
|
||||
|
||||
This is what sokol_glue.h is for. Simply include the header after other
|
||||
sokol headers (both for the implementation and declaration), and
|
||||
depending on what headers have been included before, sokol_glue.h
|
||||
will make available "glue functions".
|
||||
|
||||
PROVIDED FUNCTIONS
|
||||
==================
|
||||
|
||||
- if sokol_app.h and sokol_gfx.h is included:
|
||||
|
||||
sg_context_desc sapp_sgcontext(void):
|
||||
|
||||
Returns an initialized sg_context_desc function initialized
|
||||
by calling sokol_app.h functions.
|
||||
|
||||
LICENSE
|
||||
=======
|
||||
zlib/libpng license
|
||||
|
||||
Copyright (c) 2018 Andre Weissflog
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the
|
||||
use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software in a
|
||||
product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not
|
||||
be misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
*/
|
||||
#define SOKOL_GLUE_INCLUDED
|
||||
|
||||
#if defined(SOKOL_API_DECL) && !defined(SOKOL_GLUE_API_DECL)
|
||||
#define SOKOL_GLUE_API_DECL SOKOL_API_DECL
|
||||
#endif
|
||||
#ifndef SOKOL_GLUE_API_DECL
|
||||
#if defined(_WIN32) && defined(SOKOL_DLL) && defined(SOKOL_GLUE_IMPL)
|
||||
#define SOKOL_GLUE_API_DECL __declspec(dllexport)
|
||||
#elif defined(_WIN32) && defined(SOKOL_DLL)
|
||||
#define SOKOL_GLUE_API_DECL __declspec(dllimport)
|
||||
#else
|
||||
#define SOKOL_GLUE_API_DECL extern
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(SOKOL_GFX_INCLUDED) && defined(SOKOL_APP_INCLUDED)
|
||||
SOKOL_GLUE_API_DECL sg_context_desc sapp_sgcontext(void);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
#endif /* SOKOL_GLUE_INCLUDED */
|
||||
|
||||
/*-- IMPLEMENTATION ----------------------------------------------------------*/
|
||||
#ifdef SOKOL_GLUE_IMPL
|
||||
#define SOKOL_GLUE_IMPL_INCLUDED (1)
|
||||
#include <string.h> /* memset */
|
||||
|
||||
#ifndef SOKOL_API_IMPL
|
||||
#define SOKOL_API_IMPL
|
||||
#endif
|
||||
|
||||
#if defined(SOKOL_GFX_INCLUDED) && defined(SOKOL_APP_INCLUDED)
|
||||
SOKOL_API_IMPL sg_context_desc sapp_sgcontext(void) {
|
||||
sg_context_desc desc;
|
||||
memset(&desc, 0, sizeof(desc));
|
||||
desc.color_format = (sg_pixel_format) sapp_color_format();
|
||||
desc.depth_format = (sg_pixel_format) sapp_depth_format();
|
||||
desc.sample_count = sapp_sample_count();
|
||||
desc.metal.device = sapp_metal_get_device();
|
||||
desc.metal.renderpass_descriptor_cb = sapp_metal_get_renderpass_descriptor;
|
||||
desc.metal.drawable_cb = sapp_metal_get_drawable;
|
||||
desc.d3d11.device = sapp_d3d11_get_device();
|
||||
desc.d3d11.device_context = sapp_d3d11_get_device_context();
|
||||
desc.d3d11.render_target_view_cb = sapp_d3d11_get_render_target_view;
|
||||
desc.d3d11.depth_stencil_view_cb = sapp_d3d11_get_depth_stencil_view;
|
||||
desc.wgpu.device = sapp_wgpu_get_device();
|
||||
desc.wgpu.render_view_cb = sapp_wgpu_get_render_view;
|
||||
desc.wgpu.resolve_view_cb = sapp_wgpu_get_resolve_view;
|
||||
desc.wgpu.depth_stencil_view_cb = sapp_wgpu_get_depth_stencil_view;
|
||||
return desc;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SOKOL_GLUE_IMPL */
|
Loading…
Reference in a new issue