Merge branch 'develop' of github.com:OpenSpace/OpenSpace into pr/kameleonvolume

Conflicts:
	src/engine/openspaceengine.cpp
This commit is contained in:
Emil Axelsson
2017-03-03 18:08:29 +01:00
70 changed files with 1038 additions and 1595 deletions

View File

@@ -40,13 +40,10 @@ set(OPENSPACE_SOURCE
${OPENSPACE_BASE_DIR}/src/engine/wrapper/sgctwindowwrapper.cpp
${OPENSPACE_BASE_DIR}/src/engine/wrapper/windowwrapper.cpp
${OPENSPACE_BASE_DIR}/src/interaction/controller.cpp
${OPENSPACE_BASE_DIR}/src/interaction/deviceidentifier.cpp
${OPENSPACE_BASE_DIR}/src/interaction/interactionhandler.cpp
${OPENSPACE_BASE_DIR}/src/interaction/interactionmode.cpp
${OPENSPACE_BASE_DIR}/src/interaction/interactionhandler_lua.inl
${OPENSPACE_BASE_DIR}/src/interaction/keyboardcontroller.cpp
${OPENSPACE_BASE_DIR}/src/interaction/luaconsole.cpp
${OPENSPACE_BASE_DIR}/src/interaction/luaconsole_lua.inl
${OPENSPACE_BASE_DIR}/src/mission/mission.cpp
${OPENSPACE_BASE_DIR}/src/mission/missionmanager.cpp
${OPENSPACE_BASE_DIR}/src/mission/missionmanager_lua.inl
@@ -179,10 +176,8 @@ set(OPENSPACE_HEADER
${OPENSPACE_BASE_DIR}/include/openspace/engine/wrapper/sgctwindowwrapper.h
${OPENSPACE_BASE_DIR}/include/openspace/engine/wrapper/windowwrapper.h
${OPENSPACE_BASE_DIR}/include/openspace/interaction/controller.h
${OPENSPACE_BASE_DIR}/include/openspace/interaction/deviceidentifier.h
${OPENSPACE_BASE_DIR}/include/openspace/interaction/interactionhandler.h
${OPENSPACE_BASE_DIR}/include/openspace/interaction/interactionmode.h
${OPENSPACE_BASE_DIR}/include/openspace/interaction/keyboardcontroller.h
${OPENSPACE_BASE_DIR}/include/openspace/interaction/luaconsole.h
${OPENSPACE_BASE_DIR}/include/openspace/mission/mission.h
${OPENSPACE_BASE_DIR}/include/openspace/mission/missionmanager.h

View File

@@ -26,11 +26,11 @@
#include <openspace/documentation/documentationengine.h>
#include <openspace/engine/configurationmanager.h>
#include <openspace/engine/logfactory.h>
#include <openspace/engine/moduleengine.h>
#include <openspace/engine/openspaceengine.h>
#include <openspace/engine/wrapper/windowwrapper.h>
#include <openspace/interaction/interactionhandler.h>
#include <openspace/interaction/luaconsole.h>
#include <openspace/mission/mission.h>
#include <openspace/mission/missionmanager.h>
#include <openspace/rendering/renderable.h>
@@ -51,6 +51,7 @@ namespace openspace {
void registerCoreClasses(documentation::DocumentationEngine& engine) {
engine.addDocumentation(ConfigurationManager::Documentation());
engine.addDocumentation(LogFactoryDocumentation());
engine.addDocumentation(Mission::Documentation());
engine.addDocumentation(Renderable::Documentation());
engine.addDocumentation(Rotation::Documentation());
@@ -69,7 +70,6 @@ void registerCoreClasses(scripting::ScriptEngine& engine) {
engine.addLibrary(Scene::luaLibrary());
engine.addLibrary(Time::luaLibrary());
engine.addLibrary(interaction::InteractionHandler::luaLibrary());
engine.addLibrary(LuaConsole::luaLibrary());
engine.addLibrary(ParallelConnection::luaLibrary());
engine.addLibrary(ModuleEngine::luaLibrary());
engine.addLibrary(scripting::ScriptScheduler::luaLibrary());

View File

@@ -31,6 +31,7 @@
#include <ghoul/filesystem/filesystem.h>
#include <fstream>
#include <sstream>
#include <streambuf>
#include <fmt/format.h>

View File

@@ -225,25 +225,25 @@ TestResult ReferencingVerifier::operator()(const ghoul::Dictionary& dictionary,
[this](const Documentation& doc) { return doc.id == identifier; }
);
if (it == documentations.end()) {
return { false, { { key, TestResult::Offense::Reason::UnknownIdentifier } } };
ghoul_assert(
it != documentations.end(),
"Did not find referencing identifier '" + identifier + "'"
);
ghoul::Dictionary d = dictionary.value<ghoul::Dictionary>(key);
TestResult res = testSpecification(*it, d);
// Add the 'key' as a prefix to make the offender a fully qualified identifer
for (TestResult::Offense& s : res.offenses) {
s.offender = key + "." + s.offender;
}
else {
ghoul::Dictionary d = dictionary.value<ghoul::Dictionary>(key);
TestResult res = testSpecification(*it, d);
// Add the 'key' as a prefix to make the offender a fully qualified identifer
for (TestResult::Offense& s : res.offenses) {
s.offender = key + "." + s.offender;
}
// Add the 'key' as a prefix to make the warning a fully qualified identifer
for (TestResult::Warning& w : res.warnings) {
w.offender = key + "." + w.offender;
}
return res;
// Add the 'key' as a prefix to make the warning a fully qualified identifer
for (TestResult::Warning& w : res.warnings) {
w.offender = key + "." + w.offender;
}
return res;
}
else {
return res;

View File

@@ -113,31 +113,8 @@ documentation::Documentation ConfigurationManager::Documentation() {
new TableVerifier({
{
"*",
new TableVerifier({
{
ConfigurationManager::PartType,
new StringInListVerifier({
// List from logfactory.cpp::createLog
"text", "html"
}),
"The type of the new log to be generated."
},
{
ConfigurationManager::PartFile,
new StringVerifier,
"The filename to which the log will be written."
},
{
ConfigurationManager::PartAppend,
new BoolVerifier,
"Determines whether the file will be cleared at "
"startup or if the contents will be appended to "
"previous runs.",
Optional::Yes
}
}),
"Additional log files",
Optional::Yes
new ReferencingVerifier("core_logfactory"),
"Additional log files"
}
}),
"Per default, log messages are written to the console, the "

View File

@@ -162,7 +162,10 @@ std::shared_ptr<DownloadManager::FileFuture> DownloadManager::downloadFile(
std::shared_ptr<FileFuture> future = std::make_shared<FileFuture>(file.filename());
errno = 0;
FILE* fp = fopen(file.path().c_str(), "wb"); // write binary
ghoul_assert(fp != nullptr, "Could not open/create file:\n" << file.path().c_str() << " \nerrno: " << errno);
ghoul_assert(
fp != nullptr,
"Could not open/create file:\n" + file.path() + " \nerrno: " + std::to_string(errno)
);
//LDEBUG("Start downloading file: '" << url << "' into file '" << file.path() << "'");

View File

@@ -24,6 +24,9 @@
#include <openspace/engine/logfactory.h>
#include <openspace/documentation/documentation.h>
#include <openspace/documentation/verifier.h>
#include <ghoul/misc/dictionary.h>
#include <ghoul/misc/exception.h>
#include <ghoul/filesystem/filesystem.h>
@@ -51,37 +54,105 @@ namespace {
namespace openspace {
documentation::Documentation LogFactoryDocumentation() {
using namespace documentation;
return {
"LogFactory",
"core_logfactory",
{
{
keyType,
new StringInListVerifier({
// List from createLog
valueTextLog, valueHtmlLog
}),
"The type of the new log to be generated."
},
{
keyFilename,
new StringVerifier,
"The filename to which the log will be written."
},
{
keyAppend,
new BoolVerifier,
"Determines whether the file will be cleared at startup or if the "
"contents will be appended to previous runs.",
Optional::Yes
},
{
keyTimeStamping,
new BoolVerifier,
"Determines whether the log entires should be stamped with the time at "
"which the message was logged.",
Optional::Yes
},
{
keyDateStamping,
new BoolVerifier,
"Determines whether the log entries should be stamped with the date at "
"which the message was logged.",
Optional::Yes
},
{
keyCategoryStamping,
new BoolVerifier,
"Determines whether the log entries should be stamped with the "
"category that creates the log message.",
Optional::Yes
},
{
keyLogLevelStamping,
new BoolVerifier,
"Determines whether the log entries should be stamped with the log level "
"that was used to create the log message.",
Optional::Yes
}
},
Exhaustive::Yes
};
}
std::unique_ptr<ghoul::logging::Log> createLog(const ghoul::Dictionary& dictionary) {
using namespace std::string_literals;
std::string type;
bool typeSuccess = dictionary.getValue(keyType, type);
if (!typeSuccess) {
throw ghoul::RuntimeError(
"Requested log did not contain key '"s + keyType + "'", "LogFactory"
);
}
std::string filename;
bool filenameSuccess = dictionary.getValue(keyFilename, filename);
if (!filenameSuccess) {
throw ghoul::RuntimeError(
"Requested log did not contain key '"s + keyFilename + "'", "LogFactory"
);
}
filename = absPath(filename);
documentation::testSpecificationAndThrow(
LogFactoryDocumentation(),
dictionary,
"LogFactory"
);
// 'type' and 'filename' are required keys
std::string type = dictionary.value<std::string>(keyType);
std::string filename = absPath(dictionary.value<std::string>(keyFilename));
// the rest are optional
bool append = true;
dictionary.getValue(keyAppend, append);
if (dictionary.hasKeyAndValue<bool>(keyAppend)) {
dictionary.value<bool>(keyAppend);
}
bool timeStamp = true;
dictionary.getValue(keyTimeStamping, timeStamp);
if (dictionary.hasKeyAndValue<bool>(keyTimeStamping)) {
dictionary.value<bool>(keyTimeStamping);
}
bool dateStamp = true;
dictionary.getValue(keyDateStamping, dateStamp);
if (dictionary.hasKeyAndValue<bool>(keyDateStamping)) {
dictionary.value<bool>(keyDateStamping);
}
bool categoryStamp = true;
dictionary.getValue(keyCategoryStamping, categoryStamp);
if (dictionary.hasKeyAndValue<bool>(keyCategoryStamping)) {
dictionary.value<bool>(keyCategoryStamping);
}
bool logLevelStamp = true;
dictionary.getValue(keyLogLevelStamping, logLevelStamp);
if (dictionary.hasKeyAndValue<bool>(keyLogLevelStamping)) {
dictionary.value<bool>(keyLogLevelStamping);
}
std::string logLevel;
dictionary.getValue(keyLogLevel, logLevel);
if (dictionary.hasKeyAndValue<std::string>(keyLogLevel)) {
dictionary.value<std::string>(keyLogLevel);
}
using Append = ghoul::logging::TextLog::Append;
using TimeStamping = ghoul::logging::Log::TimeStamping;
@@ -90,7 +161,6 @@ std::unique_ptr<ghoul::logging::Log> createLog(const ghoul::Dictionary& dictiona
using LogLevelStamping = ghoul::logging::Log::LogLevelStamping;
if (type == valueHtmlLog) {
std::vector<std::string> cssFiles{absPath(BootstrapPath), absPath(CssPath)};
std::vector<std::string> jsFiles{absPath(JsPath)};
@@ -102,7 +172,8 @@ std::unique_ptr<ghoul::logging::Log> createLog(const ghoul::Dictionary& dictiona
dateStamp ? DateStamping::Yes : DateStamping::No,
categoryStamp ? CategoryStamping::Yes : CategoryStamping::No,
logLevelStamp ? LogLevelStamping::Yes : LogLevelStamping::No,
cssFiles, jsFiles
cssFiles,
jsFiles
);
}
else {
@@ -141,11 +212,7 @@ std::unique_ptr<ghoul::logging::Log> createLog(const ghoul::Dictionary& dictiona
);
}
}
else {
throw ghoul::RuntimeError(
"Log with type '" + type + "' did not name a valid log", "LogFactory"
);
}
ghoul_assert(false, "Missing case in the documentation for LogFactory");
}
} // namespace openspace

View File

@@ -25,6 +25,7 @@
#include <openspace/engine/moduleengine.h>
#include <openspace/moduleregistration.h>
#include <openspace/scripting/lualibrary.h>
#include <openspace/util/openspacemodule.h>
#include <ghoul/logging/logmanager.h>
@@ -34,7 +35,7 @@
#include "moduleengine_lua.inl"
namespace {
const std::string _loggerCat = "ModuleEngine";
const char* _loggerCat = "ModuleEngine";
}
namespace openspace {
@@ -67,7 +68,8 @@ void ModuleEngine::registerModule(std::unique_ptr<OpenSpaceModule> module) {
);
if (it != _modules.end()) {
throw ghoul::RuntimeError(
"Module name '" + module->name() + "' was registered before", "ModuleEngine"
"Module name '" + module->name() + "' was registered before",
"ModuleEngine"
);
}
@@ -85,11 +87,8 @@ std::vector<OpenSpaceModule*> ModuleEngine::modules() const {
return result;
}
ghoul::systemcapabilities::OpenGLCapabilitiesComponent::Version
ModuleEngine::requiredOpenGLVersion() const
{
using Version = ghoul::systemcapabilities::OpenGLCapabilitiesComponent::Version;
Version version = { 0,0 };
ghoul::systemcapabilities::Version ModuleEngine::requiredOpenGLVersion() const {
ghoul::systemcapabilities::Version version = { 0, 0 };
for (const auto& m : _modules) {
version = std::max(version, m->requiredOpenGLVersion());

View File

@@ -27,7 +27,6 @@
#include <openspace/openspace.h>
#include <openspace/documentation/core_registration.h>
#include <openspace/documentation/documentation.h>
#include <openspace/documentation/documentationengine.h>
#include <openspace/engine/configurationmanager.h>
#include <openspace/engine/downloadmanager.h>
@@ -37,45 +36,32 @@
#include <openspace/engine/syncengine.h>
#include <openspace/engine/wrapper/windowwrapper.h>
#include <openspace/interaction/interactionhandler.h>
#include <openspace/interaction/keyboardcontroller.h>
#include <openspace/interaction/luaconsole.h>
#include <openspace/mission/missionmanager.h>
#include <openspace/network/networkengine.h>
#include <openspace/properties/propertyowner.h>
#include <openspace/rendering/renderable.h>
#include <openspace/rendering/renderengine.h>
#include <openspace/rendering/screenspacerenderable.h>
#include <openspace/scripting/scriptengine.h>
#include <openspace/scripting/scriptscheduler.h>
#include <openspace/scene/translation.h>
#include <openspace/scene/rotation.h>
#include <openspace/scene/scale.h>
#include <openspace/scene/scene.h>
#include <openspace/scene/translation.h>
#include <openspace/util/factorymanager.h>
#include <openspace/util/task.h>
#include <openspace/util/openspacemodule.h>
#include <openspace/util/time.h>
#include <openspace/util/timemanager.h>
#include <openspace/util/spicemanager.h>
#include <openspace/util/syncbuffer.h>
#include <openspace/util/transformationmanager.h>
#include <ghoul/ghoul.h>
#include <ghoul/cmdparser/commandlineparser.h>
#include <ghoul/cmdparser/singlecommand.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/filesystem/cachemanager.h>
#include <ghoul/font/fontmanager.h>
#include <ghoul/font/fontrenderer.h>
#include <ghoul/logging/consolelog.h>
#include <ghoul/logging/visualstudiooutputlog.h>
#include <ghoul/lua/ghoul_lua.h>
#include <ghoul/lua/lua_helper.h>
#include <ghoul/lua/luastate.h>
#include <ghoul/misc/dictionary.h>
#include <ghoul/misc/exception.h>
#include <ghoul/misc/onscopeexit.h>
#include <ghoul/systemcapabilities/systemcapabilities>
#include <fstream>
#include <queue>
#if defined(_MSC_VER) && defined(OPENSPACE_ENABLE_VLD)
#include <vld.h>
@@ -128,7 +114,7 @@ OpenSpaceEngine::OpenSpaceEngine(std::string programName,
, _scriptEngine(new scripting::ScriptEngine)
, _scriptScheduler(new scripting::ScriptScheduler)
, _networkEngine(new NetworkEngine)
, _syncEngine(std::make_unique<SyncEngine>(new SyncBuffer(4096)))
, _syncEngine(std::make_unique<SyncEngine>(4096))
, _commandlineParser(new ghoul::cmdparser::CommandlineParser(
programName, ghoul::cmdparser::CommandlineParser::AllowUnknownCommands::Yes
))
@@ -139,7 +125,7 @@ OpenSpaceEngine::OpenSpaceEngine(std::string programName,
, _downloadManager(nullptr)
, _parallelConnection(new ParallelConnection)
, _windowWrapper(std::move(windowWrapper))
, _globalPropertyNamespace(new properties::PropertyOwner)
, _globalPropertyNamespace(new properties::PropertyOwner(""))
, _runTime(0.0)
, _shutdown({false, 0.f, 0.f})
, _isFirstRenderingFirstFrame(true)
@@ -240,6 +226,8 @@ void OpenSpaceEngine::create(int argc, char** argv,
LDEBUG("Creating OpenSpaceEngine");
_engine = new OpenSpaceEngine(std::string(argv[0]), std::move(windowWrapper));
registerCoreClasses(DocEng);
// Query modules for commandline arguments
_engine->gatherCommandlineArguments();
@@ -346,7 +334,6 @@ void OpenSpaceEngine::create(int argc, char** argv,
// Register modules
_engine->_moduleEngine->initialize();
registerCoreClasses(DocEng);
// After registering the modules, the documentations for the available classes
// can be added as well
for (OpenSpaceModule* m : _engine->_moduleEngine->modules()) {
@@ -451,9 +438,9 @@ void OpenSpaceEngine::initialize() {
SysCap.logCapabilities(verbosity);
// Check the required OpenGL versions of the registered modules
ghoul::systemcapabilities::OpenGLCapabilitiesComponent::Version version =
ghoul::systemcapabilities::Version version =
_engine->_moduleEngine->requiredOpenGLVersion();
LINFO("Required OpenGL version: " << version.toString());
LINFO("Required OpenGL version: " << std::to_string(version));
if (OpenGLCap.openGLVersion() < version) {
throw ghoul::RuntimeError(
@@ -848,7 +835,7 @@ void OpenSpaceEngine::preSynchronization() {
bool master = _windowWrapper->isMaster();
_syncEngine->presync(master);
_syncEngine->preSynchronization(SyncEngine::IsMaster(master));
if (master) {
double dt = _windowWrapper->averageDeltaTime();
_timeManager->preSynchronization(dt);
@@ -880,7 +867,7 @@ void OpenSpaceEngine::postSynchronizationPreDraw() {
LTRACE("OpenSpaceEngine::postSynchronizationPreDraw(begin)");
bool master = _windowWrapper->isMaster();
_syncEngine->postsync(master);
_syncEngine->postSynchronization(SyncEngine::IsMaster(master));
if (_shutdown.inShutdown) {
if (_shutdown.timer <= 0.f) {
@@ -943,8 +930,7 @@ void OpenSpaceEngine::render(const glm::mat4& viewMatrix,
bool showGui = _windowWrapper->hasGuiWindow() ? _windowWrapper->isGuiWindow() : true;
if (showGui && _windowWrapper->isMaster() && _windowWrapper->isRegularRendering()) {
_renderEngine->renderScreenLog();
if (_console->isVisible())
_console->render();
_console->render();
}
if (_shutdown.inShutdown) {
@@ -973,25 +959,18 @@ void OpenSpaceEngine::postDraw() {
void OpenSpaceEngine::keyboardCallback(Key key, KeyModifier mod, KeyAction action) {
for (const auto& func : _moduleCallbacks.keyboard) {
bool consumed = func(key, mod, action);
const bool consumed = func(key, mod, action);
if (consumed) {
return;
}
}
// @CLEANUP: Remove the commandInputButton and replace with a method just based
// on Lua by binding a key to the Lua script toggling the console ---abock
if (key == _console->commandInputButton()) {
if (action == KeyAction::Press) {
_console->toggleMode();
}
} else if (!_console->isVisible()) {
// @CLEANUP: Make the interaction handler return whether a key has been consumed
// and then pass it on to the console ---abock
_interactionHandler->keyboardCallback(key, mod, action);
} else {
_console->keyboardCallback(key, mod, action);
const bool consoleConsumed = _console->keyboardCallback(key, mod, action);
if (consoleConsumed) {
return;
}
_interactionHandler->keyboardCallback(key, mod, action);
}
void OpenSpaceEngine::charCallback(unsigned int codepoint, KeyModifier modifier) {
@@ -1002,9 +981,7 @@ void OpenSpaceEngine::charCallback(unsigned int codepoint, KeyModifier modifier)
}
}
if (_console->isVisible()) {
_console->charCallback(codepoint, modifier);
}
_console->charCallback(codepoint, modifier);
}
void OpenSpaceEngine::mouseButtonCallback(MouseButton button, MouseAction action) {

View File

@@ -40,94 +40,40 @@
namespace {
const std::string _loggerCat = "SettingsEngine";
const char* _loggerCat = "SettingsEngine";
}
namespace openspace {
SettingsEngine::SettingsEngine()
: _eyeSeparation("eyeSeparation", "Eye Separation" , 0.f, 0.f, 10.f)
: properties::PropertyOwner("Global Properties")
, _eyeSeparation("eyeSeparation", "Eye Separation", 0.f, 0.f, 10.f)
, _scenes("scenes", "Scene", properties::OptionProperty::DisplayType::Dropdown)
, _busyWaitForDecode("busyWaitForDecode", "Busy Wait for decode", false)
, _logSGCTOutOfOrderErrors("logSGCTOutOfOrderErrors", "Log SGCT out-of-order", false)
, _useDoubleBuffering("useDoubleBuffering", "Use double buffering", false)
, _spiceUseExceptions("enableSpiceExceptions", "Enable Spice Exceptions", false)
{
setName("Global Properties");
_spiceUseExceptions.onChange([this]{
_spiceUseExceptions.onChange([this] {
if (_spiceUseExceptions) {
SpiceManager::ref().setExceptionHandling(SpiceManager::UseException::Yes);
}
else {
} else {
SpiceManager::ref().setExceptionHandling(SpiceManager::UseException::No);
}
});
addProperty(_spiceUseExceptions);
addProperty(_eyeSeparation);
addProperty(_busyWaitForDecode);
addProperty(_logSGCTOutOfOrderErrors);
addProperty(_useDoubleBuffering);
addProperty(_scenes);
}
void SettingsEngine::initialize() {
initEyeSeparation();
initSceneFiles();
initBusyWaitForDecode();
initLogSGCTOutOfOrderErrors();
initUseDoubleBuffering();
}
void SettingsEngine::setModules(std::vector<OpenSpaceModule*> modules) {
for (OpenSpaceModule* m : modules) {
addPropertySubOwner(m);
}
}
void SettingsEngine::initEyeSeparation() {
addProperty(_eyeSeparation);
// Set interaction to change the window's (SGCT's) eye separation
_eyeSeparation.onChange(
[this]() { OsEng.windowWrapper().setEyeSeparationDistance(_eyeSeparation); });
}
void SettingsEngine::initBusyWaitForDecode() {
addProperty(_busyWaitForDecode);
_busyWaitForDecode.onChange(
[this]() {
LINFO((_busyWaitForDecode.value() ? "Busy wait for decode" : "Async decode"));
});
}
bool SettingsEngine::busyWaitForDecode() {
return _busyWaitForDecode.value();
}
void SettingsEngine::initLogSGCTOutOfOrderErrors() {
addProperty(_logSGCTOutOfOrderErrors);
_logSGCTOutOfOrderErrors.onChange(
[this]() {
LINFO("Turn " << (_logSGCTOutOfOrderErrors.value() ? "on" : "off") << " SGCT out of order logging");
});
}
bool SettingsEngine::logSGCTOutOfOrderErrors() {
return _logSGCTOutOfOrderErrors.value();
}
void SettingsEngine::initUseDoubleBuffering() {
addProperty(_useDoubleBuffering);
_useDoubleBuffering.onChange(
[this]() {
LINFO("Turn " << (_useDoubleBuffering.value() ? "on" : "off") << " double buffering");
});
}
bool SettingsEngine::useDoubleBuffering() {
return _useDoubleBuffering.value();
}
void SettingsEngine::initSceneFiles() {
addProperty(_scenes);
[this]() { OsEng.windowWrapper().setEyeSeparationDistance(_eyeSeparation); }
);
// Load all matching files in the Scene
// TODO: match regex with either with new ghoul readFiles or local code
@@ -135,18 +81,36 @@ void SettingsEngine::initSceneFiles() {
std::vector<std::string> scenes = ghoul::filesystem::Directory(sceneDir).readFiles();
for (std::size_t i = 0; i < scenes.size(); ++i) {
std::size_t found = scenes[i].find_last_of("/\\");
_scenes.addOption(i, scenes[i].substr(found+1));
_scenes.addOption(i, scenes[i].substr(found + 1));
}
// Set interaction to change ConfigurationManager and schedule the load
_scenes.onChange(
[this]() {
std::string sceneFile = _scenes.getDescriptionByValue(_scenes);
OsEng.configurationManager().setValue(
ConfigurationManager::KeyConfigScene, sceneFile);
OsEng.renderEngine().scene()->scheduleLoadSceneFile(sceneFile);
}
std::string sceneFile = _scenes.getDescriptionByValue(_scenes);
OsEng.configurationManager().setValue(
ConfigurationManager::KeyConfigScene, sceneFile);
OsEng.renderEngine().scene()->scheduleLoadSceneFile(sceneFile);
}
);
}
void SettingsEngine::setModules(const std::vector<OpenSpaceModule*>& modules) {
for (OpenSpaceModule* m : modules) {
addPropertySubOwner(m);
}
}
bool SettingsEngine::busyWaitForDecode() {
return _busyWaitForDecode.value();
}
bool SettingsEngine::logSGCTOutOfOrderErrors() {
return _logSGCTOutOfOrderErrors.value();
}
bool SettingsEngine::useDoubleBuffering() {
return _useDoubleBuffering.value();
}
} // namespace openspace

View File

@@ -23,73 +23,67 @@
****************************************************************************************/
#include <openspace/engine/syncengine.h>
#include <openspace/util/syncdata.h>
#include <openspace/util/syncbuffer.h>
#include <ghoul/logging/logmanager.h>
#include <ghoul/misc/assert.h>
#include <algorithm>
#include <string>
namespace {
const std::string _loggerCat = "SyncEngine";
}
namespace openspace {
SyncEngine::SyncEngine(SyncBuffer* syncBuffer)
: _syncBuffer(syncBuffer)
{
}
void SyncEngine::presync(bool isMaster) {
for (const auto& syncable : _syncables) {
syncable->presync(isMaster);
}
}
// should be called on sgct master
void SyncEngine::encodeSyncables() {
for (const auto& syncable : _syncables) {
syncable->encode(_syncBuffer.get());
}
_syncBuffer->write();
}
//should be called on sgct slaves
void SyncEngine::decodeSyncables() {
_syncBuffer->read();
for (const auto& syncable : _syncables) {
syncable->decode(_syncBuffer.get());
}
}
void SyncEngine::postsync(bool isMaster) {
for (const auto& syncable : _syncables) {
syncable->postsync(isMaster);
}
}
void SyncEngine::addSyncable(Syncable* syncable) {
_syncables.push_back(syncable);
}
void SyncEngine::addSyncables(const std::vector<Syncable*>& syncables) {
for (const auto& syncable : syncables) {
addSyncable(syncable);
}
}
void SyncEngine::removeSyncable(Syncable* syncable) {
_syncables.erase(
std::remove(_syncables.begin(), _syncables.end(), syncable),
_syncables.end()
);
}
SyncEngine::SyncEngine(unsigned int syncBufferSize)
: _syncBuffer(syncBufferSize)
{
ghoul_assert(syncBufferSize > 0, "syncBufferSize must be bigger than 0");
}
// should be called on sgct master
void SyncEngine::encodeSyncables() {
for (Syncable* syncable : _syncables) {
syncable->encode(&_syncBuffer);
}
_syncBuffer.write();
}
//should be called on sgct slaves
void SyncEngine::decodeSyncables() {
_syncBuffer.read();
for (Syncable* syncable : _syncables) {
syncable->decode(&_syncBuffer);
}
}
void SyncEngine::preSynchronization(IsMaster isMaster) {
for (Syncable* syncable : _syncables) {
syncable->presync(isMaster);
}
}
void SyncEngine::postSynchronization(IsMaster isMaster) {
for (Syncable* syncable : _syncables) {
syncable->postsync(isMaster);
}
}
void SyncEngine::addSyncable(Syncable* syncable) {
ghoul_assert(syncable, "synable must not be nullptr");
_syncables.push_back(syncable);
}
void SyncEngine::addSyncables(const std::vector<Syncable*>& syncables) {
for (Syncable* syncable : syncables) {
ghoul_assert(syncable, "syncables must not contain any nullptr");
addSyncable(syncable);
}
}
void SyncEngine::removeSyncable(Syncable* syncable) {
_syncables.erase(
std::remove(_syncables.begin(), _syncables.end(), syncable),
_syncables.end()
);
}
} // namespace openspace

View File

@@ -1,163 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2017 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
// open space includes
#include <openspace/interaction/deviceidentifier.h>
#include <assert.h>
namespace openspace {
DeviceIdentifier* DeviceIdentifier::this_ = nullptr;
DeviceIdentifier::DeviceIdentifier() {
// scan for devices on init
devices_ = 0;
for(int i = 0; i < MAXDEVICES; ++i) {
inputDevice_[i] = InputDevice::NONE;
}
}
DeviceIdentifier::~DeviceIdentifier() {
// deallocates memory on exit
for(int i = 0; i < MAXDEVICES; ++i) {
if(inputDevice_[i] != InputDevice::NONE) {
delete axesPos_[i];
delete buttons_[i];
}
}
}
void DeviceIdentifier::init() {
assert( ! this_);
this_ = new DeviceIdentifier();
}
void DeviceIdentifier::deinit() {
assert(this_);
delete this_;
this_ = nullptr;
}
DeviceIdentifier& DeviceIdentifier::ref() {
assert(this_);
return *this_;
}
bool DeviceIdentifier::isInitialized() {
return this_ != nullptr;
}
void DeviceIdentifier::scanDevices() {
assert(this_);
// sgct/glfw supports 16 joysticks, scans all of them
for (int i = 0; i < MAXDEVICES; ++i)
{
void* joystickName = NULL;
if( joystickName != NULL ) {
// allocate
axesPos_[i] = new float[numberOfAxes_[i]];
buttons_[i] = new unsigned char[numberOfButtons_[i]];
// increment the device count
++devices_;
// identify what device it is
if(numberOfAxes_[i] == 6 && numberOfButtons_[i] == 10) {
printf("XBOX controller ");
inputDevice_[i] = InputDevice::XBOX;
} else if(numberOfAxes_[i] == 6 && numberOfButtons_[i] == 4) {
printf("SPACENAVIGATOR ");
inputDevice_[i] = InputDevice::SPACENAVIGATOR;
} else {
printf("UNKNOWN device ");
inputDevice_[i] = InputDevice::UNKNOWN;
}
printf("found at position %i, b=%i, a=%i\n", i, numberOfButtons_[i], numberOfAxes_[i]);
} else {
inputDevice_[i] = InputDevice::NONE;
}
}
}
const int DeviceIdentifier::numberOfDevices() const {
assert(this_);
return devices_;
}
const InputDevice DeviceIdentifier::type(const int device) const {
assert(this_);
return inputDevice_[device];
}
void DeviceIdentifier::update() {
assert(this_);
for(int i = 0; i < devices_; ++i) {
update(i);
}
}
void DeviceIdentifier::update(const int device) {
assert(this_);
if(inputDevice_[device] != InputDevice::NONE) {
}
}
const int DeviceIdentifier::getButtons(const int device, unsigned char **buttons) const {
assert(this_);
if(inputDevice_[device] != InputDevice::NONE) {
if(buttons)
*buttons = buttons_[device];
return numberOfButtons_[device];
}
return 0;
}
const int DeviceIdentifier::getAxes(const int device, float **axespos) const {
assert(this_);
if(inputDevice_[device] != InputDevice::NONE) {
if(axespos)
*axespos = axesPos_[device];
return numberOfAxes_[device];
}
return 0;
}
void DeviceIdentifier::get(const int device, unsigned char **buttons, float **axespos) const {
assert(this_);
if(inputDevice_[device] != InputDevice::NONE) {
*axespos = axesPos_[device];
*buttons = buttons_[device];
}
}
} // namespace openspace

View File

@@ -31,6 +31,7 @@
#include <openspace/interaction/interactionmode.h>
#include <openspace/query/query.h>
#include <openspace/rendering/renderengine.h>
#include <openspace/scene/scenegraphnode.h>
#include <openspace/util/time.h>
#include <openspace/util/keys.h>
@@ -50,19 +51,19 @@
#include <fstream>
namespace {
const std::string _loggerCat = "InteractionHandler";
const char* _loggerCat = "InteractionHandler";
const std::string KeyFocus = "Focus";
const std::string KeyPosition = "Position";
const std::string KeyRotation = "Rotation";
const char* KeyFocus = "Focus";
const char* KeyPosition = "Position";
const char* KeyRotation = "Rotation";
const std::string MainTemplateFilename = "${OPENSPACE_DATA}/web/keybindings/main.hbs";
const std::string KeybindingTemplateFilename = "${OPENSPACE_DATA}/web/keybindings/keybinding.hbs";
const std::string HandlebarsFilename = "${OPENSPACE_DATA}/web/common/handlebars-v4.0.5.js";
const std::string JsFilename = "${OPENSPACE_DATA}/web/keybindings/script.js";
const std::string BootstrapFilename = "${OPENSPACE_DATA}/web/common/bootstrap.min.css";
const std::string CssFilename = "${OPENSPACE_DATA}/web/common/style.css";
}
const char* MainTemplateFilename = "${OPENSPACE_DATA}/web/keybindings/main.hbs";
const char* KeybindingTemplateFilename = "${OPENSPACE_DATA}/web/keybindings/keybinding.hbs";
const char* HandlebarsFilename = "${OPENSPACE_DATA}/web/common/handlebars-v4.0.5.js";
const char* JsFilename = "${OPENSPACE_DATA}/web/keybindings/script.js";
const char* BootstrapFilename = "${OPENSPACE_DATA}/web/common/bootstrap.min.css";
const char* CssFilename = "${OPENSPACE_DATA}/web/common/style.css";
} // namespace
#include "interactionhandler_lua.inl"
@@ -71,15 +72,14 @@ namespace interaction {
// InteractionHandler
InteractionHandler::InteractionHandler()
: _origin("origin", "Origin", "")
: properties::PropertyOwner("Interaction")
, _origin("origin", "Origin", "")
, _rotationalFriction("rotationalFriction", "Rotational Friction", true)
, _horizontalFriction("horizontalFriction", "Horizontal Friction", true)
, _verticalFriction("verticalFriction", "Vertical Friction", true)
, _sensitivity("sensitivity", "Sensitivity", 0.5, 0.001, 1)
, _rapidness("rapidness", "Rapidness", 1, 0.1, 60)
{
setName("Interaction");
_origin.onChange([this]() {
SceneGraphNode* node = sceneGraphNode(_origin.value());
if (!node) {

View File

@@ -28,6 +28,7 @@
#include <openspace/engine/openspaceengine.h>
#include <openspace/query/query.h>
#include <openspace/rendering/renderengine.h>
#include <openspace/scene/scenegraphnode.h>
#include <openspace/util/time.h>
#include <openspace/util/keys.h>

View File

@@ -1,329 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2017 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <openspace/interaction/keyboardcontroller.h>
#include <openspace/interaction/interactionhandler.h>
#include <openspace/engine/openspaceengine.h>
#include <openspace/rendering/renderengine.h>
#include <openspace/util/time.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/logging/logmanager.h>
#include <ghoul/lua/ghoul_lua.h>
#include <chrono>
namespace {
const std::string _loggerCat = "KeyboardController";
}
namespace openspace {
namespace interaction {
void KeyboardControllerFixed::keyPressed(KeyAction action, Key key, KeyModifier modifier) {
// TODO package in script
/*
const float dt = static_cast<float>( _handler->deltaTime());
if(action == KeyAction::Press|| action == KeyAction::Repeat) {
const float speed = 2.75;
if (key == Key::S) {
glm::vec3 euler(speed * dt, 0.0, 0.0);
glm::quat rot = glm::quat(euler);
_handler->orbitDelta(rot);
}
if (key == Key::W) {
glm::vec3 euler(-speed * dt, 0.0, 0.0);
glm::quat rot = glm::quat(euler);
_handler->orbitDelta(rot);
}
if (key == Key::A) {
glm::vec3 euler(0.0, -speed * dt, 0.0);
glm::quat rot = glm::quat(euler);
_handler->orbitDelta(rot);
}
if (key == Key::D) {
glm::vec3 euler(0.0, speed * dt, 0.0);
glm::quat rot = glm::quat(euler);
_handler->orbitDelta(rot);
}
if (key == Key::Q) {
Time::ref().advanceTime(dt);
}
if (key == Key::Right) {
glm::vec3 euler(0.0, speed * dt, 0.0);
glm::quat rot = glm::quat(euler);
_handler->rotateDelta(rot);
}
if (key == Key::Left) {
glm::vec3 euler(0.0, -speed * dt, 0.0);
glm::quat rot = glm::quat(euler);
_handler->rotateDelta(rot);
}
if (key == Key::Down) {
glm::vec3 euler(speed * dt, 0.0, 0.0);
glm::quat rot = glm::quat(euler);
_handler->rotateDelta(rot);
}
if (key == Key::Up) {
glm::vec3 euler(-speed * dt, 0.0, 0.0);
glm::quat rot = glm::quat(euler);
_handler->rotateDelta(rot);
}
if (key == Key::R) {
PowerScaledScalar dist(-speed * dt, 0.0);
_handler->distanceDelta(dist);
}
if (key == Key::F) {
PowerScaledScalar dist(speed * dt, 0.0);
_handler->distanceDelta(dist);
}
if (key == Key::T) {
PowerScaledScalar dist(-speed * pow(10.0f, 11.0f) * dt, 0.0f);
_handler->distanceDelta(dist);
}
//if (key == Keys::G) {
// acc += 0.001;
// PowerScaledScalar dist(speed * pow(10, 8 * acc) * dt, 0.0);
// distanceDelta(dist);
//}
if (key == Key::Y) {
PowerScaledScalar dist(-speed * 100.0f * dt, 6.0f);
_handler->distanceDelta(dist);
}
if (key == Key::H) {
PowerScaledScalar dist(speed * 100.0f * dt, 6.0f);
_handler->distanceDelta(dist);
}
if (key == Key::KeypadSubtract) {
glm::vec2 s = OsEng.renderEngine().camera()->scaling();
s[1] -= 0.5;
OsEng.renderEngine().camera()->setScaling(s);
}
if (key == Key::KeypadAdd) {
glm::vec2 s = OsEng.renderEngine().camera()->scaling();
s[1] += 0.5;
OsEng.renderEngine().camera()->setScaling(s);
}
}
*/
/*
if (key == '1') {
SceneGraphNode* node = getSceneGraphNode("sun");
setFocusNode(node);
getCamera()->setPosition(node->getWorldPosition() + psc(0.0, 0.0, 0.5, 10.0));
getCamera()->setCameraDirection(glm::vec3(0.0, 0.0, -1.0));
}
if (key == '2') {
SceneGraphNode* node = getSceneGraphNode("earth");
setFocusNode(node);
getCamera()->setPosition(node->getWorldPosition() + psc(0.0, 0.0, 1.0, 8.0));
getCamera()->setCameraDirection(glm::vec3(0.0, 0.0, -1.0));
}
if (key == '3') {
SceneGraphNode* node = getSceneGraphNode("moon");
setFocusNode(node);
getCamera()->setPosition(node->getWorldPosition() + psc(0.0, 0.0, 0.5, 8.0));
getCamera()->setCameraDirection(glm::vec3(0.0, 0.0, -1.0));
}
*/
}
void KeyboardControllerLua::keyPressed(KeyAction action, Key key, KeyModifier modifier) {
lua_State* s = luaL_newstate();
luaL_openlibs(s);
int status = luaL_loadfile(s, absPath("${SCRIPTS}/default_keybinding.lua").c_str());
if (status != LUA_OK) {
LERROR("Error loading script: '" << lua_tostring(s, -1) << "'");
return;
}
if (lua_pcall(s, 0, LUA_MULTRET, 0)) {
LERROR("Error executing script: " << lua_tostring(s, -1));
return;
}
auto start = std::chrono::high_resolution_clock::now();
lua_getfield(s, -1, keyToString(key, modifier).c_str());
if (!lua_isnil(s, -1))
lua_pcall(s, 0, 0, 0);
else
LINFO("Key not found");
auto end = std::chrono::high_resolution_clock::now();
LINFO("Keyboard timing: " << std::chrono::duration_cast<std::chrono::nanoseconds>(end - start).count() << "ns");
}
std::string KeyboardControllerLua::keyToString(Key key, KeyModifier mod) const {
std::string result = "";
int intMod = static_cast<int>(mod);
if (intMod & static_cast<int>(KeyModifier::Control))
result += "CTRL + ";
if (intMod & static_cast<int>(KeyModifier::Super))
result += "SUPER + ";
if (intMod & static_cast<int>(KeyModifier::Alt))
result += "ALT + ";
if (intMod & static_cast<int>(KeyModifier::Shift))
result += "SHIFT + ";
switch (key) {
case Key::Unknown: result += "Unknown"; break;
case Key::Space: result += "Space"; break;
case Key::Apostrophe: result += "Apostrophe"; break;
case Key::Comma: result += "Comma"; break;
case Key::Minus: result += "Minus"; break;
case Key::Period: result += "Period"; break;
case Key::Slash: result += "Slash"; break;
case Key::Num0: result += "0"; break;
case Key::Num1: result += "1"; break;
case Key::Num2: result += "2"; break;
case Key::Num3: result += "3"; break;
case Key::Num4: result += "4"; break;
case Key::Num5: result += "5"; break;
case Key::Num6: result += "6"; break;
case Key::Num7: result += "7"; break;
case Key::Num8: result += "8"; break;
case Key::Num9: result += "9"; break;
case Key::SemiColon: result += "SemiColon"; break;
case Key::Equal: result += "Equal"; break;
case Key::A: result += "A"; break;
case Key::B: result += "B"; break;
case Key::C: result += "C"; break;
case Key::D: result += "D"; break;
case Key::E: result += "E"; break;
case Key::F: result += "F"; break;
case Key::G: result += "G"; break;
case Key::H: result += "H"; break;
case Key::I: result += "I"; break;
case Key::J: result += "J"; break;
case Key::K: result += "K"; break;
case Key::L: result += "L"; break;
case Key::M: result += "M"; break;
case Key::N: result += "N"; break;
case Key::O: result += "O"; break;
case Key::P: result += "P"; break;
case Key::Q: result += "Q"; break;
case Key::R: result += "R"; break;
case Key::S: result += "S"; break;
case Key::T: result += "T"; break;
case Key::U: result += "U"; break;
case Key::V: result += "V"; break;
case Key::W: result += "W"; break;
case Key::X: result += "X"; break;
case Key::Y: result += "Y"; break;
case Key::Z: result += "Z"; break;
case Key::LeftBracket: result += "LeftBracket"; break;
case Key::BackSlash: result += "BackSlash"; break;
case Key::RightBracket: result += "RightBracket"; break;
case Key::GraveAccent: result += "GraveAccent"; break;
case Key::World1: result += "World1"; break;
case Key::World2: result += "World2"; break;
case Key::Escape: result += "Escape"; break;
case Key::Enter: result += "Enter"; break;
case Key::Tab: result += "Tab"; break;
case Key::BackSpace: result += "BackSpace"; break;
case Key::Insert: result += "Insert"; break;
case Key::Delete: result += "Delete"; break;
case Key::Right: result += "Right"; break;
case Key::Left: result += "Left"; break;
case Key::Down: result += "Down"; break;
case Key::Up: result += "Up"; break;
case Key::PageUp: result += "PageUp"; break;
case Key::PageDown: result += "PageDown"; break;
case Key::Home: result += "Home"; break;
case Key::End: result += "End"; break;
case Key::CapsLock: result += "CapsLock"; break;
case Key::ScrollLock: result += "ScrollLock"; break;
case Key::NumLock: result += "NumLock"; break;
case Key::PrintScreen: result += "PrintScreen"; break;
case Key::Pause: result += "Pause"; break;
case Key::F1: result += "F1"; break;
case Key::F2: result += "F2"; break;
case Key::F3: result += "F3"; break;
case Key::F4: result += "F4"; break;
case Key::F5: result += "F5"; break;
case Key::F6: result += "F6"; break;
case Key::F7: result += "F7"; break;
case Key::F8: result += "F8"; break;
case Key::F9: result += "F9"; break;
case Key::F10: result += "F10"; break;
case Key::F11: result += "F11"; break;
case Key::F12: result += "F12"; break;
case Key::F13: result += "F13"; break;
case Key::F14: result += "F14"; break;
case Key::F15: result += "F15"; break;
case Key::F16: result += "F16"; break;
case Key::F17: result += "F17"; break;
case Key::F18: result += "F18"; break;
case Key::F19: result += "F19"; break;
case Key::F20: result += "F20"; break;
case Key::F21: result += "F21"; break;
case Key::F22: result += "F22"; break;
case Key::F23: result += "F23"; break;
case Key::F24: result += "F24"; break;
case Key::F25: result += "F25"; break;
case Key::Keypad0: result += "Keypad0"; break;
case Key::Keypad1: result += "Keypad1"; break;
case Key::Keypad2: result += "Keypad2"; break;
case Key::Keypad3: result += "Keypad3"; break;
case Key::Keypad4: result += "Keypad4"; break;
case Key::Keypad5: result += "Keypad5"; break;
case Key::Keypad6: result += "Keypad6"; break;
case Key::Keypad7: result += "Keypad7"; break;
case Key::Keypad8: result += "Keypad8"; break;
case Key::Keypad9: result += "Keypad9"; break;
case Key::KeypadDecimal: result += "KeypadDecimal"; break;
case Key::KeypadDivide: result += "KeypadDivide"; break;
case Key::KeypadMultiply: result += "KeypadMultiply"; break;
case Key::KeypadSubtract: result += "KeypadSubtract"; break;
case Key::KeypadAdd: result += "KeypadAdd"; break;
case Key::KeypadEnter: result += "KeypadEnter"; break;
case Key::LeftShift: result += "LeftShift"; break;
case Key::LeftControl: result += "LeftControl"; break;
case Key::LeftAlt: result += "LeftAlt"; break;
case Key::LeftSuper: result += "LeftSuper"; break;
case Key::RightShift: result += "RightShift"; break;
case Key::RightControl: result += "RightControl"; break;
case Key::RightAlt: result += "RightAlt"; break;
case Key::RightSuper: result += "RightSuper"; break;
case Key::Menu: result += "Menu"; break;
default:
assert(false);
}
return result;
}
} // namespace interaction
} // namespace openspace

View File

@@ -24,280 +24,350 @@
#include <openspace/interaction/luaconsole.h>
#include <openspace/network/parallelconnection.h>
#include <openspace/engine/openspaceengine.h>
#include <openspace/engine/wrapper/windowwrapper.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/filesystem/cachemanager.h>
#include <ghoul/logging/logmanager.h>
#include <ghoul/misc/clipboard.h>
#include <ghoul/opengl/ghoul_gl.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/font/font.h>
#include <ghoul/font/fontmanager.h>
#include <ghoul/font/fontrenderer.h>
#include <ghoul/misc/clipboard.h>
#include <ghoul/opengl/ghoul_gl.h>
#include <string>
#include <iostream>
#include <iterator>
#include <fstream>
#include <string>
namespace {
const std::string _loggerCat = "LuaConsole";
const std::string historyFile = "ConsoleHistory";
const char* HistoryFile = "ConsoleHistory";
const int NoAutoComplete = -1;
}
#include "luaconsole_lua.inl"
const openspace::Key CommandInputButton = openspace::Key::GraveAccent;
} // namespace
namespace openspace {
LuaConsole::LuaConsole()
: _inputPosition(0)
, _activeCommand(0)
, _filename("")
, _autoCompleteInfo({NoAutoComplete, false, ""})
, _isVisible(false)
LuaConsole::LuaConsole()
: properties::PropertyOwner("LuaConsole")
, _isVisible("isVisible", "Is Visible", false)
, _remoteScripting(true)
, _inputPosition(0)
, _activeCommand(0)
, _autoCompleteInfo({NoAutoComplete, false, ""})
{
// _commands.push_back("");
// _activeCommand = _commands.size() - 1;
_isVisible.onChange([this](){
if (_isVisible) {
_remoteScripting = false;
} else {
_remoteScripting = OsEng.parallelConnection().isHost();
}
});
addProperty(_isVisible);
}
void LuaConsole::initialize() {
_filename = FileSys.cacheManager()->cachedFilename(
historyFile,
std::string filename = FileSys.cacheManager()->cachedFilename(
HistoryFile,
"",
ghoul::filesystem::CacheManager::Persistent::Yes
);
std::ifstream file(_filename, std::ios::binary | std::ios::in);
if (file.good()) {
int64_t nCommands;
file.read(reinterpret_cast<char*>(&nCommands), sizeof(int64_t));
std::ifstream file;
file.exceptions(~std::ofstream::goodbit);
file.open(filename, std::ios::binary | std::ios::in);
std::vector<char> tmp;
for (int64_t i = 0; i < nCommands; ++i) {
int64_t length;
file.read(reinterpret_cast<char*>(&length), sizeof(int64_t));
tmp.resize(length + 1);
file.read(tmp.data(), length);
tmp[length] = '\0';
_commandsHistory.emplace_back(std::string(tmp.begin(), tmp.end()));
}
file.close();
_commands = _commandsHistory;
// Read the number of commands from the history
int64_t nCommands;
file.read(reinterpret_cast<char*>(&nCommands), sizeof(int64_t));
for (int64_t i = 0; i < nCommands; ++i) {
int64_t length;
file.read(reinterpret_cast<char*>(&length), sizeof(int64_t));
std::vector<char> tmp(length + 1);
file.read(tmp.data(), length);
tmp[length] = '\0';
_commandsHistory.emplace_back(std::string(tmp.begin(), tmp.end()));
}
file.close();
_commands = _commandsHistory;
_commands.push_back("");
_activeCommand = _commands.size() - 1;
OsEng.parallelConnection().connectionEvent()->subscribe("luaConsole",
"statusChanged", [this]() {
ParallelConnection::Status status = OsEng.parallelConnection().status();
parallelConnectionChanged(status);
});
OsEng.parallelConnection().connectionEvent()->subscribe(
"luaConsole",
"statusChanged",
[this]() {
ParallelConnection::Status status = OsEng.parallelConnection().status();
parallelConnectionChanged(status);
}
);
}
void LuaConsole::deinitialize() {
std::ofstream file(_filename, std::ios::binary | std::ios::out);
if (file.good()) {
int64_t nCommands = _commandsHistory.size();
file.write(reinterpret_cast<const char*>(&nCommands), sizeof(int64_t));
for (const std::string& s : _commandsHistory) {
int64_t length = s.length();
file.write(reinterpret_cast<const char*>(&length), sizeof(int64_t));
file.write(s.c_str(), length);
}
std::string filename = FileSys.cacheManager()->cachedFilename(
HistoryFile,
"",
ghoul::filesystem::CacheManager::Persistent::Yes
);
std::ofstream file;
file.exceptions(~std::ofstream::goodbit);
file.open(filename, std::ios::binary | std::ios::in);
int64_t nCommands = _commandsHistory.size();
file.write(reinterpret_cast<const char*>(&nCommands), sizeof(int64_t));
for (const std::string& s : _commandsHistory) {
int64_t length = s.length();
file.write(reinterpret_cast<const char*>(&length), sizeof(int64_t));
// We don't write the \0 at the end on purpose
file.write(s.c_str(), length);
}
OsEng.parallelConnection().connectionEvent()->unsubscribe("luaConsole");
}
void LuaConsole::keyboardCallback(Key key, KeyModifier modifier, KeyAction action) {
if (action == KeyAction::Press || action == KeyAction::Repeat) {
const bool modifierControl = (modifier == KeyModifier::Control);
const bool modifierShift = (modifier == KeyModifier::Shift);
bool LuaConsole::keyboardCallback(Key key, KeyModifier modifier, KeyAction action) {
if (action != KeyAction::Press && action != KeyAction::Repeat) {
return false;
}
// Paste from clipboard
if (modifierControl && (key == Key::V))
addToCommand(ghoul::clipboardText());
if (key == CommandInputButton) {
// Button left of 1 and above TAB
// How to deal with different keyboard languages? ---abock
_isVisible = !_isVisible;
return true;
}
// Copy to clipboard
if (modifierControl && (key == Key::C))
ghoul::setClipboardText(_commands.at(_activeCommand));
if (!_isVisible) {
return false;
}
// Go to the previous character
if ((key == Key::Left) && (_inputPosition > 0))
const bool modifierControl = (modifier == KeyModifier::Control);
const bool modifierShift = (modifier == KeyModifier::Shift);
// Paste from clipboard
if (modifierControl && (key == Key::V)) {
addToCommand(ghoul::clipboardText());
return true;
}
// Copy to clipboard
if (modifierControl && (key == Key::C)) {
ghoul::setClipboardText(_commands.at(_activeCommand));
return true;
}
// Go to the previous character
if ((key == Key::Left) && (_inputPosition > 0)) {
--_inputPosition;
return true;
}
// Go to the next character
if (key == Key::Right) {
//&& _inputPosition < _commands.at(_activeCommand).length())
//++_inputPosition;
_inputPosition = std::min(
_inputPosition + 1,
_commands.at(_activeCommand).length()
);
return true;
}
// Go to previous command
if (key == Key::Up) {
if (_activeCommand > 0) {
--_activeCommand;
}
_inputPosition = _commands.at(_activeCommand).length();
return true;
}
// Go to next command (the last is empty)
if (key == Key::Down) {
if (_activeCommand < _commands.size() - 1) {
++_activeCommand;
}
_inputPosition = _commands.at(_activeCommand).length();
return true;
}
// Remove character before _inputPosition
if (key == Key::BackSpace) {
if (_inputPosition > 0) {
_commands.at(_activeCommand).erase(_inputPosition - 1, 1);
--_inputPosition;
// Go to the next character
if ((key == Key::Right) && _inputPosition < _commands.at(_activeCommand).length())
++_inputPosition;
// Go to previous command
if (key == Key::Up) {
if (_activeCommand > 0)
--_activeCommand;
_inputPosition = _commands.at(_activeCommand).length();
}
return true;
}
// Go to next command (the last is empty)
if (key == Key::Down) {
if (_activeCommand < _commands.size() - 1)
++_activeCommand;
_inputPosition = _commands.at(_activeCommand).length();
}
// Remove character before _inputPosition
if (key == Key::BackSpace) {
if (_inputPosition > 0) {
_commands.at(_activeCommand).erase(_inputPosition - 1, 1);
--_inputPosition;
}
}
// Remove character after _inputPosition
if (key == Key::Delete) {
if (_inputPosition <= _commands.at(_activeCommand).size())
_commands.at(_activeCommand).erase(_inputPosition, 1);
// Remove character after _inputPosition
if (key == Key::Delete) {
if (_inputPosition <= _commands.at(_activeCommand).size()) {
_commands.at(_activeCommand).erase(_inputPosition, 1);
}
return true;
}
// Go to the beginning of command string
if (key == Key::Home)
_inputPosition = 0;
// Go to the beginning of command string
if (key == Key::Home) {
_inputPosition = 0;
return true;
}
// Go to the end of command string
if (key == Key::End)
_inputPosition = _commands.at(_activeCommand).size();
// Go to the end of command string
if (key == Key::End) {
_inputPosition = _commands.at(_activeCommand).size();
return true;
}
if (key == Key::Enter) {
// SHIFT+ENTER == new line
if (modifierShift)
addToCommand("\n");
// ENTER == run lua script
else {
std::string cmd = _commands.at(_activeCommand);
if (cmd != "") {
OsEng.scriptEngine().queueScript(cmd,
_remoteScripting ? scripting::ScriptEngine::RemoteScripting::Yes : scripting::ScriptEngine::RemoteScripting::No);
if (key == Key::Enter) {
// SHIFT+ENTER == new line
if (modifierShift) {
addToCommand("\n");
}
// ENTER == run lua script
else {
std::string cmd = _commands.at(_activeCommand);
if (cmd != "") {
using RemoteScripting = scripting::ScriptEngine::RemoteScripting;
OsEng.scriptEngine().queueScript(
cmd,
_remoteScripting ? RemoteScripting::Yes : RemoteScripting::No
);
// Only add the current command to the history if it hasn't been
// executed before. We don't want two of the same commands in a row
if (_commandsHistory.empty() || (cmd != _commandsHistory.back()))
_commandsHistory.push_back(_commands.at(_activeCommand));
// Only add the current command to the history if it hasn't been
// executed before. We don't want two of the same commands in a row
if (_commandsHistory.empty() || (cmd != _commandsHistory.back())) {
_commandsHistory.push_back(_commands.at(_activeCommand));
}
// Some clean up after the execution of the command
_commands = _commandsHistory;
_commands.push_back("");
_activeCommand = _commands.size() - 1;
_inputPosition = 0;
setVisible(false);
}
// Some clean up after the execution of the command
_commands = _commandsHistory;
_commands.push_back("");
_activeCommand = _commands.size() - 1;
_inputPosition = 0;
_isVisible = false;
}
return true;
}
if (key == Key::Tab) {
// We get a list of all the available commands and initially find the first
// command that starts with how much we typed sofar. We store the index so
// that in subsequent "tab" presses, we will discard previous commands. This
// implements the 'hop-over' behavior. As soon as another key is pressed,
// everything is set back to normal
// If the shift key is pressed, we decrement the current index so that we will
// find the value before the one that was previously found
if (_autoCompleteInfo.lastIndex != NoAutoComplete && modifierShift) {
_autoCompleteInfo.lastIndex -= 2;
}
std::vector<std::string> allCommands = OsEng.scriptEngine().allLuaFunctions();
std::sort(allCommands.begin(), allCommands.end());
std::string currentCommand = _commands.at(_activeCommand);
// Check if it is the first time the tab has been pressed. If so, we need to
// store the already entered command so that we can later start the search
// from there. We will overwrite the 'currentCommand' thus making the storage
// necessary
if (!_autoCompleteInfo.hasInitialValue) {
_autoCompleteInfo.initialValue = currentCommand;
_autoCompleteInfo.hasInitialValue = true;
}
if (key == Key::Tab) {
// We get a list of all the available commands and initially find the first
// command that starts with how much we typed sofar. We store the index so
// that in subsequent "tab" presses, we will discard previous commands. This
// implements the 'hop-over' behavior. As soon as another key is pressed,
// everything is set back to normal
for (int i = 0; i < static_cast<int>(allCommands.size()); ++i) {
const std::string& command = allCommands[i];
// If the shift key is pressed, we decrement the current index so that we will
// find the value before the one that was previously found
if (_autoCompleteInfo.lastIndex != NoAutoComplete && modifierShift)
_autoCompleteInfo.lastIndex -= 2;
std::vector<std::string> allCommands = OsEng.scriptEngine().allLuaFunctions();
std::sort(allCommands.begin(), allCommands.end());
// Check if the command has enough length (we don't want crashes here)
// Then check if the iterator-command's start is equal to what we want
// then check if we need to skip the first found values as the user has
// pressed TAB repeatedly
size_t fullLength = _autoCompleteInfo.initialValue.length();
bool correctLength = command.length() >= fullLength;
std::string currentCommand = _commands.at(_activeCommand);
// Check if it is the first time the tab has been pressed. If so, we need to
// store the already entered command so that we can later start the search
// from there. We will overwrite the 'currentCommand' thus making the storage
// necessary
if (!_autoCompleteInfo.hasInitialValue) {
_autoCompleteInfo.initialValue = currentCommand;
_autoCompleteInfo.hasInitialValue = true;
}
for (int i = 0; i < static_cast<int>(allCommands.size()); ++i) {
const std::string& command = allCommands[i];
// Check if the command has enough length (we don't want crashes here)
// Then check if the iterator-command's start is equal to what we want
// then check if we need to skip the first found values as the user has
// pressed TAB repeatedly
size_t fullLength = _autoCompleteInfo.initialValue.length();
bool correctLength = command.length() >= fullLength;
std::string commandLowerCase;
std::transform(
command.begin(), command.end(),
std::back_inserter(commandLowerCase),
::tolower
);
std::string commandLowerCase;
std::transform(
command.begin(), command.end(),
std::back_inserter(commandLowerCase),
::tolower
);
std::string initialValueLowerCase;
std::transform(
_autoCompleteInfo.initialValue.begin(),
_autoCompleteInfo.initialValue.end(),
std::back_inserter(initialValueLowerCase),
::tolower
);
std::string initialValueLowerCase;
std::transform(
_autoCompleteInfo.initialValue.begin(),
_autoCompleteInfo.initialValue.end(),
std::back_inserter(initialValueLowerCase),
::tolower
);
bool correctCommand =
commandLowerCase.substr(0, fullLength) == initialValueLowerCase;
bool correctCommand =
commandLowerCase.substr(0, fullLength) == initialValueLowerCase;
if (correctLength && correctCommand && (i > _autoCompleteInfo.lastIndex)){
// We found our index, so store it
_autoCompleteInfo.lastIndex = i;
if (correctLength && correctCommand && (i > _autoCompleteInfo.lastIndex)){
// We found our index, so store it
_autoCompleteInfo.lastIndex = i;
// We only want to auto-complete until the next separator "."
size_t pos = command.find('.', fullLength);
if (pos == std::string::npos) {
// If we don't find a separator, we autocomplete until the end
// Set the found command as active command
_commands.at(_activeCommand) = command + "();";
// Set the cursor position to be between the brackets
_inputPosition = _commands.at(_activeCommand).size() - 2;
// We only want to auto-complete until the next separator "."
size_t pos = command.find('.', fullLength);
if (pos == std::string::npos) {
// If we don't find a separator, we autocomplete until the end
// Set the found command as active command
_commands.at(_activeCommand) = command + "();";
// Set the cursor position to be between the brackets
_inputPosition = _commands.at(_activeCommand).size() - 2;
}
else {
// If we find a separator, we autocomplete until and including the
// separator unless the autocompletion would be the same that we
// already have (the case if there are multiple commands in the
// same group
std::string subCommand = command.substr(0, pos + 1);
if (subCommand == _commands.at(_activeCommand)) {
continue;
}
else {
// If we find a separator, we autocomplete until and including the
// separator unless the autocompletion would be the same that we
// already have (the case if there are multiple commands in the
// same group
std::string subCommand = command.substr(0, pos + 1);
if (subCommand == _commands.at(_activeCommand))
continue;
else {
_commands.at(_activeCommand) = command.substr(0, pos + 1);
_inputPosition = _commands.at(_activeCommand).length();
// We only want to remove the autocomplete info if we just
// entered the 'default' openspace namespace
if (command.substr(0, pos + 1) == "openspace.")
_autoCompleteInfo = { NoAutoComplete, false, "" };
_commands.at(_activeCommand) = command.substr(0, pos + 1);
_inputPosition = _commands.at(_activeCommand).length();
// We only want to remove the autocomplete info if we just
// entered the 'default' openspace namespace
if (command.substr(0, pos + 1) == "openspace.") {
_autoCompleteInfo = { NoAutoComplete, false, "" };
}
}
break;
}
break;
}
}
else {
// If any other key is pressed, we want to remove our previous findings
// The special case for Shift is necessary as we want to allow Shift+TAB
if (!modifierShift)
_autoCompleteInfo = { NoAutoComplete, false, ""};
return true;
}
else {
// If any other key is pressed, we want to remove our previous findings
// The special case for Shift is necessary as we want to allow Shift+TAB
if (!modifierShift) {
_autoCompleteInfo = { NoAutoComplete, false, "" };
}
}
return true;
}
void LuaConsole::charCallback(unsigned int codepoint, KeyModifier modifier) {
if (codepoint == static_cast<unsigned int>(commandInputButton()))
if (!_isVisible) {
return;
}
if (codepoint == static_cast<unsigned int>(CommandInputButton)) {
return;
}
#ifndef WIN32
const bool modifierControl = (modifier == KeyModifier::Control);
@@ -308,50 +378,84 @@ void LuaConsole::charCallback(unsigned int codepoint, KeyModifier modifier) {
return;
}
#endif
addToCommand(UnicodeToUTF8(codepoint));
// Disallow all non ASCII characters for now
if (codepoint > 0x7f) {
return;
}
addToCommand(std::string(1, codepoint));
}
void LuaConsole::render() {
const float font_size = 10.0f;
int ySize = OsEng.renderEngine().fontResolution().y;
//int ySize = OsEng.windowWrapper().currentWindowSize().y;
//int ySize = OsEng.windowWrapper().viewportPixelCoordinates().w;
const float FontSize = 10.0f;
float startY = static_cast<float>(ySize) - 2.0f * font_size;
startY = startY - font_size * 15.0f * 2.0f;
if (!_isVisible) {
return;
}
const int ySize = OsEng.renderEngine().fontResolution().y;
const float startY =
static_cast<float>(ySize) - 2.0f * FontSize - FontSize * 15.0f * 2.0f;;
const glm::vec4 red(1, 0, 0, 1);
const glm::vec4 lightBlue(0.4, 0.4, 1, 1);
const glm::vec4 green(0, 1, 0, 1);
const glm::vec4 white(1, 1, 1, 1);
std::shared_ptr<ghoul::fontrendering::Font> font = OsEng.fontManager().font("Mono", font_size);
std::shared_ptr<ghoul::fontrendering::Font> font = OsEng.fontManager().font(
"Mono", FontSize
);
using ghoul::fontrendering::RenderFont;
if (_remoteScripting) {
int nClients = OsEng.parallelConnection().nConnections() - 1;
if (nClients == 1) {
RenderFont(*font, glm::vec2(15.f, startY + 20.0f), red, "Broadcasting script to 1 client");
RenderFont(
*font,
glm::vec2(15.f, startY + 20.0f),
red,
"Broadcasting script to 1 client"
);
} else {
RenderFont(*font, glm::vec2(15.f, startY + 20.0f), red, ("Broadcasting script to " + std::to_string(nClients) + " clients").c_str());
RenderFont(
*font,
glm::vec2(15.f, startY + 20.0f),
red,
("Broadcasting script to " + std::to_string(nClients) + " clients").c_str()
);
}
RenderFont(*font, glm::vec2(15.f, startY), red, "$");
}
else {
if (OsEng.parallelConnection().isHost()) {
RenderFont(*font, glm::vec2(15.f, startY + 20.0f), lightBlue, "Local script execution");
RenderFont(
*font,
glm::vec2(15.f, startY + 20.0f),
lightBlue,
"Local script execution"
);
}
RenderFont(*font, glm::vec2(15.f, startY), lightBlue, "$");
}
RenderFont(*font, glm::vec2(15.f + font_size, startY), white, "%s", _commands.at(_activeCommand).c_str());
RenderFont(
*font,
glm::vec2(15.f + FontSize, startY),
white,
"%s",
_commands.at(_activeCommand).c_str()
);
size_t n = std::count(_commands.at(_activeCommand).begin(), _commands.at(_activeCommand).begin() + _inputPosition, '\n');
const size_t n = std::count(
_commands.at(_activeCommand).begin(),
_commands.at(_activeCommand).begin() + _inputPosition,
'\n'
);
size_t p = _commands.at(_activeCommand).find_last_of('\n', _inputPosition);
size_t linepos = _inputPosition;
if (n>0) {
if (n > 0) {
if (p == _inputPosition) {
p = _commands.at(_activeCommand).find_last_of('\n', _inputPosition - 1);
if (p != std::string::npos) {
@@ -361,107 +465,30 @@ void LuaConsole::render() {
linepos = _inputPosition - 1;
}
}
else{
else {
linepos -= p + 1;
}
}
std::stringstream ss;
ss << "%" << linepos + 1 << "s";
RenderFont(*font, glm::vec2(15.f + font_size * 0.5f, startY - (font_size)*(n + 1)*3.0f / 2.0f), green, ss.str().c_str(), "^");
// sgct_text::print(font, 15.0f + font_size*0.5f, startY - (font_size)*(n + 1)*3.0f / 2.0f, green, ss.str().c_str(), "^");
}
Key LuaConsole::commandInputButton() {
// Button left of 1 and above TAB
// How to deal with different keyboard languages? ---abock
return Key::GraveAccent;
RenderFont(
*font,
glm::vec2(15.f + FontSize * 0.5f, startY - (FontSize) * (n + 1) * 3.0f / 2.0f),
green,
ss.str().c_str(),
"^"
);
}
void LuaConsole::addToCommand(std::string c) {
size_t length = c.length();
_commands.at(_activeCommand).insert(_inputPosition, c);
const size_t length = c.length();
_commands.at(_activeCommand).insert(_inputPosition, std::move(c));
_inputPosition += length;
}
std::string LuaConsole::UnicodeToUTF8(unsigned int codepoint) {
std::string out;
if (codepoint <= 0x7f)
out.append(1, static_cast<char>(codepoint));
else if (codepoint <= 0x7ff)
{
out.append(1, static_cast<char>(0xc0 | ((codepoint >> 6) & 0x1f)));
out.append(1, static_cast<char>(0x80 | (codepoint & 0x3f)));
}
else if (codepoint <= 0xffff)
{
out.append(1, static_cast<char>(0xe0 | ((codepoint >> 12) & 0x0f)));
out.append(1, static_cast<char>(0x80 | ((codepoint >> 6) & 0x3f)));
out.append(1, static_cast<char>(0x80 | (codepoint & 0x3f)));
}
else
{
out.append(1, static_cast<char>(0xf0 | ((codepoint >> 18) & 0x07)));
out.append(1, static_cast<char>(0x80 | ((codepoint >> 12) & 0x3f)));
out.append(1, static_cast<char>(0x80 | ((codepoint >> 6) & 0x3f)));
out.append(1, static_cast<char>(0x80 | (codepoint & 0x3f)));
}
return out;
}
bool LuaConsole::isVisible() const {
return _isVisible;
}
void LuaConsole::setVisible(bool visible) {
_isVisible = visible;
}
void LuaConsole::toggleMode() {
if (_isVisible) {
if (_remoteScripting) {
_remoteScripting = false;
} else {
_isVisible = false;
}
} else {
_remoteScripting = OsEng.parallelConnection().isHost();
_isVisible = true;
}
}
void LuaConsole::parallelConnectionChanged(const ParallelConnection::Status& status) {
_remoteScripting = status == ParallelConnection::Status::Host;
_remoteScripting = (status == ParallelConnection::Status::Host);
}
scripting::LuaLibrary LuaConsole::luaLibrary() {
return {
"console",
{
{
"show",
&luascriptfunctions::show,
"",
"Shows the console"
},
{
"hide",
&luascriptfunctions::hide,
"",
"Hides the console"
},
{
"toggle",
&luascriptfunctions::toggle,
"",
"Toggles the console"
}
}
};
}
} // namespace openspace

View File

@@ -1,73 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2017 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
namespace openspace {
namespace luascriptfunctions {
/**
* \ingroup LuaScripts
* show():
* Shows the console
*/
int show(lua_State* L) {
int nArguments = lua_gettop(L);
if (nArguments != 0)
return luaL_error(L, "Expected %i arguments, got %i", 0, nArguments);
OsEng.console().setVisible(true);
return 0;
}
/**
* \ingroup LuaScripts
* hide():
* Hides the console
*/
int hide(lua_State* L) {
int nArguments = lua_gettop(L);
if (nArguments != 0)
return luaL_error(L, "Expected %i arguments, got %i", 0, nArguments);
OsEng.console().setVisible(false);
return 0;
}
/**
* \ingroup LuaScripts
* toggle():
* Toggles the console
*/
int toggle(lua_State* L) {
int nArguments = lua_gettop(L);
if (nArguments != 0)
return luaL_error(L, "Expected %i arguments, got %i", 0, nArguments);
OsEng.console().toggleMode();
return 0;
}
} // namespace luascriptfunctions
} // namespace openspace

View File

@@ -32,24 +32,24 @@ namespace openspace {
namespace properties {
namespace {
const std::string _loggerCat = "Property";
const std::string MetaDataKeyGuiName = "guiName";
const std::string MetaDataKeyGroup = "Group";
const std::string MetaDataKeyVisibility = "Visibility";
const std::string MetaDataKeyReadOnly = "isReadOnly";
const char* _loggerCat = "Property";
const char* MetaDataKeyGuiName = "guiName";
const char* MetaDataKeyGroup = "Group";
const char* MetaDataKeyVisibility = "Visibility";
const char* MetaDataKeyReadOnly = "isReadOnly";
const std::string _metaDataKeyViewPrefix = "view.";
const char* _metaDataKeyViewPrefix = "view.";
}
const std::string Property::ViewOptions::Color = "color";
const std::string Property::ViewOptions::LightPosition = "lightPosition";
const std::string Property::ViewOptions::PowerScaledCoordinate = "powerScaledCoordinate";
const std::string Property::ViewOptions::PowerScaledScalar = "powerScaledScalar";
const char* Property::ViewOptions::Color = "color";
const char* Property::ViewOptions::LightPosition = "lightPosition";
const char* Property::ViewOptions::PowerScaledCoordinate = "powerScaledCoordinate";
const char* Property::ViewOptions::PowerScaledScalar = "powerScaledScalar";
const std::string Property::IdentifierKey = "Identifier";
const std::string Property::NameKey = "Name";
const std::string Property::TypeKey = "Type";
const std::string Property::MetaDataKey = "MetaData";
const char* Property::IdentifierKey = "Identifier";
const char* Property::NameKey = "Name";
const char* Property::TypeKey = "Type";
const char* Property::MetaDataKey = "MetaData";
Property::Property(std::string identifier, std::string guiName, Visibility visibility)
: _owner(nullptr)
@@ -181,7 +181,7 @@ void Property::notifyListener() {
std::string Property::generateBaseDescription() const {
return
TypeKey + " = \"" + className() + "\", " +
std::string(TypeKey) + " = \"" + className() + "\", " +
IdentifierKey + " = \"" + fullyQualifiedIdentifier() + "\", " +
NameKey + " = \"" + guiName() + "\", " +
generateMetaDataDescription() + ", " +
@@ -201,7 +201,7 @@ std::string Property::generateMetaDataDescription() const {
std::string vis = VisibilityConverter.at(visibility);
return
MetaDataKey + " = {" +
std::string(MetaDataKey) + " = {" +
MetaDataKeyGroup + " = '" + groupIdentifier() + "'," +
MetaDataKeyVisibility + " = " + vis + "," +
MetaDataKeyReadOnly +" = " + (isReadOnly ? "true" : "false") + "}";

View File

@@ -24,33 +24,33 @@
#include <openspace/properties/propertyowner.h>
#include <openspace/properties/property.h>
#include <ghoul/logging/logmanager.h>
#include <ghoul/misc/assert.h>
#include <algorithm>
#include <assert.h>
namespace openspace {
namespace properties {
namespace {
const std::string _loggerCat = "PropertyOwner";
const char* _loggerCat = "PropertyOwner";
bool propertyLess(Property* lhs, Property* rhs)
{
return lhs->identifier() < rhs->identifier();
}
bool propertyLess(Property* lhs, Property* rhs)
{
return lhs->identifier() < rhs->identifier();
}
bool subOwnerLess(PropertyOwner* lhs, PropertyOwner* rhs) {
return lhs->name() < rhs->name();
}
bool subOwnerLess(PropertyOwner* lhs, PropertyOwner* rhs) {
return lhs->name() < rhs->name();
}
}
} // namespace
PropertyOwner::PropertyOwner()
: _name("")
PropertyOwner::PropertyOwner(std::string name)
: _name(std::move(name))
, _owner(nullptr)
{
}
{}
PropertyOwner::~PropertyOwner() {
_properties.clear();
@@ -73,14 +73,20 @@ std::vector<Property*> PropertyOwner::propertiesRecursive() const {
}
Property* PropertyOwner::property(const std::string& id) const {
assert(std::is_sorted(_properties.begin(), _properties.end(), propertyLess));
ghoul_assert(
std::is_sorted(_properties.begin(), _properties.end(), propertyLess),
"Property list must be sorted"
);
// As the _properties list is sorted, just finding the lower bound is sufficient
std::vector<Property*>::const_iterator it
= std::lower_bound(_properties.begin(), _properties.end(), id,
[](Property* prop, const std::string& str) {
return prop->identifier() < str;
});
std::vector<Property*>::const_iterator it = std::lower_bound(
_properties.begin(),
_properties.end(),
id,
[](Property* prop, const std::string& str) {
return prop->identifier() < str;
}
);
if (it == _properties.end() || (*it)->identifier() != id) {
// if we do not own the searched property, it must consist of a concatenated
@@ -118,19 +124,27 @@ std::vector<PropertyOwner*> PropertyOwner::propertySubOwners() const {
}
PropertyOwner* PropertyOwner::propertySubOwner(const std::string& name) const {
assert(std::is_sorted(_subOwners.begin(), _subOwners.end(), subOwnerLess));
ghoul_assert(
std::is_sorted(_subOwners.begin(), _subOwners.end(), subOwnerLess),
"List of subowners must be sorted"
);
// As the _subOwners list is sorted, getting the lower bound is sufficient
std::vector<PropertyOwner*>::const_iterator it
= std::lower_bound(_subOwners.begin(), _subOwners.end(), name,
[](PropertyOwner* owner, const std::string& str) {
return owner->name() < str;
});
std::vector<PropertyOwner*>::const_iterator it = std::lower_bound(
_subOwners.begin(),
_subOwners.end(),
name,
[](PropertyOwner* owner, const std::string& str) {
return owner->name() < str;
}
);
if (it == _subOwners.end() || (*it)->name() != name)
if (it == _subOwners.end() || (*it)->name() != name) {
return nullptr;
else
}
else {
return *it;
}
}
bool PropertyOwner::hasPropertySubOwner(const std::string& name) const {
@@ -143,17 +157,24 @@ void PropertyOwner::setPropertyGroupName(std::string groupID, std::string name)
std::string PropertyOwner::propertyGroupName(const std::string& groupID) const {
auto it = _groupNames.find(groupID);
if (it == _groupNames.end())
if (it == _groupNames.end()) {
return groupID;
else
}
else {
return it->second;
}
}
void PropertyOwner::addProperty(Property* prop)
{
assert(prop != nullptr);
assert(std::is_sorted(_properties.begin(), _properties.end(), propertyLess));
assert(std::is_sorted(_subOwners.begin(), _subOwners.end(), subOwnerLess));
void PropertyOwner::addProperty(Property* prop) {
ghoul_assert(prop != nullptr, "prop must not be nullptr");
ghoul_assert(
std::is_sorted(_properties.begin(), _properties.end(), propertyLess),
"Property list must be sorted"
);
ghoul_assert(
std::is_sorted(_subOwners.begin(), _subOwners.end(), subOwnerLess),
"Subowner list must be sorted"
);
if (prop->identifier().empty()) {
LERROR("No property identifier specified");
@@ -162,23 +183,25 @@ void PropertyOwner::addProperty(Property* prop)
// See if we can find the identifier of the property to add in the properties list
// The _properties list is sorted, so getting the lower bound is sufficient
std::vector<Property*>::iterator it
= std::lower_bound(_properties.begin(), _properties.end(), prop->identifier(),
[](Property* prop, const std::string& str) {
return prop->identifier() < str;
});
std::vector<Property*>::iterator it = std::lower_bound(
_properties.begin(),
_properties.end(),
prop->identifier(),
[](Property* prop, const std::string& str) {
return prop->identifier() < str;
}
);
// If we found the property identifier, we need to bail out
if (it != _properties.end() && (*it)->identifier() == prop->identifier()) {
LERROR("Property identifier '" << prop->identifier()
<< "' already present in PropertyOwner '"
<< name() << "'");
LERROR("Property identifier '" << prop->identifier() <<
"' already present in PropertyOwner '" << name() << "'");
return;
} else {
// Otherwise we still have to look if there is a PropertyOwner with the same name
const bool hasOwner = hasPropertySubOwner(prop->identifier());
if (hasOwner) {
LERROR("Property identifier '" << prop->identifier() << "' already names a"
LERROR("Property identifier '" << prop->identifier() << "' already names a "
<< "registed PropertyOwner");
return;
}
@@ -195,26 +218,30 @@ void PropertyOwner::addProperty(Property& prop) {
}
void PropertyOwner::addPropertySubOwner(openspace::properties::PropertyOwner* owner) {
assert(owner != nullptr);
assert(std::is_sorted(_properties.begin(), _properties.end(), propertyLess));
assert(std::is_sorted(_subOwners.begin(), _subOwners.end(), subOwnerLess));
ghoul_assert(owner != nullptr, "owner must not be nullptr");
ghoul_assert(
std::is_sorted(_properties.begin(), _properties.end(), propertyLess),
"Property list must be sorted"
);
ghoul_assert(
std::is_sorted(_subOwners.begin(), _subOwners.end(), subOwnerLess),
"Subowner list must be sorted"
);
if (owner->name().empty()) {
LERROR("PropertyOwner did not have a name");
return;
}
ghoul_assert(!owner->name().empty(), "PropertyOwner must have a name");
// See if we can find the name of the propertyowner to add using the lower bound
std::vector<PropertyOwner*>::iterator it
= std::lower_bound(_subOwners.begin(), _subOwners.end(), owner->name(),
[](PropertyOwner* owner, const std::string& str) {
return owner->name() < str;
});
std::vector<PropertyOwner*>::iterator it = std::lower_bound(
_subOwners.begin(), _subOwners.end(), owner->name(),
[](PropertyOwner* owner, const std::string& str) {
return owner->name() < str;
}
);
// If we found the propertyowner's name, we need to bail out
if (it != _subOwners.end() && (*it)->name() == owner->name()) {
LERROR("PropertyOwner '" << owner->name()
<< "' already present in PropertyOwner '" << name() << "'");
LERROR("PropertyOwner '" << owner->name() <<
"' already present in PropertyOwner '" << name() << "'");
return;
} else {
// We still need to check if the PropertyOwners name is used in a Property
@@ -230,7 +257,6 @@ void PropertyOwner::addPropertySubOwner(openspace::properties::PropertyOwner* ow
owner->setPropertyOwner(this);
}
}
}
void PropertyOwner::addPropertySubOwner(openspace::properties::PropertyOwner& owner) {
@@ -238,22 +264,26 @@ void PropertyOwner::addPropertySubOwner(openspace::properties::PropertyOwner& ow
}
void PropertyOwner::removeProperty(Property* prop) {
assert(prop != nullptr);
ghoul_assert(prop != nullptr, "prop must not be nullptr");
// See if we can find the identifier of the property to add in the properties list
std::vector<Property*>::iterator it
= std::lower_bound(_properties.begin(), _properties.end(), prop->identifier(),
[](Property* prop, const std::string& str) {
return prop->identifier() < str;
});
std::vector<Property*>::iterator it = std::lower_bound(
_properties.begin(),
_properties.end(),
prop->identifier(),
[](Property* prop, const std::string& str) {
return prop->identifier() < str;
}
);
// If we found the property identifier, we can delete it
if (it != _properties.end() && (*it)->identifier() == prop->identifier()) {
(*it)->setPropertyOwner(nullptr);
_properties.erase(it);
} else
LERROR("Property with identifier '" << prop->identifier()
<< "' not found for removal.");
} else {
LERROR("Property with identifier '" << prop->identifier() <<
"' not found for removal.");
}
}
void PropertyOwner::removeProperty(Property& prop) {
@@ -261,21 +291,25 @@ void PropertyOwner::removeProperty(Property& prop) {
}
void PropertyOwner::removePropertySubOwner(openspace::properties::PropertyOwner* owner) {
assert(owner != nullptr);
ghoul_assert(owner != nullptr, "owner must not be nullptr");
// See if we can find the name of the propertyowner to add
std::vector<PropertyOwner*>::iterator it
= std::lower_bound(_subOwners.begin(), _subOwners.end(), owner->name(),
[](PropertyOwner* owner, const std::string& str) {
return owner->name() < str;
});
std::vector<PropertyOwner*>::iterator it = std::lower_bound(
_subOwners.begin(),
_subOwners.end(),
owner->name(),
[](PropertyOwner* owner, const std::string& str) {
return owner->name() < str;
}
);
// If we found the propertyowner, we can delete it
if (it != _subOwners.end() && (*it)->name() == owner->name()) {
_subOwners.erase(it);
} else
LERROR("PropertyOwner with name '" << owner->name()
<< "' not found for removal.");
} else {
LERROR("PropertyOwner with name '" << owner->name() <<
"' not found for removal.");
}
}
void PropertyOwner::removePropertySubOwner(openspace::properties::PropertyOwner& owner) {

View File

@@ -88,7 +88,8 @@ std::unique_ptr<Renderable> Renderable::createFromDictionary(
}
Renderable::Renderable()
: _enabled("enabled", "Is Enabled", true)
: properties::PropertyOwner("renderable")
, _enabled("enabled", "Is Enabled", true)
, _renderBin(RenderBin::Opaque)
, _startTime("")
, _endTime("")
@@ -96,17 +97,16 @@ Renderable::Renderable()
{}
Renderable::Renderable(const ghoul::Dictionary& dictionary)
: _enabled("enabled", "Is Enabled", true)
: properties::PropertyOwner("renderable")
, _enabled("enabled", "Is Enabled", true)
, _renderBin(RenderBin::Opaque)
, _startTime("")
, _endTime("")
, _hasTimeInterval(false)
{
setName("renderable");
ghoul_assert(
dictionary.hasKeyAndValue<std::string>(SceneGraphNode::KeyName),
"SceneGraphNode must specify '" << SceneGraphNode::KeyName << "'"
std::string("SceneGraphNode must specify '") + SceneGraphNode::KeyName + "'"
);
dictionary.getValue(keyStart, _startTime);

View File

@@ -39,6 +39,7 @@
#include <openspace/rendering/raycastermanager.h>
#include <openspace/rendering/renderer.h>
#include <openspace/rendering/screenspacerenderable.h>
#include <openspace/scene/scenegraphnode.h>
#include <openspace/util/camera.h>
#include <openspace/util/time.h>
#include <openspace/util/screenlog.h>
@@ -91,7 +92,8 @@ namespace {
namespace openspace {
RenderEngine::RenderEngine()
: _mainCamera(nullptr)
: properties::PropertyOwner("RenderEngine")
, _mainCamera(nullptr)
, _raycasterManager(nullptr)
, _performanceMeasurements("performanceMeasurements", "Performance Measurements")
, _frametimeType(
@@ -118,8 +120,6 @@ RenderEngine::RenderEngine()
, _fadeDirection(0)
, _frameNumber(0)
{
setName("RenderEngine");
_performanceMeasurements.onChange([this](){
if (_performanceMeasurements) {
if (!_performanceManager) {
@@ -185,7 +185,7 @@ void RenderEngine::initialize() {
if (confManager.hasKeyAndValue<std::string>(KeyRenderingMethod)) {
renderingMethod = confManager.value<std::string>(KeyRenderingMethod);
} else {
using Version = ghoul::systemcapabilities::OpenGLCapabilitiesComponent::Version;
using Version = ghoul::systemcapabilities::Version;
// The default rendering method has a requirement of OpenGL 4.3, so if we are
// below that, we will fall back to frame buffer operation
@@ -555,7 +555,9 @@ void RenderEngine::postDraw() {
}
if (_performanceManager) {
_performanceManager->storeScenePerformanceMeasurements(scene()->allSceneGraphNodes());
_performanceManager->storeScenePerformanceMeasurements(
scene()->allSceneGraphNodes()
);
}
}
@@ -1098,6 +1100,8 @@ void RenderEngine::renderInformation() {
penPosition.y -= _fontInfo->height();
}
catch (...) {
// @CLEANUP: This is bad as it will discard all exceptions
// without telling us about it! ---abock
}
}

View File

@@ -97,7 +97,8 @@ std::unique_ptr<ScreenSpaceRenderable> ScreenSpaceRenderable::createFromDictiona
}
ScreenSpaceRenderable::ScreenSpaceRenderable(const ghoul::Dictionary& dictionary)
: _enabled("enabled", "Is Enabled", true)
: properties::PropertyOwner("")
, _enabled("enabled", "Is Enabled", true)
, _useFlatScreen("flatScreen", "Flat Screen", true)
, _euclideanPosition(
"euclideanPosition",
@@ -130,14 +131,15 @@ ScreenSpaceRenderable::ScreenSpaceRenderable(const ghoul::Dictionary& dictionary
addProperty(_alpha);
addProperty(_delete);
dictionary.getValue(KeyFlatScreen, _useFlatScreen);
useEuclideanCoordinates(_useFlatScreen);
if (_useFlatScreen)
if (_useFlatScreen) {
dictionary.getValue(KeyPosition, _euclideanPosition);
else
}
else {
dictionary.getValue(KeyPosition, _sphericalPosition);
}
dictionary.getValue(KeyScale, _scale);

View File

@@ -72,11 +72,13 @@ std::unique_ptr<Rotation> Rotation::createFromDictionary(const ghoul::Dictionary
return result;
}
Rotation::Rotation() {
setName("Rotation");
}
Rotation::Rotation()
: properties::PropertyOwner("Rotation")
{}
Rotation::Rotation(const ghoul::Dictionary& dictionary) {}
Rotation::Rotation(const ghoul::Dictionary& dictionary)
: properties::PropertyOwner("Rotation")
{}
Rotation::~Rotation() {}

View File

@@ -76,6 +76,10 @@ std::unique_ptr<Scale> Scale::createFromDictionary(const ghoul::Dictionary& dict
return result;
}
Scale::Scale()
: properties::PropertyOwner("Scale")
{}
Scale::~Scale() {}
bool Scale::initialize() {

View File

@@ -113,6 +113,7 @@ bool SceneGraph::loadFromFile(const std::string& sceneDescription) {
);
}
catch (...) {
// @CLEANUP: This is bad to just catch all exceptions! ---abock
return false;
}

View File

@@ -145,7 +145,8 @@ SceneGraphNode* SceneGraphNode::createFromDictionary(const ghoul::Dictionary& di
}
SceneGraphNode::SceneGraphNode()
: _parent(nullptr)
: properties::PropertyOwner("")
, _parent(nullptr)
, _transform {
std::make_unique<StaticTranslation>(),
std::make_unique<StaticRotation>(),

View File

@@ -80,6 +80,10 @@ std::unique_ptr<Translation> Translation::createFromDictionary(
return result;
}
Translation::Translation()
: properties::PropertyOwner("Translation")
{}
Translation::~Translation() {}
bool Translation::initialize() {

View File

@@ -111,7 +111,7 @@ int hasOpenGLVersion(lua_State* L) {
int major = std::stoi(v[0]);
int minor = std::stoi(v[1]);
int release = v.size() == 3 ? std::stoi(v[2]) : 0;
OpenGLCapabilitiesComponent::Version version = { major, minor, release };
Version version = { major, minor, release };
bool supported = OpenGLCap.openGLVersion() >= version;
@@ -121,7 +121,7 @@ int hasOpenGLVersion(lua_State* L) {
}
int openGLVersion(lua_State* L) {
lua_pushstring(L, OpenGLCap.openGLVersion().toString().c_str());
lua_pushstring(L, std::to_string(OpenGLCap.openGLVersion()).c_str());
return 1;
}

View File

@@ -30,15 +30,16 @@
#include <iterator>
#include <fstream>
#include <sstream>
namespace {
const std::string MainTemplateFilename = "${OPENSPACE_DATA}/web/factories/main.hbs";
const std::string FactoryTemplateFilename = "${OPENSPACE_DATA}/web/factories/factory.hbs";
const std::string HandlebarsFilename = "${OPENSPACE_DATA}/web/common/handlebars-v4.0.5.js";
const std::string JsFilename = "${OPENSPACE_DATA}/web/factories/script.js";
const std::string BootstrapFilename = "${OPENSPACE_DATA}/web/common/bootstrap.min.css";
const std::string CssFilename = "${OPENSPACE_DATA}/web/common/style.css";
}
const char* MainTemplateFilename = "${OPENSPACE_DATA}/web/factories/main.hbs";
const char* FactoryTemplateFilename = "${OPENSPACE_DATA}/web/factories/factory.hbs";
const char* HandlebarsFilename = "${OPENSPACE_DATA}/web/common/handlebars-v4.0.5.js";
const char* JsFilename = "${OPENSPACE_DATA}/web/factories/script.js";
const char* BootstrapFilename = "${OPENSPACE_DATA}/web/common/bootstrap.min.css";
const char* CssFilename = "${OPENSPACE_DATA}/web/common/style.css";
} // namespace
namespace openspace {

View File

@@ -65,7 +65,7 @@ KeyModifier operator|(KeyModifier lhs, KeyModifier rhs) {
return static_cast<KeyModifier>(
static_cast<std::underlying_type_t<KeyModifier>>(lhs) |
static_cast<std::underlying_type_t<KeyModifier>>(rhs)
);
);
}
KeyModifier operator|=(KeyModifier& lhs, KeyModifier rhs) {
@@ -82,8 +82,9 @@ KeyWithModifier stringToKey(std::string str) {
// default is unknown
Key k = Key::Unknown;
auto it = KeyMapping.find(tokens.back());
if (it != KeyMapping.end())
if (it != KeyMapping.end()) {
k = it->second;
}
KeyModifier m = KeyModifier::NoModifier;
@@ -92,10 +93,12 @@ KeyWithModifier stringToKey(std::string str) {
tokens.end() - 1,
[&m](const std::string& s) {
auto it = KeyModifierMapping.find(s);
if (it != KeyModifierMapping.end())
if (it != KeyModifierMapping.end()) {
m |= it->second;
else
}
else {
LERROR("Unknown modifier key '" << s << "'");
}
}
);
@@ -103,10 +106,12 @@ KeyWithModifier stringToKey(std::string str) {
}
bool operator<(const KeyWithModifier& lhs, const KeyWithModifier& rhs) {
if (lhs.modifier == rhs.modifier)
if (lhs.modifier == rhs.modifier) {
return lhs.key < rhs.key;
else
}
else {
return lhs.modifier < rhs.modifier;
}
}
} // namespace openspace
@@ -115,8 +120,9 @@ namespace std {
std::string to_string(openspace::Key key) {
for (const auto& p : openspace::KeyMapping) {
if (p.second == key)
if (p.second == key) {
return p.first;
}
}
ghoul_assert(false, "Missing key in KeyMapping");
}
@@ -124,8 +130,9 @@ std::string to_string(openspace::Key key) {
std::string to_string(openspace::KeyModifier mod) {
using namespace openspace;
if (mod == KeyModifier::NoModifier)
if (mod == KeyModifier::NoModifier) {
return "";
}
std::string result;
for (const auto& p : KeyModifierMapping) {
@@ -139,10 +146,12 @@ std::string to_string(openspace::KeyModifier mod) {
}
std::string to_string(openspace::KeyWithModifier key) {
if (key.modifier == openspace::KeyModifier::NoModifier)
if (key.modifier == openspace::KeyModifier::NoModifier) {
return to_string(key.key);
else
}
else {
return to_string(key.modifier) + "+" + to_string(key.key);
}
}
} // namespace std

View File

@@ -38,11 +38,9 @@ namespace {
namespace openspace {
OpenSpaceModule::OpenSpaceModule(std::string name) {
ghoul_assert(!name.empty(), "Name must not be empty");
setName(std::move(name));
}
OpenSpaceModule::OpenSpaceModule(std::string name)
: properties::PropertyOwner(std::move(name))
{}
void OpenSpaceModule::initialize() {
std::string upperName = name();
@@ -73,9 +71,7 @@ scripting::LuaLibrary OpenSpaceModule::luaLibrary() const {
return {};
}
ghoul::systemcapabilities::OpenGLCapabilitiesComponent::Version
OpenSpaceModule::requiredOpenGLVersion() const
{
ghoul::systemcapabilities::Version OpenSpaceModule::requiredOpenGLVersion() const {
return { 3, 3 };
}