TickHook: Fix crash when TickHook isn't set.
[gemrb.git] / gemrb / plugins / CHUImporter / CHUImporter.cpp
blob5f965b7cf0030f1c31e2a1da904ef9ae7dca9296
1 /* GemRB - Infinity Engine Emulator
2 * Copyright (C) 2003 The GemRB Project
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 #include "CHUImporter.h"
23 #include "RGBAColor.h"
24 #include "win32def.h"
26 #include "AnimationFactory.h"
27 #include "GameData.h"
28 #include "ImageMgr.h"
29 #include "Interface.h"
30 #include "GUI/Button.h"
31 #include "GUI/Label.h"
32 #include "GUI/Progressbar.h"
33 #include "GUI/ScrollBar.h"
34 #include "GUI/Slider.h"
35 #include "GUI/TextArea.h"
36 #include "GUI/TextEdit.h"
38 CHUImporter::CHUImporter()
40 str = NULL;
41 autoFree = false;
44 CHUImporter::~CHUImporter()
46 if (autoFree) {
47 delete str;
51 /** This function loads all available windows from the 'stream' parameter. */
52 bool CHUImporter::Open(DataStream* stream, bool autoFree)
54 if (stream == NULL) {
55 return false;
57 if (this->autoFree) {
58 delete str;
60 str = stream;
61 this->autoFree = autoFree;
62 char Signature[8];
63 str->Read( Signature, 8 );
64 if (strncmp( Signature, "CHUIV1 ", 8 ) != 0) {
65 printMessage( "CHUImporter","Not a Valid CHU File\n",LIGHT_RED );
66 return false;
68 str->ReadDword( &WindowCount );
69 str->ReadDword( &CTOffset );
70 str->ReadDword( &WEOffset );
71 return true;
74 /** Returns the i-th window in the Previously Loaded Stream */
75 Window* CHUImporter::GetWindow(unsigned int wid)
77 ieWord WindowID, XPos, YPos, Width, Height, BackGround;
78 ieWord ControlsCount, FirstControl;
79 ieResRef MosFile;
80 unsigned int i;
82 bool found = false;
83 for (unsigned int c = 0; c < WindowCount; c++) {
84 str->Seek( WEOffset + ( 0x1c * c ), GEM_STREAM_START );
85 str->ReadWord( &WindowID );
86 if (WindowID == wid) {
87 found = true;
88 break;
91 if (!found) {
92 return NULL;
94 str->Seek( 2, GEM_CURRENT_POS );
95 str->ReadWord( &XPos );
96 str->ReadWord( &YPos );
97 str->ReadWord( &Width );
98 str->ReadWord( &Height );
99 str->ReadWord( &BackGround );
100 str->ReadWord( &ControlsCount );
101 str->ReadResRef( MosFile );
102 str->ReadWord( &FirstControl );
104 Window* win = new Window( WindowID, XPos, YPos, Width, Height );
105 if (BackGround == 1) {
106 ResourceHolder<ImageMgr> mos(MosFile);
107 if (mos != NULL) {
108 win->SetBackGround( mos->GetSprite2D(), true );
109 } else
110 printMessage( "CHUImporter","Cannot Load BackGround, skipping\n",YELLOW );
112 if (!core->IsAvailable( IE_BAM_CLASS_ID )) {
113 printMessage( "CHUImporter","No BAM Importer Available, skipping controls\n",LIGHT_RED );
114 return win;
116 for (i = 0; i < ControlsCount; i++) {
117 str->Seek( CTOffset + ( ( FirstControl + i ) * 8 ), GEM_STREAM_START );
118 ieDword COffset, CLength, ControlID;
119 ieWord XPos, YPos, Width, Height;
120 ieByte ControlType, temp;
121 str->ReadDword( &COffset );
122 str->ReadDword( &CLength );
123 str->Seek( COffset, GEM_STREAM_START );
124 str->ReadDword( &ControlID );
125 str->ReadWord( &XPos );
126 str->ReadWord( &YPos );
127 str->ReadWord( &Width );
128 str->ReadWord( &Height );
129 str->Read( &ControlType, 1 );
130 str->Read( &temp, 1 );
131 switch (ControlType) {
132 case IE_GUI_BUTTON:
134 //Button
135 Button* btn = new Button( );
136 btn->ControlID = ControlID;
137 btn->XPos = XPos;
138 btn->YPos = YPos;
139 btn->Width = Width;
140 btn->Height = Height;
141 btn->ControlType = ControlType;
142 ieResRef BAMFile;
143 ieByte Cycle, tmp;
144 ieDword Flags;
145 ieByte UnpressedIndex, x1;
146 ieByte PressedIndex, x2;
147 ieByte SelectedIndex, y1;
148 ieByte DisabledIndex, y2;
149 str->ReadResRef( BAMFile );
150 str->Read( &Cycle, 1 );
151 str->Read( &tmp, 1 );
152 Flags = ((ieDword) tmp)<<8;
153 str->Read( &UnpressedIndex, 1 );
154 str->Read( &x1, 1 );
155 str->Read( &PressedIndex, 1 );
156 str->Read( &x2, 1 );
157 str->Read( &SelectedIndex, 1 );
158 str->Read( &y1, 1 );
159 str->Read( &DisabledIndex, 1 );
160 str->Read( &y2, 1 );
161 btn->Owner = win;
162 /** Justification comes from the .chu, other bits are set by script */
163 if (!Width) {
164 btn->SetFlags(IE_GUI_BUTTON_NO_IMAGE, BM_OR);
166 if (core->HasFeature(GF_UPPER_BUTTON_TEXT)) {
167 btn->SetFlags(IE_GUI_BUTTON_CAPS, BM_OR);
170 btn->SetFlags( Flags, BM_OR );
171 if (Flags & IE_GUI_BUTTON_ANCHOR) {
172 btn->SetAnchor(x1 | (x2<<8), y1 | (y2<<8));
175 if (strnicmp( BAMFile, "guictrl\0", 8 ) == 0) {
176 if (UnpressedIndex == 0) {
177 //printMessage("CHUImporter", "Special Button Control, Skipping Image Loading\n",GREEN );
178 win->AddControl( btn );
179 break;
182 AnimationFactory* bam = ( AnimationFactory* )
183 gamedata->GetFactoryResource( BAMFile,
184 IE_BAM_CLASS_ID, IE_NORMAL );
185 if (!bam ) {
186 printMessage( "CHUImporter","Cannot Load Button Images, skipping control\n",LIGHT_RED );
187 /* IceWind Dale 2 has fake BAM ResRefs for some Buttons,
188 this will handle bad ResRefs */
189 win->AddControl( btn );
190 break;
192 /** Cycle is only a byte for buttons */
193 Sprite2D* tspr = bam->GetFrame( UnpressedIndex, (unsigned char) Cycle );
194 btn->SetImage( IE_GUI_BUTTON_UNPRESSED, tspr );
195 tspr = bam->GetFrame( PressedIndex, Cycle );
196 btn->SetImage( IE_GUI_BUTTON_PRESSED, tspr );
197 //ignorebuttonframes is a terrible hack
198 if (core->HasFeature( GF_IGNORE_BUTTON_FRAMES) ) {
199 if (bam->GetCycleSize(Cycle) == 4 )
200 SelectedIndex=2;
202 tspr = bam->GetFrame( SelectedIndex, (unsigned char) Cycle );
203 btn->SetImage( IE_GUI_BUTTON_SELECTED, tspr );
204 if (core->HasFeature( GF_IGNORE_BUTTON_FRAMES) ) {
205 if (bam->GetCycleSize( (unsigned char) Cycle) == 4 )
206 DisabledIndex=3;
208 tspr = bam->GetFrame( DisabledIndex, (unsigned char) Cycle );
209 btn->SetImage( IE_GUI_BUTTON_DISABLED, tspr );
210 win->AddControl( btn );
212 break;
214 case IE_GUI_PROGRESSBAR:
216 //GemRB specific, progressbar
217 ieResRef MOSFile, MOSFile2;
218 ieResRef BAMFile;
219 ieWord KnobXPos, KnobYPos;
220 ieWord CapXPos, CapYPos;
221 ieWord KnobStepsCount;
222 ieWord Cycle;
224 str->ReadResRef( MOSFile );
225 str->ReadResRef( MOSFile2 );
226 str->ReadResRef( BAMFile );
227 str->ReadWord( &KnobStepsCount );
228 str->ReadWord( &Cycle );
229 str->ReadWord( &KnobXPos );
230 str->ReadWord( &KnobYPos );
231 str->ReadWord( &CapXPos );
232 str->ReadWord( &CapYPos );
233 Progressbar* pbar = new Progressbar(KnobStepsCount, true );
234 pbar->ControlID = ControlID;
235 pbar->XPos = XPos;
236 pbar->YPos = YPos;
237 pbar->ControlType = ControlType;
238 pbar->Width = Width;
239 pbar->Height = Height;
240 pbar->SetSliderPos( KnobXPos, KnobYPos, CapXPos, CapYPos );
242 Sprite2D* img = NULL;
243 Sprite2D* img2 = NULL;
244 if ( MOSFile[0] ) {
245 ResourceHolder<ImageMgr> mos(MOSFile);
246 img = mos->GetSprite2D();
248 if ( MOSFile2[0] ) {
249 ResourceHolder<ImageMgr> mos(MOSFile2);
250 img2 = mos->GetSprite2D();
253 pbar->SetImage( img, img2 );
254 if( KnobStepsCount ) {
255 /* getting the bam */
256 AnimationFactory *af = (AnimationFactory *)
257 gamedata->GetFactoryResource(BAMFile, IE_BAM_CLASS_ID );
258 /* Getting the Cycle of the bam */
259 pbar->SetAnimation(af->GetCycle( Cycle & 0xff ) );
261 else {
262 ResourceHolder<ImageMgr> mos(BAMFile);
263 Sprite2D* img3 = mos->GetSprite2D();
264 pbar->SetBarCap( img3 );
266 win->AddControl( pbar );
268 break;
269 case IE_GUI_SLIDER:
271 //Slider
272 ieResRef MOSFile, BAMFile;
273 ieWord Cycle, Knob, GrabbedKnob;
274 ieWord KnobXPos, KnobYPos, KnobStep, KnobStepsCount;
275 str->ReadResRef( MOSFile );
276 str->ReadResRef( BAMFile );
277 str->ReadWord( &Cycle );
278 str->ReadWord( &Knob );
279 str->ReadWord( &GrabbedKnob );
280 str->ReadWord( &KnobXPos );
281 str->ReadWord( &KnobYPos );
282 str->ReadWord( &KnobStep );
283 str->ReadWord( &KnobStepsCount );
284 Slider* sldr = new Slider( KnobXPos, KnobYPos, KnobStep, KnobStepsCount, true );
285 sldr->ControlID = ControlID;
286 sldr->XPos = XPos;
287 sldr->YPos = YPos;
288 sldr->ControlType = ControlType;
289 sldr->Width = Width;
290 sldr->Height = Height;
291 ResourceHolder<ImageMgr> mos(MOSFile);
292 Sprite2D* img = mos->GetSprite2D();
293 sldr->SetImage( IE_GUI_SLIDER_BACKGROUND, img);
295 AnimationFactory* bam = ( AnimationFactory* )
296 gamedata->GetFactoryResource( BAMFile,
297 IE_BAM_CLASS_ID, IE_NORMAL );
298 if( bam ) {
299 img = bam->GetFrame( Knob, 0 );
300 sldr->SetImage( IE_GUI_SLIDER_KNOB, img );
301 img = bam->GetFrame( GrabbedKnob, 0 );
302 sldr->SetImage( IE_GUI_SLIDER_GRABBEDKNOB, img );
304 else {
305 sldr->SetState(IE_GUI_SLIDER_BACKGROUND);
307 win->AddControl( sldr );
309 break;
311 case IE_GUI_EDIT:
313 //Text Edit
314 ieResRef BGMos;
315 ieResRef FontResRef, CursorResRef;
316 ieWord maxInput;
317 ieWord CurCycle, CurFrame;
318 ieWord PosX, PosY;
320 str->ReadResRef( BGMos );
321 str->Seek( 16, GEM_CURRENT_POS );
322 str->ReadResRef( CursorResRef );
323 str->ReadWord( &CurCycle );
324 str->ReadWord( &CurFrame );
325 str->ReadWord( &PosX );
326 str->ReadWord( &PosY );
327 str->Seek( 4, GEM_CURRENT_POS );
328 str->ReadResRef( FontResRef );
329 str->Seek( 34, GEM_CURRENT_POS );
330 str->ReadWord( &maxInput );
331 Font* fnt = core->GetFont( FontResRef );
333 AnimationFactory* bam = ( AnimationFactory* )
334 gamedata->GetFactoryResource( CursorResRef,
335 IE_BAM_CLASS_ID,
336 IE_NORMAL );
337 Sprite2D *cursor = NULL;
338 if (bam) {
339 cursor = bam->GetFrame( CurCycle, CurFrame );
342 ResourceHolder<ImageMgr> mos(BGMos);
343 Sprite2D *img = NULL;
344 if(mos) {
345 img = mos->GetSprite2D();
348 TextEdit* te = new TextEdit( maxInput, PosX, PosY );
349 te->ControlID = ControlID;
350 te->XPos = XPos;
351 te->YPos = YPos;
352 te->Width = Width;
353 te->Height = Height;
354 te->ControlType = ControlType;
355 te->SetFont( fnt );
356 te->SetCursor( cursor );
357 te->SetBackGround( img );
358 win->AddControl( te );
360 break;
362 case IE_GUI_TEXTAREA:
364 //Text Area
365 ieResRef FontResRef, InitResRef;
366 Color fore, init, back;
367 ieWord SBID;
368 str->ReadResRef( FontResRef );
369 str->ReadResRef( InitResRef );
370 Font* fnt = core->GetFont( FontResRef );
371 Font* ini = core->GetFont( InitResRef );
372 str->Read( &fore, 4 );
373 str->Read( &init, 4 );
374 str->Read( &back, 4 );
375 str->ReadWord( &SBID );
376 TextArea* ta = new TextArea( fore, init, back );
377 ta->ControlID = ControlID;
378 ta->XPos = XPos;
379 ta->YPos = YPos;
380 ta->Width = Width;
381 ta->Height = Height;
382 ta->ControlType = ControlType;
383 ta->SetFonts( ini, fnt );
384 win->AddControl( ta );
385 if (SBID != 0xffff)
386 win->Link( SBID, ( unsigned short ) ControlID );
388 break;
390 case IE_GUI_LABEL:
392 //Label
393 ieResRef FontResRef;
394 ieStrRef StrRef;
395 RevColor fore, back;
396 ieWord alignment;
397 str->ReadDword( &StrRef );
398 str->ReadResRef( FontResRef );
399 Font* fnt = core->GetFont( FontResRef );
400 str->Read( &fore, 4 );
401 str->Read( &back, 4 );
402 str->ReadWord( &alignment );
403 Label* lab = new Label( fnt );
404 lab->ControlID = ControlID;
405 lab->XPos = XPos;
406 lab->YPos = YPos;
407 lab->Width = Width;
408 lab->Height = Height;
409 lab->ControlType = ControlType;
410 char* str = core->GetString( StrRef );
411 lab->SetText( str );
412 core->FreeString( str );
413 if (alignment & 1) {
414 lab->useRGB = true;
415 Color f, b;
416 f.r = fore.b;
417 f.g = fore.g;
418 f.b = fore.r;
419 f.a = 0;
420 b.r = back.b;
421 b.g = back.g;
422 b.b = back.r;
423 b.a = 0;
424 lab->SetColor( f, b );
426 int align = IE_FONT_ALIGN_CENTER;
427 if (( alignment & 0x10 ) != 0) {
428 align = IE_FONT_ALIGN_RIGHT;
429 goto endvertical;
431 if (( alignment & 0x04 ) != 0) {
432 goto endvertical;
434 if (( alignment & 0x08 ) != 0) {
435 align = IE_FONT_ALIGN_LEFT;
436 goto endvertical;
438 endvertical:
439 if (( alignment & 0x20 ) != 0) {
440 align |= IE_FONT_ALIGN_TOP;
441 goto endalign;
443 if (( alignment & 0x80 ) != 0) {
444 align |= IE_FONT_ALIGN_BOTTOM;
445 } else {
446 align |= IE_FONT_ALIGN_MIDDLE;
448 endalign:
449 lab->SetAlignment( align );
450 win->AddControl( lab );
452 break;
454 case IE_GUI_SCROLLBAR:
456 //ScrollBar
457 ieResRef BAMResRef;
458 ieWord Cycle, Trough, Slider, TAID;
459 ieWord UpUnPressed, UpPressed;
460 ieWord DownUnPressed, DownPressed;
462 str->ReadResRef( BAMResRef );
463 str->ReadWord( &Cycle );
464 str->ReadWord( &UpUnPressed );
465 str->ReadWord( &UpPressed );
466 str->ReadWord( &DownUnPressed );
467 str->ReadWord( &DownPressed );
468 str->ReadWord( &Trough );
469 str->ReadWord( &Slider );
470 str->ReadWord( &TAID );
471 ScrollBar* sbar = new ScrollBar();
472 sbar->ControlID = ControlID;
473 sbar->XPos = XPos;
474 sbar->YPos = YPos;
475 sbar->Width = Width;
476 sbar->Height = Height;
477 sbar->ControlType = ControlType;
479 AnimationFactory* bam = ( AnimationFactory* )
480 gamedata->GetFactoryResource( BAMResRef,
481 IE_BAM_CLASS_ID, IE_NORMAL );
482 if (bam) {
483 sbar->SetImage( IE_GUI_SCROLLBAR_UP_UNPRESSED,
484 bam->GetFrame( UpUnPressed, Cycle ) );
485 sbar->SetImage( IE_GUI_SCROLLBAR_UP_PRESSED,
486 bam->GetFrame( UpPressed, Cycle ) );
487 sbar->SetImage( IE_GUI_SCROLLBAR_DOWN_UNPRESSED,
488 bam->GetFrame( DownUnPressed, Cycle ) );
489 sbar->SetImage( IE_GUI_SCROLLBAR_DOWN_PRESSED,
490 bam->GetFrame( DownPressed, Cycle ) );
491 sbar->SetImage( IE_GUI_SCROLLBAR_TROUGH,
492 bam->GetFrame( Trough, Cycle ) );
493 sbar->SetImage( IE_GUI_SCROLLBAR_SLIDER,
494 bam->GetFrame( Slider, Cycle ) );
496 win->AddControl( sbar );
497 if (TAID != 0xffff)
498 win->Link( ( unsigned short ) ControlID, TAID );
500 break;
502 default:
503 printMessage( "CHUImporter","Control Not Supported\n",LIGHT_RED );
506 return win;
508 /** Returns the number of available windows */
509 unsigned int CHUImporter::GetWindowsCount()
511 return WindowCount;
514 #include "plugindef.h"
516 GEMRB_PLUGIN(0x23A7F6CA, "CHU File Importer")
517 PLUGIN_CLASS(IE_CHU_CLASS_ID, CHUImporter)
518 END_PLUGIN()