1 #include "isogen.h"
2 #include "edges.h"
3 #include <vector>
4 #include "../../grinliz/gldynamic.h"
5 
6 using namespace grinliz;
7 using namespace std;
8 
9 typedef SDL_Surface* (*ImageLoaderFunc)( const char* );
10 ImageLoaderFunc ImageLoader = 0;
11 
12 // Set by the top level <isogen> tag
13 string spriteName;
14 int isoWidth = 120;
15 int tileWidth = isoWidth - 2;
16 int tileHeight = isoWidth / 2;
17 int step = 10;
18 
19 int outWidth = 800;
20 int outHeight = 600;
21 
22 Color3F diffuse = { 0.4f, 0.4f, 0.4f };
23 Color3F ambient = { 0.6f, 0.6f, 0.6f };
24 Vector3F lightVector = { 0, 2, -3 };
25 
26 
27 const Vector3F ZFACE = { 0, 0, 1 };
28 const Vector3F YFACE = { 0, -1, 0 };
29 const Vector3F XFACE = { -1, 0, 0 };
30 
31 int saveX = 0;
32 int saveY = 0;
33 int saveMax = 0;
34 
35 vector< SetData > setData;
36 SetData* pSet = 0;		// the current setData
37 SDL_Surface* whiteSurface = 0;
38 
Clear()39 void SetData::Clear()
40 {
41 	unsigned i;
42 	for( i=0; i<wallTexture.size(); ++i ) {
43 		if ( wallTexture[i].surface != whiteSurface )
44 			SDL_FreeSurface( wallTexture[i].surface );
45 	}
46 
47 	for( i=0; i<floorTexture.size(); ++i ) {
48 		if ( floorTexture[i].surface != whiteSurface )
49 			SDL_FreeSurface( floorTexture[i].surface );
50 	}
51 }
52 
GetPixel(int u,int v)53 Color4U8 Texture::GetPixel( int u, int v )
54 {
55 	GLASSERT( u >=0 && u < surface->w );
56 	GLASSERT( v >=0 && v < surface->h );
57 
58 	// Remember that the texture can be any format:
59 	int bytes = surface->format->BytesPerPixel;
60 	U8 *p = (U8*)surface->pixels + (surface->h-1-v)*surface->pitch + u*bytes;
61 
62 	U32 c = 0;
63 	switch(bytes) {
64 		case 1:		c = *p;			break;
65 		case 2:		c = *(U16*)p;	break;
66 		#if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
67 		case 3:		c = p[0] << 16 | p[1] << 8 | p[2];
68 		#else
69 		case 3:		c = p[0] | p[1] << 8 | p[2] << 16;
70 		#endif
71 		case 4:		c = *(U32*)p;
72 
73 		default:	break;
74 	}
75 
76 	Color4U8 color;
77 	SDL_GetRGBA( c, surface->format, &color.r, &color.g, &color.b, &color.a );
78 //	if ( bytes < 4 ) color.a = 255;	// give SDL a little help here. It should always be 255...
79 
80 	if ( colorKey && ( ( color.r | color.g | color.b ) == 0 ) )
81 		color.a = 0;
82 
83 	return color;
84 }
85 
WrapX(SDL_Surface * surface,int x)86 int Texture::WrapX( SDL_Surface* surface, int x )
87 {
88 	while ( x >= surface->w )
89 		x -= surface->w;
90 	while ( x < 0 )
91 		x += surface->w;
92 	return x;
93 }
94 
95 
WrapY(SDL_Surface * surface,int y)96 int Texture::WrapY( SDL_Surface* surface, int y )
97 {
98 	while ( y >= surface->h )
99 		y -= surface->h;
100 	while ( y < 0 )
101 		y += surface->h;
102 	return y;
103 }
104 
105 
Lookup(int _x,int _y)106 Color4U8 Texture::Lookup( int _x, int _y )
107 {
108 	// x,y: pixels on screen
109 	// u,x: texels in the texture, normalized
110 	// i,j: texels in the texture, pixels
111 	int x = _x - origin.x;
112 	int y = _y - origin.y;
113 
114 	float uF = (float)x*a + (float)y*b;
115 	float vF = (float)x*c + (float)y*d;
116 
117 	float iF = uF*(float)(surface->w);
118 	float jF = vF*(float)(surface->h);
119 
120 	int i0 = (int)floorf( iF );
121 	int j0 = (int)floorf( jF );
122 
123 	float di = iF-(float)i0;
124 	float dj = jF-(float)j0;
125 
126 	GLASSERT( InRange( di, 0.0f, 1.0f ) );
127 	GLASSERT( InRange( dj, 0.0f, 1.0f ) );
128 
129 	i0 = WrapX( surface, i0 );
130 	j0 = WrapY( surface, j0 );
131 
132 	Color4U8 c01, c10, c11;
133 	Color4U8 c = { 0, 0, 0, 0 };
134 	Color4U8 c00 = GetPixel( i0, j0 );
135 
136 	if ( pSet->useAA )
137 	{
138 		c10 = GetPixel( WrapX( surface, i0+1 ), j0 );
139 		c01 = GetPixel( i0, WrapY( surface, j0+1 ) );
140 		c11 = GetPixel( WrapX( surface, i0+1 ), WrapY( surface, j0+1 ) );
141 	}
142 	else
143 	{
144 		c10 = c01 = c11 = c00;
145 	}
146 
147 	// Try to deal with the color ghosting problem. A pixel that isn't 0x00000000 probably is
148 	// a color with alpha. A truly black, transparent pixel is probably just extra.
149 
150 	if (    ( ( c00.a | c01.a | c10.a | c11.a ) == 0 )
151 		 || ( ( c00.a & c01.a & c10.a & c11.a ) == 255 ) )
152 	{
153 		float r = BilinearInterpolate( (float)c00.r, (float)c10.r, (float)c01.r, (float)c11.r, di, dj );
154 		float g = BilinearInterpolate( (float)c00.g, (float)c10.g, (float)c01.g, (float)c11.g, di, dj );
155 		float b = BilinearInterpolate( (float)c00.b, (float)c10.b, (float)c01.b, (float)c11.b, di, dj );
156 
157 		c.r = (U8)(r);
158 		c.g = (U8)(g);
159 		c.b = (U8)(b);
160 		c.a = c00.a; // whatever the value is, they are all the same
161 	}
162 	else
163 	{
164 //		float weight = 0.0f;
165 //		float r = 0.0f, g = 0.0f, b = 0.0f;
166 
167 		float qr[4] = { c00.r, c10.r, c01.r, c11.r };
168 		float qg[4] = { c00.g, c10.g, c01.g, c11.g };
169 		float qb[4] = { c00.b, c10.b, c01.b, c11.b };
170 
171 		float w[4] = {	c00.a ? 1.0f : 0.0f,
172 						c01.a ? 1.0f : 0.0f,
173 						c10.a ? 1.0f : 0.0f,
174 						c11.a ? 1.0f : 0.0f };
175 
176 		// The RGB channel uses a weighted interpolation to try to not pick up a transparent
177 		// pixel of the wrong color. The A channel is a simple bi-linear interp.
178 		c.r = (U8)BilinearInterpolate( qr, di, dj, w );
179 		c.g = (U8)BilinearInterpolate( qg, di, dj, w );
180 		c.b = (U8)BilinearInterpolate( qb, di, dj, w );
181 		c.a = (U8)BilinearInterpolate( (float)c00.a, (float)c10.a, (float)c01.a, (float)c11.a, di, dj );
182 	}
183 	return c;
184 }
185 
186 /* Set up a texture. Requires:
187 	 - P the origin of the texture in screen pixels
188 	 - Q the u-stride of the texture in screen pixels
189 	 - R the v-stride of the texture in screen pixels
190 */
InitTexture(SDL_Surface * s,bool overlay,const Vector2I & p,const Vector2I & _q,const Vector2I & _r,U8 alpha,bool emit)191 void Texture::InitTexture(	SDL_Surface* s,
192 							bool overlay,
193 							const Vector2I& p,
194 							const Vector2I& _q,
195 							const Vector2I& _r,
196 							U8 alpha,
197 							bool emit )
198 {
199 	if ( !s ) {
200 		surface = 0;
201 		return;
202 	}
203 	this->alpha = alpha;
204 	this->emit = emit;
205 
206 	if ( overlay && s->format->BytesPerPixel < 4 )
207 		colorKey = true;
208 
209 	surface = s;
210 	origin = p;
211 
212 	Vector2I q = { _q.x - p.x, _q.y - p.y };
213 	Vector2I r = { _r.x - p.x, _r.y - p.y };
214 
215 	// derived from at q, u=1, v=0
216 	// at r, u=0, v=1
217 
218 	int abDenom = q.y*r.x - q.x*r.y;
219 	int cdDenom = q.x*r.y - q.y*r.x;
220 	GLASSERT( abDenom );
221 	GLASSERT( cdDenom );
222 
223 	a = (float)(-r.y) / (float)(abDenom);
224 	b = (float)(r.x)  / (float)(abDenom);
225 	c = (float)(-q.y) / (float)(cdDenom);
226 	d = (float)(q.x)  / (float)(cdDenom);
227 }
228 
229 
CreateSurface(int x,int y,int z)230 SDL_Surface* CreateSurface( int x, int y, int z )
231 {
232 	int sx = isoWidth*(x+y)/2;
233 	int sy = tileHeight*(1+z);
234 
235 	SDL_Surface* surface = SDL_CreateRGBSurface(	SDL_SWSURFACE,
236 													sx, sy,
237 													32,
238 													0xff, 0xff<<8, 0xff<<16, 0xff<<24 );
239 	return surface;
240 }
241 
242 
Render(SDL_Surface * surface,list<Edge * > * leftEdges,list<Edge * > * rightEdges,const Vector3F & normal,Texture * textureArr,int numTexture)243 void Render(	SDL_Surface* surface,
244 				list< Edge* > *leftEdges, list< Edge* > *rightEdges,
245 				const Vector3F& normal,
246 				Texture* textureArr,
247 				int numTexture )
248 {
249 	// Initialize the edges.
250 	Edge* left = leftEdges->front();
251 	leftEdges->pop_front();
252 	Edge* right = rightEdges->front();
253 	rightEdges->pop_front();
254 
255 	// Compute the color components.
256 	Color3F light;
257 	float dot = DotProduct( normal, lightVector );
258 	GLASSERT( dot >= 0.0f );
259 	light.r = ambient.r + diffuse.r * dot;
260 	light.g = ambient.g + diffuse.g * dot;
261 	light.b = ambient.b + diffuse.b * dot;
262 	U8 r = Clamp( LRintf( 255.0f * light.r ), (long)0, (long)255 );
263 	U8 g = Clamp( LRintf( 255.0f * light.g ), (long)0, (long)255 );
264 	U8 b = Clamp( LRintf( 255.0f * light.b ), (long)0, (long)255 );
265 
266 	// Main rendering loop.
267 	while ( left && right )
268 	{
269 		GLASSERT( left->Y() == right->Y() );
270 
271 		int xmin = left->X();
272 		int xmax = right->X();
273 
274 		GLASSERT( xmin <= xmax );
275 
276 		if ( left->NoTouch() ) xmin++;
277 		if ( right->NoTouch() ) xmax--;
278 
279 		GLASSERT( left->Y() >= 0 && left->Y() < surface->h );
280 		U32* scanline = (U32*)((U8*)surface->pixels + left->Y()*surface->pitch);
281 
282 		const U32 color = (r) | (g<<8) | (b<<16) | (255<<24);
283 		Color4U8 frag;
284 		Color4U8 cPrime;
285 
286 		for( int i=0; i<numTexture; ++i )
287 		{
288 			Texture* texture = &textureArr[i];
289 
290 			for( int x=xmin; x<=xmax; ++x )
291 			{
292 				GLASSERT( x >= 0 && x < surface->w );
293 				#ifdef DEBUG
294 				if ( i == 0 ) GLASSERT( !texture || !texture->Valid() || texture->Alpha() == 255 );
295 				#endif
296 
297 				if ( texture && texture->Valid() ) {
298 
299 					// Get the textel color
300 					grinliz::Color4U8 textel = texture->Lookup( x, left->Y() );
301 
302 					if ( !texture->Emit() ) {
303 						// Not emmissive, so apply the lighting.
304 						textel.r = textel.r * r / 255;
305 						textel.g = textel.g * g / 255;
306 						textel.b = textel.b * b / 255;
307 						// the alpha is uneffected
308 					}
309 
310 					if ( texture->Alpha() == 255 && textel.a == 255 )
311 					{
312 						// Opaque
313 						scanline[x] = (textel.r) | (textel.g<<8) | (textel.b<<16) | (255<<24);
314 					}
315 					else if ( textel.a != 0 )
316 					{
317 						// Translucent (or possibly transparent)
318 						U32 alpha = texture->Alpha() * textel.a / 255;
319 						GLASSERT( alpha < 256 );
320 
321 						frag.r = (scanline[x]>>0)  & 0xff;
322 						frag.g = (scanline[x]>>8)  & 0xff;
323 						frag.b = (scanline[x]>>16) & 0xff;
324 
325 						cPrime.r = ( frag.r*(255-alpha) + textel.r*alpha )/255;
326 						cPrime.g = ( frag.g*(255-alpha) + textel.g*alpha )/255;
327 						cPrime.b = ( frag.b*(255-alpha) + textel.b*alpha )/255;
328 
329 						scanline[x] = (cPrime.r) | (cPrime.g<<8) | (cPrime.b<<16) | (255<<24);
330 					}
331 				}
332 				else {
333 					scanline[x] = color;
334 				}
335 			}
336 		}
337 		// Through all the texture stuff. Back to edge processing.
338 		if ( !left->Next() ) {
339 			delete left;
340 			left = 0;
341 			if ( !leftEdges->empty() ) {
342 				left = leftEdges->front();
343 				leftEdges->pop_front();
344 			}
345 		}
346 		if ( !right->Next() ) {
347 			delete right;
348 			right = 0;
349 			if ( !rightEdges->empty() ) {
350 				right = rightEdges->front();
351 				rightEdges->pop_front();
352 			}
353 		}
354 	}
355 }
356 
357 
RenderZ(SDL_Surface * surface,U32 flags)358 void RenderZ( SDL_Surface* surface, U32 flags )
359 {
360 	list< Edge* > left, right;
361 
362 	int leftX0 = tileWidth/2-1;
363 	int leftX1 = 0;
364 	int leftY0min = 0;
365 	int leftY0max = tileHeight/2-1;
366 	int leftY1min = tileHeight/2;
367 	int leftY1max = tileHeight-1;
368 
369 	int rightX0 = tileWidth/2;
370 	int rightX1 = tileWidth-1;
371 	int rightY0min = 0;
372 	int rightY0max = tileHeight/2-1;
373 	int rightY1min = tileHeight/2;
374 	int rightY1max = tileHeight-1;
375 
376 	int ox = 1;
377 
378 	if ( flags & NORTH )
379 	{
380 		left.push_back( new IsoEdgeNeg( leftX0-step*2+ox, leftY0min+step, leftY0max-step ));
381 		left.push_back( new IsoEdgePos( leftX1+step*2+ox, leftY1min-step, leftY1max-step*3 ));
382 
383 		right.push_back( new IsoEdgePos( rightX0-step*2+ox, rightY0min+step, rightY0max-step ));
384 		right.push_back( new IsoEdgeNeg( rightX1-step*6+ox, rightY1min-step, rightY1max-step*3 ));
385 	}
386 	else if ( flags & SOUTH )
387 	{
388 		left.push_back( new IsoEdgeNeg( leftX0+step*2+ox, leftY0min+step*3, leftY0max+step ));
389 		left.push_back( new IsoEdgePos( leftX1+step*6+ox, leftY1min+step, leftY1max-step ));
390 
391 		right.push_back( new IsoEdgePos( rightX0+step*2+ox, rightY0min+step*3, rightY0max+step ));
392 		right.push_back( new IsoEdgeNeg( rightX1-step*2+ox, rightY1min+step, rightY1max-step ));
393 	}
394 	else if ( flags & CENTER )
395 	{
396 		left.push_back( new IsoEdgeNeg( leftX0+ox, leftY0min+step*2, leftY0max ));
397 		left.push_back( new IsoEdgePos( leftX1+step*4+ox, leftY1min, leftY1max-step*2 ));
398 
399 		right.push_back( new IsoEdgePos( rightX0+ox, rightY0min+step*2, rightY0max ));
400 		right.push_back( new IsoEdgeNeg( rightX1-step*4+ox, rightY1min, rightY1max-step*2 ));
401 	}
402 	else if ( flags & EAST )
403 	{
404 		left.push_back( new IsoEdgeNeg( leftX0+step*2+ox, leftY0min+step, leftY0max-step ));
405 		left.push_back( new IsoEdgePos( leftX1+step*6+ox, leftY1min-step, leftY1max-step*2 ));
406 
407 		right.push_back( new IsoEdgePos( rightX0+step*2+ox, rightY0min+step, rightY0max-step ));
408 		right.push_back( new IsoEdgeNeg( rightX1-step*2+ox, rightY1min-step, rightY1max-step*3 ));
409 	}
410 	else if ( flags & WEST )
411 	{
412 		left.push_back( new IsoEdgeNeg( leftX0-step*2+ox, leftY0min+step*3, leftY0max+step ));
413 		left.push_back( new IsoEdgePos( leftX1+step*2+ox, leftY1min+step, leftY1max-step ));
414 
415 		right.push_back( new IsoEdgePos( rightX0-step*2+ox, rightY0min+step*3, rightY0max+step ));
416 		right.push_back( new IsoEdgeNeg( rightX1-step*6+ox, rightY1min+step, rightY1max-step ));
417 	}
418 	else
419 	{
420 		// Simple draw.
421 		left.push_back( new IsoEdgeNeg( leftX0+ox, leftY0min, leftY0max ));
422 		left.push_back( new IsoEdgePos( leftX1+ox, leftY1min, leftY1max ));
423 
424 		right.push_back( new IsoEdgePos( rightX0+ox, rightY0min, rightY0max ));
425 		right.push_back( new IsoEdgeNeg( rightX1+ox, rightY1min, rightY1max ));
426 	}
427 
428 	//Texture tex[ MAX_TEXTURE_COUNT ];
429 	std::vector< Texture > tex( pSet->floorTexture.size() );
430 
431 	if ( flags & USE_TEXTURE )
432 	{
433 		// Note that for the Z face, the texture coordinates never change if
434 		// an inset is used.
435 		Vector2I p = { tileWidth/2-1+ox, tileHeight };
436 		Vector2I q = { p.x + isoWidth / 2, p.y - isoWidth / 4 };
437 		Vector2I r = { p.x - isoWidth / 2, p.y - isoWidth / 4 };
438 
439 		for( unsigned i=0; i<pSet->floorTexture.size(); ++i ) {
440 			tex[i].InitTexture( pSet->floorTexture[i].surface, i>0, p, q, r,
441 								pSet->floorTexture[i].alpha,
442 								pSet->floorTexture[i].emit );
443 		}
444 	}
445 	GLASSERT( pSet->floorTexture.size() >=1 );
446 	int numTexture = (flags & OVERLAYS) ? pSet->floorTexture.size() : 1;
447 	Render( surface, &left, &right, ZFACE, &tex[0], numTexture );
448 }
449 
RenderX(SDL_Surface * surface,U32 flags,int xFactor=0,int yFactor=0)450 void RenderX( SDL_Surface* surface, U32 flags, int xFactor = 0, int yFactor = 0 )
451 {
452 	list< Edge* > left, right;
453 
454 	int ox = 1 + xFactor*isoWidth/2;
455 	int oy = yFactor*isoWidth/2;
456 	if ( flags & OFFSET ) {
457 		ox += step*2;
458 		oy += -step;
459 	}
460 
461 	int tileHeight3_2 = tileHeight + tileHeight/2;
462 
463 	if ( flags & NORTH )
464 	{
465 		left.push_back( new VEdge(	-1+ox, tileHeight/2+oy,	tileHeight3_2-1+oy ));	// see comment in simple case about -1
466 		left.push_back( new IsoEdgePos(	0+ox, tileHeight3_2+oy, tileHeight3_2+step+oy ));
467 
468 		Edge* edge = new IsoEdgePos( 0+ox, tileHeight/2+oy, tileHeight/2+step+oy );
469 		edge->SetNoTouch();
470 		right.push_back( edge );
471 		right.push_back( new VEdge( step*2+ox, tileHeight/2+step+1+oy, tileHeight3_2+step+oy ));
472 	}
473 	else if ( flags & SOUTH )
474 	{
475 		left.push_back( new VEdge(	tileWidth/2-1-2*step+ox, tileHeight-1-step+oy,	tileHeight*2-2-step+oy ));
476 		left.push_back( new IsoEdgePos(	tileWidth/2-1-2*step+ox, tileHeight*2-1-step+oy, tileHeight*2-1+oy ));
477 
478 		Edge* edge = new IsoEdgePos( tileWidth/2-1-2*step+ox, tileHeight-1-step+oy, tileHeight-1+oy );
479 		edge->SetNoTouch();
480 		right.push_back( edge );
481 		right.push_back( new VEdge( tileWidth/2-1+ox, tileHeight+oy, tileHeight*2-1+oy ));
482 	}
483 	else if ( flags & CENTER )
484 	{
485 		left.push_back( new VEdge(	0+step*2+ox, tileHeight/2+step+oy,	tileHeight3_2-1+step+oy ));
486 		left.push_back( new IsoEdgePos(	0+step*2+ox, tileHeight3_2+step+oy, tileHeight*2-1-step+oy ));
487 
488 		Edge* edge = new IsoEdgePos( 0+step*2+ox, tileHeight/2+step+oy, tileHeight-1-step+oy );
489 		edge->SetNoTouch();
490 		right.push_back( edge );
491 		right.push_back( new VEdge( tileWidth/2-1-step*2+ox, tileHeight-step+oy, tileHeight*2-1-step+oy ));
492 	}
493 	else
494 	{
495 		// Note the -1 "cheat" patches up texture seeming between tiles - filling
496 		// the difference between the isoSize and the tileWidth.
497 		//
498 		left.push_back( new VEdge(	-1+ox, tileHeight/2+oy,	tileHeight3_2-1+oy ));
499 		left.push_back( new IsoEdgePos(	0+ox, tileHeight3_2+oy, tileHeight*2-1+oy ));
500 
501 		Edge* edge = new IsoEdgePos( 0+ox, tileHeight/2+oy, tileHeight-1+oy );
502 		edge->SetNoTouch();
503 		right.push_back( edge );
504 		right.push_back( new VEdge( tileWidth/2-1+ox, tileHeight+oy, tileHeight*2-1+oy ));
505 	}
506 
507 	//Texture tex[ MAX_TEXTURE_COUNT ];
508 	std::vector< Texture > tex( pSet->wallTexture.size() );
509 	if ( flags & USE_TEXTURE )
510 	{
511 		Vector2I p = { -1+ox, -1+tileHeight + tileHeight/2 + oy};
512 		Vector2I q = { p.x + isoWidth / 2, p.y + isoWidth / 4 };
513 		Vector2I r = { p.x, p.y - isoWidth / 2 };
514 		for( unsigned i=0; i<pSet->wallTexture.size(); ++i ) {
515 			tex[i].InitTexture( pSet->wallTexture[i].surface, i>0, p, q, r,
516 								pSet->wallTexture[i].alpha,
517 								pSet->wallTexture[i].emit );
518 		}
519 	}
520 	GLASSERT( pSet->wallTexture.size() >=1 );
521 	int numTexture = (flags & OVERLAYS) ? pSet->wallTexture.size() : 1;
522 
523 	Render( surface, &left, &right, XFACE, &tex[0], numTexture );
524 }
525 
526 
RenderY(SDL_Surface * surface,U32 flags,int xFactor=0,int yFactor=0)527 void RenderY( SDL_Surface* surface, U32 flags, int xFactor=0, int yFactor=0 )
528 {
529 	list< Edge* > left, right;
530 
531 	int ox = 1 + xFactor*isoWidth/2;
532 	int oy = 0 + yFactor*isoWidth/2;
533 	if ( flags & OFFSET ) {
534 		ox += -step*2;
535 		oy += -step;
536 	}
537 
538 	int tileHeight3_2 = tileHeight+tileHeight/2;
539 
540 	if ( flags & CENTER )
541 	{
542 		Edge* edge = new IsoEdgeNeg( tileWidth-1-step*2+ox, tileHeight/2+step+oy,  tileHeight-1-step+oy );
543 		edge->SetNoTouch();
544 		left.push_back( edge );
545 		left.push_back( new VEdge( tileWidth/2+step*2+ox, tileHeight-step+oy, tileHeight*2-1-step+oy ));
546 
547 		right.push_back( new VEdge( tileWidth-1-step*2+ox, tileHeight/2+step+oy, tileHeight3_2-1+step+oy ));
548 		right.push_back( new IsoEdgeNeg( tileWidth-1-step*2+ox, tileHeight3_2+step+oy, tileHeight*2-1-step+oy ));
549 	}
550 	else if ( flags & EAST )
551 	{
552 		Edge* edge = new IsoEdgeNeg( tileWidth-1+ox, tileHeight/2+oy,  tileHeight/2+step+oy );
553 		edge->SetNoTouch();
554 		left.push_back( edge );
555 		left.push_back( new VEdge( tileWidth-1-step*2+ox, tileHeight/2+step+1+oy, tileHeight3_2+step+oy ));
556 
557 		// The +1 in the VEdge x patches the isoTile vs isoWidth discrepancy
558 		right.push_back( new VEdge( tileWidth-1+ox+1, tileHeight/2+oy, tileHeight3_2-1+oy ));
559 		right.push_back( new IsoEdgeNeg( tileWidth-1+ox, tileHeight3_2+oy, tileHeight3_2+step+oy ));
560 	}
561 	else if ( flags & WEST )
562 	{
563 		Edge* edge = new IsoEdgeNeg( tileWidth/2+step*2+ox, tileHeight-1-step+oy,  tileHeight-1+oy );
564 		edge->SetNoTouch();
565 		left.push_back( edge );
566 		left.push_back( new VEdge( tileWidth/2+ox, tileHeight+oy, tileHeight*2-1+oy ));
567 
568 		right.push_back( new VEdge( tileWidth/2+step*2+ox, tileHeight-1-step+oy, tileHeight*2-2-step+oy ));
569 		right.push_back( new IsoEdgeNeg( tileWidth/2+step*2+ox, tileHeight*2-1-step+oy, tileHeight*2-1+oy ));
570 	}
571 	else
572 	{
573 		Edge* edge = new IsoEdgeNeg( tileWidth-1+ox, tileHeight/2+oy,  tileHeight-1+oy );
574 		edge->SetNoTouch();
575 		left.push_back( edge );
576 		left.push_back( new VEdge( tileWidth/2+ox, tileHeight+oy, tileHeight*2-1+oy ));
577 
578 		// The erraint +1 in the x value of the VEdge account for the difference between
579 		// the isoWidth and the tileWidth
580 		right.push_back( new VEdge( tileWidth-1+ox+1, tileHeight/2+oy, tileHeight3_2-1+oy ));
581 		right.push_back( new IsoEdgeNeg( tileWidth-1+ox, tileHeight3_2+oy, tileHeight*2-1+oy ));
582 	}
583 
584 	//Texture tex[ MAX_TEXTURE_COUNT ];
585 	std::vector< Texture > tex( pSet->wallTexture.size() );
586 	if ( flags & USE_TEXTURE )
587 	{
588 		Vector2I p = { tileWidth/2+ox, tileHeight*2-1+oy };
589 		Vector2I q = { p.x + isoWidth / 2, p.y - isoWidth / 4 };
590 		Vector2I r = { p.x, p.y - isoWidth / 2 };
591 
592 		for( unsigned i=0; i<pSet->wallTexture.size(); ++i ) {
593 			tex[i].InitTexture( pSet->wallTexture[i].surface, i>0, p, q, r,
594 								pSet->wallTexture[i].alpha,
595 								pSet->wallTexture[i].emit );
596 		}
597 	}
598 	GLASSERT( pSet->wallTexture.size() >=1 );
599 	int numTexture = (flags & OVERLAYS) ? pSet->wallTexture.size() : 1;
600 
601 	Render( surface, &left, &right, YFACE, &tex[0], numTexture );
602 }
603 
RenderRamp(SDL_Surface * surface,U32 flags,int size)604 void RenderRamp( SDL_Surface* surface, U32 flags, int size )
605 {
606 	list< Edge* > left, right;
607 
608 	int ox = 1;
609 	int oy = 0;
610 	int mult = size-1;
611 
612 //	if ( flags & OFFSET ) {
613 //		ox += -step*2;
614 //		oy += -step;
615 //	}
616 
617 	int tileHeight3_2 = tileHeight+tileHeight/2;
618 
619 	Vector2I p, q, r;
620 	Vector3F normal;
621 
622 	if ( flags & NORTH )
623 	{
624 		left.push_back( new IsoEdgeNeg( tileWidth/2-1+ox, 0+oy, tileHeight/2-1+oy ));
625 		left.push_back( new LineEdge( 0+ox, tileHeight/2+oy,
626 									  tileWidth/2-1+ox+isoWidth*mult/2, tileHeight*2-1+oy+tileHeight3_2*mult ));
627 
628 		right.push_back( new LineEdge(	tileWidth/2+ox, oy,
629 										tileWidth-1+ox+isoWidth*mult/2, tileHeight3_2-1+oy+tileHeight3_2*mult ));
630 		right.push_back( new IsoEdgeNeg( tileWidth-1+ox+isoWidth*mult/2, tileHeight3_2+oy+tileHeight3_2*mult, tileHeight*2-1+oy+tileHeight3_2*mult ));
631 
632 		p.x = tileWidth/2-1+ox+tileWidth*mult/2;		p.y = tileHeight*2+oy+tileHeight3_2*mult;
633 		q.x = p.x + isoWidth/2;		q.y = p.y - isoWidth / 4;
634 		r.x = p.x - isoWidth/2;		r.y = p.y - isoWidth * 3 / 4;
635 
636 		normal.Set( 0, -1, 1 );
637 	}
638 	else
639 	{
640 		left.push_back( new LineEdge(	tileWidth/2-1+ox+mult*isoWidth/2, 0+oy,
641 										0+ox, tileHeight3_2-1+oy+tileHeight3_2*mult ) );
642 		left.push_back( new IsoEdgePos( 0+ox, tileHeight3_2+oy+tileHeight3_2*mult, tileHeight*mult+tileHeight*2-1+oy+tileHeight3_2*mult ) );
643 
644 		right.push_back( new IsoEdgePos( tileWidth/2+ox+mult*isoWidth/2, 0+oy, tileHeight/2-1+oy ) );
645 		right.push_back( new LineEdge(	tileWidth-1+ox+mult*isoWidth/2, tileHeight/2+oy,
646 										tileWidth/2+ox, tileHeight*2-1+oy+tileHeight3_2*mult ) );
647 
648 		p.x = tileWidth/2-1+ox;		p.y = tileHeight*2+oy+tileHeight3_2*mult;
649 		q.x = p.x + isoWidth/2;		q.y = p.y - isoWidth*3/ 4;
650 		r.x = p.x - isoWidth/2;		r.y = p.y - isoWidth / 4;
651 
652 		normal.Set( -1, 0, 1 );
653 	}
654 
655 	normal.Normalize();
656 
657 	//Texture tex[ MAX_TEXTURE_COUNT ];
658 	std::vector< Texture > tex( pSet->floorTexture.size() );
659 	if ( flags & USE_TEXTURE )
660 	{
661 		for( unsigned i=0; i<pSet->floorTexture.size(); ++i ) {
662 			tex[i].InitTexture( pSet->floorTexture[i].surface, i>0, p, q, r,
663 								pSet->floorTexture[i].alpha,
664 								pSet->floorTexture[i].emit );
665 		}
666 	}
667 	Render( surface, &left, &right, normal,
668 			&tex[0], (flags&OVERLAYS) ? pSet->floorTexture.size() : 1);
669 }
670 
671 enum {
672 	FLOOR_FLAT,
673 	CUBE_FLAT,
674 	FLOOR_BASIC,
675 	CUBE_BASIC,
676 
677 	JOIN_NWSE,
678 	WALL_NS,
679 	WALL_WE,
680 
681 	JOIN_NW,
682 	JOIN_NE,
683 	JOIN_WS,
684 	JOIN_SE,
685 
686 	JOIN_NWS,
687 	JOIN_NSE,
688 	JOIN_NWE,
689 	JOIN_WSE,
690 
691 	RAMP_E,
692 	RAMP_N,
693 
694 	JOIN_NWSE_DOUBLE,
695 	WALL_NS_DOUBLE,
696 	WALL_WE_DOUBLE,
697 	JOIN_NW_DOUBLE,
698 	JOIN_NE_DOUBLE,
699 	JOIN_WS_DOUBLE,
700 	JOIN_SE_DOUBLE,
701 	JOIN_NWS_DOUBLE,
702 	JOIN_NSE_DOUBLE,
703 	JOIN_NWE_DOUBLE,
704 	JOIN_WSE_DOUBLE,
705 	RAMP_E_DOUBLE,
706 	RAMP_N_DOUBLE,
707 
708 	ICON_TYPE_COUNT
709 };
710 
711 
712 const char* const gIconName[ICON_TYPE_COUNT] =
713 {
714 	"BASE_FLOOR",
715 	"BASE_CUBE",
716 	"FLOOR",
717 	"CUBE",
718 
719 	"JOIN.NWSE",
720 	"WALL.NS",
721 	"WALL.WE",
722 
723 	"JOIN.NW",
724 	"JOIN.NE",
725 	"JOIN.WS",
726 	"JOIN.SE",
727 
728 	"JOIN.NWS",
729 	"JOIN.NSE",
730 	"JOIN.NWE",
731 	"JOIN.WSE",
732 
733 	"RAMP.E",
734 	"RAMP.N",
735 
736 	"JOIN.NWSE.2",
737 	"WALL.NS.2",
738 	"WALL.WE.2",
739 
740 	"JOIN.NW.2",
741 	"JOIN.NE.2",
742 	"JOIN.WS.2",
743 	"JOIN.SE.2",
744 
745 	"JOIN.NWS.2",
746 	"JOIN.NSE.2",
747 	"JOIN.NWE.2",
748 	"JOIN.WSE.2",
749 
750 	"RAMP.E.2",
751 	"RAMP.N.2",
752 };
753 
754 
755 
WriteIconToXML(TiXmlNode * xmlNode,const char * name,int x,int y,int w,int h,int hotX,int hotY)756 void WriteIconToXML( TiXmlNode* xmlNode, const char* name, int x, int y, int w, int h, int hotX, int hotY )
757 {
758 	string actionName = pSet->action + "." + name;
759 
760 	TiXmlElement frame( "Frame" );
761 	frame.SetAttribute( "x", x );
762 	frame.SetAttribute( "y", y );
763 	frame.SetAttribute( "width", w );
764 	frame.SetAttribute( "height", h );
765 	frame.SetAttribute( "hotspotx", hotX );
766 	frame.SetAttribute( "hotspoty", hotY );
767 
768 	TiXmlElement action( "Action" );
769 	action.InsertEndChild( frame );
770 	action.SetAttribute( "name", actionName.c_str() );
771 
772 	xmlNode->InsertEndChild( action );
773 }
774 
775 
DrawIcons(SDL_Surface * saveSurface,TiXmlNode * xmlNode)776 void DrawIcons( SDL_Surface* saveSurface, TiXmlNode* xmlNode )
777 {
778 	static bool flatWritten = false;
779 
780 	bool done = false;
781 
782 	for( int count=0; !done; ++count )
783 	{
784 		SDL_Surface* surface = 0;
785 		int hotX = 0;
786 		int hotY = 0;
787 
788 		switch (count)
789 		{
790 			case FLOOR_FLAT:
791 			if ( ( pSet->drawAll || pSet->drawBasic ) && !flatWritten )
792 			{
793 				// Draw the top z plane. This
794 				// is for creating more tiles and checking color.
795 				surface = CreateSurface( 1, 1, 1 );
796 				RenderZ( surface, 0 );
797 
798 				hotX = isoWidth / 2 - 1;
799 				hotY = tileHeight * 2 - 1;
800 			}
801 			break;
802 
803 			case CUBE_FLAT:
804 			if ( ( pSet->drawAll || pSet->drawBasic ) && !flatWritten )
805 			{
806 				flatWritten = true;
807 
808 				// Draw a white cube. This
809 				// is for creating more tiles and checking color.
810 				surface = CreateSurface( 1, 1, 1 );
811 				surface = CreateSurface( 1, 1, 1 );
812 				RenderZ( surface, 0 );
813 				RenderX( surface, 0 );
814 				RenderY( surface, 0 );
815 
816 				hotX = isoWidth / 2 - 1;
817 				hotY = tileHeight * 2 - 1;
818 			}
819 			break;
820 
821 			case FLOOR_BASIC:
822 			if ( pSet->drawAll || pSet->drawBasic )
823 			{
824 				// Draw the top z plane textured.
825 				surface = CreateSurface( 1, 1, 1 );
826 				RenderZ( surface, USE_TEXTURE | OVERLAYS );
827 
828 				hotX = isoWidth / 2 - 1;
829 				hotY = tileHeight * 2 - 1;
830 			}
831 			break;
832 
833 			case CUBE_BASIC:
834 			if ( pSet->drawAll || pSet->drawBasic )
835 			{
836 				// Draw the basic cube
837 				surface = CreateSurface( 1, 1, 1 );
838 				RenderZ( surface, USE_TEXTURE | OVERLAYS );
839 				RenderX( surface, USE_TEXTURE | OVERLAYS);
840 				RenderY( surface, USE_TEXTURE | OVERLAYS);
841 
842 				hotX = isoWidth / 2 - 1;
843 				hotY = tileHeight * 2 - 1;
844 			}
845 			break;
846 
847 			case JOIN_NWSE:
848 			if ( pSet->drawAll || pSet->drawJoin )
849 			{
850 				// Draw a NWSE wall (the first one because
851 				// it tends to break when something goes wrong).
852 				surface = CreateSurface( 1, 1, 1 );
853 
854 				RenderX( surface, USE_TEXTURE | NORTH | OFFSET );
855 				RenderY( surface, USE_TEXTURE | EAST | OFFSET );
856 
857 				RenderX( surface, USE_TEXTURE | SOUTH | OFFSET );
858 				RenderX( surface, USE_TEXTURE | CENTER );
859 
860 				RenderY( surface, USE_TEXTURE | WEST | OFFSET );
861 				RenderY( surface, USE_TEXTURE | CENTER );
862 
863 				RenderZ( surface, USE_TEXTURE | NORTH );
864 				RenderZ( surface, USE_TEXTURE | SOUTH );
865 				RenderZ( surface, USE_TEXTURE | CENTER );
866 				RenderZ( surface, USE_TEXTURE | EAST );
867 				RenderZ( surface, USE_TEXTURE | WEST );
868 
869 				hotX = isoWidth / 2 - 1;
870 				hotY = tileHeight * 2 - 1;
871 			}
872 			break;
873 
874 			case WALL_NS:
875 			if ( pSet->drawAll || pSet->drawWall )
876 			{
877 				// Draw a NS wall
878 				surface = CreateSurface( 1, 1, 1 );
879 				RenderX( surface, USE_TEXTURE | OFFSET | OVERLAYS);
880 
881 				RenderY( surface, USE_TEXTURE | CENTER );
882 
883 				RenderZ( surface, USE_TEXTURE | NORTH );
884 				RenderZ( surface, USE_TEXTURE | SOUTH );
885 				RenderZ( surface, USE_TEXTURE | CENTER );
886 
887 				hotX = isoWidth / 2 - 1;
888 				hotY = tileHeight * 2 - 1;
889 			}
890 			break;
891 
892 			case WALL_WE:
893 			if ( pSet->drawAll || pSet->drawWall )
894 			{
895 				// Draw a WE wall
896 				surface = CreateSurface( 1, 1, 1 );
897 				RenderY( surface, USE_TEXTURE | OFFSET | OVERLAYS);
898 
899 				RenderX( surface, USE_TEXTURE | CENTER );
900 
901 				RenderZ( surface, USE_TEXTURE | EAST );
902 				RenderZ( surface, USE_TEXTURE | WEST );
903 				RenderZ( surface, USE_TEXTURE | CENTER );
904 
905 				hotX = isoWidth / 2 - 1;
906 				hotY = tileHeight * 2 - 1;
907 			}
908 			break;
909 
910 			case JOIN_NW:
911 			if ( pSet->drawAll || pSet->drawJoin )
912 			{
913 				surface = CreateSurface( 1, 1, 1 );
914 
915 				RenderX( surface, USE_TEXTURE | NORTH | OFFSET );
916 				RenderX( surface, USE_TEXTURE | CENTER );
917 
918 				RenderY( surface, USE_TEXTURE | WEST | OFFSET );
919 				RenderY( surface, USE_TEXTURE | CENTER | OFFSET);
920 
921 				RenderZ( surface, USE_TEXTURE | NORTH );
922 				RenderZ( surface, USE_TEXTURE | CENTER );
923 				RenderZ( surface, USE_TEXTURE | WEST );
924 
925 				hotX = isoWidth / 2 - 1;
926 				hotY = tileHeight * 2 - 1;
927 			}
928 			break;
929 
930 			case JOIN_NE:
931 			if ( pSet->drawAll || pSet->drawJoin )
932 			{
933 				surface = CreateSurface( 1, 1, 1 );
934 
935 				RenderX( surface, USE_TEXTURE | NORTH | OFFSET );
936 				RenderX( surface, USE_TEXTURE | CENTER | OFFSET );
937 
938 				RenderY( surface, USE_TEXTURE | EAST | OFFSET );
939 				RenderY( surface, USE_TEXTURE | CENTER | OFFSET);
940 
941 				RenderZ( surface, USE_TEXTURE | NORTH );
942 				RenderZ( surface, USE_TEXTURE | CENTER );
943 				RenderZ( surface, USE_TEXTURE | EAST );
944 
945 				hotX = isoWidth / 2 - 1;
946 				hotY = tileHeight * 2 - 1;
947 			}
948 			break;
949 
950 			case JOIN_WS:
951 			if ( pSet->drawAll || pSet->drawJoin )
952 			{
953 				surface = CreateSurface( 1, 1, 1 );
954 
955 				RenderX( surface, USE_TEXTURE | SOUTH | OFFSET );
956 				RenderX( surface, USE_TEXTURE | CENTER );
957 
958 				RenderY( surface, USE_TEXTURE | WEST | OFFSET );
959 				RenderY( surface, USE_TEXTURE | CENTER);
960 
961 				RenderZ( surface, USE_TEXTURE | WEST );
962 				RenderZ( surface, USE_TEXTURE | CENTER );
963 				RenderZ( surface, USE_TEXTURE | SOUTH );
964 
965 				hotX = isoWidth / 2 - 1;
966 				hotY = tileHeight * 2 - 1;
967 			}
968 			break;
969 
970 			case JOIN_SE:
971 			if ( pSet->drawAll || pSet->drawJoin )
972 			{
973 				surface = CreateSurface( 1, 1, 1 );
974 
975 				RenderY( surface, USE_TEXTURE | EAST | OFFSET );
976 				RenderX( surface, USE_TEXTURE | SOUTH | OFFSET );
977 				RenderX( surface, USE_TEXTURE | CENTER | OFFSET );
978 				RenderY( surface, USE_TEXTURE | CENTER );
979 
980 				RenderZ( surface, USE_TEXTURE | EAST );
981 				RenderZ( surface, USE_TEXTURE | CENTER );
982 				RenderZ( surface, USE_TEXTURE | SOUTH );
983 
984 				hotX = isoWidth / 2 - 1;
985 				hotY = tileHeight * 2 - 1;
986 			}
987 			break;
988 
989 			case JOIN_NWS:
990 			if ( pSet->drawAll || pSet->drawJoin )
991 			{
992 				// NWS
993 				surface = CreateSurface( 1, 1, 1 );
994 
995 				RenderX( surface, USE_TEXTURE | SOUTH | OFFSET );
996 				RenderX( surface, USE_TEXTURE | NORTH | OFFSET );
997 				RenderX( surface, USE_TEXTURE | CENTER );
998 
999 				RenderY( surface, USE_TEXTURE | WEST | OFFSET );
1000 				RenderY( surface, USE_TEXTURE | CENTER );
1001 
1002 				RenderZ( surface, USE_TEXTURE | NORTH );
1003 				RenderZ( surface, USE_TEXTURE | SOUTH );
1004 				RenderZ( surface, USE_TEXTURE | CENTER );
1005 				RenderZ( surface, USE_TEXTURE | WEST );
1006 
1007 				hotX = isoWidth / 2 - 1;
1008 				hotY = tileHeight * 2 - 1;
1009 			}
1010 			break;
1011 
1012 			case JOIN_NSE:
1013 			if ( pSet->drawAll || pSet->drawJoin || pSet->drawWallJoin )
1014 			{
1015 				// NSE
1016 				surface = CreateSurface( 1, 1, 1 );
1017 
1018 				RenderY( surface, USE_TEXTURE | EAST | OFFSET );
1019 				RenderY( surface, USE_TEXTURE | CENTER );
1020 
1021 				RenderX( surface, USE_TEXTURE | OFFSET | OVERLAYS );
1022 
1023 				RenderZ( surface, USE_TEXTURE | NORTH );
1024 				RenderZ( surface, USE_TEXTURE | SOUTH );
1025 				RenderZ( surface, USE_TEXTURE | CENTER );
1026 				RenderZ( surface, USE_TEXTURE | EAST );
1027 
1028 				hotX = isoWidth / 2 - 1;
1029 				hotY = tileHeight * 2 - 1;
1030 			}
1031 			break;
1032 
1033 			case JOIN_NWE:
1034 			if ( pSet->drawAll || pSet->drawJoin || pSet->drawWallJoin )
1035 			{
1036 				// NWE
1037 				surface = CreateSurface( 1, 1, 1 );
1038 
1039 				RenderX( surface, USE_TEXTURE | NORTH | OFFSET );
1040 				RenderX( surface, USE_TEXTURE | CENTER );
1041 
1042 				RenderY( surface, USE_TEXTURE | OFFSET | OVERLAYS );
1043 
1044 				RenderZ( surface, USE_TEXTURE | NORTH );
1045 				RenderZ( surface, USE_TEXTURE | CENTER );
1046 				RenderZ( surface, USE_TEXTURE | EAST );
1047 				RenderZ( surface, USE_TEXTURE | WEST );
1048 
1049 				hotX = isoWidth / 2 - 1;
1050 				hotY = tileHeight * 2 - 1;
1051 			}
1052 			break;
1053 
1054 			case JOIN_WSE:
1055 			if ( pSet->drawAll || pSet->drawJoin )
1056 			{
1057 				// WSE
1058 
1059 				surface = CreateSurface( 1, 1, 1 );
1060 
1061 				RenderY( surface, USE_TEXTURE | EAST | OFFSET );
1062 				RenderY( surface, USE_TEXTURE | WEST | OFFSET );
1063 				RenderY( surface, USE_TEXTURE | CENTER );
1064 
1065 				RenderX( surface, USE_TEXTURE | SOUTH | OFFSET );
1066 				RenderX( surface, USE_TEXTURE | CENTER );
1067 
1068 				RenderZ( surface, USE_TEXTURE | SOUTH );
1069 				RenderZ( surface, USE_TEXTURE | CENTER );
1070 				RenderZ( surface, USE_TEXTURE | EAST );
1071 				RenderZ( surface, USE_TEXTURE | WEST );
1072 
1073 				hotX = isoWidth / 2 - 1;
1074 				hotY = tileHeight * 2 - 1;
1075 			}
1076 			break;
1077 
1078 			case RAMP_E:
1079 			if ( pSet->drawAll || pSet->drawRamp )
1080 			{
1081 				surface = CreateSurface( 1, 1, 1 );
1082 
1083 				RenderRamp( surface, USE_TEXTURE | EAST | OVERLAYS, 1 );
1084 
1085 				hotX = isoWidth / 2 - 1;
1086 				hotY = tileHeight * 2 - 1;
1087 			}
1088 			break;
1089 
1090 			case RAMP_N:
1091 			if ( pSet->drawAll || pSet->drawRamp )
1092 			{
1093 				surface = CreateSurface( 1, 1, 1 );
1094 
1095 				RenderRamp( surface, USE_TEXTURE | NORTH | OVERLAYS, 1 );
1096 
1097 				hotX = isoWidth / 2 - 1;
1098 				hotY = tileHeight * 2 - 1;
1099 			}
1100 			break;
1101 
1102 			case JOIN_NWSE_DOUBLE:
1103 			if ( (pSet->drawAll || pSet->drawJoin ) && pSet->drawDouble )
1104 			{
1105 				// Draw a NWSE wall (the first one because
1106 				// it tends to break when something goes wrong).
1107 				surface = CreateSurface( 1, 1, 2 );
1108 
1109 				RenderX( surface, USE_TEXTURE | NORTH | OFFSET, 0, 0 );
1110 				RenderX( surface, USE_TEXTURE | NORTH | OFFSET, 0, 1 );
1111 				RenderY( surface, USE_TEXTURE | EAST | OFFSET, 0, 0 );
1112 				RenderY( surface, USE_TEXTURE | EAST | OFFSET, 0, 1 );
1113 
1114 				RenderX( surface, USE_TEXTURE | SOUTH | OFFSET, 0, 0 );
1115 				RenderX( surface, USE_TEXTURE | SOUTH | OFFSET, 0, 1 );
1116 				RenderX( surface, USE_TEXTURE | CENTER, 0, 0 );
1117 				RenderX( surface, USE_TEXTURE | CENTER, 0, 1 );
1118 
1119 				RenderY( surface, USE_TEXTURE | WEST | OFFSET, 0, 0 );
1120 				RenderY( surface, USE_TEXTURE | WEST | OFFSET, 0, 1 );
1121 				RenderY( surface, USE_TEXTURE | CENTER, 0, 0 );
1122 				RenderY( surface, USE_TEXTURE | CENTER, 0, 1 );
1123 
1124 				RenderZ( surface, USE_TEXTURE | NORTH );
1125 				RenderZ( surface, USE_TEXTURE | SOUTH );
1126 				RenderZ( surface, USE_TEXTURE | CENTER );
1127 				RenderZ( surface, USE_TEXTURE | EAST );
1128 				RenderZ( surface, USE_TEXTURE | WEST );
1129 
1130 				hotX = isoWidth / 2 - 1;
1131 				hotY = tileHeight * 3 - 1;
1132 			}
1133 			break;
1134 
1135 			case WALL_NS_DOUBLE:
1136 			if ( (pSet->drawAll || pSet->drawWall) && pSet->drawDouble )
1137 			{
1138 				// Draw a NS wall
1139 				surface = CreateSurface( 1, 1, 2 );
1140 				RenderX( surface, USE_TEXTURE | OFFSET | OVERLAYS, 0, 0 );
1141 				RenderX( surface, USE_TEXTURE | OFFSET | OVERLAYS, 0, 1 );
1142 
1143 				RenderY( surface, USE_TEXTURE | CENTER, 0, 0 );
1144 				RenderY( surface, USE_TEXTURE | CENTER, 0, 1 );
1145 
1146 				RenderZ( surface, USE_TEXTURE | NORTH );
1147 				RenderZ( surface, USE_TEXTURE | SOUTH );
1148 				RenderZ( surface, USE_TEXTURE | CENTER );
1149 
1150 				hotX = isoWidth / 2 - 1;
1151 				hotY = tileHeight * 3 - 1;
1152 			}
1153 			break;
1154 
1155 			case WALL_WE_DOUBLE:
1156 			if ( (pSet->drawAll || pSet->drawWall )&& pSet->drawDouble )
1157 			{
1158 				// Draw a WE wall
1159 				surface = CreateSurface( 1, 1, 2 );
1160 				RenderY( surface, USE_TEXTURE | OFFSET | OVERLAYS, 0, 0 );
1161 				RenderY( surface, USE_TEXTURE | OFFSET | OVERLAYS, 0, 1 );
1162 
1163 				RenderX( surface, USE_TEXTURE | CENTER, 0, 0 );
1164 				RenderX( surface, USE_TEXTURE | CENTER, 0, 1 );
1165 
1166 				RenderZ( surface, USE_TEXTURE | EAST );
1167 				RenderZ( surface, USE_TEXTURE | WEST );
1168 				RenderZ( surface, USE_TEXTURE | CENTER );
1169 
1170 				hotX = isoWidth / 2 - 1;
1171 				hotY = tileHeight * 3 - 1;
1172 			}
1173 			break;
1174 
1175 			case JOIN_NW_DOUBLE:
1176 			if ( (pSet->drawAll || pSet->drawJoin ) && pSet->drawDouble )
1177 			{
1178 				surface = CreateSurface( 1, 1, 2 );
1179 
1180 				RenderX( surface, USE_TEXTURE | NORTH | OFFSET, 0, 0 );
1181 				RenderX( surface, USE_TEXTURE | NORTH | OFFSET, 0, 1 );
1182 				RenderX( surface, USE_TEXTURE | CENTER, 0, 0 );
1183 				RenderX( surface, USE_TEXTURE | CENTER, 0, 1 );
1184 
1185 				RenderY( surface, USE_TEXTURE | WEST | OFFSET, 0, 0 );
1186 				RenderY( surface, USE_TEXTURE | WEST | OFFSET, 0, 1 );
1187 				RenderY( surface, USE_TEXTURE | CENTER | OFFSET, 0, 0);
1188 				RenderY( surface, USE_TEXTURE | CENTER | OFFSET, 0, 1);
1189 
1190 				RenderZ( surface, USE_TEXTURE | NORTH );
1191 				RenderZ( surface, USE_TEXTURE | CENTER );
1192 				RenderZ( surface, USE_TEXTURE | WEST );
1193 
1194 				hotX = isoWidth / 2 - 1;
1195 				hotY = tileHeight * 3 - 1;
1196 			}
1197 			break;
1198 
1199 			case JOIN_NE_DOUBLE:
1200 			if ( (pSet->drawAll || pSet->drawJoin ) && pSet->drawDouble )
1201 			{
1202 				surface = CreateSurface( 1, 1, 2 );
1203 
1204 				RenderX( surface, USE_TEXTURE | NORTH | OFFSET, 0, 0 );
1205 				RenderX( surface, USE_TEXTURE | NORTH | OFFSET, 0, 1 );
1206 				RenderX( surface, USE_TEXTURE | CENTER | OFFSET, 0, 0 );
1207 				RenderX( surface, USE_TEXTURE | CENTER | OFFSET, 0, 1 );
1208 
1209 				RenderY( surface, USE_TEXTURE | EAST | OFFSET, 0, 0 );
1210 				RenderY( surface, USE_TEXTURE | EAST | OFFSET, 0, 1 );
1211 				RenderY( surface, USE_TEXTURE | CENTER | OFFSET, 0, 0);
1212 				RenderY( surface, USE_TEXTURE | CENTER | OFFSET, 0, 1);
1213 
1214 				RenderZ( surface, USE_TEXTURE | NORTH );
1215 				RenderZ( surface, USE_TEXTURE | CENTER );
1216 				RenderZ( surface, USE_TEXTURE | EAST );
1217 
1218 				hotX = isoWidth / 2 - 1;
1219 				hotY = tileHeight * 3 - 1;
1220 			}
1221 			break;
1222 
1223 			case JOIN_WS_DOUBLE:
1224 			if ( (pSet->drawAll || pSet->drawJoin ) && pSet->drawDouble )
1225 			{
1226 				surface = CreateSurface( 1, 1, 2 );
1227 
1228 				RenderX( surface, USE_TEXTURE | SOUTH | OFFSET , 0, 0);
1229 				RenderX( surface, USE_TEXTURE | SOUTH | OFFSET , 0, 1);
1230 				RenderX( surface, USE_TEXTURE | CENTER , 0, 0);
1231 				RenderX( surface, USE_TEXTURE | CENTER , 0, 1);
1232 
1233 				RenderY( surface, USE_TEXTURE | WEST | OFFSET , 0, 0);
1234 				RenderY( surface, USE_TEXTURE | WEST | OFFSET , 0, 1);
1235 				RenderY( surface, USE_TEXTURE | CENTER, 0, 0);
1236 				RenderY( surface, USE_TEXTURE | CENTER, 0, 1);
1237 
1238 				RenderZ( surface, USE_TEXTURE | WEST );
1239 				RenderZ( surface, USE_TEXTURE | CENTER );
1240 				RenderZ( surface, USE_TEXTURE | SOUTH );
1241 
1242 				hotX = isoWidth / 2 - 1;
1243 				hotY = tileHeight * 3 - 1;
1244 			}
1245 			break;
1246 
1247 			case JOIN_SE_DOUBLE:
1248 			if ( (pSet->drawAll || pSet->drawJoin ) && pSet->drawDouble )
1249 			{
1250 				surface = CreateSurface( 1, 1, 2 );
1251 
1252 				RenderY( surface, USE_TEXTURE | EAST | OFFSET , 0, 0);
1253 				RenderY( surface, USE_TEXTURE | EAST | OFFSET , 0, 1);
1254 				RenderX( surface, USE_TEXTURE | SOUTH | OFFSET , 0, 0);
1255 				RenderX( surface, USE_TEXTURE | SOUTH | OFFSET , 0, 1);
1256 				RenderX( surface, USE_TEXTURE | CENTER | OFFSET , 0, 0);
1257 				RenderX( surface, USE_TEXTURE | CENTER | OFFSET , 0, 1);
1258 				RenderY( surface, USE_TEXTURE | CENTER , 0, 0);
1259 				RenderY( surface, USE_TEXTURE | CENTER , 0, 1);
1260 
1261 				RenderZ( surface, USE_TEXTURE | EAST );
1262 				RenderZ( surface, USE_TEXTURE | CENTER );
1263 				RenderZ( surface, USE_TEXTURE | SOUTH );
1264 
1265 				hotX = isoWidth / 2 - 1;
1266 				hotY = tileHeight * 3 - 1;
1267 			}
1268 			break;
1269 
1270 			case JOIN_NWS_DOUBLE:
1271 			if ( (pSet->drawAll || pSet->drawJoin ) && pSet->drawDouble )
1272 			{
1273 				// NWS
1274 				surface = CreateSurface( 1, 1, 2 );
1275 
1276 				RenderX( surface, USE_TEXTURE | SOUTH | OFFSET, 0, 0 );
1277 				RenderX( surface, USE_TEXTURE | SOUTH | OFFSET, 0, 1 );
1278 				RenderX( surface, USE_TEXTURE | NORTH | OFFSET, 0, 0 );
1279 				RenderX( surface, USE_TEXTURE | NORTH | OFFSET, 0, 1 );
1280 				RenderX( surface, USE_TEXTURE | CENTER, 0, 0 );
1281 				RenderX( surface, USE_TEXTURE | CENTER, 0, 1 );
1282 
1283 				RenderY( surface, USE_TEXTURE | WEST | OFFSET, 0, 0 );
1284 				RenderY( surface, USE_TEXTURE | WEST | OFFSET, 0, 1 );
1285 				RenderY( surface, USE_TEXTURE | CENTER, 0, 0 );
1286 				RenderY( surface, USE_TEXTURE | CENTER, 0, 1 );
1287 
1288 				RenderZ( surface, USE_TEXTURE | NORTH );
1289 				RenderZ( surface, USE_TEXTURE | SOUTH );
1290 				RenderZ( surface, USE_TEXTURE | CENTER );
1291 				RenderZ( surface, USE_TEXTURE | WEST );
1292 
1293 				hotX = isoWidth / 2 - 1;
1294 				hotY = tileHeight * 3 - 1;
1295 			}
1296 			break;
1297 
1298 			case JOIN_NSE_DOUBLE:
1299 			if ( (pSet->drawAll || pSet->drawJoin ) && pSet->drawDouble )
1300 			{
1301 				// NSE
1302 				surface = CreateSurface( 1, 1, 2 );
1303 
1304 				RenderY( surface, USE_TEXTURE | EAST | OFFSET, 0, 0 );
1305 				RenderY( surface, USE_TEXTURE | EAST | OFFSET, 0, 1 );
1306 				RenderY( surface, USE_TEXTURE | CENTER, 0, 0 );
1307 				RenderY( surface, USE_TEXTURE | CENTER, 0, 1 );
1308 
1309 				RenderX( surface, USE_TEXTURE | OFFSET | OVERLAYS, 0, 0 );
1310 				RenderX( surface, USE_TEXTURE | OFFSET | OVERLAYS, 0, 1 );
1311 
1312 				RenderZ( surface, USE_TEXTURE | NORTH );
1313 				RenderZ( surface, USE_TEXTURE | SOUTH );
1314 				RenderZ( surface, USE_TEXTURE | CENTER );
1315 				RenderZ( surface, USE_TEXTURE | EAST );
1316 
1317 				hotX = isoWidth / 2 - 1;
1318 				hotY = tileHeight * 3 - 1;
1319 			}
1320 			break;
1321 
1322 			case JOIN_NWE_DOUBLE:
1323 			if ( (pSet->drawAll || pSet->drawJoin ) && pSet->drawDouble )
1324 			{
1325 				// NWE
1326 				surface = CreateSurface( 1, 1, 2 );
1327 
1328 				RenderX( surface, USE_TEXTURE | NORTH | OFFSET, 0, 0 );
1329 				RenderX( surface, USE_TEXTURE | NORTH | OFFSET, 0, 1 );
1330 				RenderX( surface, USE_TEXTURE | CENTER, 0, 0 );
1331 				RenderX( surface, USE_TEXTURE | CENTER, 0, 1 );
1332 
1333 				RenderY( surface, USE_TEXTURE | OFFSET | OVERLAYS, 0, 0 );
1334 				RenderY( surface, USE_TEXTURE | OFFSET | OVERLAYS, 0, 1 );
1335 
1336 				RenderZ( surface, USE_TEXTURE | NORTH );
1337 				RenderZ( surface, USE_TEXTURE | CENTER );
1338 				RenderZ( surface, USE_TEXTURE | EAST );
1339 				RenderZ( surface, USE_TEXTURE | WEST );
1340 
1341 				hotX = isoWidth / 2 - 1;
1342 				hotY = tileHeight * 3 - 1;
1343 			}
1344 			break;
1345 
1346 			case JOIN_WSE_DOUBLE:
1347 			if ( (pSet->drawAll || pSet->drawJoin ) && pSet->drawDouble )
1348 			{
1349 				// WSE
1350 
1351 				surface = CreateSurface( 1, 1, 2 );
1352 
1353 				RenderY( surface, USE_TEXTURE | EAST | OFFSET, 0, 0 );
1354 				RenderY( surface, USE_TEXTURE | EAST | OFFSET, 0, 1 );
1355 				RenderY( surface, USE_TEXTURE | WEST | OFFSET, 0, 0 );
1356 				RenderY( surface, USE_TEXTURE | WEST | OFFSET, 0, 1 );
1357 				RenderY( surface, USE_TEXTURE | CENTER, 0, 0 );
1358 				RenderY( surface, USE_TEXTURE | CENTER, 0, 1 );
1359 
1360 				RenderX( surface, USE_TEXTURE | SOUTH | OFFSET, 0, 0 );
1361 				RenderX( surface, USE_TEXTURE | SOUTH | OFFSET, 0, 1 );
1362 				RenderX( surface, USE_TEXTURE | CENTER, 0, 0 );
1363 				RenderX( surface, USE_TEXTURE | CENTER, 0, 1 );
1364 
1365 				RenderZ( surface, USE_TEXTURE | SOUTH );
1366 				RenderZ( surface, USE_TEXTURE | CENTER );
1367 				RenderZ( surface, USE_TEXTURE | EAST );
1368 				RenderZ( surface, USE_TEXTURE | WEST );
1369 
1370 				hotX = isoWidth / 2 - 1;
1371 				hotY = tileHeight * 3 - 1;
1372 			}
1373 			break;
1374 
1375 			case RAMP_E_DOUBLE:
1376 			if ( pSet->drawDouble && (pSet->drawRamp || pSet->drawAll ))
1377 			{
1378 				surface = CreateSurface( 2, 1, 3 );
1379 
1380 				RenderRamp( surface, USE_TEXTURE | EAST | OVERLAYS, 2 );
1381 				RenderRamp( surface, USE_TEXTURE | EAST | OVERLAYS, 2 );
1382 
1383 				hotX = isoWidth / 2 - 1;
1384 				hotY = tileHeight*3 + tileHeight/2 - 1;
1385 			}
1386 			break;
1387 
1388 			case RAMP_N_DOUBLE:
1389 			if ( pSet->drawDouble && (pSet->drawRamp || pSet->drawAll ))
1390 			{
1391 				surface = CreateSurface( 1, 2, 3 );
1392 
1393 				RenderRamp( surface, USE_TEXTURE | NORTH | OVERLAYS, 2 );
1394 				RenderRamp( surface, USE_TEXTURE | NORTH | OVERLAYS, 2 );
1395 
1396 				hotX = isoWidth - 1;
1397 				hotY = tileHeight*3 + tileHeight/2 - 1;
1398 			}
1399 			break;
1400 
1401 			default:
1402 				done = true;
1403 		}
1404 
1405 		// Save off the surface we just used.
1406 		if ( surface )
1407 		{
1408 			int border = 0;
1409 			if ( saveX + surface->w >= saveSurface->w ) {
1410 				saveX = 0;
1411 				saveY += saveMax;
1412 				saveMax = 0;
1413 			}
1414 			saveMax = Max( saveMax, surface->h );
1415 
1416 			SDL_Rect src = { 0, 0, surface->w, surface->h };
1417 			SDL_Rect dst = { saveX, saveY, surface->w, surface->h };
1418 			saveX += surface->w + border;
1419 
1420 			SDL_BlitSurface( surface, &src, saveSurface, &dst );
1421 			SDL_FreeSurface( surface );
1422 
1423 			WriteIconToXML( xmlNode, gIconName[count], dst.x, dst.y, dst.w, dst.h, dst.x+hotX, dst.y+hotY );
1424 		}
1425 	}
1426 }
1427 
1428 
WriteXMLHeader(TiXmlDocument * doc,const char * imageName,const char * spriteName)1429 TiXmlNode* WriteXMLHeader( TiXmlDocument* doc, const char* imageName, const char* spriteName )
1430 {
1431 	TiXmlElement definition( "Definition" );
1432 	definition.SetAttribute( "filename", imageName );
1433 	definition.SetAttribute( "Transparent0", "#000000" );
1434 
1435 	TiXmlElement sprite( "Sprite" );
1436 	sprite.SetAttribute( "name", spriteName );
1437 
1438 	definition.InsertEndChild( sprite );
1439 	doc->InsertEndChild( definition );
1440 
1441 	return doc->FirstChildElement()->FirstChildElement();
1442 }
1443 
1444 
ParseTF(TiXmlElement * ele,const char * value,bool * result)1445 void ParseTF( TiXmlElement* ele, const char* value, bool *result )
1446 {
1447 	if ( ele->Attribute( value ) )
1448 	{
1449 		if ( strcmp( ele->Attribute( value ), "true" ) == 0 ) {
1450 			*result = true;
1451 		}
1452 		else if ( strcmp( ele->Attribute( value ), "false" ) == 0 ) {
1453 			*result = false;
1454 		}
1455 	}
1456 }
1457 
1458 
ReadOverlayAttributes(TiXmlElement * ele,TexData * tex)1459 void ReadOverlayAttributes( TiXmlElement* ele, TexData* tex )
1460 {
1461 	if ( ele->Attribute( "alpha" ) ) {
1462 		double alpha = 1.0f;
1463 		ele->Attribute( "alpha", &alpha );
1464 		tex->alpha = (U8) Clamp( LRint( alpha*255.0 ), (long)0, (long)255 );
1465 	}
1466 	ParseTF( ele, "emit", &tex->emit );
1467 }
1468 
1469 
ParseXML(TiXmlDocument * doc)1470 bool ParseXML( TiXmlDocument* doc )
1471 {
1472 	static int nameCount = 0;
1473 
1474 	TiXmlHandle docH( doc );
1475 
1476 	TiXmlElement* isogen = docH.FirstChildElement( "Isogen" ).Element();
1477 	if ( isogen ) {
1478 		bool wallInsetSet = false;
1479 
1480 		if ( isogen->Attribute( "sprite" )) {
1481 			spriteName = isogen->Attribute( "sprite" );
1482 		}
1483 		else {
1484 			printf( "Required 'sprite' attribute in <Isogen> not specified.\n" );
1485 			return false;
1486 		}
1487 		if ( isogen->Attribute( "isoWidth" )) {
1488 			isogen->Attribute( "isoWidth", &isoWidth );
1489 			isoWidth = ((isoWidth+3)/4)*4;
1490 			tileWidth = isoWidth - 2;
1491 			tileHeight = isoWidth / 2;
1492 		}
1493 		if ( isogen->Attribute( "wallInset" )) {
1494 			isogen->Attribute( "wallInset", &step );
1495 			wallInsetSet = true;
1496 		}
1497 		if ( isogen->Attribute( "width" )) {
1498 			isogen->Attribute( "width", &outWidth );
1499 		}
1500 		if ( isogen->Attribute( "height" )) {
1501 			isogen->Attribute( "height", &outHeight );
1502 		}
1503 		if ( isogen->Attribute( "ambient" )) {
1504 			sscanf( isogen->Attribute( "ambient" ), "%f %f %f", &ambient.r, &ambient.g, &ambient.b );
1505 		}
1506 		if ( isogen->Attribute( "diffuse" )) {
1507 			sscanf( isogen->Attribute( "diffuse" ), "%f %f %f", &diffuse.r, &diffuse.g, &diffuse.b );
1508 		}
1509 		if ( isogen->Attribute( "lightVector" )) {
1510 			sscanf( isogen->Attribute( "lightVector" ), "%f %f %f", &lightVector.x, &lightVector.y, &lightVector.z );
1511 		}
1512 
1513 		if ( !wallInsetSet )
1514 			step = isoWidth / 12;
1515 
1516 		lightVector.Normalize();
1517 		lightVector.x = -lightVector.x;
1518 		lightVector.y = -lightVector.y;
1519 		lightVector.z = -lightVector.z;
1520 
1521 		TiXmlElement* setEle = 0;
1522 		for(	setEle = isogen->FirstChildElement( "Set" );
1523 				setEle;
1524 				setEle = setEle->NextSiblingElement( "Set" ) )
1525 		{
1526 			setData.resize( setData.size() + 1 );
1527 			pSet = &setData[ setData.size()-1 ];
1528 
1529 			pSet->Init();
1530 
1531 			ParseTF( setEle, "useAA", &pSet->useAA );
1532 			ParseTF( setEle, "drawAll", &pSet->drawAll );
1533 			ParseTF( setEle, "drawBasic", &pSet->drawBasic );
1534 			ParseTF( setEle, "drawWall", &pSet->drawWall );
1535 			ParseTF( setEle, "drawJoin", &pSet->drawJoin );
1536 			ParseTF( setEle, "drawWallJoin", &pSet->drawWallJoin );
1537 			ParseTF( setEle, "drawRamp", &pSet->drawRamp );
1538 			ParseTF( setEle, "drawDouble", &pSet->drawDouble );
1539 
1540 			pSet->floorTexture.resize(1);
1541 			pSet->floorTexture[0].Clear();
1542 			pSet->floorTexture[0].surface = whiteSurface;
1543 
1544 			pSet->wallTexture.resize(1);
1545 			pSet->wallTexture[0].Clear();
1546 			pSet->wallTexture[0].surface = whiteSurface;
1547 
1548 			if ( setEle->Attribute( "floor" ) ) {
1549 				GLASSERT( pSet->floorTexture.size() == 1 );
1550 				pSet->floorTexture[0].surface = ImageLoader( setEle->Attribute( "floor" ) );
1551 				if ( !pSet->floorTexture[0].surface ) {
1552 					printf( "Failed to load texture '%s'\n", setEle->Attribute( "floor" ) );
1553 					return false;
1554 				}
1555 			}
1556 			if ( setEle->Attribute( "wall" ) ) {
1557 				GLASSERT( pSet->wallTexture.size() == 1 );
1558 				pSet->wallTexture[0].surface = ImageLoader( setEle->Attribute( "wall" ) );
1559 				if ( !pSet->wallTexture[0].surface ) {
1560 					printf( "Failed to load texture '%s'\n", setEle->Attribute( "wall" ) );
1561 					return false;
1562 				}
1563 			}
1564 
1565 			if ( setEle->Attribute( "action" )) {
1566 				pSet->action = setEle->Attribute( "action" );
1567 			}
1568 			else {
1569 				char buf[256];
1570 				sprintf( buf, "ICON%d", nameCount++ );
1571 				pSet->action = buf;
1572 			}
1573 
1574 			TexData dummy;
1575 			dummy.Clear();
1576 
1577 			TiXmlElement* overEle = 0;
1578 			for(	overEle = setEle->FirstChildElement( "FloorOverlay" );
1579 					overEle;
1580 					overEle = overEle->NextSiblingElement( "FloorOverlay" ) )
1581 			{
1582 				if ( overEle->Attribute( "name" ) ) {
1583 					pSet->floorTexture.push_back( dummy );
1584 					TexData* tex = &pSet->floorTexture.back();
1585 
1586 					tex->surface = ImageLoader( overEle->Attribute( "name" ) );
1587 					if ( !tex->surface ) {
1588 						printf( "Failed to load texture '%s'\n", overEle->Attribute( "name" ) );
1589 						return false;
1590 					}
1591 					ReadOverlayAttributes( overEle, tex );
1592 				}
1593 			}
1594 			for(	overEle = setEle->FirstChildElement( "WallOverlay" );
1595 					overEle;
1596 					overEle = overEle->NextSiblingElement( "WallOverlay" ) )
1597 			{
1598 				if ( overEle->Attribute( "name" ) ) {
1599 					pSet->wallTexture.push_back( dummy );
1600 					TexData* tex = &pSet->wallTexture.back();
1601 
1602 					tex->surface = ImageLoader( overEle->Attribute( "name" ) );
1603 					if ( !tex->surface ) {
1604 						printf( "Failed to load texture '%s'\n", overEle->Attribute( "name" ) );
1605 						return false;
1606 					}
1607 					ReadOverlayAttributes( overEle, tex );
1608 				}
1609 			}
1610 			//printf( "Set has %d wall and %d floor\n", pSet->wallTexture.size(), pSet->floorTexture.size() );
1611 		}
1612 		pSet = 0;
1613 		return true;
1614 	}
1615 	return false;
1616 }
1617 
1618 
main(int argc,char * argv[])1619 int main( int argc, char* argv[] )
1620 {
1621 	if ( SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_NOPARACHUTE) < 0 ) {
1622 		printf( "Couldn't initialize SDL: %s\n", SDL_GetError() );
1623 		return 255;
1624 	}
1625 
1626 	void* handle = GL_LoadLibrary( "SDL_image" );
1627 	if ( !handle )
1628 	{
1629 		exit( 1 );
1630 	}
1631 	ImageLoader = (ImageLoaderFunc) GL_LoadFunction( handle, "IMG_Load" );
1632 	GLASSERT( ImageLoader );
1633 
1634 	if ( argc < 2 ) {
1635 		printf( "isogen minimal usage:\n"
1636 				"  isogen sprite='spriteName'\n"
1637 				"Where the 'spriteName' is the name of the output XML and BMP file.\n"
1638 				"To provide floor and wall textures:\n"
1639 				"  isogen sprite='spriteName' floor='floor.bmp' wall='wall.bmp'\n"
1640 				"To use an isogen XML file:\n"
1641 				"  isogen data.xml\n"
1642 				"isogen has many more options - please see the docs.\n" );
1643 		return 1;
1644 	}
1645 
1646 	TiXmlDocument doc;
1647 
1648 	if ( argc == 2 && strstr( argv[1], ".xml" ) ) {
1649 		doc.LoadFile( argv[1] );
1650 	}
1651 	else {
1652 		string input = "<Isogen ";
1653 		int i;
1654 		for( i=1; i<argc; ++i ) {
1655 			input += argv[i];
1656 			input += " ";
1657 		}
1658 		input += "><Set ";
1659 		for( i=1; i<argc; ++i ) {
1660 			input += argv[i];
1661 			input += " ";
1662 		}
1663 		input += " /></Isogen>";
1664 
1665 		doc.Parse( input.c_str() );
1666 	}
1667 
1668 	if ( doc.Error() ) {
1669 		printf( "Error parsing input arguments.\n" );
1670 		printf( "%s\n", doc.ErrorDesc() );
1671 		return 1;
1672 	}
1673 
1674 	if ( ParseXML( &doc ) == false ) {
1675 		printf( "Error parsing command line or XML.\n" );
1676 		return 1;
1677 	}
1678 
1679 	// Create the surface to save to:
1680 	SDL_Surface* surface = SDL_CreateRGBSurface(	SDL_SWSURFACE,
1681 													outWidth, outHeight,
1682 													32,
1683 													0xff, 0xff<<8, 0xff<<16, 0xff<<24 );
1684 	Uint32 color = SDL_MapRGBA( surface->format, 0, 0, 0, 255 );
1685 	SDL_FillRect( surface, 0, color );
1686 
1687 	whiteSurface = SDL_CreateRGBSurface(	SDL_SWSURFACE,
1688 											4, 4,
1689 											32,
1690 											0xff, 0xff<<8, 0xff<<16, 0xff<<24 );
1691 	memset( whiteSurface->pixels, 255, whiteSurface->pitch * whiteSurface->h );
1692 
1693 	string saveXMLName = spriteName + "_encoder.xml";
1694 	string saveImageName = spriteName + ".bmp";
1695 
1696 	TiXmlDocument outputDoc( saveXMLName.c_str() );
1697 	TiXmlNode* node = WriteXMLHeader( &outputDoc, saveImageName.c_str(), spriteName.c_str() );
1698 
1699 	for( unsigned i=0; i<setData.size(); ++i )
1700 	{
1701 		pSet = &setData[i];
1702 		DrawIcons( surface, node );
1703 		pSet->Clear();
1704 	}
1705 
1706 	printf( "Writing image file '%s'.\n", saveImageName.c_str() );
1707 	SDL_SaveBMP( surface, saveImageName.c_str() );
1708 	printf( "Writing kyra encoder file '%s'.\n", outputDoc.Value() );
1709 	outputDoc.SaveFile();
1710 
1711 	SDL_FreeSurface( surface );
1712 	surface = 0;
1713 	SDL_FreeSurface( whiteSurface );
1714 	whiteSurface = 0;
1715 
1716 	SDL_Quit();
1717 	return 0;
1718 }
1719