summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVito Caputo <vcaputo@pengaru.com>2018-06-11 23:24:23 -0700
committerVito Caputo <vcaputo@pengaru.com>2018-06-11 23:35:00 -0700
commit853b6f1c47caa825aea09d3e8fefee47098f3be7 (patch)
treefd64539e8f945d1d4427a52183f68609875464fa
parent5caa894a3612b8bc090271f5c26daa556237dd97 (diff)
libstage: add alternate node mappings
Until now all aabb and position mapping has been simple linear filling of the stage. When the stage isn't square, which is usually, this isn't always desirable especially for the aabb sizing of things. This introduces per-node settings for the mapping of the node's aabb and position. The default continues to be to map the full stage, with two new settings for the minimum square and maximum square.
-rw-r--r--src/stage.c75
-rw-r--r--src/stage.h8
2 files changed, 71 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,
diff --git a/src/stage.h b/src/stage.h
index f157653..6e0a93c 100644
--- a/src/stage.h
+++ b/src/stage.h
@@ -23,6 +23,12 @@ typedef struct SDL_Texture SDL_Texture;
#define STAGE_NODE_NAME_MAX 16
#define STAGE_LAYERS_MAX 10
+typedef enum stage_map_t {
+ STAGE_MAP_FILL, /* -1,-1...1,1 linearly maps to the AR-constrained stage dimensions, the default */
+ STAGE_MAP_MAXSQ, /* -1,-1...1,1 linearly maps to a square the size of the maximum axis of the AR-constrained stage dimensions */
+ STAGE_MAP_MINSQ, /* -1,-1...1,1 linearly maps to a square the size of the minimum axis of the AR-constrained stage dimensions */
+} stage_map_t;
+
typedef struct v2f_t v2f_t;
typedef struct aabb_t aabb_t;
typedef struct stage_t stage_t;
@@ -60,6 +66,8 @@ void stage_node_set_static(const stage_t *stage, stage_node_t *node, int station
void stage_node_set_layer(stage_t *stage, stage_node_t *node, int layer);
void stage_node_set_angle(const stage_t *stage, stage_node_t *node, double angle);
void stage_node_get_angle(const stage_t *stage, stage_node_t *node, double *res_angle);
+void stage_node_set_aabb_map(const stage_t *stage, stage_node_t *node, stage_map_t fit);
+void stage_node_set_position_map(const stage_t *stage, stage_node_t *node, stage_map_t fit);
stage_node_t * stage_node_lookup_name(const stage_t *stage, const char *name);
stage_node_t * stage_node_lookup_cartesian(const stage_t *stage, int x, int y);
© All Rights Reserved