1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199
|
#include "EditingStopwatch.h"
#include <sigc++/functors/mem_fun.h>
#include "iradiant.h"
#include "itextstream.h"
#include "imap.h"
#include "imapresource.h"
#include "imapinfofile.h"
#include <fmt/format.h>
#include "string/convert.h"
#include "module/StaticModule.h"
#include "EditingStopwatchInfoFileModule.h"
#include "messages/ApplicationIsActiveRequest.h"
namespace map
{
namespace
{
const int TIMER_INTERVAL_SECS = 1;
const char* const MAP_PROPERTY_KEY = "EditTimeInSeconds";
}
EditingStopwatch::EditingStopwatch() :
_secondsEdited(0)
{}
const std::string& EditingStopwatch::getName() const
{
static std::string _name(MODULE_EDITING_STOPWATCH);
return _name;
}
const StringSet& EditingStopwatch::getDependencies() const
{
static StringSet _dependencies;
if (_dependencies.empty())
{
_dependencies.insert(MODULE_MAP);
_dependencies.insert(MODULE_MAPINFOFILEMANAGER);
_dependencies.insert(MODULE_MAPRESOURCEMANAGER);
}
return _dependencies;
}
void EditingStopwatch::initialiseModule(const IApplicationContext& ctx)
{
_mapSignal = GlobalMapModule().signal_mapEvent().connect(
sigc::mem_fun(*this, &EditingStopwatch::onMapEvent)
);
GlobalMapInfoFileManager().registerInfoFileModule(
std::make_shared<EditingStopwatchInfoFileModule>()
);
GlobalMapResourceManager().signal_onResourceExporting().connect(
sigc::mem_fun(this, &EditingStopwatch::onResourceExporting)
);
_timer.reset(new util::Timer(TIMER_INTERVAL_SECS * 1000,
sigc::mem_fun(*this, &EditingStopwatch::onIntervalReached)));
}
void EditingStopwatch::shutdownModule()
{
stop();
_mapSignal.disconnect();
}
void EditingStopwatch::onIntervalReached()
{
if (applicationIsActive())
{
setTotalSecondsEdited(getTotalSecondsEdited() + TIMER_INTERVAL_SECS);
}
}
bool EditingStopwatch::applicationIsActive()
{
radiant::ApplicationIsActiveRequest msg;
GlobalRadiantCore().getMessageBus().sendMessage(msg);
return msg.getApplicationIsActive();
}
void EditingStopwatch::onMapEvent(IMap::MapEvent ev)
{
switch (ev)
{
// We reset the timer when a map is about to be loaded,
// such that we don't use any previously found value.
// If a persisted info could be found in the info file,
// the new value will be set by the InfoFileModule.
case IMap::MapLoading:
stop();
setTotalSecondsEdited(0);
break;
// Start the clock once the map is done loading
case IMap::MapLoaded:
// Check if we have a non-empty property on the map root node
readFromMapProperties();
start();
break;
// When a map is unloaded, we reset the value to 0 again
// to prevent leaving stuff behind.
case IMap::MapUnloaded:
stop();
setTotalSecondsEdited(0);
break;
// We start/stop during save operations
case IMap::MapSaving:
// the timing is not written to the map root node here,
// but in the separate resource-exporting event
stop();
break;
case IMap::MapSaved:
start();
break;
default:
break;
};
}
void EditingStopwatch::onResourceExporting(const scene::IMapRootNodePtr& root)
{
writeToMapProperties(root);
}
void EditingStopwatch::start()
{
if (_timer)
{
_timer->start(TIMER_INTERVAL_SECS * 1000);
}
}
void EditingStopwatch::stop()
{
if (_timer)
{
_timer->stop();
}
}
unsigned long EditingStopwatch::getTotalSecondsEdited()
{
std::lock_guard<std::recursive_mutex> lock(_timingMutex);
return _secondsEdited;
}
void EditingStopwatch::setTotalSecondsEdited(unsigned long newValue)
{
std::lock_guard<std::recursive_mutex> lock(_timingMutex);
_secondsEdited = newValue;
_sigTimerChanged.emit();
}
sigc::signal<void>& EditingStopwatch::sig_TimerChanged()
{
return _sigTimerChanged;
}
void EditingStopwatch::readFromMapProperties()
{
auto root = GlobalMapModule().getRoot();
if (root && !root->getProperty(MAP_PROPERTY_KEY).empty())
{
auto value = string::convert<unsigned long>(root->getProperty(MAP_PROPERTY_KEY));
rMessage() << "Read " << value << " seconds of total map editing time." << std::endl;
setTotalSecondsEdited(value);
}
}
void EditingStopwatch::writeToMapProperties(const scene::IMapRootNodePtr& root)
{
if (root)
{
root->setProperty(MAP_PROPERTY_KEY, string::to_string(getTotalSecondsEdited()));
}
}
// Static module registration
module::StaticModuleRegistration<EditingStopwatch> _stopwatchModule;
}
|