diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 5bbd1cbc37..12cd210edf 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,13 @@ +April 9, 2008 (SBarInfo Update #17) +- Fixed: SBarInfo tried to calculate scaled offsets on unscaled status bars. +- Added: createpopup to SBarInfo. No we don't have custom popups yet. It only + defines the transition effect. Currently none or slideinbottom. +- Made the first argument of DrawMugShot optional (think of it as an overloaded + function). The use of the first argument is deprecated due to the event of + per player class faces. +- More changes from DrawImage to screen->DrawTexture(). I guess I didn't get + them all just yet. + April 8, 2008 - Added the FCriticalSection class in critsec.h to make it easier to use critical sections in other places besides the OPL player. diff --git a/src/g_shared/sbarinfo.h b/src/g_shared/sbarinfo.h index 7d38c32497..510da22bf0 100644 --- a/src/g_shared/sbarinfo.h +++ b/src/g_shared/sbarinfo.h @@ -40,6 +40,7 @@ #include "v_collection.h" #define NUMHUDS 9 +#define NUMPOPUPS 3 class FBarTexture; class FScanner; @@ -47,6 +48,35 @@ class FScanner; struct SBarInfoCommand; //we need to be able to use this before it is defined. struct MugShotState; +//Popups! +enum PopupTransition +{ + TRANSITION_NONE, + TRANSITION_SLIDEINBOTTOM, +}; + +struct Popup +{ + PopupTransition transition; + bool opened; + bool moving; + int height; + int width; + int speed; + int x; + int y; + + Popup(); + void init(); + void tick(); + void open(); + void close(); + bool isDoneMoving(); + int getXOffset(); + int getYOffset(); +}; + +//SBarInfo struct SBarInfoBlock { TArray commands; @@ -82,6 +112,7 @@ struct SBarInfo { TArray Images; SBarInfoBlock huds[NUMHUDS]; + Popup popups[NUMPOPUPS]; bool automapbar; bool interpolateHealth; bool interpolateArmor; @@ -276,6 +307,7 @@ enum //Key words SBARINFO_LOWERHEALTHCAP, SBARINFO_STATUSBAR, SBARINFO_MUGSHOT, + SBARINFO_CREATEPOPUP, }; enum //Bar types @@ -340,7 +372,7 @@ public: void ShowPop(int popnum); void SetMugShotState(const char* stateName, bool waitTillDone=false); private: - void doCommands(SBarInfoBlock &block); + void doCommands(SBarInfoBlock &block, int xOffset=0, int yOffset=0); void DrawGraphic(FTexture* texture, int x, int y, int flags=0); void DrawString(const char* str, int x, int y, EColorRange translation, int spacing=0); void DrawNumber(int num, int len, int x, int y, EColorRange translation, int spacing=0, bool fillzeros=false); @@ -366,6 +398,7 @@ private: int mugshotHealth; int chainWiggle; int artiflash; + int pendingPopup; int currentPopup; unsigned int invBarOffset; FBarShader shader_horz_normal; diff --git a/src/g_shared/sbarinfo_display.cpp b/src/g_shared/sbarinfo_display.cpp index 77cb7f7bc1..21a9da55fe 100644 --- a/src/g_shared/sbarinfo_display.cpp +++ b/src/g_shared/sbarinfo_display.cpp @@ -267,6 +267,8 @@ DSBarInfo::DSBarInfo () : DBaseStatusBar (SBarInfoScript->height), chainWiggle = 0; artiflash = 4; currentState = NULL; + currentPopup = POP_None; + pendingPopup = POP_None; } DSBarInfo::~DSBarInfo () @@ -320,11 +322,11 @@ void DSBarInfo::Draw (EHudState state) if(currentPopup != POP_None) { if(currentPopup == POP_Log) - doCommands(SBarInfoScript->huds[STBAR_POPUPLOG]); + doCommands(SBarInfoScript->huds[STBAR_POPUPLOG], SBarInfoScript->popups[currentPopup].getXOffset(), SBarInfoScript->popups[currentPopup].getYOffset()); else if(currentPopup == POP_Keys) - doCommands(SBarInfoScript->huds[STBAR_POPUPKEYS]); + doCommands(SBarInfoScript->huds[STBAR_POPUPKEYS], SBarInfoScript->popups[currentPopup].getXOffset(), SBarInfoScript->popups[currentPopup].getYOffset()); else if(currentPopup == POP_Status) - doCommands(SBarInfoScript->huds[STBAR_POPUPSTATUS]); + doCommands(SBarInfoScript->huds[STBAR_POPUPSTATUS], SBarInfoScript->popups[currentPopup].getXOffset(), SBarInfoScript->popups[currentPopup].getYOffset()); } } @@ -410,6 +412,16 @@ void DSBarInfo::Tick () rampageTimer = 0; } mugshotHealth = CPlayer->health; + if(currentPopup != POP_None) + { + SBarInfoScript->popups[currentPopup].tick(); + if(SBarInfoScript->popups[currentPopup].opened == false && SBarInfoScript->popups[currentPopup].isDoneMoving()) + { + currentPopup = pendingPopup; + if(currentPopup != POP_None) + SBarInfoScript->popups[currentPopup].open(); + } + } } void DSBarInfo::ReceivedWeapon (AWeapon *weapon) @@ -426,9 +438,20 @@ void DSBarInfo::ShowPop(int popnum) { DBaseStatusBar::ShowPop(popnum); if(popnum != currentPopup) - currentPopup = popnum; + { + pendingPopup = popnum; + } else - currentPopup = POP_None; + pendingPopup = POP_None; + if(currentPopup != POP_None) + SBarInfoScript->popups[currentPopup].close(); + else + { + currentPopup = pendingPopup; + pendingPopup = POP_None; + if(currentPopup != POP_None) + SBarInfoScript->popups[currentPopup].open(); + } } //Public so it can be called by ACS @@ -447,7 +470,7 @@ void DSBarInfo::SetMugShotState(const char* stateName, bool waitTillDone) } } -void DSBarInfo::doCommands(SBarInfoBlock &block) +void DSBarInfo::doCommands(SBarInfoBlock &block, int xOffset, int yOffset) { //prepare ammo counts AAmmo *ammo1, *ammo2; @@ -467,6 +490,8 @@ void DSBarInfo::doCommands(SBarInfoBlock &block) for(unsigned int i = 0;i < block.commands.Size();i++) { SBarInfoCommand& cmd = block.commands[i]; + cmd.x += xOffset; + cmd.y += yOffset; switch(cmd.type) //read and execute all the commands { case SBARINFO_DRAWSWITCHABLEIMAGE: //draw the alt image if we don't have the item else this is like a normal drawimage @@ -712,7 +737,7 @@ void DSBarInfo::doCommands(SBarInfoBlock &block) } else if((cmd.flags & DRAWSELECTEDINVENTORY_ALTERNATEONEMPTY)) { - doCommands(cmd.subBlock); + doCommands(cmd.subBlock, xOffset, yOffset); } break; case SBARINFO_DRAWINVENTORYBAR: @@ -1063,7 +1088,7 @@ void DSBarInfo::doCommands(SBarInfoBlock &block) ((cmd.flags & GAMETYPE_COOPERATIVE) && multiplayer && !deathmatch) || ((cmd.flags & GAMETYPE_TEAMGAME) && teamplay)) { - doCommands(cmd.subBlock); + doCommands(cmd.subBlock, xOffset, yOffset); } break; case SBARINFO_PLAYERCLASS: @@ -1072,14 +1097,14 @@ void DSBarInfo::doCommands(SBarInfoBlock &block) int spawnClass = CPlayer->cls->ClassIndex; if(cmd.special == spawnClass || cmd.special2 == spawnClass || cmd.special3 == spawnClass) { - doCommands(cmd.subBlock); + doCommands(cmd.subBlock, xOffset, yOffset); } break; } case SBARINFO_ASPECTRATIO: if(CheckRatio(screen->GetWidth(), screen->GetHeight()) == cmd.value) { - doCommands(cmd.subBlock); + doCommands(cmd.subBlock, xOffset, yOffset); } break; case SBARINFO_ISSELECTED: @@ -1090,16 +1115,16 @@ void DSBarInfo::doCommands(SBarInfoBlock &block) if(weapon2 != NULL) { if((cmd.flags & SBARINFOEVENT_NOT) && (weapon1 != CPlayer->ReadyWeapon->GetSpecies() && weapon2 != CPlayer->ReadyWeapon->GetSpecies())) - doCommands(cmd.subBlock); + doCommands(cmd.subBlock, xOffset, yOffset); else if(!(cmd.flags & SBARINFOEVENT_NOT) && (weapon1 == CPlayer->ReadyWeapon->GetSpecies() || weapon2 == CPlayer->ReadyWeapon->GetSpecies())) - doCommands(cmd.subBlock); + doCommands(cmd.subBlock, xOffset, yOffset); } else { if(!(cmd.flags & SBARINFOEVENT_NOT) && weapon1 == CPlayer->ReadyWeapon->GetSpecies()) - doCommands(cmd.subBlock); + doCommands(cmd.subBlock, xOffset, yOffset); else if((cmd.flags & SBARINFOEVENT_NOT) && weapon1 != CPlayer->ReadyWeapon->GetSpecies()) - doCommands(cmd.subBlock); + doCommands(cmd.subBlock, xOffset, yOffset); } } break; @@ -1115,7 +1140,7 @@ void DSBarInfo::doCommands(SBarInfoBlock &block) bool usesammo2 = (AmmoType2 != NULL); if(!(cmd.flags & SBARINFOEVENT_NOT) && !usesammo1 && !usesammo2) //if the weapon doesn't use ammo don't go though the trouble. { - doCommands(cmd.subBlock); + doCommands(cmd.subBlock, xOffset, yOffset); break; } //Or means only 1 ammo type needs to match and means both need to match. @@ -1126,11 +1151,11 @@ void DSBarInfo::doCommands(SBarInfoBlock &block) if(((cmd.flags & SBARINFOEVENT_OR) && (match1 || match2)) || ((cmd.flags & SBARINFOEVENT_AND) && (match1 && match2))) { if(!(cmd.flags & SBARINFOEVENT_NOT)) - doCommands(cmd.subBlock); + doCommands(cmd.subBlock, xOffset, yOffset); } else if(cmd.flags & SBARINFOEVENT_NOT) { - doCommands(cmd.subBlock); + doCommands(cmd.subBlock, xOffset, yOffset); } } else //Every thing here could probably be one long if statement but then it would be more confusing. @@ -1138,11 +1163,11 @@ void DSBarInfo::doCommands(SBarInfoBlock &block) if((usesammo1 && (AmmoType1 == IfAmmo1)) || (usesammo2 && (AmmoType2 == IfAmmo1))) { if(!(cmd.flags & SBARINFOEVENT_NOT)) - doCommands(cmd.subBlock); + doCommands(cmd.subBlock, xOffset, yOffset); } else if(cmd.flags & SBARINFOEVENT_NOT) { - doCommands(cmd.subBlock); + doCommands(cmd.subBlock, xOffset, yOffset); } } } @@ -1154,24 +1179,26 @@ void DSBarInfo::doCommands(SBarInfoBlock &block) if(cmd.flags & SBARINFOEVENT_AND) { if((item1 != NULL && item2 != NULL) && !(cmd.flags & SBARINFOEVENT_NOT)) - doCommands(cmd.subBlock); + doCommands(cmd.subBlock, xOffset, yOffset); else if((item1 == NULL || item2 == NULL) && (cmd.flags & SBARINFOEVENT_NOT)) - doCommands(cmd.subBlock); + doCommands(cmd.subBlock, xOffset, yOffset); } else if(cmd.flags & SBARINFOEVENT_OR) { if((item1 != NULL || item2 != NULL) && !(cmd.flags & SBARINFOEVENT_NOT)) - doCommands(cmd.subBlock); + doCommands(cmd.subBlock, xOffset, yOffset); else if((item1 == NULL && item2 == NULL) && (cmd.flags & SBARINFOEVENT_NOT)) - doCommands(cmd.subBlock); + doCommands(cmd.subBlock, xOffset, yOffset); } else if((item1 != NULL) && !(cmd.flags & SBARINFOEVENT_NOT)) - doCommands(cmd.subBlock); + doCommands(cmd.subBlock, xOffset, yOffset); else if((item1 == NULL) && (cmd.flags & SBARINFOEVENT_NOT)) - doCommands(cmd.subBlock); + doCommands(cmd.subBlock, xOffset, yOffset); break; } } + cmd.x -= xOffset; + cmd.y -= yOffset; } } @@ -1191,7 +1218,8 @@ void DSBarInfo::DrawGraphic(FTexture* texture, int x, int y, int flags) y += ST_Y; int w = texture->GetScaledWidth(); int h = texture->GetScaledHeight() + y; - screen->VirtualToRealCoordsInt(x, y, w, h, 320, 200, true); + if(Scaled) + screen->VirtualToRealCoordsInt(x, y, w, h, 320, 200, true); h -= y; if((flags & DRAWIMAGE_TRANSLATABLE)) { @@ -1238,7 +1266,8 @@ void DSBarInfo::DrawString(const char* str, int x, int y, EColorRange translatio int ry = y + ST_Y; int rw = character->GetScaledWidth(); int rh = character->GetScaledHeight(); - screen->VirtualToRealCoordsInt(rx, ry, rw, rh, 320, 200, true); + if(Scaled) + screen->VirtualToRealCoordsInt(rx, ry, rw, rh, 320, 200, true); screen->DrawTexture(character, rx, ry, DTA_DestWidth, rw, DTA_DestHeight, rh, @@ -1297,7 +1326,8 @@ void DSBarInfo::DrawFace(FString &defaultFace, int accuracy, bool xdth, bool ani y += ST_Y; int w = face->GetScaledWidth(); int h = face->GetScaledHeight(); - screen->VirtualToRealCoordsInt(x, y, w, h, 320, 200, true); + if(Scaled) + screen->VirtualToRealCoordsInt(x, y, w, h, 320, 200, true); screen->DrawTexture(face, x, y, DTA_DestWidth, w, DTA_DestHeight, h, @@ -1492,10 +1522,10 @@ void DSBarInfo::DrawGem(FTexture* chain, FTexture* gem, int value, int x, int y, int offset = (int) (((double) (chainWidth-padleft-padright)/100)*value); if(chain != NULL) { - DrawImage(chain, x+(offset%chainsize), y); + DrawGraphic(chain, x+(offset%chainsize), y); } if(gem != NULL) - DrawImage(gem, x+padleft+offset, y, translate ? getTranslation() : NULL); + DrawGraphic(gem, x+padleft+offset, y, translate ? DRAWIMAGE_TRANSLATABLE : 0); } FRemapTable* DSBarInfo::getTranslation() diff --git a/src/g_shared/sbarinfo_parser.cpp b/src/g_shared/sbarinfo_parser.cpp index fb87786cbd..fb683e6b0e 100644 --- a/src/g_shared/sbarinfo_parser.cpp +++ b/src/g_shared/sbarinfo_parser.cpp @@ -60,6 +60,7 @@ static const char *SBarInfoTopLevel[] = "lowerhealthcap", "statusbar", "mugshot", + "createpopup", NULL }; @@ -305,6 +306,43 @@ void SBarInfo::ParseSBarInfo(int lump) MugShotStates.Push(state); break; } + case SBARINFO_CREATEPOPUP: + { + int pop = 0; + sc.MustGetToken(TK_Identifier); + if(sc.Compare("keys")) + pop = 0; + else if(sc.Compare("log")) + pop = 1; + else if(sc.Compare("status")) + pop = 2; + else + sc.ScriptError("Unkown popup: '%s'", sc.String); + Popup &popup = popups[pop]; + sc.MustGetToken(','); + sc.MustGetToken(TK_IntConst); + popup.width = sc.Number; + sc.MustGetToken(','); + sc.MustGetToken(TK_IntConst); + popup.height = sc.Number; + sc.MustGetToken(','); + if(!sc.CheckToken(TK_None)) + { + sc.MustGetToken(TK_Identifier); + if(sc.Compare("slideinbottom")) + { + popup.transition = TRANSITION_SLIDEINBOTTOM; + sc.MustGetToken(','); + sc.MustGetToken(TK_IntConst); + popup.speed = sc.Number; + } + else + sc.ScriptError("Unkown transition type: '%s'", sc.String); + } + popup.init(); + sc.MustGetToken(';'); + break; + } } } } @@ -553,9 +591,11 @@ void SBarInfo::ParseSBarInfoBlock(FScanner &sc, SBarInfoBlock &block) sc.MustGetToken(';'); break; case SBARINFO_DRAWMUGSHOT: - sc.MustGetToken(TK_StringConst); - cmd.setString(sc, sc.String, 0, 3, true); - sc.MustGetToken(','); + if(sc.CheckToken(TK_StringConst)) + { + cmd.setString(sc, sc.String, 0, 3, true); + sc.MustGetToken(','); + } sc.MustGetToken(TK_IntConst); //accuracy if(sc.Number < 1 || sc.Number > 9) sc.ScriptError("Expected a number between 1 and 9, got %d instead.", sc.Number); @@ -1237,6 +1277,88 @@ const MugShotState *FindMugShotState(FString state) return NULL; } +//Popup +Popup::Popup() +{ + transition = TRANSITION_NONE; + height = 320; + width = 200; + speed = 0; + x = 320; + y = 200; + opened = false; + moving = false; +} + +void Popup::init() +{ + x = width; + y = height; + if(transition == TRANSITION_SLIDEINBOTTOM) + { + x = 0; + } +} + +void Popup::tick() +{ + if(transition == TRANSITION_SLIDEINBOTTOM) + { + if(moving) + { + if(opened) + y -= clamp(height + (y - height), 1, speed); + else + y += clamp(height - y, 1, speed); + } + if(y != 0 && y != height) + moving = true; + else + moving = false; + } + else + { + moving = false; + if(opened) + { + y = 0; + x = 0; + } + else + { + y = height; + x = width; + } + } +} + +bool Popup::isDoneMoving() +{ + return !moving; +} + +int Popup::getXOffset() +{ + return x; +} + +int Popup::getYOffset() +{ + return y; +} + +void Popup::open() +{ + opened = true; + moving = true; +} + +void Popup::close() +{ + opened = false; + moving = true; +} + //Used to allow replacements of states int FindMugShotStateIndex(FName state) {