parts: add basic implementation of Flash type

Sprite objects and sounds are not implemented yet.
This commit is contained in:
kichikuou
2023-06-17 11:32:14 +09:00
parent 88c37a9165
commit 3496f45e39
10 changed files with 609 additions and 73 deletions
+12 -5
View File
@@ -62,11 +62,6 @@ bool PE_SetNumeralSpace(int parts_no, int space, int state);
bool PE_SetNumeralLength(int parts_no, int length, int state);
bool PE_SetNumeralSurfaceArea(int parts_no, int x, int y, int w, int h, int state);
bool PE_SetPartsRectangleDetectionSize(int PartsNumber, int Width, int Height, int State);
bool PE_SetPartsFlash(int PartsNumber, struct string *pIFlashFileName, int State);
bool PE_IsPartsFlashEnd(int PartsNumber, int State);
int PE_GetPartsFlashCurrentFrameNumber(int PartsNumber, int State);
bool PE_BackPartsFlashBeginFrame(int PartsNumber, int State);
bool PE_StepPartsFlashFinalFrame(int PartsNumber, int State);
void PE_ReleaseParts(int parts_no);
void PE_ReleaseAllParts(void);
void PE_ReleaseAllPartsWithoutSystem(void);
@@ -207,4 +202,16 @@ bool PE_SetPartsFontEdgeWeight(int parts_no, float edge_weight, int state);
bool PE_SetTextCharSpace(int parts_no, int char_space, int state);
bool PE_SetTextLineSpace(int parts_no, int line_space, int state);
// flash.c
bool PE_SetPartsFlash(int parts_no, struct string *flash_filename, int state);
bool PE_IsPartsFlashEnd(int parts_no, int state);
int PE_GetPartsFlashCurrentFrameNumber(int parts_no, int state);
bool PE_BackPartsFlashBeginFrame(int parts_no, int state);
bool PE_StepPartsFlashFinalFrame(int parts_no, int state);
bool PE_SetPartsFlashAndStop(int parts_no, struct string *flash_filename, int state);
bool PE_StopPartsFlash(int parts_no, int state);
bool PE_StartPartsFlash(int parts_no, int state);
bool PE_GoFramePartsFlash(int parts_no, int frame_no, int state);
int PE_GetPartsFlashEndFrame(int parts_no, int state);
#endif /* SYSTEM4_PARTS_H */
+10 -10
View File
@@ -56,11 +56,11 @@ HLL_LIBRARY(GoatGUIEngine,
HLL_EXPORT(SetNumeralShowComma, PE_SetNumeralShowComma),
HLL_EXPORT(SetNumeralSpace, PE_SetNumeralSpace),
HLL_TODO_EXPORT(SetPartsRectangleDetectionSize, PE_SetPartsRectangleDetectionSize),
HLL_TODO_EXPORT(SetPartsFlash, PE_SetPartsFlash),
HLL_TODO_EXPORT(IsPartsFlashEnd, PE_IsPartsFlashEnd),
HLL_TODO_EXPORT(GetPartsFlashCurrentFrameNumber, PE_GetPartsFlashCurrentFrameNumber),
HLL_TODO_EXPORT(BackPartsFlashBeginFrame, PE_BackPartsFlashBeginFrame),
HLL_TODO_EXPORT(StepPartsFlashFinalFrame, PE_StepPartsFlashFinalFrame),
HLL_EXPORT(SetPartsFlash, PE_SetPartsFlash),
HLL_EXPORT(IsPartsFlashEnd, PE_IsPartsFlashEnd),
HLL_EXPORT(GetPartsFlashCurrentFrameNumber, PE_GetPartsFlashCurrentFrameNumber),
HLL_EXPORT(BackPartsFlashBeginFrame, PE_BackPartsFlashBeginFrame),
HLL_EXPORT(StepPartsFlashFinalFrame, PE_StepPartsFlashFinalFrame),
HLL_EXPORT(ReleaseParts, PE_ReleaseParts),
HLL_EXPORT(ReleaseAllParts, PE_ReleaseAllParts),
HLL_EXPORT(ReleaseAllPartsWithoutSystem, PE_ReleaseAllPartsWithoutSystem),
@@ -126,11 +126,11 @@ HLL_LIBRARY(GoatGUIEngine,
HLL_EXPORT(Save, PE_Save),
HLL_EXPORT(Load, PE_Load),
HLL_TODO_EXPORT(SetPartsFlashAndStop, PE_SetPartsFlashAndStop),
HLL_TODO_EXPORT(StopPartsFlash, PE_StopPartsFlash),
HLL_TODO_EXPORT(StartPartsFlash, PE_StartPartsFlash),
HLL_TODO_EXPORT(GoFramePartsFlash, PE_GoFramePartsFlash),
HLL_TODO_EXPORT(GetPartsFlashEndFrame, PE_GetPartsFlashEndFrame),
HLL_EXPORT(SetPartsFlashAndStop, PE_SetPartsFlashAndStop),
HLL_EXPORT(StopPartsFlash, PE_StopPartsFlash),
HLL_EXPORT(StartPartsFlash, PE_StartPartsFlash),
HLL_EXPORT(GoFramePartsFlash, PE_GoFramePartsFlash),
HLL_EXPORT(GetPartsFlashEndFrame, PE_GetPartsFlashEndFrame),
HLL_TODO_EXPORT(ClearPartsConstructionProcess, PE_ClearPartsConstructionProcess),
HLL_TODO_EXPORT(AddCreateToPartsConstructionProcess, PE_AddCreateToPartsConstructionProcess),
HLL_TODO_EXPORT(AddCreatePixelOnlyToPartsConstructionProcess, PE_AddCreatePixelOnlyToPartsConstructionProcess),
+12 -12
View File
@@ -85,18 +85,18 @@ HLL_LIBRARY(PartsEngine,
HLL_TODO_EXPORT(SetPartsRectangleDetectionSurfaceArea, PartsEngine_SetPartsRectangleDetectionSurfaceArea),
HLL_TODO_EXPORT(SetPartsCGDetectionSize, PartsEngine_SetPartsCGDetectionSize),
HLL_TODO_EXPORT(SetPartsCGDetectionSurfaceArea, PartsEngine_SetPartsCGDetectionSurfaceArea),
HLL_TODO_EXPORT(SetPartsFlash, PartsEngine_SetPartsFlash),
HLL_TODO_EXPORT(IsPartsFlashEnd, PartsEngine_IsPartsFlashEnd),
HLL_TODO_EXPORT(GetPartsFlashCurrentFrameNumber, PartsEngine_GetPartsFlashCurrentFrameNumber),
HLL_TODO_EXPORT(BackPartsFlashBeginFrame, PartsEngine_BackPartsFlashBeginFrame),
HLL_TODO_EXPORT(StepPartsFlashFinalFrame, PartsEngine_StepPartsFlashFinalFrame),
HLL_TODO_EXPORT(SetPartsFlashSurfaceArea, PartsEngine_SetPartsFlashSurfaceArea),
HLL_TODO_EXPORT(SetPartsFlashAndStop, PartsEngine_SetPartsFlashAndStop),
HLL_TODO_EXPORT(StopPartsFlash, PartsEngine_StopPartsFlash),
HLL_TODO_EXPORT(StartPartsFlash, PartsEngine_StartPartsFlash),
HLL_TODO_EXPORT(GoFramePartsFlash, PartsEngine_GoFramePartsFlash),
HLL_TODO_EXPORT(GetPartsFlashEndFrame, PartsEngine_GetPartsFlashEndFrame),
HLL_TODO_EXPORT(ExistsFlashFile, PartsEngine_ExistsFlashFile),
HLL_EXPORT(SetPartsFlash, PE_SetPartsFlash),
HLL_EXPORT(IsPartsFlashEnd, PE_IsPartsFlashEnd),
HLL_EXPORT(GetPartsFlashCurrentFrameNumber, PE_GetPartsFlashCurrentFrameNumber),
HLL_EXPORT(BackPartsFlashBeginFrame, PE_BackPartsFlashBeginFrame),
HLL_EXPORT(StepPartsFlashFinalFrame, PE_StepPartsFlashFinalFrame),
HLL_TODO_EXPORT(SetPartsFlashSurfaceArea, PE_SetPartsFlashSurfaceArea),
HLL_EXPORT(SetPartsFlashAndStop, PE_SetPartsFlashAndStop),
HLL_EXPORT(StopPartsFlash, PE_StopPartsFlash),
HLL_EXPORT(StartPartsFlash, PE_StartPartsFlash),
HLL_EXPORT(GoFramePartsFlash, PE_GoFramePartsFlash),
HLL_EXPORT(GetPartsFlashEndFrame, PE_GetPartsFlashEndFrame),
HLL_TODO_EXPORT(ExistsFlashFile, PE_ExistsFlashFile),
HLL_TODO_EXPORT(ClearPartsConstructionProcess, PartsEngine_ClearPartsConstructionProcess),
HLL_EXPORT(AddCreateToPartsConstructionProcess, PE_AddCreateToPartsConstructionProcess),
HLL_EXPORT(AddCreatePixelOnlyToPartsConstructionProcess, PE_AddCreatePixelOnlyToPartsConstructionProcess),
+1
View File
@@ -53,6 +53,7 @@ xsystem4 = [version_h,
'parts/construction.c',
'parts/debug.c',
'parts/flash.c',
'parts/input.c',
'parts/motion.c',
'parts/parts.c',
+16 -2
View File
@@ -172,6 +172,13 @@ static void parts_construction_process_to_json(struct parts_construction_process
}
}
static void parts_flash_to_json(struct parts_flash *flash, cJSON *out, bool verbose)
{
cJSON_AddSjisToObject(out, "filename", flash->name->text);
cJSON_AddNumberToObject(out, "frame_count", flash->swf->frame_count);
cJSON_AddNumberToObject(out, "current_frame", flash->current_frame);
}
static cJSON *parts_state_to_json(struct parts_state *state, bool verbose)
{
static const char *state_types[PARTS_NR_TYPES] = {
@@ -182,7 +189,8 @@ static cJSON *parts_state_to_json(struct parts_state *state, bool verbose)
[PARTS_NUMERAL] = "numeral",
[PARTS_HGAUGE] = "hgauge",
[PARTS_VGAUGE] = "vgauge",
[PARTS_CONSTRUCTION_PROCESS] = "construction_process"
[PARTS_CONSTRUCTION_PROCESS] = "construction_process",
[PARTS_FLASH] = "flash"
};
const char *type = "invalid";
if (state->type >= 0 && state->type < PARTS_NR_TYPES)
@@ -192,6 +200,8 @@ static cJSON *parts_state_to_json(struct parts_state *state, bool verbose)
cJSON_AddStringToObject(obj, "type", type);
switch (state->type) {
case PARTS_UNINITIALIZED:
break;
case PARTS_CG:
parts_cg_to_json(&state->cg, obj, verbose);
break;
@@ -211,7 +221,8 @@ static cJSON *parts_state_to_json(struct parts_state *state, bool verbose)
case PARTS_CONSTRUCTION_PROCESS:
parts_construction_process_to_json(&state->cproc, obj, verbose);
break;
default:
case PARTS_FLASH:
parts_flash_to_json(&state->flash, obj, verbose);
break;
}
@@ -463,6 +474,9 @@ static void parts_list_print(struct parts *parts, int indent)
sys_message(")");
break;
}
case PARTS_FLASH:
sys_message("(flash %s)", display_sjis0(state->flash.name->text));
break;
}
sys_message(" @ z=%d (%d)\n", parts->global.z, parts->local.z);
+380
View File
@@ -0,0 +1,380 @@
/* Copyright (C) 2023 kichikuou <KichikuouChrome@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://gnu.org/licenses/>.
*/
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include "system4.h"
#include "system4/archive.h"
#include "system4/hashtable.h"
#include "system4/string.h"
#include "asset_manager.h"
#include "swf.h"
#include "xsystem4.h"
#include "parts.h"
#include "parts_internal.h"
#define muldiv(x, y, denom) ((int64_t)(x) * (int64_t)(y) / (int64_t)(denom))
static void clear_display_list(struct parts_flash *f)
{
while (!TAILQ_EMPTY(&f->display_list)) {
struct parts_flash_object *obj = TAILQ_FIRST(&f->display_list);
TAILQ_REMOVE(&f->display_list, obj, entry);
free(obj);
}
}
static void free_bitmap(void *value)
{
gfx_delete_texture(value);
free(value);
}
void parts_flash_free(struct parts_flash *f)
{
clear_display_list(f);
if (f->swf)
swf_free(f->swf);
if (f->name)
free_string(f->name);
if (f->dictionary)
ht_free_int(f->dictionary);
if (f->bitmaps) {
ht_foreach_value(f->bitmaps, free_bitmap);
ht_free_int(f->bitmaps);
}
}
bool parts_flash_load(struct parts *parts, struct parts_flash *f, struct string *filename)
{
if (f->swf) {
parts_flash_free(f);
memset(f, 0, sizeof(struct parts_flash));
}
TAILQ_INIT(&f->display_list);
if (!filename)
return false;
struct archive_data *dfile = asset_get_by_name(ASSET_FLASH, filename->text, NULL);
if (!dfile)
return false;
f->swf = aff_load(dfile->data, dfile->size);
archive_free_data(dfile);
if (!f->swf)
return false;
f->name = string_dup(filename);
f->tag = f->swf->tags;
f->stopped = false;
f->elapsed = 0;
f->current_frame = 0;
f->dictionary = ht_create(256);
f->bitmaps = ht_create(64);
int width = f->swf->frame_size.x_max / 20;
int height = f->swf->frame_size.y_max / 20;
parts_set_dims(parts, &f->common, width, height);
return true;
}
static void define_bits_lossless(struct parts_flash *f, struct swf_tag_define_bits_lossless *tag)
{
ht_put_int(f->dictionary, tag->character_id, tag);
struct ht_slot *slot = ht_put_int(f->bitmaps, tag->character_id, NULL);
if (!slot->value) {
struct texture *t = xcalloc(1, sizeof(struct texture));
gfx_init_texture_with_pixels(t, tag->width, tag->height, tag->data);
slot->value = t;
}
}
static void define_shape(struct parts_flash *f, struct swf_tag_define_shape *tag)
{
ht_put_int(f->dictionary, tag->shape_id, tag);
}
static void do_action(struct parts_flash *f, struct swf_tag_do_action *tag)
{
for (struct swf_action *a = tag->actions; a->code != ACTION_END; a = a->next) {
switch (a->code) {
case ACTION_STOP:
f->stopped = true;
break;
case ACTION_CONSTANT_POOL:
case ACTION_PUSH:
case ACTION_POP:
case ACTION_CALL_FUNCTION:
break;
default:
ERROR("unimplemented action %x", a->code);
break;
}
}
}
static struct parts_flash_object *update_object(struct parts_flash_object *obj, struct swf_tag_place_object *tag)
{
if (!obj) {
if (tag->flags & PLACE_FLAG_HAS_CHARACTER) {
obj = xcalloc(1, sizeof(struct parts_flash_object));
obj->depth = tag->depth;
} else {
ERROR("no object to update (depth=%d)", tag->depth);
}
}
if (tag->flags & PLACE_FLAG_HAS_CHARACTER) {
obj->character_id = tag->character_id;
obj->matrix = (struct swf_matrix) {
.scale_x = 1 << 16,
.scale_y = 1 << 16,
};
obj->color_transform = (struct swf_cxform_with_alpha) {
.mult_terms = { 256, 256, 256, 256 }
};
}
if (tag->flags & PLACE_FLAG_HAS_MATRIX)
obj->matrix = tag->matrix;
if (tag->flags & PLACE_FLAG_HAS_COLOR_TRANSFORM)
obj->color_transform = tag->color_transform;
if (tag->flags & PLACE_FLAG_HAS_BLEND_MODE)
WARNING("PLACE_FLAG_HAS_BLEND_MODE is not supported yet");
return obj;
}
static void place_object(struct parts_flash *f, struct swf_tag_place_object *tag)
{
struct parts_flash_object *p;
TAILQ_FOREACH(p, &f->display_list, entry) {
if (p->depth == tag->depth) {
update_object(p, tag);
return;
} else if (p->depth > tag->depth) {
struct parts_flash_object *obj = update_object(NULL, tag);
TAILQ_INSERT_BEFORE(p, obj, entry);
return;
}
}
p = update_object(NULL, tag);
TAILQ_INSERT_TAIL(&f->display_list, p, entry);
}
static void remove_object(struct parts_flash *f, struct swf_tag_remove_object2 *tag)
{
struct parts_flash_object *p;
TAILQ_FOREACH(p, &f->display_list, entry) {
if (p->depth == tag->depth) {
TAILQ_REMOVE(&f->display_list, p, entry);
free(p);
return;
}
}
}
bool parts_flash_seek(struct parts_flash *f, int frame)
{
if (!f->swf || f->current_frame == frame)
return false;
if (f->current_frame > frame) {
f->current_frame = 0;
f->tag = f->swf->tags;
clear_display_list(f);
}
struct swf_tag *t;
for (t = f->tag; t && f->current_frame < frame; t = t->next) {
switch (t->type) {
case TAG_FILE_ATTRIBUTES:
case TAG_SET_BACKGROUND_COLOR:
// Do nothing.
break;
case TAG_END:
f->stopped = true;
break;
case TAG_SHOW_FRAME:
f->current_frame++;
break;
case TAG_DEFINE_BITS_LOSSLESS:
case TAG_DEFINE_BITS_LOSSLESS2:
define_bits_lossless(f, (struct swf_tag_define_bits_lossless*)t);
break;
case TAG_DEFINE_SHAPE:
define_shape(f, (struct swf_tag_define_shape*)t);
break;
case TAG_DO_ACTION:
do_action(f, (struct swf_tag_do_action*)t);
break;
case TAG_PLACE_OBJECT2:
case TAG_PLACE_OBJECT3:
place_object(f, (struct swf_tag_place_object*)t);
break;
case TAG_REMOVE_OBJECT2:
remove_object(f, (struct swf_tag_remove_object2*)t);
break;
default:
ERROR("unknown tag 0x%x", t->type);
}
}
f->tag = t;
return true;
}
bool parts_flash_update(struct parts_flash *f, int passed_time)
{
if (!f->swf || f->stopped)
return false;
f->elapsed += passed_time;
int delta_frame = muldiv(f->elapsed, f->swf->frame_rate, 256000);
if (!delta_frame)
return false;
f->elapsed -= muldiv(delta_frame, 256000, f->swf->frame_rate);
return parts_flash_seek(f, f->current_frame + delta_frame);
}
bool PE_SetPartsFlash(int parts_no, struct string *flash_filename, int state)
{
if (!parts_state_valid(--state))
return false;
struct parts *parts = parts_get(parts_no);
struct parts_flash *f = parts_get_flash(parts, state);
if (parts_flash_load(parts, f, flash_filename)) {
parts_flash_seek(f, 1);
parts_dirty(parts);
return true;
}
return false;
}
bool PE_IsPartsFlashEnd(int parts_no, int state)
{
if (!parts_state_valid(--state))
return false;
struct parts *parts = parts_get(parts_no);
struct parts_flash *f = parts_get_flash(parts, state);
return f->swf && f->current_frame == f->swf->frame_count;
}
int PE_GetPartsFlashCurrentFrameNumber(int parts_no, int state)
{
if (!parts_state_valid(--state))
return 0;
struct parts *parts = parts_get(parts_no);
struct parts_flash *f = parts_get_flash(parts, state);
return f->current_frame;
}
bool PE_BackPartsFlashBeginFrame(int parts_no, int state)
{
if (!parts_state_valid(--state))
return false;
struct parts *parts = parts_get(parts_no);
struct parts_flash *f = parts_get_flash(parts, state);
if (!f->swf)
return false;
if (parts_flash_seek(f, 1))
parts_dirty(parts);
f->elapsed = 0;
return true;
}
bool PE_StepPartsFlashFinalFrame(int parts_no, int state)
{
if (!parts_state_valid(--state))
return false;
struct parts *parts = parts_get(parts_no);
struct parts_flash *f = parts_get_flash(parts, state);
if (!f->swf)
return false;
if (parts_flash_seek(f, f->swf->frame_count))
parts_dirty(parts);
f->elapsed = 0;
return true;
}
bool PE_SetPartsFlashAndStop(int parts_no, struct string *flash_filename, int state)
{
if (!parts_state_valid(--state))
return false;
struct parts *parts = parts_get(parts_no);
struct parts_flash *f = parts_get_flash(parts, state);
bool result = parts_flash_load(parts, f, flash_filename);
f->stopped = true;
return result;
}
bool PE_StopPartsFlash(int parts_no, int state)
{
if (!parts_state_valid(--state))
return false;
struct parts *parts = parts_get(parts_no);
struct parts_flash *f = parts_get_flash(parts, state);
if (!f->swf)
return false;
f->stopped = true;
return true;
}
bool PE_StartPartsFlash(int parts_no, int state)
{
if (!parts_state_valid(--state))
return false;
struct parts *parts = parts_get(parts_no);
struct parts_flash *f = parts_get_flash(parts, state);
if (!f->swf)
return false;
f->stopped = false;
return true;
}
bool PE_GoFramePartsFlash(int parts_no, int frame_no, int state)
{
if (!parts_state_valid(--state))
return false;
struct parts *parts = parts_get(parts_no);
struct parts_flash *f = parts_get_flash(parts, state);
if (!f->swf)
return false;
if (parts_flash_seek(f, frame_no))
parts_dirty(parts);
f->elapsed = 0;
return true;
}
int PE_GetPartsFlashEndFrame(int parts_no, int state)
{
if (!parts_state_valid(--state))
return 0;
struct parts *parts = parts_get(parts_no);
struct parts_flash *f = parts_get_flash(parts, state);
if (!f->swf)
return 0;
return f->swf->frame_count;
}
+18 -11
View File
@@ -170,6 +170,9 @@ static void parts_state_free(struct parts_state *state)
parts_cp_op_free(op);
}
break;
case PARTS_FLASH:
parts_flash_free(&state->flash);
break;
}
memset(state, 0, sizeof(struct parts_state));
}
@@ -213,6 +216,7 @@ void parts_state_reset(struct parts_state *state, enum parts_type type)
case PARTS_UNINITIALIZED:
case PARTS_CG:
case PARTS_ANIMATION:
case PARTS_FLASH:
break;
}
}
@@ -273,6 +277,14 @@ struct parts_construction_process *parts_get_construction_process(struct parts *
return &parts->states[state].cproc;
}
struct parts_flash *parts_get_flash(struct parts *parts, int state)
{
if (parts->states[state].type != PARTS_FLASH) {
parts_state_reset(&parts->states[state], PARTS_FLASH);
}
return &parts->states[state].flash;
}
static Point calculate_offset(int mode, int w, int h)
{
switch (mode) {
@@ -652,6 +664,12 @@ void parts_set_surface_area(struct parts *parts, struct parts_common *common, in
static void parts_update_loop(struct parts *parts, int passed_time)
{
if (parts->states[parts->state].type == PARTS_FLASH) {
if (parts_flash_update(&parts->states[parts->state].flash, passed_time))
parts_dirty(parts);
return;
}
if (parts->states[parts->state].type != PARTS_ANIMATION)
return;
@@ -1325,11 +1343,6 @@ bool PE_SetNumeralSurfaceArea(int parts_no, int x, int y, int w, int h, int stat
}
bool PE_SetPartsRectangleDetectionSize(int PartsNumber, int Width, int Height, int State);
bool PE_SetPartsFlash(int PartsNumber, struct string *pIFlashFileName, int State);
bool PE_IsPartsFlashEnd(int PartsNumber, int State);
int PE_GetPartsFlashCurrentFrameNumber(int PartsNumber, int State);
bool PE_BackPartsFlashBeginFrame(int PartsNumber, int State);
bool PE_StepPartsFlashFinalFrame(int PartsNumber, int State);
void PE_ReleaseParts(int parts_no)
{
@@ -1546,9 +1559,3 @@ bool PE_IsExist(int parts_no)
{
return !!ht_get_int(parts_table, parts_no, NULL);
}
bool PE_SetPartsFlashAndStop(int PartsNumber, struct string *pIFlashFileName, int State);
bool PE_StopPartsFlash(int PartsNumber, int State);
bool PE_StartPartsFlash(int PartsNumber, int State);
bool PE_GoFramePartsFlash(int PartsNumber, int FrameNumber, int State);
int PE_GetPartsFlashEndFrame(int PartsNumber, int State);
+34 -1
View File
@@ -20,9 +20,11 @@
#include "gfx/gfx.h"
#include "gfx/font.h"
#include "queue.h"
#include "swf.h"
typedef struct cJSON cJSON;
struct string;
struct hash_table;
// NOTE: actual value is +1
enum parts_state_type {
@@ -96,7 +98,8 @@ enum parts_type {
PARTS_HGAUGE,
PARTS_VGAUGE,
PARTS_CONSTRUCTION_PROCESS,
#define PARTS_NR_TYPES (PARTS_CONSTRUCTION_PROCESS+1)
PARTS_FLASH,
#define PARTS_NR_TYPES (PARTS_FLASH+1)
};
struct parts_common {
@@ -210,6 +213,28 @@ struct parts_construction_process {
TAILQ_HEAD(, parts_cp_op) ops;
};
struct parts_flash_object {
TAILQ_ENTRY(parts_flash_object) entry;
uint16_t depth;
uint16_t character_id;
struct swf_matrix matrix;
struct swf_cxform_with_alpha color_transform;
};
struct parts_flash {
struct parts_common common;
struct string *name;
struct swf *swf;
struct swf_tag *tag;
bool stopped;
unsigned elapsed;
int current_frame;
struct hash_table *dictionary;
struct hash_table *bitmaps; // bitmap character id -> struct texture *
TAILQ_HEAD(, parts_flash_object) display_list;
};
struct parts_state {
enum parts_type type;
union {
@@ -220,6 +245,7 @@ struct parts_state {
struct parts_numeral num;
struct parts_gauge gauge;
struct parts_construction_process cproc;
struct parts_flash flash;
};
};
@@ -276,6 +302,7 @@ struct parts_numeral *parts_get_numeral(struct parts *parts, int state);
struct parts_gauge *parts_get_hgauge(struct parts *parts, int state);
struct parts_gauge *parts_get_vgauge(struct parts *parts, int state);
struct parts_construction_process *parts_get_construction_process(struct parts *parts, int state);
struct parts_flash *parts_get_flash(struct parts *parts, int state);
void parts_set_pos(struct parts *parts, Point pos);
void parts_set_dims(struct parts *parts, struct parts_common *common, int w, int h);
void parts_set_scale_x(struct parts *parts, float mag);
@@ -328,6 +355,12 @@ void parts_add_cp_op(struct parts_construction_process *cproc, struct parts_cp_o
bool parts_build_construction_process(struct parts *parts,
struct parts_construction_process *cproc);
// flash.c
void parts_flash_free(struct parts_flash *f);
bool parts_flash_load(struct parts *parts, struct parts_flash *f, struct string *filename);
bool parts_flash_update(struct parts_flash *f, int passed_time);
bool parts_flash_seek(struct parts_flash *f, int frame);
// debug.c
void parts_debug_init(void);
cJSON *parts_engine_to_json(bool verbose);
+103 -32
View File
@@ -19,6 +19,7 @@
#include <cglm/cglm.h>
#include "system4.h"
#include "system4/hashtable.h"
#include "gfx/gfx.h"
#include "scene.h"
@@ -49,6 +50,27 @@ static void parts_render_text(struct parts *parts, struct parts_common *common)
gfx_render_texture(&parts->states[parts->state].common.texture, &rect);
}
static void parts_render_texture(struct texture *texture, mat4 mw_transform, Rectangle *rect, float blend_rate, vec3 add_color, vec3 multiply_color)
{
mat4 wv_transform = WV_TRANSFORM(config.view_width, config.view_height);
struct gfx_render_job job = {
.shader = &parts_shader.shader,
.texture = texture->handle,
.world_transform = mw_transform[0],
.view_transform = wv_transform[0],
.data = texture,
};
gfx_prepare_job(&job);
glUniform1f(parts_shader.blend_rate, blend_rate);
glUniform2f(parts_shader.bot_left, rect->x, rect->y);
glUniform2f(parts_shader.top_right, rect->x + rect->w, rect->y + rect->h);
glUniform3fv(parts_shader.add_color, 1, add_color);
glUniform3fv(parts_shader.multiply_color, 1, multiply_color);
gfx_run_job(&job);
}
static void parts_render_cg(struct parts *parts, struct parts_common *common)
{
switch (parts->draw_filter) {
@@ -68,34 +90,80 @@ static void parts_render_cg(struct parts *parts, struct parts_common *common)
glm_scale(mw_transform, (vec3){ parts->global.scale.x, parts->global.scale.y, 1.0 });
glm_translate(mw_transform, (vec3){ common->origin_offset.x, common->origin_offset.y, 0 });
glm_scale(mw_transform, (vec3){ common->w, common->h, 1.0 });
mat4 wv_transform = WV_TRANSFORM(config.view_width, config.view_height);
struct gfx_render_job job = {
.shader = &parts_shader.shader,
.texture = common->texture.handle,
.world_transform = mw_transform[0],
.view_transform = wv_transform[0],
.data = &common->texture,
};
Rectangle r = common->surface_area;
if (!r.w && !r.h) {
r = (Rectangle) { 0, 0, common->texture.w, common->texture.h };
}
gfx_prepare_job(&job);
glUniform1f(parts_shader.blend_rate, parts->global.alpha / 255.0);
glUniform2f(parts_shader.bot_left, r.x, r.y);
glUniform2f(parts_shader.top_right, r.x + r.w, r.y + r.h);
glUniform3f(parts_shader.add_color, parts->global.add_color.r / 255.0f,
parts->global.add_color.g / 255.0f, parts->global.add_color.b / 255.0f);
glUniform3f(parts_shader.multiply_color, parts->global.multiply_color.r / 255.0f,
parts->global.multiply_color.g / 255.0f, parts->global.multiply_color.b / 255.0f);
gfx_run_job(&job);
vec3 add_color = {
parts->global.add_color.r / 255.0f,
parts->global.add_color.g / 255.0f,
parts->global.add_color.b / 255.0f
};
vec3 multiply_color = {
parts->global.multiply_color.r / 255.0f,
parts->global.multiply_color.g / 255.0f,
parts->global.multiply_color.b / 255.0f,
};
parts_render_texture(&common->texture, mw_transform, &r, parts->global.alpha / 255.0, add_color, multiply_color);
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);
}
static void parts_render_flash_shape(struct parts *parts, struct parts_flash *f, struct parts_flash_object *obj, struct swf_tag_define_shape *tag)
{
struct texture *src = ht_get_int(f->bitmaps, tag->fill_style.bitmap_id, NULL);
if (!src)
ERROR("undefined bitmap id %d", tag->fill_style.bitmap_id);
mat4 mw_transform = GLM_MAT4_IDENTITY_INIT;
glm_translate(mw_transform, (vec3) { parts->global.pos.x, parts->global.pos.y, 0 });
glm_rotate_z(mw_transform, parts->local.rotation.z, mw_transform);
glm_scale(mw_transform, (vec3){ parts->global.scale.x, parts->global.scale.y, 1.0 });
int x = f->common.origin_offset.x + (obj->matrix.translate_x + tag->bounds.x_min) / 20;
int y = f->common.origin_offset.y + (obj->matrix.translate_y + tag->bounds.y_min) / 20;
int width = (tag->bounds.x_max - tag->bounds.x_min) / 20 * (obj->matrix.scale_x / 65536.0f);
int height = (tag->bounds.y_max - tag->bounds.y_min) / 20 * (obj->matrix.scale_y / 65536.0f);
// TODO: consider matrix.roate_skew
glm_translate(mw_transform, (vec3){ x, y, 0 });
glm_scale(mw_transform, (vec3){ width, height, 1.0 });
Rectangle r = { 0, 0, width, height };
float blend_rate = (parts->global.alpha / 255.0f) * (obj->color_transform.mult_terms[3] / 256.0f);
vec3 add_color = {
(parts->global.add_color.r + obj->color_transform.add_terms[0]) / 255.0f,
(parts->global.add_color.g + obj->color_transform.add_terms[1]) / 255.0f,
(parts->global.add_color.b + obj->color_transform.add_terms[2]) / 255.0f
};
vec3 multiply_color = {
(parts->global.multiply_color.r / 255.0f) * (obj->color_transform.mult_terms[0] / 256.0f),
(parts->global.multiply_color.g / 255.0f) * (obj->color_transform.mult_terms[1] / 256.0f),
(parts->global.multiply_color.b / 255.0f) * (obj->color_transform.mult_terms[2] / 256.0f)
};
parts_render_texture(src, mw_transform, &r, blend_rate, add_color, multiply_color);
}
static void parts_render_flash(struct parts *parts, struct parts_flash *f)
{
struct parts_flash_object *obj;
TAILQ_FOREACH(obj, &f->display_list, entry) {
struct swf_tag *tag = ht_get_int(f->dictionary, obj->character_id, NULL);
if (!tag) {
WARNING("character %d is not defined", obj->character_id);
continue;
}
switch (tag->type) {
case TAG_DEFINE_SHAPE:
parts_render_flash_shape(parts, f, obj, (struct swf_tag_define_shape *)tag);
break;
default:
ERROR("unknown tag 0x%x", tag->type);
}
}
}
void parts_render(struct parts *parts)
{
if (!parts->global.show)
@@ -109,22 +177,25 @@ void parts_render(struct parts *parts)
// render
struct parts_state *state = &parts->states[parts->state];
if (state->common.texture.handle) {
switch (state->type) {
case PARTS_UNINITIALIZED:
break;
case PARTS_CG:
case PARTS_ANIMATION:
case PARTS_NUMERAL:
case PARTS_HGAUGE:
case PARTS_VGAUGE:
case PARTS_CONSTRUCTION_PROCESS:
switch (state->type) {
case PARTS_UNINITIALIZED:
break;
case PARTS_CG:
case PARTS_ANIMATION:
case PARTS_NUMERAL:
case PARTS_HGAUGE:
case PARTS_VGAUGE:
case PARTS_CONSTRUCTION_PROCESS:
if (state->common.texture.handle)
parts_render_cg(parts, &state->common);
break;
case PARTS_TEXT:
break;
case PARTS_TEXT:
if (state->common.texture.handle)
parts_render_text(parts, &state->common);
break;
}
break;
case PARTS_FLASH:
parts_render_flash(parts, &state->flash);
break;
}
}
+23
View File
@@ -298,6 +298,23 @@ static void load_parts_construction_process(struct iarray_reader *r, struct part
parts_build_construction_process(parts, cproc);
}
static void save_parts_flash(struct iarray_writer *w, struct parts_flash *flash)
{
iarray_write_string_or_null(w, flash->name);
iarray_write(w, flash->stopped);
iarray_write(w, flash->current_frame);
}
static void load_parts_flash(struct iarray_reader *r, struct parts *parts,
struct parts_flash *flash)
{
struct string *name = iarray_read_string_or_null(r);
parts_flash_load(parts, flash, name);
free_string(name);
flash->stopped = !!iarray_read(r);
parts_flash_seek(flash, iarray_read(r));
}
static void save_parts_state(struct iarray_writer *w, struct parts_state *state)
{
iarray_write(w, state->type);
@@ -328,6 +345,9 @@ static void save_parts_state(struct iarray_writer *w, struct parts_state *state)
case PARTS_CONSTRUCTION_PROCESS:
save_parts_construction_process(w, &state->cproc);
break;
case PARTS_FLASH:
save_parts_flash(w, &state->flash);
break;
}
}
@@ -364,6 +384,9 @@ static void load_parts_state(struct iarray_reader *r, struct parts *parts,
case PARTS_CONSTRUCTION_PROCESS:
load_parts_construction_process(r, parts, &state->cproc);
break;
case PARTS_FLASH:
load_parts_flash(r, parts, &state->flash);
break;
}
}