mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-09-22 11:23:27 -04:00
Merge branch 'asynctimer' into 'master'
Add async timer that works when the game is paused See merge request OpenMW/openmw!4886
This commit is contained in:
commit
0e2b24d774
@ -83,7 +83,7 @@ add_openmw_dir (mwworld
|
||||
store esmstore fallback actionrepair actionsoulgem livecellref actiondoor
|
||||
contentloader esmloader actiontrap cellreflist cellref weather projectilemanager
|
||||
cellpreloader datetimemanager groundcoverstore magiceffects cell ptrregistry
|
||||
positioncellgrid
|
||||
positioncellgrid asynctimer
|
||||
)
|
||||
|
||||
add_openmw_dir (mwphysics
|
||||
|
@ -69,6 +69,7 @@
|
||||
|
||||
#include "mwworld/class.hpp"
|
||||
#include "mwworld/datetimemanager.hpp"
|
||||
#include "mwworld/asynctimer.hpp"
|
||||
#include "mwworld/worldimp.hpp"
|
||||
|
||||
#include "mwrender/vismask.hpp"
|
||||
@ -721,6 +722,9 @@ void OMW::Engine::prepareEngine()
|
||||
mStateManager = std::make_unique<MWState::StateManager>(mCfgMgr.getUserDataPath() / "saves", mContentFiles);
|
||||
mEnvironment.setStateManager(*mStateManager);
|
||||
|
||||
mAsyncTimer = std::make_unique<MWWorld::AsyncTimer>();
|
||||
mEnvironment.setAsyncTimer(*mAsyncTimer);
|
||||
|
||||
const bool stereoEnabled = Settings::stereo().mStereoEnabled || osg::DisplaySettings::instance().get()->getStereo();
|
||||
mStereoManager = std::make_unique<Stereo::Manager>(
|
||||
mViewer, stereoEnabled, Settings::camera().mNearClip, Settings::camera().mViewingDistance);
|
||||
@ -1051,6 +1055,8 @@ void OMW::Engine::go()
|
||||
timeManager.setRenderingSimulationTime(timeManager.getRenderingSimulationTime() + dt);
|
||||
}
|
||||
|
||||
mAsyncTimer->updateTimer();
|
||||
|
||||
if (stats)
|
||||
{
|
||||
// The delay is required because rendering happens in parallel to the main thread and stats from there is
|
||||
|
@ -91,6 +91,7 @@ namespace MWSound
|
||||
namespace MWWorld
|
||||
{
|
||||
class World;
|
||||
class AsyncTimer;
|
||||
}
|
||||
|
||||
namespace MWScript
|
||||
@ -139,6 +140,7 @@ namespace OMW
|
||||
std::unique_ptr<MWDialogue::Journal> mJournal;
|
||||
std::unique_ptr<MWInput::InputManager> mInputManager;
|
||||
std::unique_ptr<MWState::StateManager> mStateManager;
|
||||
std::unique_ptr<MWWorld::AsyncTimer> mAsyncTimer;
|
||||
std::unique_ptr<MWLua::LuaManager> mLuaManager;
|
||||
std::unique_ptr<MWLua::Worker> mLuaWorker;
|
||||
std::unique_ptr<L10n::Manager> mL10nManager;
|
||||
|
@ -20,6 +20,7 @@ namespace MWWorld
|
||||
class ESMStore;
|
||||
class WorldModel;
|
||||
class Scene;
|
||||
class AsyncTimer;
|
||||
}
|
||||
|
||||
namespace MWBase
|
||||
@ -55,6 +56,7 @@ namespace MWBase
|
||||
Journal* mJournal = nullptr;
|
||||
InputManager* mInputManager = nullptr;
|
||||
StateManager* mStateManager = nullptr;
|
||||
MWWorld::AsyncTimer* mAsyncTimer = nullptr;
|
||||
LuaManager* mLuaManager = nullptr;
|
||||
Resource::ResourceSystem* mResourceSystem = nullptr;
|
||||
L10n::Manager* mL10nManager = nullptr;
|
||||
@ -91,6 +93,8 @@ namespace MWBase
|
||||
|
||||
void setStateManager(StateManager& value) { mStateManager = &value; }
|
||||
|
||||
void setAsyncTimer(MWWorld::AsyncTimer& value) { mAsyncTimer = &value; }
|
||||
|
||||
void setLuaManager(LuaManager& value) { mLuaManager = &value; }
|
||||
|
||||
void setResourceSystem(Resource::ResourceSystem& value) { mResourceSystem = &value; }
|
||||
@ -118,6 +122,8 @@ namespace MWBase
|
||||
|
||||
Misc::NotNullPtr<StateManager> getStateManager() const { return mStateManager; }
|
||||
|
||||
Misc::NotNullPtr<MWWorld::AsyncTimer> getAsyncTimer() const { return mAsyncTimer; }
|
||||
|
||||
Misc::NotNullPtr<LuaManager> getLuaManager() const { return mLuaManager; }
|
||||
|
||||
Misc::NotNullPtr<Resource::ResourceSystem> getResourceSystem() const { return mResourceSystem; }
|
||||
|
53
apps/openmw/mwworld/asynctimer.cpp
Normal file
53
apps/openmw/mwworld/asynctimer.cpp
Normal file
@ -0,0 +1,53 @@
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <utility>
|
||||
|
||||
#include "asynctimer.hpp"
|
||||
|
||||
namespace MWWorld
|
||||
{
|
||||
AsyncTimer::AsyncTimer() = default;
|
||||
|
||||
AsyncTimer::~AsyncTimer() = default;
|
||||
|
||||
void AsyncTimer::updateTimer(){
|
||||
auto time_now = std::chrono::steady_clock::now();
|
||||
|
||||
std::vector<Callback> expired_callbacks;
|
||||
|
||||
while(!mTasks.empty() && mTasks.begin()->trigger_time <= time_now){
|
||||
expired_callbacks.push_back(mTasks.begin()->callback);
|
||||
mTasks.erase(mTasks.begin());
|
||||
}
|
||||
|
||||
for(auto& callback : expired_callbacks){
|
||||
callback();
|
||||
}
|
||||
}
|
||||
|
||||
AsyncTimer::TaskId AsyncTimer::setTask(float delay, Callback callback){
|
||||
if(delay < 0 || !callback) return -1;
|
||||
|
||||
auto triggerTime = std::chrono::steady_clock::now() +
|
||||
std::chrono::milliseconds(static_cast<int>(delay * 1000));
|
||||
|
||||
AsyncTimer::TaskId new_id = mNext_id++;
|
||||
|
||||
mTasks.insert({triggerTime, std::move(callback), new_id});
|
||||
return new_id;
|
||||
}
|
||||
|
||||
void AsyncTimer::cancelTask(AsyncTimer::TaskId id){
|
||||
if(id < 0) return;
|
||||
|
||||
for(auto it = mTasks.begin(); it != mTasks.end(); ++it){
|
||||
if(it->id == id){
|
||||
mTasks.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
45
apps/openmw/mwworld/asynctimer.hpp
Normal file
45
apps/openmw/mwworld/asynctimer.hpp
Normal file
@ -0,0 +1,45 @@
|
||||
#ifndef GAME_MWWORLD_ASYNCTIMER_H
|
||||
#define GAME_MWWORLD_ASYNCTIMER_H
|
||||
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
#include <set>
|
||||
|
||||
namespace MWWorld
|
||||
{
|
||||
// @brief Async timer that works when the game is paused
|
||||
class AsyncTimer
|
||||
{
|
||||
public:
|
||||
AsyncTimer();
|
||||
~AsyncTimer();
|
||||
|
||||
using TimePoint = std::chrono::steady_clock::time_point;
|
||||
using Callback = std::function<void()>;
|
||||
using TaskId = uint64_t;
|
||||
struct TimerTask{
|
||||
TimePoint trigger_time;
|
||||
Callback callback;
|
||||
TaskId id;
|
||||
|
||||
// Comparator for ordering tasks by execution time (earliest first)
|
||||
bool operator < (const TimerTask& other) const{
|
||||
return trigger_time < other.trigger_time;
|
||||
}
|
||||
};
|
||||
|
||||
// @brief Updates timer state and executes due tasks
|
||||
void updateTimer();
|
||||
|
||||
// @brief Schedules a new task for delayed execution
|
||||
TaskId setTask(float delay, Callback callback);
|
||||
|
||||
// @brief Cancels a task by id
|
||||
void cancelTask(TaskId id);
|
||||
|
||||
private:
|
||||
std::multiset<TimerTask> mTasks;
|
||||
TaskId mNext_id = 0;
|
||||
};
|
||||
}
|
||||
#endif /* GAME_MWWORLD_ASYNCTIMER_H */
|
Loading…
x
Reference in New Issue
Block a user