diff options
| -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); | 
