summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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