1 /*--License:
2 	Kyra Sprite Engine
3 	Copyright Lee Thomason (Grinning Lizard Software) 2001-2005
4 	www.grinninglizard.com/kyra
5 	www.sourceforge.net/projects/kyra
6 
7 	Kyra is provided under the LGPL.
8 
9 	I kindly request you display a splash screen (provided in the HTML documentation)
10 	to promote Kyra and acknowledge the software and everyone who has contributed to it,
11 	but it is not required by the license.
12 
13 --- LGPL License --
14 
15     This library is free software; you can redistribute it and/or
16     modify it under the terms of the GNU Lesser General Public
17     License as published by the Free Software Foundation; either
18     version 2.1 of the License, or (at your option) any later version.
19 
20     This library is distributed in the hope that it will be useful,
21     but WITHOUT ANY WARRANTY; without even the implied warranty of
22     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23     Lesser General Public License for more details.
24 
25     You should have received a copy of the GNU Lesser General Public
26     License along with this library; if not, write to the Free Software
27     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
28 
29 	The full text of the license can be found in lgpl.txt
30 */
31 
32 
33 #include "sharedstate.h"
34 #include "../engine/action.h"
35 #include "../engine/parser.h"
36 #include "../engine/encoder.h"
37 #include "../engine/fontresource.h"
38 #include "../engine/canvasresource.h"
39 #include "../engine/imnode.h"
40 #include "../engine/engine.h"
41 #include "../engine/textbox.h"
42 #include "../engine/box.h"
43 #include "../engine/boxresource.h"
44 #include "../gui/console.h"
45 #include "dom.h"
46 #include "CONSOLEFONT.h"
47 
48 
SharedStateData(SDL_Surface * screen)49 SharedStateData::SharedStateData( SDL_Surface* screen )
50 {
51 	currentSprite = 0;
52 	currentFrame = 0;
53 	currentAction = 0;
54 	currentTile = 0;
55 	currentObject = SPRITE;
56 
57 	// Use the sprite engine for the editor. It's a way to
58 	// test everything.
59 	engine = new KrEngine( screen );
60 	GLASSERT( engine );
61 
62 	// Make the backgrounds reasonably sized so we don't spend
63 	// all our time sorting.
64 	backgroundRes = new KrCanvasResource( "backgroundRes", 100, 100, false );
65 	for ( int i=0; i<100; i++ )
66 	{
67 		for( int j=0; j<100; j++ )
68 		{
69 			KrRGBA* pixel = backgroundRes->Pixels() + i + j*backgroundRes->Width();
70 			if ( ( ( i / 10 ) & 0x01 ) == ( ( j / 10 ) & 0x01 ) )
71 				pixel->c.red = pixel->c.green = pixel->c.blue = 30;
72 			else
73 				pixel->c.red = pixel->c.green = pixel->c.blue = 60;
74 		}
75 	}
76 	engine->Vault()->AddResource( backgroundRes );
77 
78 	KrFontResource* fontRes = KrEncoder::CreateFixedFontResource( "CONSOLE", CONSOLEFONT_DAT, CONSOLEFONT_SIZE );
79 	engine->Vault()->AddResource( fontRes );
80 	fontResource = engine->Vault()->GetFontResource( "CONSOLE" );
81 	GLASSERT( fontResource );
82 
83 	consoleHolder = new KrImNode();
84 	consoleHolder->SetZDepth( CONSOLE_DEPTH );
85 	engine->Tree()->AddNode( 0, consoleHolder );
86 
87 	int consoleHeight = fontResource->FontHeight() * 6;
88 	int consoleWidth  = screen->w * 9 / 12;
89 	consoleHolder->SetPos( 0, screen->h - consoleHeight );
90 
91 	KrScheme scheme( fontResource );
92 	console = new KrConsole( consoleWidth, consoleHeight, 0, scheme );
93 	engine->Tree()->AddNode( consoleHolder, console );
94 
95 	KrRGBA blue;
96 	blue.Set( 0, 0, 80 );
97 	console->SetBackgroundColor( blue );
98 
99 	int a, b, c;
100 	engine->Version( &a, &b, &c );
101 	console->Print( "Welcome to the Sprite Editor! [version %d.%d.%d]\nThis area is the input console.\n",
102 					a, b, c  );
103 
104 	// A text box for output, with a background.
105 	// And toss it background for good measure.
106 	KrRGBA infoColor[2];
107 	infoColor[0].Set( 0, 120, 0 );
108 	infoColor[1].Set( 0, 70,  0 );
109 	KrBoxResource* infoResource = new KrBoxResource( "",
110 													 screen->w - consoleWidth,
111 													 consoleHeight,
112 													 infoColor, 2,
113 													 KrBoxResource::FILL );
114 	engine->Vault()->AddResource( infoResource );
115 
116 	infoBoxBack = new KrBox( infoResource );
117 	engine->Tree()->AddNode( 0, infoBoxBack );
118 	infoBoxBack->SetZDepth( INFO_BACKGROUND_DEPTH );
119 	infoBoxBack->SetPos( consoleWidth, screen->h - consoleHeight );
120 
121 	infoBox = new KrTextBox(	fontResource,
122 								screen->w - consoleWidth,
123 								consoleHeight, 0 );
124 
125 	engine->Tree()->AddNode( infoBoxBack, infoBox );
126 	infoBox->SetZDepth( INFO_DEPTH );
127 	//infoBox->SetPos( consoleWidth, screen->h - consoleHeight );
128 
129 	// Create a new node for the view state. Set
130 	// it to a depth of one, so that the image
131 	// (loaded later) won't cover up the widgets.
132 	widgetNode = new KrImNode();
133 	widgetNode->SetZDepth( WIDGET_DEPTH );
134 	engine->Tree()->AddNode( 0, widgetNode );
135 
136 	widget = new EdWidget( engine->Tree(), widgetNode, 0 );
137 
138 	imnode = new KrImNode();
139 	imnode->SetZDepth( MAIN_IMNODE_DEPTH );
140 	engine->Tree()->AddNode( 0, imnode );
141 
142 // 	spriteData = new TiXmlDocument;
143 	defFileName = "";
144 	animAction = 0;
145 	canvasResource = 0;
146 	nTrans = 0;
147 }
148 
149 
~SharedStateData()150 SharedStateData::~SharedStateData()
151 {
152 	delete widget;				// Delete first -- will delete things from tree.
153 	delete engine;
154 	delete canvasResource;		// Not in a vault -- delete explicitly.
155 }
156 
157 
Clear()158 void SharedStateData::Clear()
159 {
160 	SetCurrentTile( 0 );
161 	SetCurrentSprite( 0 );
162 
163 	delete widget;
164 	widget = new EdWidget( engine->Tree(), widgetNode, 0 );
165 
166 	delete canvasResource;
167 	canvasResource = 0;
168 
169 	defFileName = "";
170 	surfaceFileName = "";
171 }
172 
173 
SetCurrentTile(EdWidget * tile)174 void SharedStateData::SetCurrentTile( EdWidget* tile )
175 {
176 	if ( currentFrame )		currentFrame->Select( false );
177 	if ( currentAction )	currentAction->Select( false );
178 	if ( currentSprite )	currentSprite->Select( false );
179 	if ( currentTile )		currentTile->Select( false );
180 
181 	currentObject = TILE;
182 	if ( tile )
183 	{
184 		GLASSERT( tile->Type() == EdWidget::TILE );
185 		currentTile = (EdWidgetTile*) tile;
186 		currentTile->Select( true );
187 	}
188 	else
189 	{
190 		currentTile = 0;
191 	}
192 	currentFrame = 0;
193 	currentAction = 0;
194 	currentSprite = 0;
195 
196 	SetInfoBox( true );
197 }
198 
199 
SetCurrentFrame(EdWidget * frame)200 void SharedStateData::SetCurrentFrame( EdWidget* frame )
201 {
202 	if ( currentFrame )		currentFrame->Select( false );
203 	if ( currentAction )	currentAction->Select( false );
204 	if ( currentSprite )	currentSprite->Select( false );
205 	if ( currentTile )		currentTile->Select( false );
206 
207 	currentObject = SPRITE;
208 	currentTile = 0;
209 	if ( frame )
210 	{
211 		GLASSERT( frame->Type() == EdWidget::FRAME );
212 		GLASSERT( currentAction );
213 		GLASSERT( frame->Parent() == currentAction );
214 
215 		if ( frame->Type() == EdWidget::FRAME)
216 		{
217 			currentFrame = (EdWidgetFrame*) frame;
218 			currentFrame->Select( true );
219 		}
220 	}
221 	else
222 	{
223 		currentFrame = 0;
224 	}
225 	SetInfoBox( true );
226 }
227 
228 
SetCurrentAction(EdWidget * action)229 void SharedStateData::SetCurrentAction( EdWidget* action )
230 {
231 	if ( currentFrame )		currentFrame->Select( false );
232 	if ( currentAction )	currentAction->Select( false );
233 	if ( currentSprite )	currentSprite->Select( false );
234 	if ( currentTile )		currentTile->Select( false );
235 
236 	currentObject = SPRITE;
237 	currentTile = 0;
238 	if ( action )
239 	{
240 		GLASSERT( action->Type() == EdWidget::ACTION );
241 		GLASSERT( currentSprite );
242 		GLASSERT( action->Parent() == currentSprite );
243 
244 		if ( action->Type() == EdWidget::ACTION )
245 		{
246 			currentAction = (EdWidgetAction*) action;
247 		}
248 		currentFrame = 0;
249 	}
250 	else
251 	{
252 		currentAction = 0;
253 		currentFrame = 0;
254 	}
255 	SetInfoBox( true );
256 }
257 
258 
SetCurrentSprite(EdWidget * sprite)259 void SharedStateData::SetCurrentSprite( EdWidget* sprite )
260 {
261 	if ( currentFrame )		currentFrame->Select( false );
262 	if ( currentAction )	currentAction->Select( false );
263 	if ( currentSprite )	currentSprite->Select( false );
264 	if ( currentTile )		currentTile->Select( false );
265 
266 	currentObject = SPRITE;
267 	currentTile = 0;
268 	if ( sprite )
269 	{
270 		GLASSERT( sprite->Type() == EdWidget::SPRITE );
271 
272 		if ( sprite->Type() == EdWidget::SPRITE )
273 		{
274 			currentSprite = ( EdWidgetSprite* ) sprite;
275 		}
276 		currentFrame = 0;
277 		currentAction = 0;
278 	}
279 	else
280 	{
281 		currentSprite = 0;
282 		currentAction = 0;
283 		currentFrame = 0;
284 	}
285 
286 // 	ClearInfo();
287 	SetInfoBox( true );
288 }
289 
290 
DefFileName()291 const std::string& SharedStateData::DefFileName()
292 {
293 	return defFileName;
294 }
295 
296 
SurfaceFileName()297 const std::string& SharedStateData::SurfaceFileName()
298 {
299 	return surfaceFileName;
300 }
301 
302 
LoadSurface(int nTrans,const KrRGBA * trans)303 bool SharedStateData::LoadSurface( int nTrans, const KrRGBA* trans )
304 {
305 	const char* filename = SurfaceFileName().c_str();
306 	if ( filename && *filename )
307 	{
308 		// We are borrowing functionality from the encoder -
309 		// it does all the surface loading processing
310 		// that we would like to do.
311 		canvasResource = KrEncoder::Load32Canvas(	filename,
312 													trans,
313 													nTrans,
314 													0 );
315 		return canvasResource != 0;
316 	}
317 
318 	GLOUTPUT(( "Error in SharedStateData::LoadSurface\n" ));
319 	return false;
320 }
321 
322 
323 // This is a rather tricky function. The (human) sprite editor has
324 // created a documented describing a sprite action. We look at this
325 // document, extract the relevent information, and create KrRle objects
326 // that are frames of an action. These frames are assembled into an
327 // action which is returned.
328 //
329 
CreateAnimationAction()330 KrAction* SharedStateData::CreateAnimationAction()
331 {
332 	KrAction* action = 0;
333 
334 	// If there is a current action, write the frame actions
335 	// and encode them.
336 	if ( currentAction )
337 	{
338 		int nFrames = currentAction->children.Count();
339 		int i = 0;
340 		if ( nFrames > 0 )
341 		{
342 			action = new KrAction( "no_action_name" );
343 
344 			GlSListIterator< EdWidget* > it( currentAction->children );
345 			for( i = 0, it.Begin();
346 				 !it.Done();
347 				 ++i, it.Next() )
348 			{
349 				EdWidgetFrame* frame = it.Current()->ToFrame();
350 				GLASSERT( frame );
351 				KrDom::Frame frameData = frame->GetFrameData();
352 
353 				KrPaintInfo info(	canvasResource->Pixels(),
354 									canvasResource->Width(),
355 									canvasResource->Height() );
356 
357 				action->AddFrame();
358 				GLASSERT( action->NumFrames() == i+1 );
359 				action->GetFrame( i )->Create(	&info,
360 												frameData.x,
361 												frameData.y,
362 												frameData.width,
363 												frameData.height,
364 												frameData.hotspotX,
365 												frameData.hotspotY,
366 												frameData.deltaX,
367 												frameData.deltaY );
368 			}
369 		}
370 	}
371 	return action;
372 }
373 
SetInfoBox(bool on)374 void SharedStateData::SetInfoBox( bool on )
375 {
376 	if ( on )
377 	{
378 		infoBoxBack->SetVisible( true );
379 	}
380 	else
381 	{
382 		infoBoxBack->SetVisible( false );
383 		return;
384 	}
385 
386 	char buf[256];
387 
388 	for( int i=INFO_CLEAR_START; i<=INFO_CLEAR_END; ++i )
389 	{
390 		infoBox->SetText16( 0, i );
391 	}
392 
393 	if ( currentTile )
394 	{
395 		infoBox->SetTextChar( currentTile->Name().c_str(), INFO_TILE );
396 		sprintf( buf, "%d x %d", currentTile->Size(), currentTile->Size() );
397 		infoBox->SetTextChar( buf, INFO_TILE_SIZE );
398 
399 		if ( currentTile->Size() == 0 )
400 			infoBox->SetTextChar( "Creating new tile", INFO_CREATING );
401 		else
402 			infoBox->SetText16( 0, INFO_CREATING );
403 	}
404 	else if ( currentFrame || currentAction || currentSprite )
405 	{
406 		if ( currentFrame )
407 		{
408 			// Which frame is this?
409 			int frameNum = 0;
410 			int frameCount = 0;
411 			GlSListIterator<EdWidget*> it( currentFrame->Parent()->children );
412 
413 			for( it.Begin(); !it.Done(); it.Next() )
414 			{
415 				if ( it.Current() == currentFrame )
416 					frameNum = frameCount;
417 				++frameCount;
418 			}
419 			char buf[64];
420 
421 			KrDom::Frame frameData;
422 			frameData = currentFrame->GetFrameData();
423 
424 			//if ( frameData.isotile > 0 )
425 			//	sprintf( buf, "%d of %d Iso=%d", frameNum, frameCount, frameData.isotile );
426 			//else
427 
428 			sprintf( buf, "%d of %d", frameNum, frameCount );
429 
430 			infoBox->SetTextChar( buf, INFO_FRAME );
431 			infoBox->SetText16( 0, INFO_CREATING );
432 
433 			sprintf( buf, "%dx%d hotspot %d,%d",
434 						  frameData.width, frameData.height,
435 						  frameData.hotspotX, frameData.hotspotY );
436 			infoBox->SetTextChar( buf, INFO_FRAME_SIZE );
437 		}
438 
439 		if ( currentAction )
440 		{
441 			sprintf( buf, "%s", currentAction->Name().c_str() );
442 
443 			infoBox->SetTextChar( buf, INFO_ACTION );
444 
445 			if ( currentAction->children.Count() == 0 )
446 				infoBox->SetTextChar( "Creating new action.", INFO_CREATING );
447 		}
448 
449 		if ( currentSprite )
450 		{
451 			infoBox->SetTextChar( currentSprite->Name().c_str(),
452 								  INFO_SPRITE );
453 			if ( currentSprite->children.Count() == 0 )
454 				infoBox->SetTextChar( "Creating new sprite.", INFO_CREATING );
455 		}
456 	}
457 	else
458 	{
459 		infoBox->SetTextChar( "Info about selection", 0 );
460 		infoBox->SetTextChar( "is shown here.", 1 );
461 	}
462 }
463 
464 
SetInfoBoxMouse(int x,int y)465 void SharedStateData::SetInfoBoxMouse( int x, int y )
466 {
467 	char buf[64];
468 	sprintf( buf, "pos=(%d,%d)", x, y );
469 	infoBox->SetTextChar( buf, INFO_MOUSE );
470 }
471