void GAFObject::step() { m_showingFrame = m_currentFrame; if (!getIsAnimationRunning()) { processAnimation(); return; } if (m_sequenceDelegate && m_timeline) { const GAFAnimationSequence * seq = nullptr; if (!m_isReversed) { seq = m_timeline->getSequenceByLastFrame(m_currentFrame); } else { seq = m_timeline->getSequenceByFirstFrame(m_currentFrame + 1); } if (seq) { m_sequenceDelegate(this, seq->name); } } if (isCurrentFrameLastInSequence()) { if (m_isLooped) { if (m_animationStartedNextLoopDelegate) m_animationStartedNextLoopDelegate(this); } else { setAnimationRunning(false, false); if (m_animationFinishedPlayDelegate) m_animationFinishedPlayDelegate(this); } } processAnimation(); m_showingFrame = m_currentFrame; m_currentFrame = nextFrame(); }
void GAFAnimation::step() { if (_sequenceDelegate && _asset) { GAFAnimationSequence * seq = _asset->getSequenceByLastFrame(_currentFrameIndex); if (seq) { _sequenceDelegate->onFinishSequence(dynamic_cast<GAFAnimatedObject*>(this), seq->name); } } if (_isLooped) { if (_currentFrameIndex >= _currentSequenceEnd) { _currentFrameIndex = _currentSequenceStart; } } else { if (_currentFrameIndex >= _currentSequenceEnd) { _isRunning = false; return; } } processAnimation(); ++_currentFrameIndex; }
bool GAFAnimation::setFrame(int aFrameIndex) { if (aFrameIndex >= 0 && aFrameIndex < m_totalFrameCount) { _currentFrameIndex = aFrameIndex; processAnimation(); return true; } return false; }
bool GAFObject::setFrame(uint32_t index) { if (index < m_totalFrameCount) { m_showingFrame = m_currentFrame = index; processAnimation(); return true; } return false; }
void SceneDisplayCallback(void) { // Setup viewing transformation glLoadIdentity(); glScalef(scale, scale, scale); glTranslatef(translation[0], translation[1], 0.0); // Set projection transformation glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0, (GLfloat) GLUTwindow_width / (GLfloat) GLUTwindow_height, 0.1, 100.0); // Set camera transformation glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(translation[0], translation[1], translation[2]); glScalef(scale, scale, scale); glRotatef(rotation[0], 1.0, 0.0, 0.0); glRotatef(rotation[1], 0.0, 1.0, 0.0); glRotatef(rotation[2], 0.0, 0.0, 1.0); glTranslatef(-center[0], -center[1], -center[2]); // Clear window glClearColor(0.0, 0.0, 0.0, 1.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Set lights glLightfv(GL_LIGHT0, GL_POSITION, difflight_position); glLightfv(GL_LIGHT0, GL_DIFFUSE, difflight_color); static GLfloat light1_position[] = {-3.0, -4.0, -5.0, 0.0}; glLightfv(GL_LIGHT1, GL_POSITION, light1_position); // Draw stuff drawScene(); drawDebugInfo(); processAnimation(); // Swap buffers glutSwapBuffers(); }
void CruiseEngine::pauseEngine(bool pause) { Engine::pauseEngine(pause); if (pause) { // Draw the 'Paused' message drawSolidBox(64, 100, 256, 117, 0); drawString(10, 100, langString(ID_PAUSED), gfxModuleData.pPage00, itemColor, 300); gfxModuleData_flipScreen(); _savedCursor = currentCursor; changeCursor(CURSOR_NOMOUSE); } else { processAnimation(); flipScreen(); changeCursor(_savedCursor); } gfxModuleData_addDirtyRect(Common::Rect(64, 100, 256, 117)); }
void ColladaShapeLoader::processAnimation(const domAnimation* anim, F32& maxEndTime, F32& minFrameTime) { const char* sRGBANames[] = { ".R", ".G", ".B", ".A", "" }; const char* sXYZNames[] = { ".X", ".Y", ".Z", "" }; const char* sXYZANames[] = { ".X", ".Y", ".Z", ".ANGLE" }; const char* sLOOKATNames[] = { ".POSITIONX", ".POSITIONY", ".POSITIONZ", ".TARGETX", ".TARGETY", ".TARGETZ", ".UPX", ".UPY", ".UPZ", "" }; const char* sSKEWNames[] = { ".ROTATEX", ".ROTATEY", ".ROTATEZ", ".AROUNDX", ".AROUNDY", ".AROUNDZ", ".ANGLE", "" }; const char* sNullNames[] = { "" }; for (S32 iChannel = 0; iChannel < anim->getChannel_array().getCount(); iChannel++) { // Get the animation elements: <channel>, <sampler> domChannel* channel = anim->getChannel_array()[iChannel]; domSampler* sampler = daeSafeCast<domSampler>(channel->getSource().getElement()); if (!sampler) continue; // Find the animation channel target daeSIDResolver resolver(channel, channel->getTarget()); daeElement* target = resolver.getElement(); if (!target) { daeErrorHandler::get()->handleWarning(avar("Failed to resolve animation " "target: %s", channel->getTarget())); continue; } /* // If the target is a <source>, point it at the array instead // @todo:Only support targeting float arrays for now... if (target->getElementType() == COLLADA_TYPE::SOURCE) { domSource* source = daeSafeCast<domSource>(target); if (source->getFloat_array()) target = source->getFloat_array(); } */ // Get the target's animation channels (create them if not already) if (!AnimData::getAnimChannels(target)) { animations.push_back(new AnimChannels(target)); } AnimChannels* targetChannels = AnimData::getAnimChannels(target); // Add a new animation channel to the target targetChannels->push_back(new AnimData()); channel->setUserData(targetChannels->last()); AnimData& data = *targetChannels->last(); for (S32 iInput = 0; iInput < sampler->getInput_array().getCount(); iInput++) { const domInputLocal* input = sampler->getInput_array()[iInput]; const domSource* source = daeSafeCast<domSource>(input->getSource().getElement()); if (!source) continue; // @todo:don't care about the input param names for now. Could // validate against the target type.... if (dStrEqual(input->getSemantic(), "INPUT")) { data.input.initFromSource(source); // Adjust the maximum sequence end time maxEndTime = getMax(maxEndTime, data.input.getFloatValue((S32)data.input.size()-1)); // Detect the frame rate (minimum time between keyframes) for (S32 iFrame = 1; iFrame < data.input.size(); iFrame++) { F32 delta = data.input.getFloatValue( iFrame ) - data.input.getFloatValue( iFrame-1 ); if ( delta < 0 ) { daeErrorHandler::get()->handleError(avar("<animation> INPUT '%s' " "has non-monotonic keys. Animation is unlikely to be imported correctly.", source->getID())); break; } minFrameTime = getMin( minFrameTime, delta ); } } else if (dStrEqual(input->getSemantic(), "OUTPUT")) data.output.initFromSource(source); else if (dStrEqual(input->getSemantic(), "IN_TANGENT")) data.inTangent.initFromSource(source); else if (dStrEqual(input->getSemantic(), "OUT_TANGENT")) data.outTangent.initFromSource(source); else if (dStrEqual(input->getSemantic(), "INTERPOLATION")) data.interpolation.initFromSource(source); } // Set initial value for visibility targets that were added automatically (in colladaUtils.cpp if (dStrEqual(target->getElementName(), "visibility")) { domAny* visTarget = daeSafeCast<domAny>(target); if (visTarget && dStrEqual(visTarget->getValue(), "")) visTarget->setValue(avar("%g", data.output.getFloatValue(0))); } // Ignore empty animations if (data.input.size() == 0) { channel->setUserData(0); delete targetChannels->last(); targetChannels->pop_back(); continue; } // Determine the number and offset the elements of the target value // targeted by this animation switch (target->getElementType()) { case COLLADA_TYPE::COLOR: data.parseTargetString(channel->getTarget(), 4, sRGBANames); break; case COLLADA_TYPE::TRANSLATE: data.parseTargetString(channel->getTarget(), 3, sXYZNames); break; case COLLADA_TYPE::ROTATE: data.parseTargetString(channel->getTarget(), 4, sXYZANames); break; case COLLADA_TYPE::SCALE: data.parseTargetString(channel->getTarget(), 3, sXYZNames); break; case COLLADA_TYPE::LOOKAT: data.parseTargetString(channel->getTarget(), 3, sLOOKATNames); break; case COLLADA_TYPE::SKEW: data.parseTargetString(channel->getTarget(), 3, sSKEWNames); break; case COLLADA_TYPE::MATRIX: data.parseTargetString(channel->getTarget(), 16, sNullNames); break; case COLLADA_TYPE::FLOAT_ARRAY: data.parseTargetString(channel->getTarget(), daeSafeCast<domFloat_array>(target)->getCount(), sNullNames); break; default: data.parseTargetString(channel->getTarget(), 1, sNullNames); break; } } // Process child animations for (S32 iAnim = 0; iAnim < anim->getAnimation_array().getCount(); iAnim++) processAnimation(anim->getAnimation_array()[iAnim], maxEndTime, minFrameTime); }
void ColladaShapeLoader::enumerateScene() { // Get animation clips Vector<const domAnimation_clip*> animationClips; for (S32 iClipLib = 0; iClipLib < root->getLibrary_animation_clips_array().getCount(); iClipLib++) { const domLibrary_animation_clips* libraryClips = root->getLibrary_animation_clips_array()[iClipLib]; for (S32 iClip = 0; iClip < libraryClips->getAnimation_clip_array().getCount(); iClip++) appSequences.push_back(new ColladaAppSequence(libraryClips->getAnimation_clip_array()[iClip])); } // Process all animations => this attaches animation channels to the targeted // Collada elements, and determines the length of the sequence if it is not // already specified in the Collada <animation_clip> element for (S32 iSeq = 0; iSeq < appSequences.size(); iSeq++) { ColladaAppSequence* appSeq = dynamic_cast<ColladaAppSequence*>(appSequences[iSeq]); F32 maxEndTime = 0; F32 minFrameTime = 1000.0f; for (S32 iAnim = 0; iAnim < appSeq->getClip()->getInstance_animation_array().getCount(); iAnim++) { domAnimation* anim = daeSafeCast<domAnimation>(appSeq->getClip()->getInstance_animation_array()[iAnim]->getUrl().getElement()); if (anim) processAnimation(anim, maxEndTime, minFrameTime); } if (appSeq->getEnd() == 0) appSeq->setEnd(maxEndTime); // Collada animations can be stored as sampled frames or true keyframes. For // sampled frames, use the same frame rate as the DAE file. For true keyframes, // resample at a fixed frame rate. appSeq->fps = mClamp(1.0f / minFrameTime + 0.5f, TSShapeLoader::MinFrameRate, TSShapeLoader::MaxFrameRate); } // First grab all of the top-level nodes Vector<domNode*> sceneNodes; for (S32 iSceneLib = 0; iSceneLib < root->getLibrary_visual_scenes_array().getCount(); iSceneLib++) { const domLibrary_visual_scenes* libScenes = root->getLibrary_visual_scenes_array()[iSceneLib]; for (S32 iScene = 0; iScene < libScenes->getVisual_scene_array().getCount(); iScene++) { const domVisual_scene* visualScene = libScenes->getVisual_scene_array()[iScene]; for (S32 iNode = 0; iNode < visualScene->getNode_array().getCount(); iNode++) sceneNodes.push_back(visualScene->getNode_array()[iNode]); } } // Set LOD option bool singleDetail = true; switch (ColladaUtils::getOptions().lodType) { case ColladaUtils::ImportOptions::DetectDTS: // Check for a baseXX->startXX hierarchy at the top-level, if we find // one, use trailing numbers for LOD, otherwise use a single size for (S32 iNode = 0; singleDetail && (iNode < sceneNodes.size()); iNode++) { domNode* node = sceneNodes[iNode]; if (dStrStartsWith(_GetNameOrId(node), "base")) { for (S32 iChild = 0; iChild < node->getNode_array().getCount(); iChild++) { domNode* child = node->getNode_array()[iChild]; if (dStrStartsWith(_GetNameOrId(child), "start")) { singleDetail = false; break; } } } } break; case ColladaUtils::ImportOptions::SingleSize: singleDetail = true; break; case ColladaUtils::ImportOptions::TrailingNumber: singleDetail = false; break; default: break; } ColladaAppMesh::fixDetailSize( singleDetail, ColladaUtils::getOptions().singleDetailSize ); // Process the top level nodes for (S32 iNode = 0; iNode < sceneNodes.size(); iNode++) { ColladaAppNode* node = new ColladaAppNode(sceneNodes[iNode], 0); if (!processNode(node)) delete node; } // Make sure that the scene has a bounds node (for getting the root scene transform) if (!boundsNode) { domVisual_scene* visualScene = root->getLibrary_visual_scenes_array()[0]->getVisual_scene_array()[0]; domNode* dombounds = daeSafeCast<domNode>( visualScene->createAndPlace( "node" ) ); dombounds->setName( "bounds" ); ColladaAppNode *appBounds = new ColladaAppNode(dombounds, 0); if (!processNode(appBounds)) delete appBounds; } }
void GAFAnimation::step() { if (! m_isReversed) { if (_currentFrameIndex < m_currentSequenceStart) { _currentFrameIndex = m_currentSequenceStart; } if (_sequenceDelegate && m_asset) { const GAFAnimationSequence * seq = m_asset->getSequenceByLastFrame(_currentFrameIndex); if (seq) { _sequenceDelegate->onFinishSequence(dynamic_cast<GAFAnimatedObject*>(this), seq->name); } } if (_currentFrameIndex >= m_currentSequenceEnd) { if (m_isLooped) { _currentFrameIndex = m_currentSequenceStart; if (m_animationPlaybackDelegate) { m_animationPlaybackDelegate->onAnimationStartedNextLoopDelegate(this); } } else { setAnimationRunning(false); if (m_animationPlaybackDelegate) { m_animationPlaybackDelegate->onAnimationFinishedPlayDelegate(this); } return; } } processAnimation(); ++_currentFrameIndex; } else { // If switched to reverse after final frame played if (_currentFrameIndex >= m_currentSequenceEnd) { _currentFrameIndex = m_currentSequenceEnd - 1; } if (_sequenceDelegate && m_asset) { const GAFAnimationSequence * seq = m_asset->getSequenceByFirstFrame(_currentFrameIndex + 1); if (seq) { _sequenceDelegate->onFinishSequence(dynamic_cast<GAFAnimatedObject*>(this), seq->name); } } if (_currentFrameIndex < m_currentSequenceStart) { if (m_isLooped) { _currentFrameIndex = m_currentSequenceEnd - 1; if (m_animationPlaybackDelegate) { m_animationPlaybackDelegate->onAnimationStartedNextLoopDelegate(this); } } else { setAnimationRunning(false); if (m_animationPlaybackDelegate) { m_animationPlaybackDelegate->onAnimationFinishedPlayDelegate(this); } return; } } processAnimation(); --_currentFrameIndex; } }
void CruiseEngine::mainLoop() { //int32 t_start,t_left; //uint32 t_end; //int32 q=0; /* Dummy */ int16 mouseX, mouseY; int16 mouseButton; int enableUser = 0; strcpy(nextOverlay, ""); strcpy(lastOverlay, ""); strcpy(cmdLine, ""); currentActiveMenu = -1; autoMsg = -1; linkedRelation = 0; main21 = 0; main22 = 0; userWait = 0; autoTrack = false; initAllData(); playerDontAskQuit = 0; int quitValue2 = 1; int quitValue = 0; if (ConfMan.hasKey("save_slot")) loadGameState(ConfMan.getInt("save_slot")); do { // Handle frame delay uint32 currentTick = g_system->getMillis(); if (!bFastMode) { // Delay for the specified amount of time, but still respond to events bool skipEvents = false; do { g_system->delayMillis(10); currentTick = g_system->getMillis(); if (!skipEvents) skipEvents = manageEvents(); if (playerDontAskQuit) break; _vm->getDebugger()->onFrame(); } while (currentTick < lastTick + _gameSpeed); } else { manageEvents(); if (currentTick >= (lastTickDebug + 10)) { lastTickDebug = currentTick; _vm->getDebugger()->onFrame(); } } if (playerDontAskQuit) break; lastTick = g_system->getMillis(); // Handle switchover in game speed after intro if (!_speedFlag && canLoadGameStateCurrently()) { _speedFlag = true; _gameSpeed = GAME_FRAME_DELAY_2; } // Handle the next frame // frames++; // t_start=Osystem_GetTicks(); // readKeyboard(); bool isUserWait = userWait != 0; playerDontAskQuit = processInput(); if (playerDontAskQuit) break; if (enableUser) { userEnabled = 1; enableUser = 0; } if (userDelay && !userWait) { userDelay--; continue; } if (isUserWait & !userWait) { // User waiting has ended changeScriptParamInList(-1, -1, &procHead, 9999, 0); changeScriptParamInList(-1, -1, &relHead, 9999, 0); // Disable any mouse click used to end the user wait currentMouseButton = 0; } // FIXME: I suspect that the original game does multiple script executions between game frames; the bug with // Raoul appearing when looking at the book is being there are 3 script iterations separation between the // scene being changed to the book, and the Raoul actor being frozen/disabled. This loop is a hack to ensure // that when a background changes, a few extra script executions are done bool bgChanged; int numIterations = 1; while (numIterations-- > 0) { bgChanged = backgroundChanged[masterScreen]; manageScripts(&relHead); manageScripts(&procHead); removeFinishedScripts(&relHead); removeFinishedScripts(&procHead); if (!bgChanged && backgroundChanged[masterScreen]) { bgChanged = true; numIterations += 2; } } processAnimation(); if (remdo) { // ASSERT(0); /* main3 = 0; * var24 = 0; * var23 = 0; * * freeStuff2(); */ } if (cmdLine[0]) { ASSERT(0); /* redrawStrings(0,&cmdLine,8); waitForPlayerInput(); cmdLine = 0; */ } if (displayOn) { if (doFade) PCFadeFlag = 0; /*if (!PCFadeFlag)*/ mainDraw(userWait); flipScreen(); if (userEnabled && !userWait && !autoTrack) { if (currentActiveMenu == -1) { static int16 oldMouseX = -1; static int16 oldMouseY = -1; getMouseStatus(&main10, &mouseX, &mouseButton, &mouseY); if (mouseX != oldMouseX || mouseY != oldMouseY) { int objectType; int newCursor1; int newCursor2; oldMouseX = mouseX; oldMouseY = mouseY; objectType = findObject(mouseX, mouseY, &newCursor1, &newCursor2); if (objectType == 9) { changeCursor(CURSOR_EXIT); } else if (objectType != -1) { changeCursor(CURSOR_MAGNIFYING_GLASS); } else { changeCursor(CURSOR_WALK); } } } else { changeCursor(CURSOR_NORMAL); } } else { changeCursor(CURSOR_NORMAL); } if (userWait == 1) { // Waiting for press - original wait loop has been integrated into the // main event loop continue; } // wait for character to finish auto track if (autoTrack) { if (isAnimFinished(narratorOvl, narratorIdx, &actorHead, ATP_MOUSE)) { if (autoMsg != -1) { freezeCell(&cellHead, autoOvl, autoMsg, 5, -1, 9998, 0); char* pText = getText(autoMsg, autoOvl); if (strlen(pText)) userWait = 1; } changeScriptParamInList(-1, -1, &relHead, 9998, 0); autoTrack = false; enableUser = 1; } else { userEnabled = false; } } else if (autoMsg != -1) { removeCell(&cellHead, autoOvl, autoMsg, 5, masterScreen); autoMsg = -1; } } else { // Keep ScummVM being responsive even when displayOn is false g_system->updateScreen(); } } while (!playerDontAskQuit && quitValue2 && quitValue != 7); // Free data removeAllScripts(&relHead); removeAllScripts(&procHead); resetActorPtr(&actorHead); freeOverlayTable(); closeCnf(); closeBase(); resetFileEntryRange(0, NUM_FILE_ENTRIES); freeObjectList(&cellHead); freeBackgroundIncrustList(&backgroundIncrustHead); }