2 @Copyright Looking Glass Studios, Inc.
3 1996,1997,1998,1999,2000 Unpublished Work.
6 // $Header: r:/t2repos/thief2/src/dark/drkamap.cpp,v 1.24 2000/03/05 17:50:23 patmac Exp $
47 ////////////////////////////////////////////////////////////
49 // Automap Annotation class
51 #define MAX_ANNOT_CHARS 128
57 char text
[ MAX_ANNOT_CHARS
];
60 typedef cDynArray
<sAmapAnnotation
> cAmapAnnotationArray
;
62 static cAmapAnnotationArray gAnnotations
;
64 ////////////////////////////////////////////////////////////
67 static IAutomapProperty
* gAutoMapProp
= NULL
;
69 // We allow up to 8 map pages, and up to 32 decals per page
71 #define MAX_AMAP_PAGES 8
72 // MAX_AMAP_DECALS_PER_PAGE should be a multiple of 32
73 #define MAX_AMAP_DECALS_PER_PAGE 64
74 #define AMAP_LONGS_PER_PAGE (MAX_AMAP_DECALS_PER_PAGE >> 5)
75 #define MAX_MISSION_MAPS 32
79 ulong visited
[MAX_MISSION_MAPS
][MAX_AMAP_PAGES
][AMAP_LONGS_PER_PAGE
];
82 // Here's my descriptor, which identifies my stuff to the tag file & editor
83 sFileVarDesc gVisitedDesc
=
85 kCampaignVar
, // Where do I get saved?
86 "VISITED", // Tag file tag
87 "Rooms Visited", // friendly name
88 FILEVAR_TYPE(sVisited
), // Type (for editing)
90 { 1, 0}, // last valid version
91 "dark", // optional: what game am I in NULL means all
94 // The actual global variable
95 cFileVar
<sVisited
,&gVisitedDesc
> gVisited
;
98 // -1 - display all decals as if they have been visited
100 // 1 - highlight all decals as if they are current player pos
101 static int gImEverywhere
= 0;
102 #define AMAP_IM_EVERYWHERE 1
103 #define AMAP_IVE_BEEN_EVERYWHERE -1
105 static BOOL gbAutomapSpew
= FALSE
;
107 // map revealed source mission
113 static sFieldDesc mapsource_fields
[] =
115 { "Source Mission", kFieldTypeInt
, FieldLocation(sMapSourceData
,sourcemiss
) },
116 { "Compass Offset", kFieldTypeFloat
, FieldLocation(sMapSourceData
,compassdiff
) },
119 static sStructDesc mapsource_sdesc
= StructDescBuild(sMapSourceData
,kStructFlagNone
,mapsource_fields
);
125 sFileVarDesc gAutomapInfoDesc
=
127 kMissionVar
, //where do I get saved?
128 "MAPISRC", //tag file tag
129 "Automap Info", //friendly name
130 FILEVAR_TYPE(sMapSourceData
), //type (for editing)
132 { 1, 0}, // last valid version
137 // Actually use the defaults when resetting
140 class cMapSourceData
: public cFileVar
<sMapSourceData
,&gAutomapInfoDesc
>
145 // the variable itself
148 static cMapSourceData gMapSourceData
;
150 int GetMapSourceNum()
152 return gMapSourceData
.sourcemiss
;
155 float GetCompassOffset()
157 return gMapSourceData
.compassdiff
;
160 void TransferMapInfo()
162 int prevmiss
= gMapSourceData
.sourcemiss
;
163 const sMissionData
* missdata
= GetMissionData();
164 Assert_((missdata
->num
< MAX_MISSION_MAPS
) && (missdata
->num
>= 0));
165 Assert_((prevmiss
< MAX_MISSION_MAPS
));
166 int curmiss
= missdata
->num
;
168 if ((curmiss
==prevmiss
) || (prevmiss
<=0)) //don't copy in this case.
171 //sigh, memcpy goes the opposite way of what I thought... copies to curmiss now.
172 memcpy(&gVisited
.visited
[curmiss
],&gVisited
.visited
[prevmiss
],sizeof(gVisited
.visited
[curmiss
]));
175 void LoadMapSourceInfo(ITagFile
* file
)
177 gMapSourceData
.DatabaseMsg(kDatabaseLoad
|kDBMission
,file
);
180 void SaveMapSourceInfo(ITagFile
* file
)
182 gMapSourceData
.DatabaseMsg(kDatabaseSave
|kDBMission
,file
);
185 void MapSourceInfoInit()
187 AutoAppIPtr_(StructDescTools
,pTools
);
188 pTools
->Register(&mapsource_sdesc
);
191 void MapSourceInfoTerm()
195 ////////////////////////////////////////////////////////////
200 typedef cGenericProperty
<IAutomapProperty
,&IID_IAutomapProperty
, sAutomapProperty
*> cAutomapPropertyBase
;
202 class cAutomapProperty
: public cAutomapPropertyBase
204 cClassDataOps
< sAutomapProperty
> mOps
;
207 cAutomapProperty(const sPropertyDesc
* desc
, IPropertyStore
* store
)
208 : cAutomapPropertyBase(desc
,store
)
213 cAutomapProperty(const sPropertyDesc
* desc
, ePropertyImpl impl
)
214 : cAutomapPropertyBase(desc
,CreateGenericPropertyStore(impl
))
219 STANDARD_DESCRIBE_TYPE( sAutomapProperty
);
225 static sPropertyDesc AutomapProp_desc
=
227 PROP_AUTOMAP_NAME
, // Name
231 0, // Last ok version (0 means none)
232 { "Room", "Automap" },
235 void SetupAutomapProperty(void);
237 void AutomapPropInit(void)
239 SetupAutomapProperty();
240 gAutoMapProp
= new cAutomapProperty(&AutomapProp_desc
, kPropertyImplDense
);
243 void AutomapPropTerm(void)
245 SafeRelease(gAutoMapProp
);
248 // Structure Descriptor
249 static sFieldDesc AutomapFields
[] =
251 { "Page", kFieldTypeInt
, FieldLocation(sAutomapProperty
, page
) },
252 { "Location", kFieldTypeInt
, FieldLocation(sAutomapProperty
, location
) },
255 static sStructDesc AutomapDesc
= StructDescBuild(sAutomapProperty
, kStructFlagNone
, AutomapFields
);
257 static void SetupAutomapProperty(void)
259 AutoAppIPtr_(StructDescTools
,pTools
);
260 pTools
->Register(&AutomapDesc
);
264 typedef cDynClassArray
<cStr
> cStringArray
;
266 ////////////////////////////////////////
268 static sAutomapProperty
* map_player_pos()
271 cRoom
* player_room
= g_pRooms
->GetObjRoom(PlayerObject());
274 ObjID room
= player_room
->GetObjID();
276 sAutomapProperty
* prop
;
277 if (room
!= OBJ_NULL
&& gAutoMapProp
->Get(room
,&prop
))
279 AutoAppIPtr(QuestData
);
280 if (prop
->page
>= pQuestData
->Get(MIN_PAGE_QVAR
)
281 && prop
->page
<= pQuestData
->Get(MAX_PAGE_QVAR
))
284 static sAutomapProperty oob_pos
;
286 oob_pos
.page
= pQuestData
->Get(OOB_PAGE_QVAR
);
287 oob_pos
.location
= pQuestData
->Get(OOB_LOC_QVAR
);
297 // tell if the player has visited the specified page & location
300 DarkAutomapGetLocationVisited( int page
, int location
)
302 const sMissionData
* missdata
= GetMissionData();
303 Assert_((missdata
->num
< MAX_MISSION_MAPS
) && (missdata
->num
>= 0));
304 // page should always be valid, location may be -1
305 assert( (page
>= 0) && (page
< MAX_AMAP_PAGES
) );
306 if ( (location
>= 0) && (location
< MAX_AMAP_DECALS_PER_PAGE
) ) {
307 // tell if the player has visited the room
308 return (gVisited
.visited
[missdata
->num
][page
][location
>>5] & (1 << (location
& 31))) != 0;
316 // set the visited flag for the specified page & location
319 DarkAutomapSetLocationVisited( int page
, int location
)
321 AutoAppIPtr(QuestData
);
322 int locsVisited
, p
, l
;
323 const sMissionData
* missdata
= GetMissionData();
324 Assert_((missdata
->num
< MAX_MISSION_MAPS
) && (missdata
->num
>= 0));
326 // page should always be valid, location may be -1
327 assert( (page
>= 0) && (page
< MAX_AMAP_PAGES
) );
328 if ( (location
>= 0) && (location
< MAX_AMAP_DECALS_PER_PAGE
) ) {
329 // tell the automap the player has visited the room
330 gVisited
.visited
[missdata
->num
][page
][location
>>5] |= (1 << (location
& 31));
333 // set the quest variable that tracks total number of locations visited
335 for ( p
= 0; p
< MAX_AMAP_PAGES
; p
++ ) {
336 for ( l
= 0; l
< MAX_AMAP_DECALS_PER_PAGE
; l
++ ) {
337 if ( gVisited
.visited
[missdata
->num
][p
][l
>>5] & (1 << (l
& 31)) ) {
342 if ( pQuestData
->Exists( LOCS_VISITED_QVAR
) ) {
343 pQuestData
->Set( LOCS_VISITED_QVAR
, locsVisited
);
345 pQuestData
->Create( LOCS_VISITED_QVAR
, locsVisited
, kQuestDataMission
);
348 if ( gbAutomapSpew
) {
349 mprintf( "Automap visited page %d, location %d. Total visited: %d\n",
350 page
, location
, locsVisited
);
355 //------------------------------------------------------------
356 // flag that an area has been visited
359 DarkAutomapRoomCB( ObjID roomEntered
)
362 // get the decal index & map page properties of the room
363 sAutomapProperty
* prop
= map_player_pos();
365 DarkAutomapSetLocationVisited( prop
->page
, prop
->location
);
372 DarkAutomapFirstFrameInit( void )
374 cRoom
* player_room
= g_pRooms
->GetObjRoom(PlayerObject());
376 DarkAutomapRoomCB( player_room
->GetObjID() );
381 //------------------------------------------------------------
382 // Automap button panel
385 enum mapMode
{ kMapModeNormal
, kMapModeAddText
, kMapModeEraseText
};
387 class cAutomap
: public cDarkPanel
389 static sDarkPanelDesc gDesc
;
392 cAutomap(): cDarkPanel(&gDesc
),mpQuestData(AppGetObj(IQuestData
)) {};
393 ~cAutomap() { SafeRelease(mpQuestData
); };
401 kNext
= kStringButts
,
409 bool MapRegionEventHandler( uiEvent
*pEvent
, Region
*pReg
, void *pState
);
413 void RedrawDisplay();
414 void OnButtonList(ushort action
, int button
);
415 void OnLoopMsg(eLoopMessage
, tLoopMessageData
);
419 void RedrawButtons();
421 static mapMode mMapMode
;
423 enum { kNumArrowImages
= 4 };
424 IImageSource
* mArrows
[kNumArrowImages
]; // 4 arrow images
426 IQuestData
* mpQuestData
;
429 int mMapRegionEventHandlerID
;
430 sAmapAnnotation mCurAnnotation
;
433 ////////////////////////////////////////
435 mapMode
cAutomap::mMapMode
;
438 regionCB( uiEvent
*pEvent
,
442 cAutomap
*pAmap
= (cAutomap
*) pState
;
444 return pAmap
->MapRegionEventHandler( pEvent
, pReg
, pState
);
448 void cAutomap::InitUI()
450 cDarkPanel::InitUI();
452 Rect
& mapr
= mRects
[(int)kMap
];
454 for (i
= 0; i
< kNumArrowImages
; i
++)
457 sprintf(buf
,"arrow%03d",i
);
458 mArrows
[i
] = FetchUIImage(buf
);
462 for (i
= kNext
; i
< kNumButts
; i
++)
464 DrawElement
& elem
= mElems
[i
];
465 memset(&elem
,0,sizeof(elem
));
466 elem
.draw_type
= DRAWTYPE_BITMAP
;
467 elem
.draw_data
= mArrows
[n
++]->Lock();
468 elem
.draw_data2
= mArrows
[n
++]->Lock();
469 elem
.draw_flags
= INTERNAL(DRAWFLAG_INT_TRANSP
);
472 // create region & handler for map window - will be used
474 region_create( LGadBoxRegion(LGadCurrentRoot()),
476 &(mRects
[ (int)kMap
]),
477 0, 0, 0, NULL
, NULL
, NULL
, NULL
);
478 uiInstallRegionHandler( &mMapRegion
, ALL_EVENTS
, regionCB
, this,
479 &mMapRegionEventHandlerID
);
481 // initialize annotation stuff
482 mMapMode
= kMapModeNormal
;
483 mCurAnnotation
.text
[0] = 0;
485 // TBD - init annotations from ???
488 void cAutomap::TermUI()
492 for (i
= 0; i
< kNumArrowImages
; i
++)
494 mArrows
[i
]->Unlock();
495 SafeRelease(mArrows
[i
]);
497 uiRemoveRegionHandler( &mMapRegion
, mMapRegionEventHandlerID
);
499 if ( mMapMode
== kMapModeAddText
) {
500 // add annotation-in-progress if not 0 length
501 if ( strlen( mCurAnnotation
.text
) ) {
502 gAnnotations
.Append( mCurAnnotation
);
505 mMapMode
= kMapModeNormal
;
506 // TBD: save annotations to ???
507 for ( i
= 0; i
< gAnnotations
.Size(); i
++ ) {
509 // TBD: free any annotation stuff
511 cDarkPanel::TermUI();
514 ////////////////////////////////////////
516 // DrawAnnotation & OverlapsAnnotation support multi-line auto-centered annotations
519 #define EXTRA_VERTICAL_SPACING 0
522 DrawAnnotation( sAmapAnnotation
*pAnnotation
,
525 int x
, y
, endX
, endY
;
527 char txtCopy
[ MAX_ANNOT_CHARS
];
531 strcpy( txtCopy
, pAnnotation
->text
);
532 bLastLineEmpty
= (txtCopy
[strlen(txtCopy
) - 1] == '\n');
533 pToken
= strtok( txtCopy
, "\n" );
534 if ( pToken
== NULL
) {
535 // if we want cursor for empty string, we at least need to know height of font
537 gr_string_size( "A", &w
, &h
);
538 endX
= pAnnotation
->x
;
539 endY
= pAnnotation
->y
;
544 gr_string_size( pToken
, &w
, &h
);
545 x
= pAnnotation
->x
- (w
/2);
546 gr_string( pToken
, x
, y
);
549 y
+= (h
+ EXTRA_VERTICAL_SPACING
);
550 pToken
= strtok( NULL
, "\n" );
553 if ( bLastLineEmpty
) {
554 // this is here so that after the user hits return, the cursor
555 // will appear on the new line, not at the end of the last line
556 // this is due to strtok refusing to return an empty token
557 endX
= pAnnotation
->x
;
561 gr_int_line( endX
, endY
, endX
, endY
+ h
);
567 OverlapsAnnotation( sAmapAnnotation
*pAnnotation
,
572 char txtCopy
[ MAX_ANNOT_CHARS
];
574 int xLeft
, yTop
, xRight
, yBottom
;
576 strcpy( txtCopy
, pAnnotation
->text
);
577 pToken
= strtok( txtCopy
, "\n" );
578 yTop
= pAnnotation
->y
;
580 gr_string_size( pToken
, &w
, &h
);
581 xLeft
= pAnnotation
->x
- (w
/ 2);
584 if ( (y
>= yTop
) && (y
< yBottom
) &&
585 (x
>= xLeft
) && (x
< xRight
) ) {
586 // x,y is within string extents
589 yTop
+= (h
+ EXTRA_VERTICAL_SPACING
);
590 pToken
= strtok( NULL
, "\n" );
596 ////////////////////////////////////////
599 // make values less than 128 smaller,
600 // values greater than 128 bigger
602 static float brightenRGB
[3] = { 0.7, 0.7, 0.3 };
603 static float darkenRGB
[3] = { 0.1, 0.1, 0.1 };
604 static float dimRGB
[3] = { 0.2, 0.2, 0.7 };
605 static int splitPoint
= 100;
608 mungeColor( uchar
*pDst
,
620 // enhance contrast in decal where player is
621 if ( ((r
+ g
+ b
) / 3) >= splitPoint
) {
622 // make color brighter
623 r
= 255 - ((255 - r
) * (1.0 - brightenRGB
[0]));
624 g
= 255 - ((255 - g
) * (1.0 - brightenRGB
[1]));
625 b
= 255 - ((255 - b
) * (1.0 - brightenRGB
[2]));
628 r
*= (1.0 - darkenRGB
[0]);
629 g
*= (1.0 - darkenRGB
[1]);
630 b
*= (1.0 - darkenRGB
[2]);
635 // this decal is where player has visited
636 // reduce the contrast of the red and green components, but
637 // increase the contrast of the blue component. This color
638 // shifts the palette toward blue, to make the visited areas
639 // stand out, without losing so much contrast text is illegible
640 r
= (r
>= splitPoint
) ? splitPoint
+ ( (r
- splitPoint
) * (1.0 - dimRGB
[0]) )
641 : splitPoint
- ( (splitPoint
- r
) * (1.0 - dimRGB
[0]) );
642 g
= (g
>= splitPoint
) ? splitPoint
+ ( (g
- splitPoint
) * (1.0 - dimRGB
[1]) )
643 : splitPoint
- ( (splitPoint
- g
) * (1.0 - dimRGB
[1]) );
644 b
= (b
>= splitPoint
) ? 255 - ((255 - b
) * (1.0 - dimRGB
[2]))
645 : b
* (1.0 - dimRGB
[2]);
655 DrawDecal( IImageSource
*pDecal
,
660 uchar
*pNewPal
, *pSrc
, *pDst
;
662 grs_bitmap
*pBM
= (grs_bitmap
*) (pDecal
->Lock());
664 // muck with pallette then display
665 oldPalSlot
= pBM
->align
;
666 assert( pBM
->w
== pBM
->row
);
668 pNewPal
= (uchar
*) Malloc( 256 * 3 );
670 pSrc
= palmgr_get_pal( oldPalSlot
);
672 for ( i
= 0; i
< 256; i
++ ) {
673 mungeColor( pDst
, pSrc
, bYouAreHere
);
677 pBM
->align
= palmgr_alloc_pal( pNewPal
);
678 gr_bitmap( pBM
, pRect
->ul
.x
, pRect
->ul
.y
);
679 palmgr_release_slot( pBM
->align
);
680 pBM
->align
= oldPalSlot
;
685 SafeRelease( pDecal
);
689 ////////////////////////////////////////
691 void cAutomap::RedrawDisplay()
694 const sMissionData
* missdata
= GetMissionData();
696 sprintf(buf
,"%s/page%03d",missdata
->path
,mPageNum
);
697 IImageSource
* mapsrc
= FetchUIImage(buf
);
700 BOOL bIAmEverywhere
= FALSE
;
701 IRes
* pFontRes
= NULL
;
704 //to prevent (no)map crash -- AMSD
707 grs_bitmap
* map
= (grs_bitmap
*)mapsrc
->Lock();
708 int numDecals
, decal
;
709 ulong
*pVisitedDecals
;
711 Rect
& mapr
= mRects
[(int)kMap
];
714 GUIsetup(&c
,&mapr
,ComposeFlagRead
,GUI_CANV_ANY
);
718 Assert_((missdata
->num
< MAX_MISSION_MAPS
) && (missdata
->num
>= 0));
719 sAutomapProperty
* prop
= map_player_pos();
721 // hack - for some reason, the location the player has just entered is sometimes
722 // not marked as visited - here force mark that location as visited
724 DarkAutomapSetLocationVisited( prop
->page
, prop
->location
);
727 pVisitedDecals
= &(gVisited
.visited
[missdata
->num
][mPageNum
][0]);
728 sprintf(buf
,"%s/p%03dra",missdata
->path
,mPageNum
);
729 FetchUIRects(buf
, tmpRects
);
730 numDecals
= tmpRects
.Size();
732 //////////////////////////////////////////////////////////////////////////
734 // draw all the decals for areas the player has visited, EXCEPT for the
735 // decal for the current player position
737 //////////////////////////////////////////////////////////////////////////
740 for ( decal
= 0; decal
< numDecals
; decal
++ ) {
741 BOOL bYouAreHere
= prop
&& (prop
->page
== mPageNum
) && (prop
->location
== decal
);
742 // is decal at current player position
743 if ( bYouAreHere
&& (gImEverywhere
== 0) ) {
745 // remember that we are really somewhere
750 if ( (pVisitedDecals
[decal
>>5] & (1 << (decal
& 31))) || (gImEverywhere
!= 0) ) {
752 sprintf(buf
,"%s/p%03dr%03d",missdata
->path
,mPageNum
,decal
);
754 img
= FetchUIImage(buf
);
756 DrawDecal( img
, &(tmpRects
[decal
]), (gImEverywhere
== AMAP_IM_EVERYWHERE
) );
763 //////////////////////////////////////////////////////////////////////////
765 // lastly, draw the decal where player is, so that it is always on top
767 //////////////////////////////////////////////////////////////////////////
768 if ( youAreHere
!= -1 ) {
770 sprintf( buf
, "%s/p%03dr%03d", missdata
->path
, mPageNum
, youAreHere
);
772 img
= FetchUIImage(buf
);
774 DrawDecal( img
, &(tmpRects
[youAreHere
]), TRUE
);
783 //////////////////////////////////////////////////////////////////////////
785 // draw all annotations
787 //////////////////////////////////////////////////////////////////////////
790 // save old clip window, clip to map window
791 gr_save_cliprect( &oldClip
.i
);
792 gr_set_cliprect( mapr
.ul
.x
, mapr
.ul
.y
, mapr
.lr
.x
, mapr
.lr
.y
);
794 // set annotation font
795 strcpy( buf
, "f_scrp12" );
796 config_get_raw( "automap_note_font", buf
, sizeof(buf
)-1 );
797 pFontRes
= pResMan
->Bind( buf
, RESTYPE_FONT
, NULL
, mResPath
);
799 grs_font
* pFont
= (grs_font
*) pFontRes
->Lock();
800 gr_set_font( pFont
);
804 for ( i
= 0; i
< gAnnotations
.Size(); i
++ ) {
805 if ( gAnnotations
[i
].page
== mPageNum
) {
806 DrawAnnotation( &(gAnnotations
[i
]), FALSE
);
810 // draw the current annotation
811 if ( mMapMode
== kMapModeAddText
) {
812 DrawAnnotation( &mCurAnnotation
, TRUE
);
819 // restore old clip window
820 gr_restore_cliprect( &oldClip
.i
);
824 ////////////////////////////////////////
826 void cAutomap::RedrawButtons()
828 if (mPageNum
== mpQuestData
->Get(MIN_PAGE_QVAR
))
830 mElems
[(int)kPrev
].draw_type
= DRAWTYPE_NONE
;
831 GUIErase(&mRects
[(int)kPrev
]);
835 mElems
[(int)kPrev
].draw_type
= DRAWTYPE_BITMAP
;
836 region_expose(LGadBoxRegion(LGadCurrentRoot()),&mRects
[(int)kPrev
]);
839 if (mPageNum
== mpQuestData
->Get(MAX_PAGE_QVAR
))
841 mElems
[(int)kNext
].draw_type
= DRAWTYPE_NONE
;
842 GUIErase(&mRects
[(int)kNext
]);
846 mElems
[(int)kNext
].draw_type
= DRAWTYPE_BITMAP
;
847 region_expose(LGadBoxRegion(LGadCurrentRoot()),&mRects
[(int)kNext
]);
852 ////////////////////////////////////////
854 void cAutomap::OnButtonList(ushort action
, int button
)
856 if (action
& (BUTTONGADG_LCLICK
|BUTTONGADG_RCLICK
))
862 IPanelMode
* pMode
= GetPanelMode();
868 SwitchToObjectivesMode(FALSE
);
873 int max
= mpQuestData
->Get(MAX_PAGE_QVAR
);
876 // if an annotation is in progress, complete it
877 if ( strlen( mCurAnnotation
.text
) ) {
878 gAnnotations
.Append( mCurAnnotation
);
880 mCurAnnotation
.text
[0] = 0;
881 mMapMode
= kMapModeNormal
;
890 int min
= mpQuestData
->Get(MIN_PAGE_QVAR
);
893 // if an annotation is in progress, complete it
894 if ( strlen( mCurAnnotation
.text
) ) {
895 gAnnotations
.Append( mCurAnnotation
);
897 mCurAnnotation
.text
[0] = 0;
898 mMapMode
= kMapModeNormal
;
908 ////////////////////////////////////////
910 void cAutomap::OnLoopMsg(eLoopMessage msg
, tLoopMessageData data
)
916 sAutomapProperty
* pos
= map_player_pos();
919 mPageNum
= pos
->page
;
920 else // default to first page
921 mPageNum
= mpQuestData
->Get(MIN_PAGE_QVAR
);
926 cDarkPanel::OnLoopMsg(msg
,data
);
931 cAutomap::MapRegionEventHandler( uiEvent
*pEvent
,
935 uiCookedKeyEvent
*pKeyEvent
;
936 uiMouseEvent
*pMouseEvent
;
939 bool doRedraw
= FALSE
;
942 switch( pEvent
->type
) {
943 case UI_EVENT_KBD_COOKED
:
944 if ( (pEvent
->subtype
& KB_FLAG_DOWN
) && (mMapMode
== kMapModeAddText
) ) {
945 pKeyEvent
= (uiCookedKeyEvent
*) pEvent
;
946 c
= kb2ascii( pKeyEvent
->code
);
951 // TBD - user hit enter, annotation is complete
952 mMapMode
= kMapModeNormal
;
953 if ( strlen( mCurAnnotation
.text
) ) {
954 gAnnotations
.Append( mCurAnnotation
);
955 mCurAnnotation
.text
[0] = 0;
960 // TBD - user hit escape, annotation is complete
961 mMapMode
= kMapModeNormal
;
962 if ( strlen( mCurAnnotation
.text
) ) {
963 gAnnotations
.Append( mCurAnnotation
);
964 mCurAnnotation
.text
[0] = 0;
970 len
= strlen( mCurAnnotation
.text
);
972 mCurAnnotation
.text
[ len
- 1 ] = 0;
979 // if key is in range, add it to end of string and redisplay
981 len
= strlen( mCurAnnotation
.text
);
982 if ( len
< (MAX_ANNOT_CHARS
- 1) ) {
983 mCurAnnotation
.text
[ len
] = c
;
984 mCurAnnotation
.text
[ len
+ 1 ] = 0;
989 } //end if KB_DOWN and ADD TEXT
991 if ( (pEvent
->subtype
& KB_FLAG_DOWN
) && (mMapMode
== kMapModeNormal
) ){
992 pKeyEvent
= (uiCookedKeyEvent
*) pEvent
;
993 c
= kb2ascii( pKeyEvent
->code
);
996 IPanelMode
* pMode
= GetPanelMode();
1001 } //if KB_DOWN and NORMAL
1005 case UI_EVENT_MOUSE
:
1009 pMouseEvent
= (uiMouseEvent
*) pEvent
;
1010 x
= pMouseEvent
->pos
.x
;
1011 y
= pMouseEvent
->pos
.y
;
1013 if ( pMouseEvent
->action
& MOUSE_LUP
) {
1014 // TBD - change into text entry mode
1015 switch( mMapMode
) {
1017 case kMapModeNormal
:
1018 // change into text entry mode
1019 mMapMode
= kMapModeAddText
;
1020 mCurAnnotation
.text
[0] = 0;
1021 mCurAnnotation
.x
= x
;
1022 mCurAnnotation
.y
= y
;
1023 mCurAnnotation
.page
= mPageNum
;
1026 case kMapModeAddText
:
1027 // end current annotation, start new one
1028 if ( strlen( mCurAnnotation
.text
) ) {
1029 gAnnotations
.Append( mCurAnnotation
);
1030 mCurAnnotation
.text
[0] = 0;
1032 mCurAnnotation
.x
= x
;
1033 mCurAnnotation
.y
= y
;
1034 mCurAnnotation
.page
= mPageNum
;
1037 case kMapModeEraseText
:
1038 // find annotation which was clicked on & delete it
1039 grs_font
* pFont
= (grs_font
*) mpFontRes
->Lock();
1040 for ( i
= 0; i
< gAnnotations
.Size(); i
++ ) {
1041 // get string extents...
1042 if ( (gAnnotations
[i
].page
== mPageNum
) &&
1043 OverlapsAnnotation( &(gAnnotations
[i
]), x
, y
) ) {
1044 gAnnotations
.DeleteItem( i
);
1048 mpFontRes
->Unlock();
1049 mMapMode
= kMapModeNormal
;
1055 if ( pMouseEvent
->action
& MOUSE_RUP
) {
1056 // if there was an annotation in progress, finish it
1057 if ( strlen( mCurAnnotation
.text
) ) {
1058 gAnnotations
.Append( mCurAnnotation
);
1059 mCurAnnotation
.text
[0] = 0;
1061 // find annotation which was clicked on & delete it
1062 grs_font
* pFont
= (grs_font
*) mpFontRes
->Lock();
1063 for ( i
= 0; i
< gAnnotations
.Size(); i
++ ) {
1064 if ( (gAnnotations
[i
].page
== mPageNum
) &&
1065 OverlapsAnnotation( &(gAnnotations
[i
]), x
, y
) ) {
1066 gAnnotations
.DeleteItem( i
);
1070 mMapMode
= kMapModeNormal
;
1071 mpFontRes
->Unlock();
1079 uiHideMouse( LGadCurrentRoot()->box
.r
.r
);
1081 uiShowMouse( LGadCurrentRoot()->box
.r
.r
);
1086 ////////////////////////////////////////
1088 static const char* butt_names
[] =
1094 sDarkPanelDesc
cAutomap::gDesc
=
1097 cAutomap::kNumButts
,
1098 cAutomap::kNumRects
,
1099 cAutomap::kStringButts
,
1103 ////////////////////////////////////////
1105 static cAutomap
* gpAutomap
= NULL
;
1107 void SwitchToDarkAutomapMode(BOOL push
)
1111 IPanelMode
* panel
= gpAutomap
->GetPanelMode();
1113 panel
->Switch((push
) ? kLoopModePush
: kLoopModeSwitch
);
1119 static void create_panel_mode()
1121 cAutomap
* automap
= new cAutomap
;
1123 gpAutomap
= automap
;
1129 void init_commands(void);
1131 void DarkAutomapInit(void)
1134 create_panel_mode();
1136 cRooms::AddAutomapCallback( DarkAutomapRoomCB
);
1140 void DarkAutomapTerm()
1144 cRooms::RemoveAutomapCallback( DarkAutomapRoomCB
);
1148 // load/save annotations stuff
1150 static TagFileTag MyTag
= { "AMAPANNO" };
1151 static TagVersion MyVersion
= { 0, 0 };
1153 static BOOL
setup_tagfile(ITagFile
* file
)
1155 if (file
->OpenMode() == kTagOpenRead
&& file
->BlockSize(&MyTag
) == 0)
1158 TagVersion v
= MyVersion
;
1159 HRESULT result
= file
->OpenBlock(&MyTag
,&v
);
1163 if (!VersionNumsEqual(&v
,&MyVersion
))
1173 void DarkAutomapDatabaseNotify( ulong msg
,
1176 int numAnnotations
, i
;
1180 case kDatabaseReset
:
1181 gAnnotations
.SetSize( 0 );
1185 if ( setup_tagfile(pFile
) ) {
1187 pFile
->Read( (char *) (&numAnnotations
), sizeof(numAnnotations
) );
1188 gAnnotations
.SetSize( numAnnotations
);
1189 for ( i
= 0; i
< numAnnotations
; i
++ ) {
1190 pFile
->Read( (char *) (&gAnnotations
[i
]), sizeof(sAmapAnnotation
) );
1192 pFile
->CloseBlock();
1197 if ( setup_tagfile(pFile
) ) {
1198 numAnnotations
= gAnnotations
.Size();
1199 pFile
->Write( (char *) (&numAnnotations
), sizeof(numAnnotations
) );
1200 for ( i
= 0; i
< numAnnotations
; i
++ ) {
1201 pFile
->Write( (char *) (&gAnnotations
[i
]), sizeof(sAmapAnnotation
) );
1203 pFile
->CloseBlock();
1216 static void do_automap()
1218 SwitchToDarkAutomapMode(TRUE
);
1222 automap_set_visited( int visitedDecal
)
1224 sAutomapProperty
*pPlayerPos
;
1225 pPlayerPos
= map_player_pos();
1227 if ( pPlayerPos
&& (pPlayerPos
->page
>= 0) && (pPlayerPos
->page
< MAX_AMAP_PAGES
) ) {
1228 if ( visitedDecal
== -1 ) {
1229 for ( visitedDecal
= 0; visitedDecal
< MAX_AMAP_DECALS_PER_PAGE
; visitedDecal
++ ) {
1230 DarkAutomapSetLocationVisited( pPlayerPos
->page
, visitedDecal
);
1233 DarkAutomapSetLocationVisited( pPlayerPos
->page
, visitedDecal
);
1240 automap_im_everywhere( int onOff
)
1242 gImEverywhere
= onOff
;
1246 static Command commands
[] =
1248 { "automap", FUNC_STRING
, do_automap
, "Display the automap", HK_ALL
},
1249 { "amap_visited", FUNC_INT
, automap_set_visited
, "mark an automap location on current page visited", HK_ALL
},
1250 { "amap_im_everywhere", FUNC_INT
, automap_im_everywhere
, "make all decals display as current location", HK_ALL
},
1251 { "amap_spew", TOGGLE_BOOL
, &gbAutomapSpew
},
1254 static void init_commands()
1256 COMMANDS(commands
,HK_ALL
);