diff options
Diffstat (limited to 'src/stage.c')
-rw-r--r-- | src/stage.c | 75 |
1 files changed, 63 insertions, 12 deletions
diff --git a/src/stage.c b/src/stage.c index 280536a..1cb3995 100644 --- a/src/stage.c +++ b/src/stage.c @@ -37,7 +37,9 @@ struct stage_node_t { char name[STAGE_NODE_NAME_MAX]; stage_cached_t cached; aabb_t aabb; /* node coordinates expressed in the space of -1.0...1.0 */ + stage_map_t aabb_map; v2f_t position; /* position of node, optionally used to move aabb as a whole */ + stage_map_t position_map; v2f_t origin; /* origin of node, 0,0 being center of aabb (the default) this determines how position relates to aabb. -1...1 being aabb.min ... aabb.max */ float alpha; /* alpha for the texture when composited */ double angle; /* angle for the texture when composited */ @@ -253,6 +255,18 @@ void stage_node_set_angle(const stage_t *stage, stage_node_t *node, double angle } +void stage_node_set_aabb_map(const stage_t *stage, stage_node_t *node, stage_map_t map) +{ + node->aabb_map = map; +} + + +void stage_node_set_position_map(const stage_t *stage, stage_node_t *node, stage_map_t map) +{ + node->position_map = map; +} + + void stage_node_get_angle(const stage_t *stage, stage_node_t *node, double *res_angle) { *res_angle = node->angle; @@ -364,38 +378,75 @@ void stage_get_position(stage_t *stage, v2f_t *res_position) } +static void map_stage_rect(const stage_t *stage, const SDL_Rect *stage_rect, stage_map_t map, float *res_w, float *res_h) +{ + switch (map) { + case STAGE_MAP_FILL: + *res_w = stage_rect->w; + *res_h = stage_rect->h; + break; + + case STAGE_MAP_MINSQ: + if (stage_rect->w < stage_rect->h) { + *res_w = stage_rect->w; + *res_h = stage_rect->w; + } else { + *res_w = stage_rect->h; + *res_h = stage_rect->h; + } + break; + + case STAGE_MAP_MAXSQ: + if (stage_rect->w > stage_rect->h) { + *res_w = stage_rect->w; + *res_h = stage_rect->w; + } else { + *res_w = stage_rect->h; + *res_h = stage_rect->h; + } + break; + } +} + + /* translate a node's aabb within the given stage to a rect witin stage_rect, storing result in *res_rect */ static void node_to_rect(const stage_t *stage, const stage_node_t *node, const SDL_Rect *stage_rect, SDL_Rect *res_rect) { float aabb_w = (node->aabb.max.x - node->aabb.min.x); float aabb_h = (node->aabb.max.y - node->aabb.min.y); - - /* res dimensions are simply aabb dimensions scaled by stage dimensions */ - res_rect->w = floorf(aabb_w * .5f * (float)stage_rect->w); - res_rect->h = floorf(aabb_h * .5f * (float)stage_rect->h); + float stage_w, stage_h; /* center in stage_rect */ res_rect->x = stage_rect->x + floorf((float)stage_rect->w * .5f); res_rect->y = stage_rect->y + floorf((float)stage_rect->h * .5f); + /* compute virtual stage dimensions according to the node's aabb_map setting for aabb calculations */ + map_stage_rect(stage, stage_rect, node->aabb_map, &stage_w, &stage_h); + + /* res dimensions are simply aabb dimensions scaled by stage dimensions according to node->aabb_map */ + res_rect->w = floorf(aabb_w * .5f * stage_w); + res_rect->h = floorf(aabb_h * .5f * stage_h); + + /* apply node->aabb (scaled relative to stage_rect) */ + res_rect->x += floorf(node->aabb.min.x * .5f * stage_w); + res_rect->y += -floorf(node->aabb.max.y * .5f * stage_h); + if (!node->statik) { - /* apply stage->position (scaled relative to stage_rect) */ + /* apply stage->position (relative to stage_rect) */ res_rect->x += floorf(stage->position.x * .5f * (float)stage_rect->w); res_rect->y += -floorf(stage->position.y * .5f * (float)stage_rect->h); } - /* apply node->position (scaled relative to stage_rect) */ - res_rect->x += floorf(node->position.x * .5f * (float)stage_rect->w); - res_rect->y += -floorf(node->position.y * .5f * (float)stage_rect->h); + /* compute virtual stage dimensions according to the node's position_map setting for position calculations */ + map_stage_rect(stage, stage_rect, node->position_map, &stage_w, &stage_h); + + res_rect->x += floorf(node->position.x * .5f * (float)stage_w); + res_rect->y += -floorf(node->position.y * .5f * (float)stage_h); /* apply node->origin (scaled relative to scaled aabb_w) (this probably needs to be inverted) */ res_rect->x += floorf(node->origin.x * .5f * (float)res_rect->w); res_rect->y += -floorf(node->origin.y * .5f * (float)res_rect->h); - /* apply node->aabb (scaled relative to stage_rect) */ - res_rect->x += floorf(node->aabb.min.x * .5f * (float)stage_rect->w); - res_rect->y += -floorf(node->aabb.max.y * .5f * (float)stage_rect->h); - /* Prevent producing 0-dimensioned non-zero rects even if it's technicaly incorrect, * what's likely going on is the window has been resized very small. Rather * than allowing things to become completely invisible in such circumstances, |