/** * Save current scene. * @param sd Pointer to the scene data */ void DoSaveScene(SAVED_DATA *sd) { sd->SavedSceneHandle = GetSceneHandle(); sd->SavedBgroundHandle = GetBgroundHandle(); SaveMovers(sd->SavedMoverInfo); sd->NumSavedActors = SaveActors(sd->SavedActorInfo); PlayfieldGetPos(FIELD_WORLD, &sd->SavedLoffset, &sd->SavedToffset); SaveInterpretContexts(sd->SavedICInfo); sd->SavedControl = ControlIsOn(); sd->SavedNoBlocking = GetNoBlocking(); GetNoScrollData(&sd->SavedNoScrollData); if (TinselV2) { // Tinsel 2 specific data save SaveActorZ(sd->savedActorZ); SaveZpositions(sd->zPositions); SavePolygonStuff(sd->SavedPolygonStuff); _vm->_pcmMusic->getTunePlaying(sd->SavedTune, sizeof(sd->SavedTune)); sd->bTinselDim = _vm->_pcmMusic->getMusicTinselDimmed(); sd->SavedScrollFocus = GetScrollFocus(); SaveSysVars(sd->SavedSystemVars); SaveSoundReels(sd->SavedSoundReels); } else { // Tinsel 1 specific data save SaveDeadPolys(sd->SavedDeadPolys); CurrentMidiFacts(&sd->SavedMidi, &sd->SavedLoop); } ASceneIsSaved = true; }
/** * Process to handle changes in the mouse buttons. */ static void MouseProcess(CORO_PARAM, const void *) { // COROUTINE CORO_BEGIN_CONTEXT; bool lastLWasDouble; bool lastRWasDouble; uint32 lastLeftClick, lastRightClick; CORO_END_CONTEXT(_ctx); CORO_BEGIN_CODE(_ctx); _ctx->lastLWasDouble = false; _ctx->lastRWasDouble = false; _ctx->lastLeftClick = _ctx->lastRightClick = DwGetCurrentTime(); while (true) { if (mouseButtons.empty()) { // allow scheduling CORO_SLEEP(1); continue; } // get next mouse button event Common::EventType type = *mouseButtons.begin(); mouseButtons.erase(mouseButtons.begin()); int xp, yp; GetCursorXYNoWait(&xp, &yp, true); const Common::Point mousePos(xp, yp); switch (type) { case Common::EVENT_LBUTTONDOWN: // left button press if (DwGetCurrentTime() - _ctx->lastLeftClick < (uint32)dclickSpeed) { // Left button double-click if (TinselV2) { // Kill off the button process and fire off the action command g_scheduler->killMatchingProcess(PID_BTN_CLICK, -1); PlayerEvent(PLR_ACTION, clickPos); } else { // signal left drag start ProcessButEvent(PLR_DRAG1_START); // signal left double click event ProcessButEvent(PLR_DLEFT); } _ctx->lastLWasDouble = true; } else { // Initial mouse down - either for a single click, or potentially // the start of a double-click action if (TinselV2) { PlayerEvent(PLR_DRAG1_START, mousePos); ProvNotProcessed(); PlayerEvent(PLR_PROV_WALKTO, mousePos); } else { // signal left drag start ProcessButEvent(PLR_DRAG1_START); // signal left single click event ProcessButEvent(PLR_SLEFT); } _ctx->lastLWasDouble = false; } break; case Common::EVENT_LBUTTONUP: // left button release // update click timer if (_ctx->lastLWasDouble == false) { _ctx->lastLeftClick = DwGetCurrentTime(); // If player control is enabled, start a process which, if it times out, // will activate a single button click if (TinselV2 && ControlIsOn()) { clickPos = mousePos; g_scheduler->createProcess(PID_BTN_CLICK, SingleLeftProcess, NULL, 0); } } else _ctx->lastLeftClick -= dclickSpeed; if (TinselV2) // Signal left drag end PlayerEvent(PLR_DRAG1_END, mousePos); else // signal left drag end ProcessButEvent(PLR_DRAG1_END); break; case Common::EVENT_RBUTTONDOWN: // right button press if (DwGetCurrentTime() - _ctx->lastRightClick < (uint32)dclickSpeed) { // Right button double-click if (TinselV2) { PlayerEvent(PLR_NOEVENT, clickPos); } else { // signal right drag start ProcessButEvent(PLR_DRAG2_START); // signal right double click event ProcessButEvent(PLR_DRIGHT); } _ctx->lastRWasDouble = true; } else { if (TinselV2) { PlayerEvent(PLR_DRAG2_START, mousePos); PlayerEvent(PLR_LOOK, mousePos); } else { // signal right drag start ProcessButEvent(PLR_DRAG2_START); // signal right single click event ProcessButEvent(PLR_SRIGHT); } _ctx->lastRWasDouble = false; } break; case Common::EVENT_RBUTTONUP: // right button release // update click timer if (_ctx->lastRWasDouble == false) _ctx->lastRightClick = DwGetCurrentTime(); else _ctx->lastRightClick -= dclickSpeed; if (TinselV2) // Signal left drag end PlayerEvent(PLR_DRAG2_END, mousePos); else // signal right drag end ProcessButEvent(PLR_DRAG2_END); break; default: break; } } CORO_END_CODE; }
/** * Main interface point for specifying player atcions */ void PlayerEvent(PLR_EVENT pEvent, const Common::Point &coOrds) { // Logging of player actions const char *actionList[] = { "PLR_PROV_WALKTO", "PLR_WALKTO", "PLR_LOOK", "PLR_ACTION", "PLR_ESCAPE", "PLR_MENU", "PLR_QUIT", "PLR_PGUP", "PLR_PGDN", "PLR_HOME", "PLR_END", "PLR_DRAG1_START", "PLR_DRAG1_END", "PLR_DRAG2_START", "PLR_DRAG2_END", "PLR_JUMP", "PLR_NOEVENT", "PLR_SAVE", "PLR_LOAD", "PLR_WHEEL_UP", "PLR_WHEEL_DOWN"}; debugC(DEBUG_BASIC, kTinselDebugActions, "%s - (%d,%d)", actionList[pEvent], coOrds.x, coOrds.y); static uint32 lastRealAction = 0; // FIXME: Avoid non-const global vars // This stuff to allow F1 key during startup. if (g_bEnableMenu && pEvent == PLR_MENU) Control(CONTROL_ON); else IncUserEvents(); if (pEvent == PLR_ESCAPE) { ++g_escEvents; ++g_leftEvents; // Yes, I do mean this } else if ((pEvent == PLR_PROV_WALKTO) || (pEvent == PLR_WALKTO) || (pEvent == PLR_LOOK) || (pEvent == PLR_ACTION)) { ++g_leftEvents; } // Only allow events if player control is on if (!ControlIsOn() && (pEvent != PLR_DRAG1_END)) return; if (TinselV2 && InventoryActive()) { int x, y; PlayfieldGetPos(FIELD_WORLD, &x, &y); EventToInventory(pEvent, Common::Point(coOrds.x - x, coOrds.y - y)); return; } switch (pEvent) { case PLR_QUIT: OpenMenu(QUIT_MENU); break; case PLR_MENU: OpenMenu(MAIN_MENU); break; case PLR_JUMP: OpenMenu(HOPPER_MENU1); break; case PLR_SAVE: OpenMenu(SAVE_MENU); break; case PLR_LOAD: OpenMenu(LOAD_MENU); break; case PLR_PROV_WALKTO: // Provisional WALKTO ! ProcessUserEvent(PROV_WALKTO, coOrds); break; case PLR_WALKTO: REAL_ACTION_CHECK; if (TinselV2 || !InventoryActive()) ProcessUserEvent(WALKTO, coOrds, PLR_SLEFT); else EventToInventory(PLR_SLEFT, coOrds); break; case PLR_ACTION: REAL_ACTION_CHECK; if (TinselV2 || !InventoryActive()) ProcessUserEvent(ACTION, coOrds, PLR_DLEFT); else EventToInventory(PLR_DLEFT, coOrds); break; case PLR_LOOK: REAL_ACTION_CHECK; if (TinselV2 || !InventoryActive()) ProcessUserEvent(LOOK, coOrds, PLR_SRIGHT); else EventToInventory(PLR_SRIGHT, coOrds); break; default: if (InventoryActive()) EventToInventory(pEvent, coOrds); break; } }