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