Plugin: Call Plugin::release directly, rather than through Interface and PluginMgr.
[gemrb.git] / gemrb / plugins / CHUImporter / CHUImporter.cpp
blob09872ff89d8c254c39e33c76437a53196e16633c
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 "win32def.h"
22 #include "CHUImporter.h"
23 #include "Interface.h"
24 #include "Button.h"
25 #include "Label.h"
26 #include "Progressbar.h"
27 #include "Slider.h"
28 #include "ScrollBar.h"
29 #include "TextArea.h"
30 #include "TextEdit.h"
31 #include "AnimationFactory.h"
32 #include "ImageMgr.h"
33 #include "RGBAColor.h"
35 CHUImporter::CHUImporter()
37 str = NULL;
38 autoFree = false;
41 CHUImporter::~CHUImporter()
43 if (autoFree) {
44 delete str;
48 /** This function loads all available windows from the 'stream' parameter. */
49 bool CHUImporter::Open(DataStream* stream, bool autoFree)
51 if (stream == NULL) {
52 return false;
54 if (this->autoFree) {
55 delete str;
57 str = stream;
58 this->autoFree = autoFree;
59 char Signature[8];
60 str->Read( Signature, 8 );
61 if (strncmp( Signature, "CHUIV1 ", 8 ) != 0) {
62 printMessage( "CHUImporter","Not a Valid CHU File\n",LIGHT_RED );
63 return false;
65 str->ReadDword( &WindowCount );
66 str->ReadDword( &CTOffset );
67 str->ReadDword( &WEOffset );
68 return true;
71 /** Returns the i-th window in the Previously Loaded Stream */
72 Window* CHUImporter::GetWindow(unsigned int wid)
74 ieWord WindowID, XPos, YPos, Width, Height, BackGround;
75 ieWord ControlsCount, FirstControl;
76 ieResRef MosFile;
77 unsigned int i;
79 bool found = false;
80 for (unsigned int c = 0; c < WindowCount; c++) {
81 str->Seek( WEOffset + ( 0x1c * c ), GEM_STREAM_START );
82 str->ReadWord( &WindowID );
83 if (WindowID == wid) {
84 found = true;
85 break;
88 if (!found) {
89 return NULL;
91 str->Seek( 2, GEM_CURRENT_POS );
92 str->ReadWord( &XPos );
93 str->ReadWord( &YPos );
94 str->ReadWord( &Width );
95 str->ReadWord( &Height );
96 str->ReadWord( &BackGround );
97 str->ReadWord( &ControlsCount );
98 str->ReadResRef( MosFile );
99 str->ReadWord( &FirstControl );
101 Window* win = new Window( WindowID, XPos, YPos, Width, Height );
102 if (BackGround == 1) {
103 ImageMgr* mos = ( ImageMgr* )
104 gamedata->GetResource( MosFile, &ImageMgr::ID );
105 if (mos != NULL) {
106 win->SetBackGround( mos->GetSprite2D(), true );
107 mos->release();
108 } else
109 printMessage( "CHUImporter","Cannot Load BackGround, skipping\n",YELLOW );
111 if (!core->IsAvailable( IE_BAM_CLASS_ID )) {
112 printMessage( "CHUImporter","No BAM Importer Available, skipping controls\n",LIGHT_RED );
113 return win;
115 for (i = 0; i < ControlsCount; i++) {
116 str->Seek( CTOffset + ( ( FirstControl + i ) * 8 ), GEM_STREAM_START );
117 ieDword COffset, CLength, ControlID;
118 ieWord XPos, YPos, Width, Height;
119 ieByte ControlType, temp;
120 str->ReadDword( &COffset );
121 str->ReadDword( &CLength );
122 str->Seek( COffset, GEM_STREAM_START );
123 str->ReadDword( &ControlID );
124 str->ReadWord( &XPos );
125 str->ReadWord( &YPos );
126 str->ReadWord( &Width );
127 str->ReadWord( &Height );
128 str->Read( &ControlType, 1 );
129 str->Read( &temp, 1 );
130 switch (ControlType) {
131 case IE_GUI_BUTTON:
133 //Button
134 Button* btn = new Button( );
135 btn->ControlID = ControlID;
136 btn->XPos = XPos;
137 btn->YPos = YPos;
138 btn->Width = Width;
139 btn->Height = Height;
140 btn->ControlType = ControlType;
141 ieResRef BAMFile;
142 ieWord Cycle, UnpressedIndex, PressedIndex,
143 SelectedIndex, DisabledIndex;
144 str->ReadResRef( BAMFile );
145 str->ReadWord( &Cycle );
146 str->ReadWord( &UnpressedIndex );
147 str->ReadWord( &PressedIndex );
148 str->ReadWord( &SelectedIndex );
149 str->ReadWord( &DisabledIndex );
150 btn->Owner = win;
151 /** Justification comes from the .chu, other bits are set by script */
152 if (!Width) {
153 btn->SetFlags(IE_GUI_BUTTON_NO_IMAGE, BM_OR);
155 if (core->HasFeature(GF_UPPER_BUTTON_TEXT)) {
156 btn->SetFlags(IE_GUI_BUTTON_CAPS, BM_OR);
159 btn->SetFlags( Cycle&0xff00, BM_OR );
160 if (strnicmp( BAMFile, "guictrl\0", 8 ) == 0) {
161 if (UnpressedIndex == 0) {
162 printMessage("CHUImporter", "Special Button Control, Skipping Image Loading\n",GREEN );
163 win->AddControl( btn );
164 break;
167 AnimationFactory* bam = ( AnimationFactory* )
168 gamedata->GetFactoryResource( BAMFile,
169 IE_BAM_CLASS_ID, IE_NORMAL );
170 if (!bam ) {
171 printMessage( "CHUImporter","Cannot Load Button Images, skipping control\n",LIGHT_RED );
172 /* IceWind Dale 2 has fake BAM ResRefs for some Buttons,
173 this will handle bad ResRefs */
174 win->AddControl( btn );
175 break;
177 /** Cycle is only a byte for buttons */
178 Sprite2D* tspr = bam->GetFrame( UnpressedIndex, (unsigned char) Cycle );
179 btn->SetImage( IE_GUI_BUTTON_UNPRESSED, tspr );
180 tspr = bam->GetFrame( PressedIndex, (unsigned char) Cycle );
181 btn->SetImage( IE_GUI_BUTTON_PRESSED, tspr );
182 //ignorebuttonframes is a terrible hack
183 if (core->HasFeature( GF_IGNORE_BUTTON_FRAMES) ) {
184 if (bam->GetCycleSize( (unsigned char) Cycle) == 4 )
185 SelectedIndex=2;
187 tspr = bam->GetFrame( SelectedIndex, (unsigned char) Cycle );
188 btn->SetImage( IE_GUI_BUTTON_SELECTED, tspr );
189 if (core->HasFeature( GF_IGNORE_BUTTON_FRAMES) ) {
190 if (bam->GetCycleSize( (unsigned char) Cycle) == 4 )
191 DisabledIndex=3;
193 tspr = bam->GetFrame( DisabledIndex, (unsigned char) Cycle );
194 btn->SetImage( IE_GUI_BUTTON_DISABLED, tspr );
195 win->AddControl( btn );
197 break;
199 case IE_GUI_PROGRESSBAR:
201 //GemRB specific, progressbar
202 ieResRef MOSFile, MOSFile2;
203 ieResRef BAMFile;
204 ieWord KnobXPos, KnobYPos;
205 ieWord CapXPos, CapYPos;
206 ieWord KnobStepsCount;
207 ieWord Cycle;
209 str->ReadResRef( MOSFile );
210 str->ReadResRef( MOSFile2 );
211 str->ReadResRef( BAMFile );
212 str->ReadWord( &KnobStepsCount );
213 str->ReadWord( &Cycle );
214 str->ReadWord( &KnobXPos );
215 str->ReadWord( &KnobYPos );
216 str->ReadWord( &CapXPos );
217 str->ReadWord( &CapYPos );
218 Progressbar* pbar = new Progressbar(KnobStepsCount, true );
219 pbar->ControlID = ControlID;
220 pbar->XPos = XPos;
221 pbar->YPos = YPos;
222 pbar->ControlType = ControlType;
223 pbar->Width = Width;
224 pbar->Height = Height;
225 pbar->SetSliderPos( KnobXPos, KnobYPos, CapXPos, CapYPos );
227 Sprite2D* img = NULL;
228 Sprite2D* img2 = NULL;
229 if ( MOSFile[0] ) {
230 ImageMgr* mos = ( ImageMgr* )
231 gamedata->GetResource( MOSFile, &ImageMgr::ID );
232 img = mos->GetSprite2D();
233 mos->release();
235 if ( MOSFile2[0] ) {
236 ImageMgr* mos = ( ImageMgr* )
237 gamedata->GetResource( MOSFile2, &ImageMgr::ID );
238 img2 = mos->GetSprite2D();
239 mos->release();
242 pbar->SetImage( img, img2 );
243 if( KnobStepsCount ) {
244 /* getting the bam */
245 AnimationFactory *af = (AnimationFactory *)
246 gamedata->GetFactoryResource(BAMFile, IE_BAM_CLASS_ID );
247 /* Getting the Cycle of the bam */
248 pbar->SetAnimation(af->GetCycle( Cycle & 0xff ) );
250 else {
251 ImageMgr* mos = ( ImageMgr* )
252 gamedata->GetResource( BAMFile, &ImageMgr::ID );
253 Sprite2D* img3 = mos->GetSprite2D();
254 pbar->SetBarCap( img3 );
255 mos->release();
257 win->AddControl( pbar );
259 break;
260 case IE_GUI_SLIDER:
262 //Slider
263 ieResRef MOSFile, BAMFile;
264 ieWord Cycle, Knob, GrabbedKnob;
265 ieWord KnobXPos, KnobYPos, KnobStep, KnobStepsCount;
266 str->ReadResRef( MOSFile );
267 str->ReadResRef( BAMFile );
268 str->ReadWord( &Cycle );
269 str->ReadWord( &Knob );
270 str->ReadWord( &GrabbedKnob );
271 str->ReadWord( &KnobXPos );
272 str->ReadWord( &KnobYPos );
273 str->ReadWord( &KnobStep );
274 str->ReadWord( &KnobStepsCount );
275 Slider* sldr = new Slider( KnobXPos, KnobYPos, KnobStep, KnobStepsCount, true );
276 sldr->ControlID = ControlID;
277 sldr->XPos = XPos;
278 sldr->YPos = YPos;
279 sldr->ControlType = ControlType;
280 sldr->Width = Width;
281 sldr->Height = Height;
282 ImageMgr* mos = ( ImageMgr* )
283 gamedata->GetResource( MOSFile, &ImageMgr::ID );
284 Sprite2D* img = mos->GetSprite2D();
285 sldr->SetImage( IE_GUI_SLIDER_BACKGROUND, img);
286 mos->release();
288 AnimationFactory* bam = ( AnimationFactory* )
289 gamedata->GetFactoryResource( BAMFile,
290 IE_BAM_CLASS_ID, IE_NORMAL );
291 if( bam ) {
292 img = bam->GetFrame( Knob, 0 );
293 sldr->SetImage( IE_GUI_SLIDER_KNOB, img );
294 img = bam->GetFrame( GrabbedKnob, 0 );
295 sldr->SetImage( IE_GUI_SLIDER_GRABBEDKNOB, img );
297 else {
298 sldr->SetState(IE_GUI_SLIDER_BACKGROUND);
300 win->AddControl( sldr );
302 break;
304 case IE_GUI_EDIT:
306 //Text Edit
307 ieResRef BGMos;
308 ieResRef FontResRef, CursorResRef;
309 ieWord maxInput;
310 ieWord CurCycle, CurFrame;
311 ieWord PosX, PosY;
313 str->ReadResRef( BGMos );
314 str->Seek( 16, GEM_CURRENT_POS );
315 str->ReadResRef( CursorResRef );
316 str->ReadWord( &CurCycle );
317 str->ReadWord( &CurFrame );
318 str->ReadWord( &PosX );
319 str->ReadWord( &PosY );
320 str->Seek( 4, GEM_CURRENT_POS );
321 str->ReadResRef( FontResRef );
322 str->Seek( 34, GEM_CURRENT_POS );
323 str->ReadWord( &maxInput );
324 Font* fnt = core->GetFont( FontResRef );
326 AnimationFactory* bam = ( AnimationFactory* )
327 gamedata->GetFactoryResource( CursorResRef,
328 IE_BAM_CLASS_ID,
329 IE_NORMAL );
330 Sprite2D *cursor = NULL;
331 if (bam) {
332 cursor = bam->GetFrame( CurCycle, CurFrame );
335 ImageMgr* mos = ( ImageMgr* )
336 gamedata->GetResource( BGMos, &ImageMgr::ID );
337 Sprite2D *img = NULL;
338 if(mos) {
339 img = mos->GetSprite2D();
340 mos->release();
343 TextEdit* te = new TextEdit( maxInput, PosX, PosY );
344 te->ControlID = ControlID;
345 te->XPos = XPos;
346 te->YPos = YPos;
347 te->Width = Width;
348 te->Height = Height;
349 te->ControlType = ControlType;
350 te->SetFont( fnt );
351 te->SetCursor( cursor );
352 te->SetBackGround( img );
353 win->AddControl( te );
355 break;
357 case IE_GUI_TEXTAREA:
359 //Text Area
360 ieResRef FontResRef, InitResRef;
361 Color fore, init, back;
362 ieWord SBID;
363 str->ReadResRef( FontResRef );
364 str->ReadResRef( InitResRef );
365 Font* fnt = core->GetFont( FontResRef );
366 Font* ini = core->GetFont( InitResRef );
367 str->Read( &fore, 4 );
368 str->Read( &init, 4 );
369 str->Read( &back, 4 );
370 str->ReadWord( &SBID );
371 TextArea* ta = new TextArea( fore, init, back );
372 ta->ControlID = ControlID;
373 ta->XPos = XPos;
374 ta->YPos = YPos;
375 ta->Width = Width;
376 ta->Height = Height;
377 ta->ControlType = ControlType;
378 ta->SetFonts( ini, fnt );
379 win->AddControl( ta );
380 if (SBID != 0xffff)
381 win->Link( SBID, ( unsigned short ) ControlID );
383 break;
385 case IE_GUI_LABEL:
387 //Label
388 ieResRef FontResRef;
389 ieStrRef StrRef;
390 RevColor fore, back;
391 ieWord alignment;
392 str->ReadDword( &StrRef );
393 str->ReadResRef( FontResRef );
394 Font* fnt = core->GetFont( FontResRef );
395 str->Read( &fore, 4 );
396 str->Read( &back, 4 );
397 str->ReadWord( &alignment );
398 Label* lab = new Label( fnt );
399 lab->ControlID = ControlID;
400 lab->XPos = XPos;
401 lab->YPos = YPos;
402 lab->Width = Width;
403 lab->Height = Height;
404 lab->ControlType = ControlType;
405 char* str = core->GetString( StrRef );
406 lab->SetText( str );
407 core->FreeString( str );
408 if (alignment & 1) {
409 lab->useRGB = true;
410 Color f, b;
411 f.r = fore.b;
412 f.g = fore.g;
413 f.b = fore.r;
414 f.a = 0;
415 b.r = back.b;
416 b.g = back.g;
417 b.b = back.r;
418 b.a = 0;
419 lab->SetColor( f, b );
421 int align = IE_FONT_ALIGN_CENTER;
422 if (( alignment & 0x10 ) != 0) {
423 align = IE_FONT_ALIGN_RIGHT;
424 goto endvertical;
426 if (( alignment & 0x04 ) != 0) {
427 goto endvertical;
429 if (( alignment & 0x08 ) != 0) {
430 align = IE_FONT_ALIGN_LEFT;
431 goto endvertical;
433 endvertical:
434 if (( alignment & 0x20 ) != 0) {
435 align |= IE_FONT_ALIGN_TOP;
436 goto endalign;
438 if (( alignment & 0x80 ) != 0) {
439 align |= IE_FONT_ALIGN_BOTTOM;
440 } else {
441 align |= IE_FONT_ALIGN_MIDDLE;
443 endalign:
444 lab->SetAlignment( align );
445 win->AddControl( lab );
447 break;
449 case IE_GUI_SCROLLBAR:
451 //ScrollBar
452 ieResRef BAMResRef;
453 ieWord Cycle, Trough, Slider, TAID;
454 ieWord UpUnPressed, UpPressed;
455 ieWord DownUnPressed, DownPressed;
457 str->ReadResRef( BAMResRef );
458 str->ReadWord( &Cycle );
459 str->ReadWord( &UpUnPressed );
460 str->ReadWord( &UpPressed );
461 str->ReadWord( &DownUnPressed );
462 str->ReadWord( &DownPressed );
463 str->ReadWord( &Trough );
464 str->ReadWord( &Slider );
465 str->ReadWord( &TAID );
466 ScrollBar* sbar = new ScrollBar();
467 sbar->ControlID = ControlID;
468 sbar->XPos = XPos;
469 sbar->YPos = YPos;
470 sbar->Width = Width;
471 sbar->Height = Height;
472 sbar->ControlType = ControlType;
474 AnimationFactory* bam = ( AnimationFactory* )
475 gamedata->GetFactoryResource( BAMResRef,
476 IE_BAM_CLASS_ID, IE_NORMAL );
477 if (bam) {
478 sbar->SetImage( IE_GUI_SCROLLBAR_UP_UNPRESSED,
479 bam->GetFrame( UpUnPressed, Cycle ) );
480 sbar->SetImage( IE_GUI_SCROLLBAR_UP_PRESSED,
481 bam->GetFrame( UpPressed, Cycle ) );
482 sbar->SetImage( IE_GUI_SCROLLBAR_DOWN_UNPRESSED,
483 bam->GetFrame( DownUnPressed, Cycle ) );
484 sbar->SetImage( IE_GUI_SCROLLBAR_DOWN_PRESSED,
485 bam->GetFrame( DownPressed, Cycle ) );
486 sbar->SetImage( IE_GUI_SCROLLBAR_TROUGH,
487 bam->GetFrame( Trough, Cycle ) );
488 sbar->SetImage( IE_GUI_SCROLLBAR_SLIDER,
489 bam->GetFrame( Slider, Cycle ) );
491 win->AddControl( sbar );
492 if (TAID != 0xffff)
493 win->Link( ( unsigned short ) ControlID, TAID );
495 break;
497 default:
498 printMessage( "CHUImporter","Control Not Supported\n",LIGHT_RED );
501 return win;
503 /** Returns the number of available windows */
504 unsigned int CHUImporter::GetWindowsCount()
506 return WindowCount;
509 #include "plugindef.h"
511 GEMRB_PLUGIN(0x23A7F6CA, "CHU File Importer")
512 PLUGIN_CLASS(IE_CHU_CLASS_ID, CHUImporter)
513 END_PLUGIN()