mirror of
https://github.com/nunuhara/xsystem4.git
synced 2026-10-03 12:28:01 +03:00
parts: add basic implementation of Flash type
Sprite objects and sounds are not implemented yet.
This commit is contained in:
+12
-5
@@ -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
@@ -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
@@ -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),
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user