[Scummvm-git-logs] scummvm master -> 68bc11b73d5ab830129132566285276e0ba7e5f3
elasota
noreply at scummvm.org
Thu Apr 27 13:48:26 UTC 2023
This automated email contains information about 2 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
e4d63a3280 VCRUISE: Add in-game menu.
68bc11b73d VCRUISE: Permit duplicate inventory items. Fixes potentially getting stuck in the final area.
Commit: e4d63a3280d17084e1be3ce6aba30a31e805c135
https://github.com/scummvm/scummvm/commit/e4d63a3280d17084e1be3ce6aba30a31e805c135
Author: elasota (ejlasota at gmail.com)
Date: 2023-04-27T09:47:43-04:00
Commit Message:
VCRUISE: Add in-game menu.
Changed paths:
engines/vcruise/menu.cpp
engines/vcruise/menu.h
engines/vcruise/runtime.cpp
engines/vcruise/runtime.h
engines/vcruise/vcruise.cpp
engines/vcruise/vcruise.h
diff --git a/engines/vcruise/menu.cpp b/engines/vcruise/menu.cpp
index 3268fc93739..c4f3499cf33 100644
--- a/engines/vcruise/menu.cpp
+++ b/engines/vcruise/menu.cpp
@@ -811,16 +811,14 @@ void ReahMainMenuPage::start() {
Graphics::Surface *buttonGraphic = _menuInterface->getUIGraphic(1);
- // FIXME: Unused
- //Common::Point buttonStateOffset = Common::Point(112, 0);
- //ommon::Point buttonTopLeft = Common::Point(492, 66);
-
const int buttonTopYs[6] = {66, 119, 171, 224, 277, 330};
for (int i = 0; i < 6; i++) {
bool isEnabled = true;
if (i == kButtonContinue)
isEnabled = _menuInterface->hasDefaultSave();
+ else if (i == kButtonLoad)
+ isEnabled = _menuInterface->hasAnySave();
_buttons.push_back(Button(buttonGraphic, Common::Rect(0, i * 44, 112, i * 44 + 44), Common::Rect(492, buttonTopYs[i], 492 + 112, buttonTopYs[i] + 44), Common::Point(112, 0), isEnabled));
}
@@ -885,4 +883,16 @@ MenuPage *createMenuReahMain() {
return new ReahMainMenuPage();
}
+MenuPage *createMenuReahQuit() {
+ return new ReahQuitMenuPage();
+}
+
+MenuPage *createMenuReahHelp() {
+ return new ReahHelpMenuPage();
+}
+
+MenuPage *createMenuReahSound() {
+ return new ReahSoundMenuPage();
+}
+
} // End of namespace VCruise
diff --git a/engines/vcruise/menu.h b/engines/vcruise/menu.h
index 5fd1beab317..9806f1bedd9 100644
--- a/engines/vcruise/menu.h
+++ b/engines/vcruise/menu.h
@@ -53,6 +53,7 @@ public:
virtual Graphics::Surface *getUIGraphic(uint index) const = 0;
virtual Graphics::ManagedSurface *getMenuSurface() const = 0;
virtual bool hasDefaultSave() const = 0;
+ virtual bool hasAnySave() const = 0;
virtual Common::Point getMouseCoordinate() const = 0;
virtual void restartGame() const = 0;
virtual void goToCredits() const = 0;
@@ -77,6 +78,9 @@ protected:
};
MenuPage *createMenuReahMain();
+MenuPage *createMenuReahHelp();
+MenuPage *createMenuReahSound();
+MenuPage *createMenuReahQuit();
} // End of namespace VCruise
diff --git a/engines/vcruise/runtime.cpp b/engines/vcruise/runtime.cpp
index 40791fd07fa..fa8a3d86654 100644
--- a/engines/vcruise/runtime.cpp
+++ b/engines/vcruise/runtime.cpp
@@ -66,6 +66,7 @@ public:
Graphics::Surface *getUIGraphic(uint index) const override;
Graphics::ManagedSurface *getMenuSurface() const override;
bool hasDefaultSave() const override;
+ bool hasAnySave() const override;
Common::Point getMouseCoordinate() const override;
void restartGame() const override;
void goToCredits() const override;
@@ -104,6 +105,10 @@ bool RuntimeMenuInterface::hasDefaultSave() const {
return static_cast<VCruiseEngine *>(g_engine)->hasDefaultSave();
}
+bool RuntimeMenuInterface::hasAnySave() const {
+ return static_cast<VCruiseEngine *>(g_engine)->hasAnySave();
+}
+
Common::Point RuntimeMenuInterface::getMouseCoordinate() const {
return _runtime->_mousePos;
}
@@ -845,6 +850,7 @@ Runtime::Runtime(OSystem *system, Audio::Mixer *mixer, const Common::FSNode &roo
_loadedAnimation(0), _loadedAnimationHasSound(false), _animPendingDecodeFrame(0), _animDisplayingFrame(0), _animFirstFrame(0), _animLastFrame(0), _animStopFrame(0),
_animStartTime(0), _animFramesDecoded(0), _animDecoderState(kAnimDecoderStateStopped),
_animPlayWhileIdle(false), _idleIsOnInteraction(false), _idleHaveClickInteraction(false), _idleHaveDragInteraction(false), _idleInteractionID(0), _haveIdleStaticAnimation(false),
+ _inGameMenuState(kInGameMenuStateInvisible), _inGameMenuActiveElement(0), _inGameMenuButtonActive {false, false, false, false, false},
/*_loadedArea(0), */_lmbDown(false), _lmbDragging(false), _lmbReleaseWasClick(false), _lmbDownTime(0),
_delayCompletionTime(0),
_panoramaState(kPanoramaStateInactive),
@@ -1196,32 +1202,36 @@ bool Runtime::runIdle() {
return true;
}
} else if (osEvent.type == kOSEventTypeLButtonUp) {
- PanoramaState oldPanoramaState = _panoramaState;
- _panoramaState = kPanoramaStateInactive;
+ if (_inGameMenuState != kInGameMenuStateInvisible) {
+ dischargeInGameMenuMouseUp();
+ } else {
+ PanoramaState oldPanoramaState = _panoramaState;
+ _panoramaState = kPanoramaStateInactive;
- // This is the correct place for matching the original game's behavior, not switching to panorama
- resetInventoryHighlights();
+ // This is the correct place for matching the original game's behavior, not switching to panorama
+ resetInventoryHighlights();
- if (_lmbReleaseWasClick) {
- bool changedState = dischargeIdleClick();
- if (changedState) {
- drawCompass();
- return true;
+ if (_lmbReleaseWasClick) {
+ bool changedState = dischargeIdleClick();
+ if (changedState) {
+ drawCompass();
+ return true;
+ }
}
- }
- // If the released from panorama mode, pick up any interactions at the new mouse location, and change the mouse back
- if (oldPanoramaState != kPanoramaStateInactive) {
- changeToCursor(_cursors[kCursorArrow]);
+ // If the released from panorama mode, pick up any interactions at the new mouse location, and change the mouse back
+ if (oldPanoramaState != kPanoramaStateInactive) {
+ changeToCursor(_cursors[kCursorArrow]);
- // Clear idle interaction so that if a drag occurs but doesn't trigger a panorama or other state change,
- // interactions are re-detected here.
- _idleIsOnInteraction = false;
+ // Clear idle interaction so that if a drag occurs but doesn't trigger a panorama or other state change,
+ // interactions are re-detected here.
+ _idleIsOnInteraction = false;
- bool changedState = dischargeIdleMouseMove();
- if (changedState) {
- drawCompass();
- return true;
+ bool changedState = dischargeIdleMouseMove();
+ if (changedState) {
+ drawCompass();
+ return true;
+ }
}
}
} else if (osEvent.type == kOSEventTypeLButtonDown) {
@@ -2258,43 +2268,15 @@ void Runtime::changeToCursor(const Common::SharedPtr<Graphics::WinCursorGroup> &
bool Runtime::dischargeIdleMouseMove() {
const MapScreenDirectionDef *sdDef = _map.getScreenDirection(_screenNumber, _direction);
- if (_panoramaState == kPanoramaStateInactive) {
- Common::Point relMouse(_mousePos.x - _gameSection.rect.left, _mousePos.y - _gameSection.rect.top);
-
- bool isOnInteraction = false;
- uint interactionID = 0;
- if (sdDef) {
- for (const InteractionDef &idef : sdDef->interactions) {
- if (idef.objectType == 1 && idef.rect.contains(relMouse)) {
- isOnInteraction = true;
- interactionID = idef.interactionID;
- break;
- }
- }
- }
-
- if (_idleIsOnInteraction && (!isOnInteraction || interactionID != _idleInteractionID)) {
- // Mouse left the previous interaction
- _idleIsOnInteraction = false;
- _idleHaveClickInteraction = false;
- _idleHaveDragInteraction = false;
- changeToCursor(_cursors[kCursorArrow]);
- resetInventoryHighlights();
- }
-
- if (isOnInteraction && _idleIsOnInteraction == false) {
- _idleIsOnInteraction = true;
- _idleInteractionID = interactionID;
+ if (_inGameMenuState != kInGameMenuStateInvisible) {
+ checkInGameMenuHover();
- // New interaction, is there a script?
- Common::SharedPtr<Script> script = findScriptForInteraction(interactionID);
+ // If still in the menu, ignore anything else
+ if (_inGameMenuState != kInGameMenuStateInvisible)
+ return false;
+ }
- if (script) {
- activateScript(script, ScriptEnvironmentVars());
- return true;
- }
- }
- } else {
+ if (_panoramaState != kPanoramaStateInactive) {
uint interactionID = 0;
Common::Point panRelMouse = _mousePos - _panoramaAnchor;
@@ -2328,11 +2310,58 @@ bool Runtime::dischargeIdleMouseMove() {
}
}
+ Common::Point relMouse(_mousePos.x - _gameSection.rect.left, _mousePos.y - _gameSection.rect.top);
+
+ bool isOnInteraction = false;
+ uint interactionID = 0;
+ if (sdDef) {
+ for (const InteractionDef &idef : sdDef->interactions) {
+ if (idef.objectType == 1 && idef.rect.contains(relMouse)) {
+ isOnInteraction = true;
+ interactionID = idef.interactionID;
+ break;
+ }
+ }
+ }
+
+ if (_idleIsOnInteraction && (!isOnInteraction || interactionID != _idleInteractionID)) {
+ // Mouse left the previous interaction
+ _idleIsOnInteraction = false;
+ _idleHaveClickInteraction = false;
+ _idleHaveDragInteraction = false;
+ changeToCursor(_cursors[kCursorArrow]);
+ resetInventoryHighlights();
+ }
+
+ if (isOnInteraction && _idleIsOnInteraction == false) {
+ _idleIsOnInteraction = true;
+ _idleInteractionID = interactionID;
+
+ // New interaction, is there a script?
+ Common::SharedPtr<Script> script = findScriptForInteraction(interactionID);
+
+ if (script) {
+ activateScript(script, ScriptEnvironmentVars());
+ return true;
+ }
+ }
+
+ if (_panoramaState == kPanoramaStateInactive)
+ checkInGameMenuHover();
+
// Didn't do anything
return false;
}
bool Runtime::dischargeIdleMouseDown() {
+ if (_inGameMenuState != kInGameMenuStateInvisible) {
+ if (_inGameMenuState == kInGameMenuStateHoveringActive) {
+ _inGameMenuState = kInGameMenuStateClickingOver;
+ drawInGameMenuButton(_inGameMenuActiveElement);
+ }
+ return false;
+ }
+
if (_idleIsOnInteraction && _idleHaveDragInteraction) {
// Interaction, is there a script?
Common::SharedPtr<Script> script = findScriptForInteraction(_idleInteractionID);
@@ -3261,7 +3290,7 @@ void Runtime::detectPanoramaDirections() {
}
void Runtime::detectPanoramaMouseMovement(uint32 timestamp) {
- if (_panoramaState == kPanoramaStateInactive && (_lmbDragging || (_lmbDown && (timestamp - _lmbDownTime) >= 500)))
+ if (_panoramaState == kPanoramaStateInactive && _inGameMenuState == kInGameMenuStateInvisible && (_lmbDragging || (_lmbDown && (timestamp - _lmbDownTime) >= 500)))
panoramaActivate();
}
@@ -3377,7 +3406,7 @@ void Runtime::clearTray() {
}
void Runtime::drawInventory(uint slot) {
- if (_subtitleQueue.size() > 0 || _loadedAnimationHasSound || !_isInGame)
+ if (!isTrayVisible())
return;
Common::Rect trayRect = _traySection.rect;
@@ -3417,7 +3446,7 @@ void Runtime::drawInventory(uint slot) {
}
void Runtime::drawCompass() {
- if (_subtitleQueue.size() > 0 || _loadedAnimationHasSound || !_isInGame)
+ if (!isTrayVisible())
return;
bool haveHorizontalRotate = false;
@@ -3486,6 +3515,10 @@ void Runtime::drawCompass() {
commitSectionToScreen(_traySection, lowerRightRect);
}
+bool Runtime::isTrayVisible() const {
+ return _subtitleQueue.size() == 0 && !_loadedAnimationHasSound && _isInGame && (_gameState != kGameStateMenu);
+}
+
void Runtime::resetInventoryHighlights() {
for (uint slot = 0; slot < kNumInventorySlots; slot++) {
InventoryItem &item = _inventory[slot];
@@ -3606,6 +3639,171 @@ void Runtime::changeToMenuPage(MenuPage *menuPage) {
menuPage->start();
}
+void Runtime::checkInGameMenuHover() {
+ if (_inGameMenuState == kInGameMenuStateInvisible) {
+ if (_menuSection.rect.contains(_mousePos)) {
+ // Figure out what elements should be visible
+
+ // Help
+ _inGameMenuButtonActive[0] = true;
+
+ // Save
+ _inGameMenuButtonActive[1] = (_saveGame != nullptr);
+
+ // Load
+ _inGameMenuButtonActive[2] = static_cast<VCruiseEngine *>(g_engine)->hasAnySave();
+
+ // Sound
+ _inGameMenuButtonActive[3] = true;
+
+ // Quit
+ _inGameMenuButtonActive[4] = true;
+
+ _inGameMenuState = kInGameMenuStateVisible;
+ for (uint i = 0; i < 5; i++)
+ drawInGameMenuButton(i);
+ }
+ }
+
+ if (_inGameMenuState == kInGameMenuStateInvisible)
+ return;
+
+ if (!_menuSection.rect.contains(_mousePos)) {
+ if (_inGameMenuState != kInGameMenuStateClickingOver && _inGameMenuState != kInGameMenuStateClickingNotOver && _inGameMenuState != kInGameMenuStateClickingInactive) {
+ dismissInGameMenu();
+ return;
+ }
+ }
+
+ uint activeElement = 0;
+ if (_mousePos.x >= _menuSection.rect.left && _mousePos.y < _menuSection.rect.right)
+ activeElement = static_cast<uint>(_mousePos.x - _menuSection.rect.left) / 128u;
+
+ assert(activeElement < 5);
+
+ switch (_inGameMenuState) {
+ case kInGameMenuStateVisible:
+ if (_inGameMenuButtonActive[activeElement]) {
+ _inGameMenuState = kInGameMenuStateHoveringActive;
+ _inGameMenuActiveElement = activeElement;
+ drawInGameMenuButton(activeElement);
+ }
+ break;
+ case kInGameMenuStateHoveringActive:
+ if (activeElement != _inGameMenuActiveElement) {
+ uint oldElement = _inGameMenuActiveElement;
+
+ if (_inGameMenuButtonActive[activeElement]) {
+ _inGameMenuState = kInGameMenuStateHoveringActive;
+ _inGameMenuActiveElement = activeElement;
+ drawInGameMenuButton(activeElement);
+ } else
+ _inGameMenuState = kInGameMenuStateVisible;
+
+ drawInGameMenuButton(oldElement);
+ }
+ break;
+ case kInGameMenuStateClickingOver:
+ if (activeElement != _inGameMenuActiveElement) {
+ _inGameMenuState = kInGameMenuStateClickingNotOver;
+ drawInGameMenuButton(_inGameMenuActiveElement);
+ }
+ break;
+ case kInGameMenuStateClickingNotOver:
+ if (activeElement == _inGameMenuActiveElement) {
+ _inGameMenuState = kInGameMenuStateClickingOver;
+ drawInGameMenuButton(_inGameMenuActiveElement);
+ }
+ break;
+ case kInGameMenuStateClickingInactive:
+ break;
+ default:
+ error("Invalid menu state");
+ break;
+ }
+}
+
+void Runtime::dismissInGameMenu() {
+ const Common::Rect menuRect(0, 0, _menuSection.surf->w, _menuSection.surf->h);
+
+ uint32 blackColor = _menuSection.surf->format.RGBToColor(0, 0, 0);
+ _menuSection.surf->fillRect(menuRect, blackColor);
+
+ commitSectionToScreen(_menuSection, menuRect);
+
+ _inGameMenuState = kInGameMenuStateInvisible;
+}
+
+void Runtime::dischargeInGameMenuMouseUp() {
+ if (_inGameMenuState == kInGameMenuStateClickingOver) {
+ dismissInGameMenu();
+
+ // Handle click event
+ switch (_inGameMenuActiveElement) {
+ case 0:
+ changeToMenuPage(createMenuReahHelp());
+ break;
+ case 1:
+ g_engine->saveGameDialog();
+ break;
+ case 2:
+ g_engine->loadGameDialog();
+ break;
+ case 3:
+ changeToMenuPage(createMenuReahSound());
+ break;
+ case 4:
+ changeToMenuPage(createMenuReahQuit());
+ break;
+ default:
+ break;
+ }
+ } else {
+ _inGameMenuState = kInGameMenuStateVisible;
+ drawInGameMenuButton(_inGameMenuActiveElement);
+
+ checkInGameMenuHover();
+ }
+}
+
+void Runtime::drawInGameMenuButton(uint element) {
+ Common::Rect buttonDestRect = Common::Rect(element * 128u, 0, element * 128u + 128u, _menuSection.rect.height());
+
+ int buttonState = 0;
+ if (_inGameMenuButtonActive[element])
+ buttonState = 1;
+
+ switch (_inGameMenuState) {
+ case kInGameMenuStateVisible:
+ break;
+ case kInGameMenuStateHoveringActive:
+ if (element == _inGameMenuActiveElement)
+ buttonState = 2;
+ break;
+ case kInGameMenuStateClickingOver:
+ if (element == _inGameMenuActiveElement)
+ buttonState = 3;
+ break;
+ case kInGameMenuStateClickingNotOver:
+ if (element == _inGameMenuActiveElement)
+ buttonState = 2;
+ break;
+ case kInGameMenuStateClickingInactive:
+ break;
+ default:
+ error("Invalid menu state");
+ break;
+ }
+
+ Common::Point buttonTopLeftPoint = Common::Point(buttonDestRect.left, buttonDestRect.top);
+ buttonTopLeftPoint.y += buttonState * 44;
+
+ Common::Rect buttonSrcRect = Common::Rect(buttonTopLeftPoint.x, buttonTopLeftPoint.y, buttonTopLeftPoint.x + 128, buttonTopLeftPoint.y + _menuSection.rect.height());
+
+ _menuSection.surf->blitFrom(*_uiGraphics[4], buttonSrcRect, buttonDestRect);
+ commitSectionToScreen(_menuSection, buttonDestRect);
+}
+
void Runtime::onLButtonDown(int16 x, int16 y) {
onMouseMove(x, y);
diff --git a/engines/vcruise/runtime.h b/engines/vcruise/runtime.h
index 8aed91311ee..491a9448f07 100644
--- a/engines/vcruise/runtime.h
+++ b/engines/vcruise/runtime.h
@@ -558,6 +558,16 @@ private:
kPanoramaStatePanningDown,
};
+ enum InGameMenuState {
+ kInGameMenuStateInvisible,
+ kInGameMenuStateVisible,
+ kInGameMenuStateHoveringInactive,
+ kInGameMenuStateHoveringActive,
+ kInGameMenuStateClickingOver, // Mouse was pressed on a button and is holding on it
+ kInGameMenuStateClickingNotOver, // Mouse was pressed on a button and dragged off
+ kInGameMenuStateClickingInactive,
+ };
+
static const uint kPanLeftInteraction = 1;
static const uint kPanDownInteraction = 2;
static const uint kPanRightInteraction = 3;
@@ -703,6 +713,7 @@ private:
void clearTray();
void drawInventory(uint slot);
void drawCompass();
+ bool isTrayVisible() const;
void resetInventoryHighlights();
Common::String getFileNameForItemGraphic(uint itemID) const;
@@ -712,6 +723,11 @@ private:
void changeToMenuPage(MenuPage *menuPage);
+ void checkInGameMenuHover();
+ void dismissInGameMenu();
+ void dischargeInGameMenuMouseUp();
+ void drawInGameMenuButton(uint element);
+
// Script things
void scriptOpNumber(ScriptArg_t arg);
void scriptOpRotate(ScriptArg_t arg);
@@ -949,6 +965,10 @@ private:
bool _idleHaveDragInteraction;
uint _idleInteractionID;
+ InGameMenuState _inGameMenuState;
+ uint _inGameMenuActiveElement;
+ bool _inGameMenuButtonActive[5];
+
Audio::Mixer *_mixer;
MapDef _map;
diff --git a/engines/vcruise/vcruise.cpp b/engines/vcruise/vcruise.cpp
index cb51405fa3b..46ea020ec37 100644
--- a/engines/vcruise/vcruise.cpp
+++ b/engines/vcruise/vcruise.cpp
@@ -291,5 +291,9 @@ bool VCruiseEngine::hasDefaultSave() {
return autoSaveExists;
}
+bool VCruiseEngine::hasAnySave() {
+ return hasDefaultSave(); // Maybe could do this better, but with how ScummVM works, if there are any saves at all, then the autosave should exist.
+}
+
} // End of namespace VCruise
diff --git a/engines/vcruise/vcruise.h b/engines/vcruise/vcruise.h
index 53b60919c01..ef0e1905d95 100644
--- a/engines/vcruise/vcruise.h
+++ b/engines/vcruise/vcruise.h
@@ -63,6 +63,7 @@ public:
void initializePath(const Common::FSNode &gamePath) override;
bool hasDefaultSave();
+ bool hasAnySave();
protected:
void pauseEngineIntern(bool pause) override;
Commit: 68bc11b73d5ab830129132566285276e0ba7e5f3
https://github.com/scummvm/scummvm/commit/68bc11b73d5ab830129132566285276e0ba7e5f3
Author: elasota (ejlasota at gmail.com)
Date: 2023-04-27T09:47:43-04:00
Commit Message:
VCRUISE: Permit duplicate inventory items. Fixes potentially getting stuck in the final area.
Changed paths:
engines/vcruise/runtime.cpp
diff --git a/engines/vcruise/runtime.cpp b/engines/vcruise/runtime.cpp
index fa8a3d86654..89502f806d8 100644
--- a/engines/vcruise/runtime.cpp
+++ b/engines/vcruise/runtime.cpp
@@ -3354,8 +3354,6 @@ void Runtime::inventoryAddItem(uint item) {
uint firstOpenSlot = kNumInventorySlots;
for (uint i = 0; i < kNumInventorySlots; i++) {
- if (_inventory[i].itemID == item)
- return;
if (_inventory[i].itemID == 0 && firstOpenSlot == kNumInventorySlots)
firstOpenSlot = i;
}
@@ -3380,6 +3378,7 @@ void Runtime::inventoryRemoveItem(uint itemID) {
item.itemID = 0;
item.graphic.reset();
drawInventory(slot);
+ break;
}
}
}
@@ -4478,6 +4477,7 @@ void Runtime::scriptOpItemHighlightSet(ScriptArg_t arg) {
if (item.itemID == static_cast<uint>(stackArgs[0])) {
item.highlighted = isHighlighted;
drawInventory(slot);
+ break;
}
}
}
More information about the Scummvm-git-logs
mailing list