diff --git a/docs/content/annotated_banner.png b/docs/content/annotated_banner.png new file mode 100644 index 00000000..554326f0 Binary files /dev/null and b/docs/content/annotated_banner.png differ diff --git a/docs/general_config.md b/docs/general_config.md index ec70add1..75850916 100644 --- a/docs/general_config.md +++ b/docs/general_config.md @@ -295,22 +295,33 @@ The user can specify one or more questions using the `questions` array, as demon Each question in the array is then asked of the user (via an independent time-sequenced dialog box) before being recorded to the output log. Note that `MultipleChoise` and `Rating` questions include a confirmation button that must be pressed to confirm the selection before proceeding. ## HUD settings -| Parameter Name |Units | Description | -|-----------------------|-------|------------------------------------------------------------------------------------| -|`showHUD` |`bool` | The master control for whether or not HUD elements are displayed (score banner, player health bar, and ammo indicator) | -|`showBanner` |`bool` | Whether or not the score banner is displayed (currently w/ time remaining, percent of session complete, and score) | -|`bannerLargeFontSize` |pt | The "large" font for the percent complete in the banner -|`bannerSmallFontSize` |pt | The "small" font for the time remaining and score -|`hudFont` |file | The font to use (as a `.fnt` file) for the HUD (for available fonts check `%g3d%/data10/common/font` or `%g3d%/G3D10/ data-files/font`). We suggest using a fixed width font (such as `console.fnt`) for HUD elements| +| Parameter Name |Units | Description | +|-----------------------|-----------|-----------------------------------------------------------------------------------------------------------------------| +|`showHUD` |`bool` | The master control for whether or not HUD elements are displayed (score banner, player health bar, and ammo indicator)| +|`showBanner` |`bool` | Whether or not the score banner is displayed (currently w/ time remaining, percent of session complete, and score) an annotated banner image is provided below for reference. | +|`bannerTimerMode` |`String` | The mode in which to show time in the banner (can be `"remaining"`, `"elapsed"`, or `"none"`) | +|`bannerShowProgress` |`bool` | Whether to show the session progress in the banner | +|`bannerShowScore` |`bool` | Whether to show the session score in the banner | +|`bannerLargeFontSize` |pt | The "large" font for the percent complete in the banner | +|`bannerSmallFontSize` |pt | The "small" font for the time remaining and score | +|`hudFont` |file | The font to use (as a `.fnt` file) for the HUD (for available fonts check `%g3d%/data10/common/font` or `%g3d%/G3D10/ data-files/font`). We suggest using a fixed width font (such as `console.fnt`) for HUD elements| ``` "showHUD": false, // Show the player HUD (banner, ammo, health bar) "showBanner": false, // Control the banner at the top of the screen (shows time, score, and session % complete) +"bannerTimerMode": "remaining", // Show remaining time in trial in timer on banner +"bannerShowProgress": true, // Show the session progress percentage in the banner +"bannerShowScore": true, // Show the session score in the banner "bannerLargeFontSize": 30.0, // Large font size to use in the banner (% complete) "bannerSmallFontSize": 14.0, // Small font size to use in the banner (time remaining and score) "hudFont": "console.fnt", // Font to use for the HUD (fixed with highly suggested!) ``` +#### Annotated Banner +The image below provides an example of the banner with the timer, progress, and score annotated with an overlay. + + + ### Player Health Bar | Parameter Name |Units | Description | |-------------------------------|---------------|------------------------------------------------------------------------------------| diff --git a/source/FPSciGraphics.cpp b/source/FPSciGraphics.cpp index 6daab841..2151b592 100644 --- a/source/FPSciGraphics.cpp +++ b/source/FPSciGraphics.cpp @@ -506,19 +506,43 @@ void FPSciApp::drawHUD(RenderDevice *rd, Vector2 resolution) { Draw::rect2D((scoreBannerTexture->rect2DBounds() * scale - scoreBannerTexture->vector2Bounds() * scale / 2.0f) * 0.8f + hudCenter, rd, Color3::white(), scoreBannerTexture); // Create strings for time remaining, progress in sessions, and score - float remainingTime = sess->getRemainingTrialTime(); - float printTime = remainingTime > 0 ? remainingTime : 0.0f; - String time_string = format("%0.2f", printTime); + float time; + if (sessConfig->hud.bannerTimerMode == "remaining") { + time = sess->getRemainingTrialTime(); + if (time < 0.f) time = 0.f; + } + else if (sessConfig->hud.bannerTimerMode == "elapsed") { + time = sess->getElapsedTrialTime(); + } + String time_string = time < 10000.f ? format("%0.1f", time) : "---"; // Only allow up to 3 digit time strings + float prog = sess->getProgress(); String prog_string = ""; if (!isnan(prog)) { - prog_string = format("%d", (int)(100.0f*prog)) + "%"; + prog_string = format("%d", (int)G3D::round(100.0f*prog)) + "%"; } - String score_string = format("%d", (int)(10 * sess->getScore())); - hudFont->draw2D(rd, time_string, hudCenter - Vector2(80, 0) * scale.x, scale.x * sessConfig->hud.bannerSmallFontSize, Color3::white(), Color4::clear(), GFont::XALIGN_RIGHT, GFont::YALIGN_CENTER); - hudFont->draw2D(rd, prog_string, hudCenter + Vector2(0, -1), scale.x * sessConfig->hud.bannerLargeFontSize, Color3::white(), Color4::clear(), GFont::XALIGN_CENTER, GFont::YALIGN_CENTER); - hudFont->draw2D(rd, score_string, hudCenter + Vector2(125, 0) * scale, scale.x * sessConfig->hud.bannerSmallFontSize, Color3::white(), Color4::clear(), GFont::XALIGN_RIGHT, GFont::YALIGN_CENTER); + const double score = sess->getScore(); + String score_string; + if (score < 1e3) { + score_string = format("%d", (int)G3D::round(score)); + } + else if (score > 1e3 && score < 1e6) { + score_string = format("%dk", (int)G3D::round(score / 1e3)); + } + else if (score > 1e6 && score < 1e9) { + score_string = format("%dM", (int)G3D::round(score / 1e6)); + } + else if (score > 1e9) { + score_string = format("%dB", (int)G3D::round(score / 1e9)); + } + + if (sessConfig->hud.bannerTimerMode != "none" && sess->inTask()) { + hudFont->draw2D(rd, time_string, hudCenter - Vector2(80, 0) * scale.x, scale.x * sessConfig->hud.bannerSmallFontSize, + Color3::white(), Color4::clear(), GFont::XALIGN_RIGHT, GFont::YALIGN_CENTER); + } + if(sessConfig->hud.bannerShowProgress) hudFont->draw2D(rd, prog_string, hudCenter + Vector2(0, -1), scale.x * sessConfig->hud.bannerLargeFontSize, Color3::white(), Color4::clear(), GFont::XALIGN_CENTER, GFont::YALIGN_CENTER); + if(sessConfig->hud.bannerShowScore) hudFont->draw2D(rd, score_string, hudCenter + Vector2(125, 0) * scale, scale.x * sessConfig->hud.bannerSmallFontSize, Color3::white(), Color4::clear(), GFont::XALIGN_RIGHT, GFont::YALIGN_CENTER); } // Draw any static HUD elements diff --git a/source/FpsConfig.cpp b/source/FpsConfig.cpp index dfc01d84..3b48a962 100644 --- a/source/FpsConfig.cpp +++ b/source/FpsConfig.cpp @@ -246,6 +246,20 @@ void HudConfig::load(AnyTableReader reader, int settingsVersion) { case 1: reader.getIfPresent("showHUD", enable); reader.getIfPresent("showBanner", showBanner); + if (reader.getIfPresent("bannerTimerMode", bannerTimerMode)) { + bannerTimerMode = toLower(bannerTimerMode); + const Array validTimeModes = { "none", "elapsed", "remaining" }; + if (!validTimeModes.contains(bannerTimerMode)) { + String errString = format("\"bannerShowTime\" value \"%s\" is invalid, must be specified as one of the valid modes (", bannerTimerMode); + for (String validTimeMode : validTimeModes) { + errString += "\"" + validTimeMode + "\", "; + } + errString = errString.substr(0, errString.length() - 2) + ")!"; + throw errString.c_str(); + } + } + reader.getIfPresent("bannerShowProgress", bannerShowProgress); + reader.getIfPresent("bannerShowScore", bannerShowScore); reader.getIfPresent("hudFont", hudFont); reader.getIfPresent("showPlayerHealthBar", showPlayerHealthBar); reader.getIfPresent("playerHealthBarSize", playerHealthBarSize); @@ -277,6 +291,9 @@ Any HudConfig::addToAny(Any a, bool forceAll) const { HudConfig def; if (forceAll || def.enable != enable) a["showHUD"] = enable; if (forceAll || def.showBanner != showBanner) a["showBanner"] = showBanner; + if (forceAll || def.bannerTimerMode != bannerTimerMode) a["bannerTimerMode"] = bannerTimerMode; + if (forceAll || def.bannerShowProgress != bannerShowProgress) a["bannerShowProgress"] = bannerShowProgress; + if (forceAll || def.bannerShowScore != bannerShowScore) a["bannerShowScore"] = bannerShowScore; if (forceAll || def.hudFont != hudFont) a["hudFont"] = hudFont; if (forceAll || def.showPlayerHealthBar != showPlayerHealthBar) a["showPlayerHealthBar"] = showPlayerHealthBar; if (forceAll || def.playerHealthBarSize != playerHealthBarSize) a["playerHealthBarSize"] = playerHealthBarSize; diff --git a/source/FpsConfig.h b/source/FpsConfig.h index 9bb1bd6d..57196b69 100644 --- a/source/FpsConfig.h +++ b/source/FpsConfig.h @@ -89,6 +89,9 @@ class HudConfig { // HUD parameters bool enable = false; ///< Master control for all HUD elements bool showBanner = false; ///< Show the banner display + String bannerTimerMode = "remaining"; ///< Time to show in the banner ("remaining", "elapsed", or "none") + bool bannerShowProgress = true; ///< Show progress in banner? + bool bannerShowScore = true; ///< Show score in banner? float bannerVertVisible = 0.41f; ///< Vertical banner visibility float bannerLargeFontSize = 30.0f; ///< Banner percent complete font size float bannerSmallFontSize = 14.0f; ///< Banner detail font size diff --git a/source/Session.cpp b/source/Session.cpp index 140e8e5a..dde9dca9 100644 --- a/source/Session.cpp +++ b/source/Session.cpp @@ -574,6 +574,14 @@ void Session::accumulateFrameInfo(RealTime t, float sdt, float idt) { } } +bool Session::inTask() { + return currentState == PresentationState::trialTask; +} + +float Session::getElapsedTrialTime() { + return m_timer.getTime(); +} + float Session::getRemainingTrialTime() { if (isNull(m_config)) return 10.0; return m_config->timing.maxTrialDuration - m_timer.getTime(); @@ -591,8 +599,8 @@ float Session::getProgress() { return fnan(); } -int Session::getScore() { - return (int)(10.0 * m_totalRemainingTime); +double Session::getScore() { + return 100.0 * m_totalRemainingTime; } String Session::formatCommand(const String& input) { diff --git a/source/Session.h b/source/Session.h index be263e89..7793e83b 100644 --- a/source/Session.h +++ b/source/Session.h @@ -403,9 +403,11 @@ class Session : public ReferenceCountedObject { /** clear all targets (used when clearing remaining targets at the end of a trial) */ void clearTargets(); + bool inTask(); + float getElapsedTrialTime(); float getRemainingTrialTime(); float getProgress(); - int getScore(); + double getScore(); String getFeedbackMessage(); /** queues action with given name to insert into database when trial completes