diff options
| author | Vito Caputo <vcaputo@pengaru.com> | 2018-06-11 23:24:23 -0700 | 
|---|---|---|
| committer | Vito Caputo <vcaputo@pengaru.com> | 2018-06-11 23:35:00 -0700 | 
| commit | 853b6f1c47caa825aea09d3e8fefee47098f3be7 (patch) | |
| tree | fd64539e8f945d1d4427a52183f68609875464fa | |
| parent | 5caa894a3612b8bc090271f5c26daa556237dd97 (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.c | 75 | ||||
| -rw-r--r-- | src/stage.h | 8 | 
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); | 
