mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-02-08 04:29:48 -06:00
Merge branch 'develop' of github.com:OpenSpace/OpenSpace into feature/parallelconnection
Conflicts: include/openspace/engine/openspaceengine.h src/engine/openspaceengine.cpp src/interaction/interactionhandler.cpp src/network/parallelconnection.cpp src/scripting/scriptengine.cpp
This commit is contained in:
@@ -24,13 +24,19 @@
|
||||
|
||||
set(OPENSPACE_SOURCE
|
||||
${OPENSPACE_BASE_DIR}/src/openspace.cpp
|
||||
${OPENSPACE_BASE_DIR}/src/documentation/core_registration.cpp
|
||||
${OPENSPACE_BASE_DIR}/src/documentation/documentation.cpp
|
||||
${OPENSPACE_BASE_DIR}/src/documentation/documentationengine.cpp
|
||||
${OPENSPACE_BASE_DIR}/src/documentation/verifier.cpp
|
||||
${OPENSPACE_BASE_DIR}/src/engine/configurationmanager.cpp
|
||||
${OPENSPACE_BASE_DIR}/src/engine/configurationmanager_doc.inl
|
||||
${OPENSPACE_BASE_DIR}/src/engine/downloadmanager.cpp
|
||||
${OPENSPACE_BASE_DIR}/src/engine/logfactory.cpp
|
||||
${OPENSPACE_BASE_DIR}/src/engine/moduleengine.cpp
|
||||
${OPENSPACE_BASE_DIR}/src/engine/moduleengine_lua.inl
|
||||
${OPENSPACE_BASE_DIR}/src/engine/openspaceengine.cpp
|
||||
${OPENSPACE_BASE_DIR}/src/engine/settingsengine.cpp
|
||||
${OPENSPACE_BASE_DIR}/src/engine/syncengine.cpp
|
||||
${OPENSPACE_BASE_DIR}/src/engine/wrapper/sgctwindowwrapper.cpp
|
||||
${OPENSPACE_BASE_DIR}/src/engine/wrapper/windowwrapper.cpp
|
||||
${OPENSPACE_BASE_DIR}/src/interaction/controller.cpp
|
||||
@@ -77,11 +83,14 @@ set(OPENSPACE_SOURCE
|
||||
${OPENSPACE_BASE_DIR}/src/scene/rotation.cpp
|
||||
${OPENSPACE_BASE_DIR}/src/scene/scale.cpp
|
||||
${OPENSPACE_BASE_DIR}/src/scene/scene.cpp
|
||||
${OPENSPACE_BASE_DIR}/src/scene/scene_doc.inl
|
||||
${OPENSPACE_BASE_DIR}/src/scene/scene_lua.inl
|
||||
${OPENSPACE_BASE_DIR}/src/scene/scenegraph.cpp
|
||||
${OPENSPACE_BASE_DIR}/src/scene/scenegraphnode.cpp
|
||||
${OPENSPACE_BASE_DIR}/src/scene/scenegraphnode_doc.inl
|
||||
${OPENSPACE_BASE_DIR}/src/scripting/lualibrary.cpp
|
||||
${OPENSPACE_BASE_DIR}/src/scripting/scriptengine.cpp
|
||||
${OPENSPACE_BASE_DIR}/src/scripting/scriptscheduler.cpp
|
||||
${OPENSPACE_BASE_DIR}/src/scripting/scriptengine_lua.inl
|
||||
${OPENSPACE_BASE_DIR}/src/util/blockplaneintersectiongeometry.cpp
|
||||
${OPENSPACE_BASE_DIR}/src/util/boxgeometry.cpp
|
||||
@@ -97,6 +106,7 @@ set(OPENSPACE_SOURCE
|
||||
${OPENSPACE_BASE_DIR}/src/util/spicemanager.cpp
|
||||
${OPENSPACE_BASE_DIR}/src/util/spicemanager_lua.inl
|
||||
${OPENSPACE_BASE_DIR}/src/util/syncbuffer.cpp
|
||||
${OPENSPACE_BASE_DIR}/src/util/syncdata.cpp
|
||||
${OPENSPACE_BASE_DIR}/src/util/histogram.cpp
|
||||
${OPENSPACE_BASE_DIR}/src/util/time.cpp
|
||||
${OPENSPACE_BASE_DIR}/src/util/timemanager.cpp
|
||||
@@ -106,12 +116,18 @@ set(OPENSPACE_SOURCE
|
||||
|
||||
set(OPENSPACE_HEADER
|
||||
${OPENSPACE_BASE_DIR}/include/openspace/openspace.h
|
||||
${OPENSPACE_BASE_DIR}/include/openspace/documentation/core_registration.h
|
||||
${OPENSPACE_BASE_DIR}/include/openspace/documentation/documentation.h
|
||||
${OPENSPACE_BASE_DIR}/include/openspace/documentation/documentationengine.h
|
||||
${OPENSPACE_BASE_DIR}/include/openspace/documentation/verifier.h
|
||||
${OPENSPACE_BASE_DIR}/include/openspace/documentation/verifier.inl
|
||||
${OPENSPACE_BASE_DIR}/include/openspace/engine/configurationmanager.h
|
||||
${OPENSPACE_BASE_DIR}/include/openspace/engine/downloadmanager.h
|
||||
${OPENSPACE_BASE_DIR}/include/openspace/engine/logfactory.h
|
||||
${OPENSPACE_BASE_DIR}/include/openspace/engine/moduleengine.h
|
||||
${OPENSPACE_BASE_DIR}/include/openspace/engine/openspaceengine.h
|
||||
${OPENSPACE_BASE_DIR}/include/openspace/engine/settingsengine.h
|
||||
${OPENSPACE_BASE_DIR}/include/openspace/engine/syncengine.h
|
||||
${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
|
||||
@@ -170,6 +186,7 @@ set(OPENSPACE_HEADER
|
||||
${OPENSPACE_BASE_DIR}/include/openspace/scripting/lualibrary.h
|
||||
${OPENSPACE_BASE_DIR}/include/openspace/scripting/script_helper.h
|
||||
${OPENSPACE_BASE_DIR}/include/openspace/scripting/scriptengine.h
|
||||
${OPENSPACE_BASE_DIR}/include/openspace/scripting/scriptscheduler.h
|
||||
${OPENSPACE_BASE_DIR}/include/openspace/util/blockplaneintersectiongeometry.h
|
||||
${OPENSPACE_BASE_DIR}/include/openspace/util/boxgeometry.h
|
||||
${OPENSPACE_BASE_DIR}/include/openspace/util/camera.h
|
||||
@@ -185,6 +202,7 @@ set(OPENSPACE_HEADER
|
||||
${OPENSPACE_BASE_DIR}/include/openspace/util/screenlog.h
|
||||
${OPENSPACE_BASE_DIR}/include/openspace/util/spicemanager.h
|
||||
${OPENSPACE_BASE_DIR}/include/openspace/util/syncbuffer.h
|
||||
${OPENSPACE_BASE_DIR}/include/openspace/util/syncdata.h
|
||||
${OPENSPACE_BASE_DIR}/include/openspace/util/time.h
|
||||
${OPENSPACE_BASE_DIR}/include/openspace/util/timemanager.h
|
||||
${OPENSPACE_BASE_DIR}/include/openspace/util/updatestructures.h
|
||||
|
||||
53
src/documentation/core_registration.cpp
Normal file
53
src/documentation/core_registration.cpp
Normal file
@@ -0,0 +1,53 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2016 *
|
||||
* *
|
||||
* 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/documentation/core_registration.h>
|
||||
|
||||
#include <openspace/documentation/documentationengine.h>
|
||||
#include <openspace/engine/configurationmanager.h>
|
||||
#include <openspace/scene/scene.h>
|
||||
#include <openspace/scene/scenegraphnode.h>
|
||||
#include <openspace/rendering/renderable.h>
|
||||
#include <openspace/rendering/screenspacerenderable.h>
|
||||
#include <openspace/scene/ephemeris.h>
|
||||
#include <openspace/scene/rotation.h>
|
||||
#include <openspace/scene/scale.h>
|
||||
|
||||
|
||||
namespace openspace {
|
||||
namespace documentation {
|
||||
|
||||
void registerCoreClasses(documentation::DocumentationEngine& engine) {
|
||||
engine.addDocumentation(ConfigurationManager::Documentation());
|
||||
engine.addDocumentation(Ephemeris::Documentation());
|
||||
engine.addDocumentation(Renderable::Documentation());
|
||||
engine.addDocumentation(Rotation::Documentation());
|
||||
engine.addDocumentation(Scale::Documentation());
|
||||
engine.addDocumentation(Scene::Documentation());
|
||||
engine.addDocumentation(SceneGraphNode::Documentation());
|
||||
engine.addDocumentation(ScreenSpaceRenderable::Documentation());
|
||||
}
|
||||
|
||||
} // namespace documentation
|
||||
} // namespace openspace
|
||||
199
src/documentation/documentation.cpp
Normal file
199
src/documentation/documentation.cpp
Normal file
@@ -0,0 +1,199 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2016 *
|
||||
* *
|
||||
* 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/documentation/documentation.h>
|
||||
#include <openspace/documentation/verifier.h>
|
||||
|
||||
#include <set>
|
||||
|
||||
namespace {
|
||||
// Structure used to make offenses unique
|
||||
struct OffenseCompare {
|
||||
using Offense = openspace::documentation::TestResult::Offense;
|
||||
bool operator()(const Offense& lhs, const Offense& rhs) const
|
||||
{
|
||||
if (lhs.offender != rhs.offender) {
|
||||
return lhs.offender < rhs.offender;
|
||||
}
|
||||
else {
|
||||
return std::underlying_type_t<Offense::Reason>(lhs.reason) <
|
||||
std::underlying_type_t<Offense::Reason>(rhs.reason);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
} // namespace
|
||||
|
||||
// Unfortunately, the standard library does not contain a no-op for the to_string method
|
||||
// so we have to include one ourselves
|
||||
namespace std {
|
||||
std::string to_string(std::string value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
std::string to_string(openspace::documentation::TestResult::Offense::Reason reason) {
|
||||
switch (reason) {
|
||||
case openspace::documentation::TestResult::Offense::Reason::ExtraKey:
|
||||
return "Extra key";
|
||||
case openspace::documentation::TestResult::Offense::Reason::MissingKey:
|
||||
return "Missing key";
|
||||
case openspace::documentation::TestResult::Offense::Reason::UnknownIdentifier:
|
||||
return "Unknown identifier";
|
||||
case openspace::documentation::TestResult::Offense::Reason::Verification:
|
||||
return "Verification failed";
|
||||
case openspace::documentation::TestResult::Offense::Reason::WrongType:
|
||||
return "Wrong type";
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace std
|
||||
|
||||
namespace openspace {
|
||||
namespace documentation {
|
||||
|
||||
const std::string DocumentationEntry::Wildcard = "*";
|
||||
|
||||
SpecificationError::SpecificationError(TestResult res, std::string component)
|
||||
: ghoul::RuntimeError("Error in specification", std::move(component))
|
||||
, result(std::move(res))
|
||||
{
|
||||
ghoul_assert(!result.success, "Result's success must be false");
|
||||
}
|
||||
|
||||
DocumentationEntry::DocumentationEntry(std::string k, std::shared_ptr<Verifier> v,
|
||||
std::string doc, Optional opt)
|
||||
: key(std::move(k))
|
||||
, verifier(std::move(v))
|
||||
, documentation(std::move(doc))
|
||||
, optional(opt)
|
||||
{
|
||||
ghoul_assert(!key.empty(), "Key must not be empty");
|
||||
ghoul_assert(verifier, "Verifier must not be nullptr");
|
||||
}
|
||||
|
||||
DocumentationEntry::DocumentationEntry(std::string key, Verifier* v, std::string doc,
|
||||
Optional optional)
|
||||
: DocumentationEntry(std::move(key), std::shared_ptr<Verifier>(v), std::move(doc),
|
||||
optional)
|
||||
{}
|
||||
|
||||
Documentation::Documentation(std::string n, std::string id, DocumentationEntries entries,
|
||||
Exhaustive exh)
|
||||
: name(std::move(n))
|
||||
, id(std::move(id))
|
||||
, entries(std::move(entries))
|
||||
, exhaustive(std::move(exh))
|
||||
{}
|
||||
|
||||
Documentation::Documentation(std::string n, DocumentationEntries entries, Exhaustive exh)
|
||||
: Documentation(n, "", entries, exh)
|
||||
{}
|
||||
|
||||
Documentation::Documentation(DocumentationEntries entries, Exhaustive exh)
|
||||
: Documentation("", "", entries, exh)
|
||||
{}
|
||||
|
||||
TestResult testSpecification(const Documentation& d, const ghoul::Dictionary& dict) {
|
||||
TestResult result;
|
||||
result.success = true;
|
||||
|
||||
auto applyVerifier = [dict, &result](Verifier& verifier, const std::string& key) {
|
||||
TestResult res = verifier(dict, key);
|
||||
if (!res.success) {
|
||||
result.success = false;
|
||||
result.offenses.insert(
|
||||
result.offenses.end(),
|
||||
res.offenses.begin(),
|
||||
res.offenses.end()
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
for (const auto& p : d.entries) {
|
||||
if (p.key == DocumentationEntry::Wildcard) {
|
||||
for (const std::string& key : dict.keys()) {
|
||||
applyVerifier(*(p.verifier), key);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (p.optional && !dict.hasKey(p.key)) {
|
||||
// If the key is optional and it doesn't exist, we don't need to check it
|
||||
// if the key exists, it has to be correct, however
|
||||
continue;
|
||||
}
|
||||
applyVerifier(*(p.verifier), p.key);
|
||||
}
|
||||
}
|
||||
|
||||
if (d.exhaustive) {
|
||||
// If the documentation is exhaustive, we have to check if there are extra values
|
||||
// in the table that are not covered by the Documentation
|
||||
|
||||
for (const std::string& key : dict.keys()) {
|
||||
auto it = std::find_if(
|
||||
d.entries.begin(),
|
||||
d.entries.end(),
|
||||
[&key](const DocumentationEntry& entry) {
|
||||
if (entry.key == DocumentationEntry::Wildcard) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return entry.key == key;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
if (it == d.entries.end()) {
|
||||
result.success = false;
|
||||
result.offenses.push_back(
|
||||
{ key, TestResult::Offense::Reason::ExtraKey }
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove duplicate offenders that might occur if multiple rules apply to a single
|
||||
// key and more than one of these rules are broken
|
||||
std::set<TestResult::Offense, OffenseCompare> uniqueOffenders(
|
||||
result.offenses.begin(), result.offenses.end()
|
||||
);
|
||||
result.offenses = std::vector<TestResult::Offense>(
|
||||
uniqueOffenders.begin(), uniqueOffenders.end()
|
||||
);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void testSpecificationAndThrow(const Documentation& doc, const ghoul::Dictionary& dict,
|
||||
std::string component)
|
||||
{
|
||||
// Perform testing against the documentation/specification
|
||||
TestResult testResult = testSpecification(doc, dict);
|
||||
if (!testResult.success) {
|
||||
throw SpecificationError(std::move(testResult), std::move(component));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace documentation
|
||||
} // namespace openspace
|
||||
281
src/documentation/documentationengine.cpp
Normal file
281
src/documentation/documentationengine.cpp
Normal file
@@ -0,0 +1,281 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2016 *
|
||||
* *
|
||||
* 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/documentation/documentationengine.h>
|
||||
|
||||
#include <openspace/documentation/verifier.h>
|
||||
|
||||
#include <ghoul/misc/assert.h>
|
||||
|
||||
#include <fstream>
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
namespace openspace {
|
||||
namespace documentation {
|
||||
|
||||
DocumentationEngine::DuplicateDocumentationException::DuplicateDocumentationException(
|
||||
Documentation documentation)
|
||||
: ghoul::RuntimeError(fmt::format(
|
||||
"Duplicate Documentation with name '{}' and id '{}'",
|
||||
documentation.name,
|
||||
documentation.id
|
||||
))
|
||||
, documentation(std::move(documentation))
|
||||
{}
|
||||
|
||||
DocumentationEngine& DocumentationEngine::ref() {
|
||||
static DocumentationEngine engine;
|
||||
return engine;
|
||||
}
|
||||
|
||||
std::string generateTextDocumentation(const Documentation& d, int& indentLevel) {
|
||||
using namespace std::string_literals;
|
||||
|
||||
auto indentMessage = [&indentLevel](std::string prefix, std::string msg) {
|
||||
if (msg.empty()) {
|
||||
return ""s;
|
||||
}
|
||||
else {
|
||||
return std::string(indentLevel, '\t') + prefix + ": " + msg + '\n';
|
||||
}
|
||||
};
|
||||
std::string result;
|
||||
|
||||
result += indentMessage("Name", d.name);
|
||||
if (!d.name.empty()) {
|
||||
++indentLevel;
|
||||
}
|
||||
for (const auto& p : d.entries) {
|
||||
result += indentMessage("Key", (p.key == "*") ? p.key : "\"" + p.key + "\"");
|
||||
result += indentMessage("Optional", (p.optional ? "true" : "false"));
|
||||
result += indentMessage("Type", p.verifier->type());
|
||||
TableVerifier* tv = dynamic_cast<TableVerifier*>(p.verifier.get());
|
||||
if (tv) {
|
||||
// We have a TableVerifier, so we need to recurse
|
||||
++indentLevel;
|
||||
result += generateTextDocumentation({ "", "", tv->documentations }, indentLevel);
|
||||
result = result.substr(0, result.size() - 2);
|
||||
--indentLevel;
|
||||
}
|
||||
else {
|
||||
result += indentMessage("Restrictions", p.verifier->documentation());
|
||||
}
|
||||
result += indentMessage("Documentation", p.documentation);
|
||||
result += "\n\n";
|
||||
}
|
||||
if (!d.name.empty()) {
|
||||
--indentLevel;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string generateJsonDocumentation(const Documentation& d) {
|
||||
std::stringstream result;
|
||||
result << "{";
|
||||
|
||||
result << "\"name\": \"" << d.name << "\",";
|
||||
result << "\"entries\": [";
|
||||
for (const auto& p : d.entries) {
|
||||
result << "{";
|
||||
result << "\"key\": \"" << p.key << "\",";
|
||||
result << "\"optional\": \"" << (p.optional ? "true" : "false") << "\",";
|
||||
result << "\"type\": \"" << p.verifier->type() << "\",";
|
||||
TableVerifier* tv = dynamic_cast<TableVerifier*>(p.verifier.get());
|
||||
if (tv) {
|
||||
std::string json = generateJsonDocumentation({ "", "", tv->documentations });
|
||||
// We have a TableVerifier, so we need to recurse
|
||||
result << "\"restrictions\": " << json << ",";
|
||||
}
|
||||
else {
|
||||
result << "\"restrictions\": \"" << p.verifier->documentation() << "\",";
|
||||
}
|
||||
result << "},";
|
||||
}
|
||||
|
||||
result << ']';
|
||||
result << "}";
|
||||
|
||||
return result.str();
|
||||
}
|
||||
|
||||
std::string generateHtmlDocumentation(const Documentation& d) {
|
||||
std::stringstream html;
|
||||
|
||||
html << "\t<tr>\n"
|
||||
<< "\t\t<td colspan=6>" << d.name << "<a name=\"" << d.id << "\"></a></td>\n";
|
||||
|
||||
for (const auto& p : d.entries) {
|
||||
html << "\t<tr>\n"
|
||||
<< "\t\t<td></td>\n"
|
||||
<< "\t\t<td>" << p.key << "</td>\n"
|
||||
<< "\t\t<td>" << (p.optional ? "Optional" : "Required") << "</td>\n"
|
||||
<< "\t\t<td>" << p.verifier->type() << "</td>\n";
|
||||
|
||||
TableVerifier* tv = dynamic_cast<TableVerifier*>(p.verifier.get());
|
||||
ReferencingVerifier* rv = dynamic_cast<ReferencingVerifier*>(p.verifier.get());
|
||||
|
||||
// We have to check ReferencingVerifier first as a ReferencingVerifier is also a
|
||||
// TableVerifier
|
||||
if (rv) {
|
||||
std::vector<Documentation> documentations = DocEng.documentations();
|
||||
auto it = std::find_if(
|
||||
documentations.begin(),
|
||||
documentations.end(),
|
||||
[rv](const Documentation& doc) { return doc.id == rv->identifier; }
|
||||
);
|
||||
|
||||
html << "\t\t<td>"
|
||||
<< "\t\t\tReferencing: "
|
||||
<< "<a href=\"#" << rv->identifier << "\">" << it->name << "</a>"
|
||||
<< "\t\t</td>";
|
||||
}
|
||||
else if (tv) {
|
||||
// We have a TableVerifier, so we need to recurse
|
||||
html << "<td><table cellpadding=3 cellspacing=0 border=1>\n"
|
||||
<< "\t<thead>\n"
|
||||
<< "\t\t<tr>\n"
|
||||
<< "\t\t\t<th></th>\n"
|
||||
<< "\t\t\t<th>Key</th>\n"
|
||||
<< "\t\t\t<th>Optional</th>\n"
|
||||
<< "\t\t\t<th>Type</th>\n"
|
||||
<< "\t\t\t<th>Restrictions</th>\n"
|
||||
<< "\t\t\t<th>Documentation</th>\n"
|
||||
<< "\t\t</tr>\n"
|
||||
<< "\t</thead>\n"
|
||||
<< "\t<tbody>\n"
|
||||
<< generateHtmlDocumentation({ "", "", tv->documentations })
|
||||
<< "\t</tbody>\n"
|
||||
<< "</table>\n"
|
||||
<< "</td>\n";
|
||||
}
|
||||
else {
|
||||
html << "\t\t<td>" << p.verifier->documentation() << "</td>\n";
|
||||
}
|
||||
html << "\t\t<td>" << p.documentation << "</td>\n"
|
||||
<< "\t</tr>\n";
|
||||
|
||||
}
|
||||
|
||||
return html.str();
|
||||
}
|
||||
|
||||
void DocumentationEngine::writeDocumentation(const std::string& f, const std::string& t) {
|
||||
if (t == "text") {
|
||||
std::ofstream file;
|
||||
file.exceptions(~std::ofstream::goodbit);
|
||||
file.open(f);
|
||||
|
||||
for (const Documentation& d : _documentations) {
|
||||
int indent = 0;
|
||||
file << documentation::generateTextDocumentation(d, indent) << "\n\n";
|
||||
}
|
||||
}
|
||||
else if (t == "html") {
|
||||
std::ofstream file;
|
||||
file.exceptions(~std::ofstream::goodbit);
|
||||
file.open(f);
|
||||
|
||||
#ifdef JSON
|
||||
std::stringstream json;
|
||||
json << "[";
|
||||
|
||||
for (const Documentation& d : _documentations) {
|
||||
json << generateJsonDocumentation(d);
|
||||
json << ",";
|
||||
}
|
||||
|
||||
json << "]";
|
||||
|
||||
std::string jsonText = json.str();
|
||||
#else
|
||||
std::stringstream html;
|
||||
|
||||
html << "<html>\n"
|
||||
<< "\t<head>\n"
|
||||
<< "\t\t<title>Documentation</title>\n"
|
||||
<< "\t</head>\n"
|
||||
<< "<body>\n";
|
||||
|
||||
|
||||
html << "<table cellpadding=3 cellspacing=0 border=1>\n"
|
||||
<< "\t<caption>Documentation</caption>\n\n"
|
||||
<< "\t<thead>\n"
|
||||
<< "\t\t<tr>\n"
|
||||
<< "\t\t\t<th rowspan=2>Name</th>\n"
|
||||
<< "\t\t</tr>\n"
|
||||
<< "\t\t<tr>\n"
|
||||
<< "\t\t\t<th>Key</th>\n"
|
||||
<< "\t\t\t<th>Optional</th>\n"
|
||||
<< "\t\t\t<th>Type</th>\n"
|
||||
<< "\t\t\t<th>Restrictions</th>\n"
|
||||
<< "\t\t\t<th>Documentation</th>\n"
|
||||
<< "\t\t</tr>\n"
|
||||
<< "\t</thead>\n"
|
||||
<< "\t<tbody>\n";
|
||||
|
||||
for (const Documentation& d : _documentations) {
|
||||
html << generateHtmlDocumentation(d);
|
||||
|
||||
html << "\t<tr><td style=\"line-height: 50px;\" colspan=6></br></td></tr>\n";
|
||||
}
|
||||
|
||||
html << "\t</tbody>\n"
|
||||
<< "</table>\n";
|
||||
|
||||
html << "</body>\n";
|
||||
html << "</html>\n";
|
||||
|
||||
file << html.str();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void DocumentationEngine::addDocumentation(Documentation doc) {
|
||||
if (doc.id.empty()) {
|
||||
_documentations.push_back(std::move(doc));
|
||||
}
|
||||
else {
|
||||
auto it = std::find_if(
|
||||
_documentations.begin(),
|
||||
_documentations.end(),
|
||||
[doc](const Documentation& d) { return doc.id == d.id; }
|
||||
);
|
||||
|
||||
if (it != _documentations.end()) {
|
||||
throw DuplicateDocumentationException(std::move(doc));
|
||||
}
|
||||
else {
|
||||
_documentations.push_back(std::move(doc));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<Documentation> DocumentationEngine::documentations() const {
|
||||
return _documentations;
|
||||
}
|
||||
|
||||
} // namespace documentation
|
||||
} // namespace openspace
|
||||
273
src/documentation/verifier.cpp
Normal file
273
src/documentation/verifier.cpp
Normal file
@@ -0,0 +1,273 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2016 *
|
||||
* *
|
||||
* 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/documentation/verifier.h>
|
||||
|
||||
#include <openspace/documentation/documentationengine.h>
|
||||
|
||||
namespace openspace {
|
||||
namespace documentation {
|
||||
|
||||
// The explicit template instantiations for many of the commonly used template values
|
||||
// This cuts down on the compilation time by only compiling these once
|
||||
template struct Vector2Verifier<bool>;
|
||||
template struct Vector2Verifier<int>;
|
||||
template struct Vector2Verifier<double>;
|
||||
template struct Vector3Verifier<bool>;
|
||||
template struct Vector3Verifier<int>;
|
||||
template struct Vector3Verifier<double>;
|
||||
template struct Vector4Verifier<bool>;
|
||||
template struct Vector4Verifier<int>;
|
||||
template struct Vector4Verifier<double>;
|
||||
|
||||
template struct LessVerifier<IntVerifier>;
|
||||
template struct LessVerifier<DoubleVerifier>;
|
||||
template struct LessEqualVerifier<IntVerifier>;
|
||||
template struct LessEqualVerifier<DoubleVerifier>;
|
||||
template struct GreaterVerifier<IntVerifier>;
|
||||
template struct GreaterVerifier<DoubleVerifier>;
|
||||
template struct GreaterEqualVerifier<IntVerifier>;
|
||||
template struct GreaterEqualVerifier<DoubleVerifier>;
|
||||
template struct EqualVerifier<BoolVerifier>;
|
||||
template struct EqualVerifier<IntVerifier>;
|
||||
template struct EqualVerifier<DoubleVerifier>;
|
||||
template struct EqualVerifier<StringVerifier>;
|
||||
template struct UnequalVerifier<BoolVerifier>;
|
||||
template struct UnequalVerifier<IntVerifier>;
|
||||
template struct UnequalVerifier<DoubleVerifier>;
|
||||
template struct UnequalVerifier<StringVerifier>;
|
||||
|
||||
template struct InListVerifier<BoolVerifier>;
|
||||
template struct InListVerifier<IntVerifier>;
|
||||
template struct InListVerifier<DoubleVerifier>;
|
||||
template struct InListVerifier<StringVerifier>;
|
||||
template struct NotInListVerifier<BoolVerifier>;
|
||||
template struct NotInListVerifier<IntVerifier>;
|
||||
template struct NotInListVerifier<DoubleVerifier>;
|
||||
template struct NotInListVerifier<StringVerifier>;
|
||||
|
||||
template struct InRangeVerifier<IntVerifier>;
|
||||
template struct InRangeVerifier<DoubleVerifier>;
|
||||
template struct NotInRangeVerifier<IntVerifier>;
|
||||
template struct NotInRangeVerifier<DoubleVerifier>;
|
||||
|
||||
template struct AnnotationVerifier<BoolVerifier>;
|
||||
template struct AnnotationVerifier<IntVerifier>;
|
||||
template struct AnnotationVerifier<DoubleVerifier>;
|
||||
template struct AnnotationVerifier<StringVerifier>;
|
||||
template struct AnnotationVerifier<TableVerifier>;
|
||||
|
||||
std::string BoolVerifier::type() const {
|
||||
return "Boolean";
|
||||
}
|
||||
|
||||
std::string DoubleVerifier::type() const {
|
||||
return "Double";
|
||||
}
|
||||
|
||||
TestResult IntVerifier::operator()(const ghoul::Dictionary & dict,
|
||||
const std::string & key) const {
|
||||
if (dict.hasKeyAndValue<int>(key)) {
|
||||
// We we have a key and the value is int, we are done
|
||||
return{ true, {} };
|
||||
}
|
||||
else {
|
||||
if (dict.hasKey(key)) {
|
||||
if (dict.hasValue<double>(key)) {
|
||||
// If we have a double value, we need to check if it is integer
|
||||
double value = dict.value<double>(key);
|
||||
double intPart;
|
||||
bool isInt = modf(value, &intPart) == 0.0;
|
||||
if (isInt) {
|
||||
return{ true,{} };
|
||||
}
|
||||
else {
|
||||
return{ false, { { key, TestResult::Offense::Reason::WrongType } } };
|
||||
}
|
||||
}
|
||||
else {
|
||||
// If we don't have a double value, we cannot have an int value
|
||||
return{ false, { { key, TestResult::Offense::Reason::WrongType } } };
|
||||
}
|
||||
}
|
||||
else {
|
||||
return{ false, { {key, TestResult::Offense::Reason::MissingKey }} };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string IntVerifier::type() const {
|
||||
return "Integer";
|
||||
}
|
||||
|
||||
std::string StringVerifier::type() const {
|
||||
return "String";
|
||||
}
|
||||
|
||||
TableVerifier::TableVerifier(std::vector<DocumentationEntry> d, Exhaustive exhaustive)
|
||||
: documentations(std::move(d))
|
||||
, exhaustive(std::move(exhaustive)) {}
|
||||
|
||||
TestResult TableVerifier::operator()(const ghoul::Dictionary& dict,
|
||||
const std::string& key) const {
|
||||
if (dict.hasKeyAndValue<Type>(key)) {
|
||||
ghoul::Dictionary d = dict.value<ghoul::Dictionary>(key);
|
||||
TestResult res = testSpecification({ "", documentations, exhaustive }, d);
|
||||
|
||||
for (TestResult::Offense& s : res.offenses) {
|
||||
s.offender = key + "." + s.offender;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
else {
|
||||
if (dict.hasKey(key)) {
|
||||
return{ false, { { key, TestResult::Offense::Reason::WrongType } } };
|
||||
|
||||
}
|
||||
else {
|
||||
return{ false, { { key, TestResult::Offense::Reason::MissingKey } } };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string TableVerifier::type() const {
|
||||
return "Table";
|
||||
}
|
||||
|
||||
ReferencingVerifier::ReferencingVerifier(std::string id)
|
||||
: identifier(std::move(id))
|
||||
{
|
||||
ghoul_assert(!identifier.empty(), "identifier must not be empty");
|
||||
}
|
||||
|
||||
TestResult ReferencingVerifier::operator()(const ghoul::Dictionary& dictionary,
|
||||
const std::string& key) const
|
||||
{
|
||||
TestResult res = TableVerifier::operator()(dictionary, key);
|
||||
if (res.success) {
|
||||
std::vector<Documentation> documentations = DocEng.documentations();
|
||||
|
||||
auto it = std::find_if(
|
||||
documentations.begin(),
|
||||
documentations.end(),
|
||||
[this](const Documentation& doc) { return doc.id == identifier; }
|
||||
);
|
||||
|
||||
if (it == documentations.end()) {
|
||||
return { false, { { key, TestResult::Offense::Reason::UnknownIdentifier } } };
|
||||
}
|
||||
else {
|
||||
ghoul::Dictionary d = dictionary.value<ghoul::Dictionary>(key);
|
||||
TestResult res = testSpecification(*it, d);
|
||||
|
||||
for (TestResult::Offense& s : res.offenses) {
|
||||
s.offender = key + "." + s.offender;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
std::string ReferencingVerifier::documentation() const {
|
||||
using namespace std::string_literals;
|
||||
return "Referencing Documentation: '"s + identifier + "'";
|
||||
}
|
||||
|
||||
AndVerifier::AndVerifier(Verifier* lhs, Verifier* rhs)
|
||||
: lhs(lhs)
|
||||
, rhs(rhs)
|
||||
{
|
||||
ghoul_assert(lhs, "lhs must not be nullptr");
|
||||
ghoul_assert(rhs, "rhs must not be nullptr");
|
||||
}
|
||||
|
||||
TestResult AndVerifier::operator()(const ghoul::Dictionary& dict,
|
||||
const std::string& key) const
|
||||
{
|
||||
TestResult resLhs = lhs->operator()(dict, key);
|
||||
TestResult resRhs = rhs->operator()(dict, key);
|
||||
|
||||
if (resLhs.success && resRhs.success) {
|
||||
return { true, {} };
|
||||
}
|
||||
else {
|
||||
return { false, { { key, TestResult::Offense::Reason::Verification } } };
|
||||
}
|
||||
}
|
||||
|
||||
std::string AndVerifier::type() const {
|
||||
if (lhs->type() != rhs->type()) {
|
||||
return lhs->type() + " and " + rhs->type();
|
||||
}
|
||||
else {
|
||||
return lhs->type();
|
||||
}
|
||||
}
|
||||
|
||||
std::string AndVerifier::documentation() const {
|
||||
return lhs->documentation() + " and " + rhs->documentation();
|
||||
}
|
||||
|
||||
OrVerifier::OrVerifier(Verifier* lhs, Verifier* rhs)
|
||||
: lhs(lhs)
|
||||
, rhs(rhs)
|
||||
{
|
||||
ghoul_assert(lhs, "lhs must not be nullptr");
|
||||
ghoul_assert(rhs, "rhs must not be nullptr");
|
||||
}
|
||||
|
||||
TestResult OrVerifier::operator()(const ghoul::Dictionary& dict,
|
||||
const std::string& key) const {
|
||||
TestResult resA = lhs->operator()(dict, key);
|
||||
TestResult resB = rhs->operator()(dict, key);
|
||||
|
||||
if (resA.success || resB.success) {
|
||||
return { true, {} };
|
||||
}
|
||||
else {
|
||||
return { false, { { key, TestResult::Offense::Reason::Verification } } };
|
||||
}
|
||||
}
|
||||
|
||||
std::string OrVerifier::type() const {
|
||||
if (lhs->type() != rhs->type()) {
|
||||
return lhs->type() + " or " + rhs->type();
|
||||
}
|
||||
else {
|
||||
return lhs->type();
|
||||
}
|
||||
}
|
||||
|
||||
std::string OrVerifier::documentation() const {
|
||||
return lhs->documentation() + " or " + rhs->documentation();
|
||||
}
|
||||
|
||||
|
||||
} // namespace documentation
|
||||
} // namespace openspace
|
||||
@@ -32,6 +32,8 @@
|
||||
|
||||
using std::string;
|
||||
|
||||
#include "configurationmanager_doc.inl"
|
||||
|
||||
namespace {
|
||||
const string _configurationFile = "openspace.cfg";
|
||||
const string _keyBasePath = "BASE_PATH";
|
||||
@@ -43,25 +45,32 @@ const string ConfigurationManager::KeyPaths = "Paths";
|
||||
const string ConfigurationManager::KeyCache = "CACHE";
|
||||
const string ConfigurationManager::KeyFonts = "Fonts";
|
||||
const string ConfigurationManager::KeyConfigSgct = "SGCTConfig";
|
||||
const string ConfigurationManager::KeyLuaDocumentationType = "LuaDocumentationFile.Type";
|
||||
const string ConfigurationManager::KeyLuaDocumentationFile = "LuaDocumentationFile.File";
|
||||
const string ConfigurationManager::KeyScriptLogType = "ScriptLogFile.Type";
|
||||
const string ConfigurationManager::KeyScriptLogFile = "ScriptLogFile.File";
|
||||
const string ConfigurationManager::KeyPropertyDocumentationType =
|
||||
"PropertyDocumentationFile.Type";
|
||||
const string ConfigurationManager::KeyPropertyDocumentationFile =
|
||||
"PropertyDocumentationFile.File";
|
||||
const string ConfigurationManager::KeyKeyboardShortcutsType = "KeyboardShortcuts.Type";
|
||||
const string ConfigurationManager::KeyKeyboardShortcutsFile = "KeyboardShortcuts.File";
|
||||
|
||||
const string ConfigurationManager::PartType = "Type";
|
||||
const string ConfigurationManager::PartFile = "File";
|
||||
|
||||
const string ConfigurationManager::KeyLuaDocumentation = "LuaDocumentation";
|
||||
const string ConfigurationManager::KeyScriptLog = "ScriptLog";
|
||||
const string ConfigurationManager::KeyPropertyDocumentation = "PropertyDocumentation";
|
||||
const string ConfigurationManager::KeyKeyboardShortcuts = "KeyboardShortcuts";
|
||||
const string ConfigurationManager::KeyDocumentation = "Documentation";
|
||||
const string ConfigurationManager::KeyFactoryDocumentation = "FactoryDocumentation";
|
||||
const string ConfigurationManager::KeyConfigScene = "Scene";
|
||||
const string ConfigurationManager::KeyLogLevel = "Logging.LogLevel";
|
||||
const string ConfigurationManager::KeyLogImmediateFlush = "Logging.ImmediateFlush";
|
||||
const string ConfigurationManager::KeyLogs = "Logging.Logs";
|
||||
|
||||
const string ConfigurationManager::KeyLogging = "Logging";
|
||||
const string ConfigurationManager::PartLogLevel = "LogLevel";
|
||||
const string ConfigurationManager::PartImmediateFlush = "ImmediateFlush";
|
||||
const string ConfigurationManager::PartLogs = "Logs";
|
||||
const string ConfigurationManager::PartAppend = "Append";
|
||||
const string ConfigurationManager::PartCapabilitiesVerbosity = "CapabilitiesVerbosity";
|
||||
|
||||
const string ConfigurationManager::KeyCapabilitiesVerbosity =
|
||||
"Logging.CapabilitiesVerbosity";
|
||||
KeyLogging + "." + PartCapabilitiesVerbosity;
|
||||
|
||||
const string ConfigurationManager::KeyShutdownCountdown = "ShutdownCountdown";
|
||||
const string ConfigurationManager::KeyDisableMasterRendering = "DisableRenderingOnMaster";
|
||||
const string ConfigurationManager::KeyDownloadRequestURL = "DownloadRequestURL";
|
||||
const string ConfigurationManager::KeyRenderingMethod = "RenderingMethod";
|
||||
|
||||
string ConfigurationManager::findConfiguration(const string& filename) {
|
||||
using ghoul::filesystem::Directory;
|
||||
@@ -94,8 +103,9 @@ string ConfigurationManager::findConfiguration(const string& filename) {
|
||||
void ConfigurationManager::loadFromFile(const string& filename) {
|
||||
using ghoul::filesystem::FileSystem;
|
||||
|
||||
if (!FileSys.fileExists(filename))
|
||||
if (!FileSys.fileExists(filename)) {
|
||||
throw ghoul::FileNotFoundError(filename, "ConfigurationManager");
|
||||
}
|
||||
|
||||
// ${BASE_PATH}
|
||||
string basePathToken = FileSystem::TokenOpeningBraces + _keyBasePath
|
||||
@@ -109,6 +119,13 @@ void ConfigurationManager::loadFromFile(const string& filename) {
|
||||
// Loading the configuration file into ourselves
|
||||
ghoul::lua::loadDictionaryFromFile(filename, *this);
|
||||
|
||||
// Perform testing against the documentation/specification
|
||||
openspace::documentation::testSpecificationAndThrow(
|
||||
ConfigurationManager::Documentation(),
|
||||
*this,
|
||||
"ConfigurationManager"
|
||||
);
|
||||
|
||||
// Register all the paths
|
||||
ghoul::Dictionary dictionary = value<ghoul::Dictionary>(KeyPaths);
|
||||
|
||||
|
||||
333
src/engine/configurationmanager_doc.inl
Normal file
333
src/engine/configurationmanager_doc.inl
Normal file
@@ -0,0 +1,333 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2016 *
|
||||
* *
|
||||
* 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/documentation/verifier.h>
|
||||
|
||||
namespace openspace {
|
||||
|
||||
Documentation ConfigurationManager::Documentation() {
|
||||
using namespace documentation;
|
||||
|
||||
return {
|
||||
"OpenSpace Configuration",
|
||||
{
|
||||
{
|
||||
ConfigurationManager::KeyConfigSgct,
|
||||
new StringAnnotationVerifier("A valid SGCT configuration file"),
|
||||
"The SGCT configuration file that determines the window and view frustum "
|
||||
"settings that are being used when OpenSpace is started."
|
||||
},
|
||||
{
|
||||
ConfigurationManager::KeyConfigScene,
|
||||
new StringAnnotationVerifier(
|
||||
"A valid scene file as described in the Scene documentation"),
|
||||
"The scene description that is used to populate the application after "
|
||||
"startup. The scene determines which objects are loaded, the startup "
|
||||
"time and other scene-specific settings. More information is provided in "
|
||||
"the Scene documentation."
|
||||
},
|
||||
{
|
||||
ConfigurationManager::KeyPaths,
|
||||
new TableVerifier({
|
||||
{ "*", new StringVerifier }
|
||||
}),
|
||||
"A list of paths that are automatically registered with the file system. "
|
||||
"If a key X is used in the table, it is then useable by referencing ${X} "
|
||||
"in all other configuration files or scripts.",
|
||||
Optional::Yes
|
||||
},
|
||||
{
|
||||
ConfigurationManager::KeyFonts,
|
||||
new TableVerifier({
|
||||
{ "*", new StringVerifier, "Font paths loadable by FreeType" }
|
||||
}),
|
||||
"A list of all fonts that will automatically be loaded on startup. Each "
|
||||
"key-value pair contained in the table will become the name and the file "
|
||||
"for a font.",
|
||||
Optional::Yes
|
||||
},
|
||||
{
|
||||
ConfigurationManager::KeyLogging,
|
||||
new TableVerifier({
|
||||
{
|
||||
ConfigurationManager::PartLogLevel,
|
||||
new StringInListVerifier(
|
||||
// List from logmanager.cpp::levelFromString
|
||||
{"Debug", "Info", "Warning", "Error", "Fatal", "None" }
|
||||
),
|
||||
"The severity of log messages that will be displayed. Only "
|
||||
"messages of the selected level or higher will be displayed. All "
|
||||
"levels below will be silently discarded. The order of "
|
||||
"severities is: Debug < Info < Warning < Error < Fatal < None.",
|
||||
Optional::Yes
|
||||
},
|
||||
{
|
||||
ConfigurationManager::PartImmediateFlush,
|
||||
new BoolVerifier,
|
||||
"Determines whether error messages will be displayed immediately "
|
||||
"or if it is acceptable to have a short delay, but being more "
|
||||
"performant. If the delay is allowed ('true'), messages might "
|
||||
"get lost if the application crashes shortly after a message was "
|
||||
"logged.",
|
||||
Optional::Yes
|
||||
},
|
||||
{
|
||||
ConfigurationManager::PartLogs,
|
||||
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
|
||||
}
|
||||
}),
|
||||
"Per default, log messages are written to the console, the "
|
||||
"onscreen text, and (if available) the Visual Studio output "
|
||||
"window. This table can define other logging methods that will "
|
||||
"be used additionally.",
|
||||
Optional::Yes
|
||||
},
|
||||
{
|
||||
ConfigurationManager::PartCapabilitiesVerbosity,
|
||||
new StringInListVerifier(
|
||||
// List from OpenspaceEngine::initialize
|
||||
{ "None", "Minimal", "Default", "Full" }
|
||||
),
|
||||
"At startup, a list of system capabilities is created and logged."
|
||||
"This value determines how verbose this listing should be.",
|
||||
Optional::Yes
|
||||
}
|
||||
}),
|
||||
"Configurations for the logging of messages that are generated "
|
||||
"throughout the code and are useful for debugging potential errors or "
|
||||
"other information.",
|
||||
Optional::Yes
|
||||
},
|
||||
{
|
||||
ConfigurationManager::KeyLuaDocumentation,
|
||||
new TableVerifier({
|
||||
{
|
||||
ConfigurationManager::PartType,
|
||||
new StringInListVerifier(
|
||||
// List from ScriptEngine::writeDocumentation
|
||||
{ "text", "html" }
|
||||
),
|
||||
"The type of documentation that will be written."
|
||||
},
|
||||
{
|
||||
ConfigurationManager::PartFile,
|
||||
new StringVerifier,
|
||||
"The filename that will be created on startup containing the "
|
||||
"documentation of available Lua functions. Any existing file "
|
||||
"will be silently overwritten."
|
||||
}
|
||||
}),
|
||||
"Descriptions of whether and where to create a documentation file that "
|
||||
"describes the available Lua functions that can be executed in scene "
|
||||
"files or per console.",
|
||||
Optional::Yes
|
||||
},
|
||||
{
|
||||
ConfigurationManager::KeyPropertyDocumentation,
|
||||
new TableVerifier({
|
||||
{
|
||||
ConfigurationManager::PartType,
|
||||
new StringInListVerifier(
|
||||
// List taken from Scene::writePropertyDocumentation
|
||||
{ "text", "html" }
|
||||
),
|
||||
"The type of property documentation file that is created."
|
||||
},
|
||||
{
|
||||
ConfigurationManager::PartFile,
|
||||
new StringVerifier,
|
||||
"The file that will be created on startup containing a list of "
|
||||
"all properties in the scene. Any existing file will be silently "
|
||||
"overwritten."
|
||||
}
|
||||
}),
|
||||
"Descriptions of whether and where to create a list of all properties "
|
||||
"that were created in the current scene.",
|
||||
Optional::Yes
|
||||
},
|
||||
{
|
||||
ConfigurationManager::KeyScriptLog,
|
||||
new TableVerifier({
|
||||
{
|
||||
ConfigurationManager::PartType,
|
||||
new StringInListVerifier(
|
||||
// List taken from ScriptEngine::writeLog
|
||||
{ "text" }
|
||||
),
|
||||
"The type of logfile that will be created."
|
||||
},
|
||||
{
|
||||
ConfigurationManager::PartFile,
|
||||
new StringVerifier,
|
||||
"The file that will be created on startup containing the log of "
|
||||
"all Lua scripts that are executed. Any existing file (including "
|
||||
"the results from previous runs) will be silently overwritten."
|
||||
}
|
||||
}),
|
||||
"Contains a log of all Lua scripts that were executed in the last "
|
||||
"session.",
|
||||
Optional::Yes
|
||||
},
|
||||
{
|
||||
ConfigurationManager::KeyKeyboardShortcuts,
|
||||
new TableVerifier({
|
||||
{
|
||||
ConfigurationManager::PartType,
|
||||
new StringInListVerifier(
|
||||
// List from InteractionHandler::writeKeyboardDocumentation
|
||||
{ "text", "html" }
|
||||
),
|
||||
"The type of keyboard binding documentation that should be "
|
||||
"written."
|
||||
},
|
||||
{
|
||||
ConfigurationManager::PartFile,
|
||||
new StringVerifier,
|
||||
"The file that will be created on startup containing the list of "
|
||||
"all keyboard bindings with their respective Lua scripts. Any "
|
||||
"previous file in this location will be silently overritten."
|
||||
}
|
||||
}),
|
||||
"Contains the collection of all keyboard shortcuts that were collected "
|
||||
"during startup. For each key, it mentions which scripts will be "
|
||||
"executed in the current session.",
|
||||
Optional::Yes
|
||||
},
|
||||
{
|
||||
ConfigurationManager::KeyDocumentation,
|
||||
new TableVerifier({
|
||||
{
|
||||
ConfigurationManager::PartType,
|
||||
new StringInListVerifier(
|
||||
// List from DocumentationEngine::writeDocumentation
|
||||
{ "text", "html" }
|
||||
),
|
||||
"The type of documentation that should be written."
|
||||
},
|
||||
{
|
||||
ConfigurationManager::PartFile,
|
||||
new StringVerifier,
|
||||
"The file that will be created on startup containing this "
|
||||
"documentation. Any previous file in this location will be silently "
|
||||
"overritten."
|
||||
}
|
||||
}),
|
||||
"This defines the location and type of this documentation file.",
|
||||
Optional::Yes
|
||||
},
|
||||
{
|
||||
ConfigurationManager::KeyFactoryDocumentation,
|
||||
new TableVerifier({
|
||||
{
|
||||
ConfigurationManager::PartType,
|
||||
new StringInListVerifier(
|
||||
// List from FactoryManager::writeDocumentation
|
||||
{ "text", "html" }
|
||||
),
|
||||
"The type of documentation that should be written."
|
||||
},
|
||||
{
|
||||
ConfigurationManager::PartFile,
|
||||
new StringVerifier,
|
||||
"The file that will be created on startup containing the factory "
|
||||
"documentation. Any previous file in this location will be silently "
|
||||
"overritten."
|
||||
}
|
||||
}),
|
||||
"This defines the location and type of the factory documentation file, which "
|
||||
"shows the different types of objects that can be created in the current "
|
||||
"application configuration."
|
||||
},
|
||||
{
|
||||
ConfigurationManager::KeyShutdownCountdown,
|
||||
new DoubleGreaterEqualVerifier(0.0),
|
||||
"The countdown that the application will wait between pressing ESC and "
|
||||
"actually shutting down. If ESC is pressed again in this time, the "
|
||||
"shutdown is aborted.",
|
||||
Optional::Yes
|
||||
},
|
||||
{
|
||||
ConfigurationManager::KeyDownloadRequestURL,
|
||||
new OrVerifier(
|
||||
new StringVerifier,
|
||||
new TableVerifier({
|
||||
{ "*", new StringVerifier }
|
||||
})
|
||||
),
|
||||
"The URL from which files will be downloaded by the Launcher. This can "
|
||||
"either be a single URL or a list of possible URLs from which the "
|
||||
"Launcher can then choose.",
|
||||
Optional::Yes
|
||||
},
|
||||
{
|
||||
ConfigurationManager::KeyRenderingMethod,
|
||||
new StringInListVerifier(
|
||||
// List from RenderEngine::setRendererFromString
|
||||
{ "Framebuffer", "ABuffer" }
|
||||
),
|
||||
"The renderer that is use after startup. The renderer 'ABuffer' requires "
|
||||
"support for at least OpenGL 4.3",
|
||||
Optional::Yes
|
||||
},
|
||||
{
|
||||
ConfigurationManager::KeyDisableMasterRendering,
|
||||
new BoolVerifier,
|
||||
"Toggles whether the master in a multi-application setup should be rendering "
|
||||
"or just managing the state of the network. This is desired in cases where "
|
||||
"the master computer does not have the resources to render a scene.",
|
||||
Optional::Yes
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
} // namespace openspace
|
||||
@@ -32,14 +32,14 @@
|
||||
|
||||
namespace {
|
||||
const std::string keyType = "Type";
|
||||
const std::string keyFilename = "FileName";
|
||||
const std::string keyFilename = "File";
|
||||
const std::string keyAppend = "Append";
|
||||
const std::string keyTimeStamping = "TimeStamping";
|
||||
const std::string keyDateStamping = "DateStamping";
|
||||
const std::string keyCategoryStamping = "CategoryStamping";
|
||||
const std::string keyLogLevelStamping = "LogLevelStamping";
|
||||
|
||||
const std::string valueHtmlLog = "HTML";
|
||||
const std::string valueHtmlLog = "html";
|
||||
const std::string valueTextLog = "Text";
|
||||
}
|
||||
|
||||
|
||||
@@ -26,11 +26,14 @@
|
||||
|
||||
#include <openspace/openspace.h>
|
||||
|
||||
#include <openspace/documentation/core_registration.h>
|
||||
#include <openspace/documentation/documentationengine.h>
|
||||
#include <openspace/engine/configurationmanager.h>
|
||||
#include <openspace/engine/downloadmanager.h>
|
||||
#include <openspace/engine/logfactory.h>
|
||||
#include <openspace/engine/moduleengine.h>
|
||||
#include <openspace/engine/settingsengine.h>
|
||||
#include <openspace/engine/syncengine.h>
|
||||
#include <openspace/engine/wrapper/windowwrapper.h>
|
||||
#include <openspace/interaction/interactionhandler.h>
|
||||
#include <openspace/interaction/keyboardcontroller.h>
|
||||
@@ -41,6 +44,7 @@
|
||||
#include <openspace/rendering/renderable.h>
|
||||
#include <openspace/rendering/renderengine.h>
|
||||
#include <openspace/scripting/scriptengine.h>
|
||||
#include <openspace/scripting/scriptscheduler.h>
|
||||
#include <openspace/scene/ephemeris.h>
|
||||
#include <openspace/scene/scene.h>
|
||||
#include <openspace/util/factorymanager.h>
|
||||
@@ -50,6 +54,7 @@
|
||||
#include <openspace/util/syncbuffer.h>
|
||||
#include <openspace/util/transformationmanager.h>
|
||||
|
||||
|
||||
#include <ghoul/ghoul.h>
|
||||
#include <ghoul/cmdparser/commandlineparser.h>
|
||||
#include <ghoul/cmdparser/singlecommand.h>
|
||||
@@ -65,6 +70,7 @@
|
||||
#include <ghoul/misc/onscopeexit.h>
|
||||
|
||||
#include <fstream>
|
||||
#include <queue>
|
||||
|
||||
#ifdef OPENSPACE_MODULE_ONSCREENGUI_ENABLED
|
||||
#include <modules/onscreengui/include/gui.h>
|
||||
@@ -107,6 +113,7 @@ namespace {
|
||||
std::string configurationName;
|
||||
std::string sgctConfigurationName;
|
||||
std::string sceneName;
|
||||
std::string cacheFolder;
|
||||
} commandlineArgumentPlaceholders;
|
||||
}
|
||||
|
||||
@@ -124,7 +131,9 @@ OpenSpaceEngine::OpenSpaceEngine(std::string programName,
|
||||
, _interactionHandler(new interaction::InteractionHandler)
|
||||
, _renderEngine(new RenderEngine)
|
||||
, _scriptEngine(new scripting::ScriptEngine)
|
||||
, _scriptScheduler(new scripting::ScriptScheduler)
|
||||
, _networkEngine(new NetworkEngine)
|
||||
, _syncEngine(std::make_unique<SyncEngine>(new SyncBuffer(4096)))
|
||||
, _commandlineParser(new ghoul::cmdparser::CommandlineParser(
|
||||
programName, ghoul::cmdparser::CommandlineParser::AllowUnknownCommands::Yes
|
||||
))
|
||||
@@ -141,7 +150,6 @@ OpenSpaceEngine::OpenSpaceEngine(std::string programName,
|
||||
, _globalPropertyNamespace(new properties::PropertyOwner)
|
||||
, _isMaster(false)
|
||||
, _runTime(0.0)
|
||||
, _syncBuffer(new SyncBuffer(4096))
|
||||
, _isInShutdownMode(false)
|
||||
, _shutdownCountdown(0.f)
|
||||
, _shutdownWait(0.f)
|
||||
@@ -150,12 +158,15 @@ OpenSpaceEngine::OpenSpaceEngine(std::string programName,
|
||||
_interactionHandler->setPropertyOwner(_globalPropertyNamespace.get());
|
||||
_globalPropertyNamespace->addPropertySubOwner(_interactionHandler.get());
|
||||
_globalPropertyNamespace->addPropertySubOwner(_settingsEngine.get());
|
||||
|
||||
FactoryManager::initialize();
|
||||
FactoryManager::ref().addFactory(
|
||||
std::make_unique<ghoul::TemplateFactory<Renderable>>()
|
||||
std::make_unique<ghoul::TemplateFactory<Renderable>>(),
|
||||
"Renderable"
|
||||
);
|
||||
FactoryManager::ref().addFactory(
|
||||
std::make_unique<ghoul::TemplateFactory<Ephemeris>>()
|
||||
std::make_unique<ghoul::TemplateFactory<Ephemeris>>(),
|
||||
"Ephemeris"
|
||||
);
|
||||
SpiceManager::initialize();
|
||||
Time::initialize();
|
||||
@@ -164,6 +175,8 @@ OpenSpaceEngine::OpenSpaceEngine(std::string programName,
|
||||
}
|
||||
|
||||
OpenSpaceEngine::~OpenSpaceEngine() {
|
||||
LINFO("_windowWrapper->isUsingSwapGroups(): " << _windowWrapper->isUsingSwapGroups());
|
||||
LINFO("_windowWrapper->isSwapGroupMaster(): " << _windowWrapper->isSwapGroupMaster());
|
||||
#ifdef OPENSPACE_MODULE_ONSCREENGUI_ENABLED
|
||||
_gui->deinitializeGL();
|
||||
#endif
|
||||
@@ -178,6 +191,7 @@ OpenSpaceEngine::~OpenSpaceEngine() {
|
||||
_renderEngine = nullptr;
|
||||
_scriptEngine = nullptr;
|
||||
_networkEngine = nullptr;
|
||||
_syncEngine = nullptr;
|
||||
_commandlineParser = nullptr;
|
||||
_console = nullptr;
|
||||
_moduleEngine = nullptr;
|
||||
@@ -185,7 +199,6 @@ OpenSpaceEngine::~OpenSpaceEngine() {
|
||||
#ifdef OPENSPACE_MODULE_ONSCREENGUI_ENABLED
|
||||
_gui = nullptr;
|
||||
#endif
|
||||
_syncBuffer = nullptr;
|
||||
}
|
||||
|
||||
OpenSpaceEngine& OpenSpaceEngine::ref() {
|
||||
@@ -275,6 +288,14 @@ bool OpenSpaceEngine::create(int argc, char** argv,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!commandlineArgumentPlaceholders.cacheFolder.empty()) {
|
||||
FileSys.registerPathToken(
|
||||
"${CACHE}",
|
||||
commandlineArgumentPlaceholders.cacheFolder,
|
||||
ghoul::filesystem::FileSystem::Override::Yes
|
||||
);
|
||||
}
|
||||
|
||||
// Initialize the requested logs from the configuration file
|
||||
_engine->configureLogging();
|
||||
|
||||
@@ -296,6 +317,15 @@ bool OpenSpaceEngine::create(int argc, char** argv,
|
||||
// Register modules
|
||||
_engine->_moduleEngine->initialize();
|
||||
|
||||
documentation::registerCoreClasses(DocEng);
|
||||
// After registering the modules, the documentations for the available classes
|
||||
// can be added as well
|
||||
for (OpenSpaceModule* m : _engine->_moduleEngine->modules()) {
|
||||
for (auto&& doc : m->documentations()) {
|
||||
DocEng.addDocumentation(doc);
|
||||
}
|
||||
}
|
||||
|
||||
// Create the cachemanager
|
||||
FileSys.createCacheManager(
|
||||
absPath("${" + ConfigurationManager::KeyCache + "}"), CacheVersion
|
||||
@@ -358,7 +388,9 @@ bool OpenSpaceEngine::initialize() {
|
||||
|
||||
using Verbosity = ghoul::systemcapabilities::SystemCapabilitiesComponent::Verbosity;
|
||||
Verbosity verbosity = Verbosity::Default;
|
||||
if (configurationManager().hasKeyAndValue<std::string>(ConfigurationManager::KeyCapabilitiesVerbosity)) {
|
||||
if (configurationManager().hasKeyAndValue<std::string>(
|
||||
|
||||
ConfigurationManager::KeyCapabilitiesVerbosity)) {
|
||||
std::map<std::string, Verbosity> verbosityMap = {
|
||||
{ "None", Verbosity::None },
|
||||
{ "Minimal", Verbosity::Minimal },
|
||||
@@ -390,6 +422,7 @@ bool OpenSpaceEngine::initialize() {
|
||||
_scriptEngine->addLibrary(gui::GUI::luaLibrary());
|
||||
_scriptEngine->addLibrary(network::ParallelConnection::luaLibrary());
|
||||
_scriptEngine->addLibrary(ModuleEngine::luaLibrary());
|
||||
_scriptEngine->addLibrary(ScriptScheduler::luaLibrary());
|
||||
|
||||
#ifdef OPENSPACE_MODULE_ISWA_ENABLED
|
||||
_scriptEngine->addLibrary(IswaManager::luaLibrary());
|
||||
@@ -399,18 +432,54 @@ bool OpenSpaceEngine::initialize() {
|
||||
scriptEngine().initialize();
|
||||
|
||||
// If a LuaDocumentationFile was specified, generate it now
|
||||
const bool hasType = configurationManager().hasKey(ConfigurationManager::KeyLuaDocumentationType);
|
||||
const bool hasFile = configurationManager().hasKey(ConfigurationManager::KeyLuaDocumentationFile);
|
||||
if (hasType && hasFile) {
|
||||
const std::string LuaDocumentationType =
|
||||
ConfigurationManager::KeyLuaDocumentation + "." + ConfigurationManager::PartType;
|
||||
const std::string LuaDocumentationFile =
|
||||
ConfigurationManager::KeyLuaDocumentation + "." + ConfigurationManager::PartFile;
|
||||
|
||||
const bool hasLuaDocType = configurationManager().hasKey(LuaDocumentationType);
|
||||
const bool hasLuaDocFile = configurationManager().hasKey(LuaDocumentationFile);
|
||||
if (hasLuaDocType && hasLuaDocFile) {
|
||||
std::string luaDocumentationType;
|
||||
configurationManager().getValue(ConfigurationManager::KeyLuaDocumentationType, luaDocumentationType);
|
||||
configurationManager().getValue(LuaDocumentationType, luaDocumentationType);
|
||||
std::string luaDocumentationFile;
|
||||
configurationManager().getValue(ConfigurationManager::KeyLuaDocumentationFile, luaDocumentationFile);
|
||||
configurationManager().getValue(LuaDocumentationFile, luaDocumentationFile);
|
||||
|
||||
luaDocumentationFile = absPath(luaDocumentationFile);
|
||||
_scriptEngine->writeDocumentation(luaDocumentationFile, luaDocumentationType);
|
||||
}
|
||||
|
||||
// If a general documentation was specified, generate it now
|
||||
const std::string DocumentationType =
|
||||
ConfigurationManager::KeyDocumentation + '.' + ConfigurationManager::PartType;
|
||||
const std::string DocumentationFile =
|
||||
ConfigurationManager::KeyDocumentation + '.' + ConfigurationManager::PartFile;
|
||||
|
||||
const bool hasDocumentationType = configurationManager().hasKey(DocumentationType);
|
||||
const bool hasDocumentationFile = configurationManager().hasKey(DocumentationFile);
|
||||
if (hasDocumentationType && hasDocumentationFile) {
|
||||
std::string documentationType;
|
||||
configurationManager().getValue(DocumentationType, documentationType);
|
||||
std::string documentationFile;
|
||||
configurationManager().getValue(DocumentationFile, documentationFile);
|
||||
documentationFile = absPath(documentationFile);
|
||||
DocEng.writeDocumentation(documentationFile, documentationType);
|
||||
}
|
||||
|
||||
const std::string FactoryDocumentationType =
|
||||
ConfigurationManager::KeyFactoryDocumentation + '.' + ConfigurationManager::PartType;
|
||||
|
||||
const std::string FactoryDocumentationFile =
|
||||
ConfigurationManager::KeyFactoryDocumentation + '.' + ConfigurationManager::PartFile;
|
||||
bool hasFactoryDocumentationType = configurationManager().hasKey(FactoryDocumentationType);
|
||||
bool hasFactoryDocumentationFile = configurationManager().hasKey(FactoryDocumentationFile);
|
||||
if (hasFactoryDocumentationType && hasFactoryDocumentationFile) {
|
||||
std::string type = configurationManager().value<std::string>(FactoryDocumentationType);
|
||||
std::string file = configurationManager().value<std::string>(FactoryDocumentationFile);
|
||||
|
||||
FactoryManager::ref().writeDocumentation(absPath(file), type);
|
||||
}
|
||||
|
||||
bool disableMasterRendering = false;
|
||||
configurationManager().getValue(
|
||||
ConfigurationManager::KeyDisableMasterRendering, disableMasterRendering);
|
||||
@@ -432,6 +501,9 @@ bool OpenSpaceEngine::initialize() {
|
||||
// Initialize the InteractionHandler
|
||||
_interactionHandler->initialize();
|
||||
|
||||
// Load a light and a monospaced font
|
||||
loadFonts();
|
||||
|
||||
// Initialize the Scene
|
||||
Scene* sceneGraph = new Scene;
|
||||
sceneGraph->initialize();
|
||||
@@ -453,8 +525,6 @@ bool OpenSpaceEngine::initialize() {
|
||||
// Run start up scripts
|
||||
runPreInitializationScripts(scenePath);
|
||||
|
||||
// Load a light and a monospaced font
|
||||
loadFonts();
|
||||
|
||||
#ifdef OPENSPACE_MODULE_ONSCREENGUI_ENABLED
|
||||
LINFO("Initializing GUI");
|
||||
@@ -507,6 +577,10 @@ bool OpenSpaceEngine::initialize() {
|
||||
IswaManager::initialize();
|
||||
#endif
|
||||
|
||||
_syncEngine->addSyncables(Time::ref().getSyncables());
|
||||
_syncEngine->addSyncables(_renderEngine->getSyncables());
|
||||
_syncEngine->addSyncable(_scriptEngine.get());
|
||||
|
||||
LINFO("Finished initializing");
|
||||
return true;
|
||||
}
|
||||
@@ -541,6 +615,14 @@ bool OpenSpaceEngine::gatherCommandlineArguments() {
|
||||
"the scene file, overriding the value set in the OpenSpace configuration file"
|
||||
));
|
||||
|
||||
commandlineArgumentPlaceholders.cacheFolder = "";
|
||||
_commandlineParser->addCommand(std::make_unique<SingleCommand<std::string>>(
|
||||
&commandlineArgumentPlaceholders.cacheFolder, "-cacheDir", "", "Provides the "
|
||||
"path to a cache file, overriding the value set in the OpenSpace configuration "
|
||||
"file"
|
||||
));
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -675,12 +757,21 @@ void OpenSpaceEngine::loadFonts() {
|
||||
}
|
||||
|
||||
void OpenSpaceEngine::configureLogging() {
|
||||
if (configurationManager().hasKeyAndValue<std::string>(ConfigurationManager::KeyLogLevel)) {
|
||||
const std::string KeyLogLevel =
|
||||
ConfigurationManager::KeyLogging + '.' + ConfigurationManager::PartLogLevel;
|
||||
const std::string KeyLogImmediateFlush =
|
||||
ConfigurationManager::KeyLogging + '.' + ConfigurationManager::PartImmediateFlush;
|
||||
const std::string KeyLogs =
|
||||
ConfigurationManager::KeyLogging + '.' + ConfigurationManager::PartLogs;
|
||||
|
||||
|
||||
|
||||
if (configurationManager().hasKeyAndValue<std::string>(KeyLogLevel)) {
|
||||
std::string logLevel;
|
||||
configurationManager().getValue(ConfigurationManager::KeyLogLevel, logLevel);
|
||||
configurationManager().getValue(KeyLogLevel, logLevel);
|
||||
|
||||
bool immediateFlush = false;
|
||||
configurationManager().getValue(ConfigurationManager::KeyLogImmediateFlush, immediateFlush);
|
||||
configurationManager().getValue(KeyLogImmediateFlush, immediateFlush);
|
||||
|
||||
LogManager::LogLevel level = LogManager::levelFromString(logLevel);
|
||||
LogManager::deinitialize();
|
||||
@@ -692,9 +783,9 @@ void OpenSpaceEngine::configureLogging() {
|
||||
LogMgr.addLog(std::make_unique<ConsoleLog>());
|
||||
}
|
||||
|
||||
if (configurationManager().hasKeyAndValue<ghoul::Dictionary>(ConfigurationManager::KeyLogs)) {
|
||||
if (configurationManager().hasKeyAndValue<ghoul::Dictionary>(KeyLogs)) {
|
||||
ghoul::Dictionary logs;
|
||||
configurationManager().getValue(ConfigurationManager::KeyLogs, logs);
|
||||
configurationManager().getValue(KeyLogs, logs);
|
||||
|
||||
for (size_t i = 1; i <= logs.size(); ++i) {
|
||||
ghoul::Dictionary logInfo;
|
||||
@@ -729,6 +820,10 @@ bool OpenSpaceEngine::initializeGL() {
|
||||
}
|
||||
#endif
|
||||
LINFO("Finished initializing OpenGL");
|
||||
|
||||
// If using swapgroups,
|
||||
LINFO("_windowWrapper->isUsingSwapGroups(): " << _windowWrapper->isUsingSwapGroups());
|
||||
LINFO("_windowWrapper->isSwapGroupMaster(): " << _windowWrapper->isSwapGroupMaster());
|
||||
return success;
|
||||
}
|
||||
|
||||
@@ -750,24 +845,33 @@ void OpenSpaceEngine::setRunTime(double d){
|
||||
|
||||
void OpenSpaceEngine::preSynchronization() {
|
||||
FileSys.triggerFilesystemEvents();
|
||||
|
||||
_syncEngine->presync(_isMaster);
|
||||
if (_isMaster) {
|
||||
double dt = _windowWrapper->averageDeltaTime();
|
||||
_timeManager->preSynchronization(dt);
|
||||
|
||||
_scriptEngine->preSynchronization();
|
||||
auto scheduledScripts = _scriptScheduler->progressTo(Time::ref().j2000Seconds());
|
||||
while(scheduledScripts.size()){
|
||||
auto scheduledScript = scheduledScripts.front();
|
||||
LINFO(scheduledScript);
|
||||
_scriptEngine->queueScript(scheduledScript, ScriptEngine::RemoteScripting::Yes);
|
||||
scheduledScripts.pop();
|
||||
}
|
||||
|
||||
_interactionHandler->updateInputStates(dt);
|
||||
|
||||
_renderEngine->preSynchronization();
|
||||
|
||||
// Update the mouse velocities for interaction handler
|
||||
_interactionHandler->preSynchronization(dt);
|
||||
|
||||
_renderEngine->camera()->preSynchronization();
|
||||
_renderEngine->updateSceneGraph();
|
||||
_interactionHandler->updateCamera();
|
||||
_renderEngine->camera()->invalidateCache();
|
||||
|
||||
_parallelConnection->preSynchronization();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void OpenSpaceEngine::postSynchronizationPreDraw() {
|
||||
_syncEngine->postsync(_isMaster);
|
||||
|
||||
if (_isInShutdownMode) {
|
||||
if (_shutdownCountdown <= 0.f) {
|
||||
@@ -776,20 +880,21 @@ void OpenSpaceEngine::postSynchronizationPreDraw() {
|
||||
_shutdownCountdown -= _windowWrapper->averageDeltaTime();
|
||||
}
|
||||
|
||||
Time::ref().postSynchronizationPreDraw();
|
||||
_renderEngine->updateFade();
|
||||
_renderEngine->updateRenderer();
|
||||
_renderEngine->updateScreenSpaceRenderables();
|
||||
_renderEngine->updateShaderPrograms();
|
||||
|
||||
_scriptEngine->postSynchronizationPreDraw();
|
||||
_renderEngine->postSynchronizationPreDraw();
|
||||
|
||||
// Sync the camera to match the previous frame
|
||||
_renderEngine->camera()->postSynchronizationPreDraw();
|
||||
if (!_isMaster) {
|
||||
_renderEngine->updateSceneGraph();
|
||||
_renderEngine->camera()->invalidateCache();
|
||||
}
|
||||
|
||||
// Step the camera using the current mouse velocities which are synced
|
||||
_interactionHandler->postSynchronizationPreDraw();
|
||||
//_interactionHandler->updateCamera();
|
||||
|
||||
|
||||
|
||||
// Update the synched variables in the camera class
|
||||
_renderEngine->camera()->preSynchronization();
|
||||
_renderEngine->camera()->postSynchronizationPreDraw();
|
||||
|
||||
#ifdef OPENSPACE_MODULE_ONSCREENGUI_ENABLED
|
||||
if (_isMaster && _gui->isEnabled() && _windowWrapper->isRegularRendering()) {
|
||||
@@ -924,28 +1029,14 @@ void OpenSpaceEngine::mouseScrollWheelCallback(double pos) {
|
||||
}
|
||||
|
||||
void OpenSpaceEngine::encode() {
|
||||
if (_syncBuffer) {
|
||||
Time::ref().serialize(_syncBuffer.get());
|
||||
_scriptEngine->serialize(_syncBuffer.get());
|
||||
_renderEngine->serialize(_syncBuffer.get());
|
||||
_interactionHandler->serialize(_syncBuffer.get());
|
||||
|
||||
_syncBuffer->write();
|
||||
}
|
||||
_syncEngine->encodeSyncables();
|
||||
|
||||
_networkEngine->publishStatusMessage();
|
||||
_networkEngine->sendMessages();
|
||||
}
|
||||
|
||||
void OpenSpaceEngine::decode() {
|
||||
if (_syncBuffer) {
|
||||
_syncBuffer->read();
|
||||
|
||||
Time::ref().deserialize(_syncBuffer.get());
|
||||
_scriptEngine->deserialize(_syncBuffer.get());
|
||||
_renderEngine->deserialize(_syncBuffer.get());
|
||||
_interactionHandler->deserialize(_syncBuffer.get());
|
||||
|
||||
}
|
||||
_syncEngine->decodeSyncables();
|
||||
}
|
||||
|
||||
void OpenSpaceEngine::externalControlCallback(const char* receivedChars, int size,
|
||||
@@ -986,6 +1077,14 @@ scripting::LuaLibrary OpenSpaceEngine::luaLibrary() {
|
||||
};
|
||||
}
|
||||
|
||||
bool OpenSpaceEngine::useBusyWaitForDecode() {
|
||||
return _settingsEngine->busyWaitForDecode();
|
||||
}
|
||||
|
||||
bool OpenSpaceEngine::logSGCTOutOfOrderErrors() {
|
||||
return _settingsEngine->logSGCTOutOfOrderErrors();
|
||||
}
|
||||
|
||||
void OpenSpaceEngine::enableBarrier() {
|
||||
_windowWrapper->setBarrier(true);
|
||||
}
|
||||
@@ -1024,6 +1123,11 @@ ScriptEngine& OpenSpaceEngine::scriptEngine() {
|
||||
return *_scriptEngine;
|
||||
}
|
||||
|
||||
ScriptScheduler& OpenSpaceEngine::scriptScheduler(){
|
||||
ghoul_assert(_scriptScheduler, "ScriptScheduler must not be nullptr");
|
||||
return *_scriptScheduler;
|
||||
}
|
||||
|
||||
LuaConsole& OpenSpaceEngine::console() {
|
||||
ghoul_assert(_console, "LuaConsole must not be nullptr");
|
||||
return *_console;
|
||||
|
||||
@@ -32,12 +32,27 @@
|
||||
|
||||
#include <ghoul/ghoul.h>
|
||||
#include <ghoul/filesystem/filesystem.h>
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
|
||||
namespace {
|
||||
const std::string _loggerCat = "SettingsEngine";
|
||||
}
|
||||
|
||||
|
||||
namespace openspace {
|
||||
|
||||
|
||||
|
||||
SettingsEngine::SettingsEngine()
|
||||
: _eyeSeparation("eyeSeparation", "Eye Separation" , 0.f, 0.f, 10.f)
|
||||
, _scenes("scenes", "Scene", properties::OptionProperty::DisplayType::DROPDOWN)
|
||||
, _showFrameNumber("showFrameNumber", "Show frame number", false)
|
||||
, _busyWaitForDecode("busyWaitForDecode", "Busy Wait for decode", false)
|
||||
, _logSGCTOutOfOrderErrors("logSGCTOutOfOrderErrors", "Log SGCT out-of-order", false)
|
||||
, _useDoubleBuffering("useDoubleBuffering", "Use double buffering", false)
|
||||
{
|
||||
setName("Global Properties");
|
||||
}
|
||||
@@ -45,6 +60,10 @@ SettingsEngine::SettingsEngine()
|
||||
void SettingsEngine::initialize() {
|
||||
initEyeSeparation();
|
||||
initSceneFiles();
|
||||
initShowFrameNumber();
|
||||
initBusyWaitForDecode();
|
||||
initLogSGCTOutOfOrderErrors();
|
||||
initUseDoubleBuffering();
|
||||
}
|
||||
|
||||
void SettingsEngine::setModules(std::vector<OpenSpaceModule*> modules) {
|
||||
@@ -61,6 +80,51 @@ void SettingsEngine::initEyeSeparation() {
|
||||
[this]() { OsEng.windowWrapper().setEyeSeparationDistance(_eyeSeparation); });
|
||||
}
|
||||
|
||||
void SettingsEngine::initShowFrameNumber() {
|
||||
addProperty(_showFrameNumber);
|
||||
|
||||
_showFrameNumber.onChange(
|
||||
[this]() { OsEng.renderEngine().setShowFrameNumber(_showFrameNumber.value()); } );
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
|
||||
95
src/engine/syncengine.cpp
Normal file
95
src/engine/syncengine.cpp
Normal file
@@ -0,0 +1,95 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2016 *
|
||||
* *
|
||||
* 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/engine/syncengine.h>
|
||||
#include <openspace/util/syncdata.h>
|
||||
#include <openspace/util/syncbuffer.h>
|
||||
#include <ghoul/logging/logmanager.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()
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -111,8 +111,7 @@ glm::ivec2 SGCTWindowWrapper::currentDrawBufferResolution() const {
|
||||
|
||||
int SGCTWindowWrapper::currentNumberOfAaSamples() const {
|
||||
return sgct::Engine::instance()->getCurrentWindowPtr()->getNumberOfAASamples();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool SGCTWindowWrapper::isRegularRendering() const {
|
||||
// TODO: Needs to implement the nonlinear rendering check ---abock
|
||||
@@ -136,6 +135,15 @@ bool SGCTWindowWrapper::hasGuiWindow() const {
|
||||
bool SGCTWindowWrapper::isGuiWindow() const {
|
||||
return sgct::Engine::instance()->getCurrentWindowPtr()->getName() == GuiWindowName;
|
||||
}
|
||||
|
||||
bool SGCTWindowWrapper::isSwapGroupMaster() const {
|
||||
return sgct::Engine::instance()->getCurrentWindowPtr()->isSwapGroupMaster();
|
||||
}
|
||||
|
||||
bool SGCTWindowWrapper::isUsingSwapGroups() const {
|
||||
return sgct::Engine::instance()->getCurrentWindowPtr()->isUsingSwapGroups();
|
||||
}
|
||||
|
||||
|
||||
glm::mat4 SGCTWindowWrapper::viewProjectionMatrix() const {
|
||||
return sgct::Engine::instance()->getCurrentModelViewProjectionMatrix();
|
||||
@@ -177,11 +185,11 @@ bool SGCTWindowWrapper::isSimpleRendering() const {
|
||||
|
||||
}
|
||||
|
||||
void SGCTWindowWrapper::takeScreenshot() const {
|
||||
void SGCTWindowWrapper::takeScreenshot(bool applyWarping) const {
|
||||
sgct::SGCTSettings::instance()->setCaptureFromBackBuffer(applyWarping);
|
||||
sgct::Engine::instance()->takeScreenshot();
|
||||
}
|
||||
|
||||
|
||||
//void forEachWindow(std::function<void (void)> function) {
|
||||
// size_t n = sgct::Engine::instance()->getNumberOfWindows();
|
||||
// for (size_t i = 0; i < n; ++i)
|
||||
|
||||
@@ -86,6 +86,15 @@ bool WindowWrapper::isGuiWindow() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WindowWrapper::isSwapGroupMaster() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WindowWrapper::isUsingSwapGroups() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
glm::mat4 WindowWrapper::viewProjectionMatrix() const {
|
||||
return glm::mat4(1.f);
|
||||
}
|
||||
@@ -119,6 +128,6 @@ bool WindowWrapper::isSimpleRendering() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
void WindowWrapper::takeScreenshot() const {}
|
||||
void WindowWrapper::takeScreenshot(bool) const {}
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -190,10 +190,6 @@ void InteractionHandler::resetCameraDirection() {
|
||||
|
||||
// Update camera Rotation
|
||||
_camera->setRotation(rotationLookAtFocusNode);
|
||||
|
||||
// Explicitly synch
|
||||
_camera->preSynchronization();
|
||||
_camera->postSynchronizationPreDraw();
|
||||
}
|
||||
|
||||
void InteractionHandler::setInteractionMode(std::shared_ptr<InteractionMode> interactionMode) {
|
||||
@@ -230,7 +226,13 @@ void InteractionHandler::unlockControls() {
|
||||
|
||||
}
|
||||
|
||||
void InteractionHandler::preSynchronization(double deltaTime) {
|
||||
void InteractionHandler::updateInputStates(double timeSinceLastUpdate) {
|
||||
ghoul_assert(_inputState != nullptr, "InputState cannot be null!");
|
||||
ghoul_assert(_camera != nullptr, "Camera cannot be null!");
|
||||
_currentInteractionMode->updateMouseStatesFromInput(*_inputState, timeSinceLastUpdate);
|
||||
}
|
||||
|
||||
void InteractionHandler::updateCamera() {
|
||||
ghoul_assert(_inputState != nullptr, "InputState cannot be null!");
|
||||
ghoul_assert(_camera != nullptr, "Camera cannot be null!");
|
||||
|
||||
@@ -238,24 +240,13 @@ void InteractionHandler::preSynchronization(double deltaTime) {
|
||||
_cameraUpdatedFromScript = false;
|
||||
}
|
||||
else {
|
||||
_currentInteractionMode->updateMouseStatesFromInput(*_inputState, deltaTime);
|
||||
if (_camera && focusNode()) {
|
||||
_currentInteractionMode->updateCameraStateFromMouseStates(*_camera);
|
||||
_camera->setFocusPositionVec3(focusNode()->worldPosition());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InteractionHandler::postSynchronizationPreDraw() {
|
||||
ghoul_assert(_inputState != nullptr, "InputState cannot be null!");
|
||||
ghoul_assert(_camera != nullptr, "Camera cannot be null!");
|
||||
|
||||
if (_cameraUpdatedFromScript) {
|
||||
_cameraUpdatedFromScript = false;
|
||||
}
|
||||
else {
|
||||
_currentInteractionMode->updateCameraStateFromMouseStates(*_camera);
|
||||
_camera->setFocusPositionVec3(focusNode()->worldPosition());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SceneGraphNode* const InteractionHandler::focusNode() const {
|
||||
return _currentInteractionMode->focusNode();
|
||||
}
|
||||
@@ -323,10 +314,6 @@ void InteractionHandler::setCameraStateFromDictionary(const ghoul::Dictionary& c
|
||||
_camera->setPositionVec3(cameraPosition);
|
||||
_camera->setRotation(glm::dquat(
|
||||
cameraRotation.x, cameraRotation.y, cameraRotation.z, cameraRotation.w));
|
||||
|
||||
// Explicitly synch
|
||||
_camera->preSynchronization();
|
||||
_camera->postSynchronizationPreDraw();
|
||||
}
|
||||
|
||||
ghoul::Dictionary InteractionHandler::getCameraStateDictionary() {
|
||||
@@ -417,7 +404,9 @@ void InteractionHandler::bindKey(Key key, KeyModifier modifier, std::string lua)
|
||||
void InteractionHandler::writeKeyboardDocumentation(const std::string& type, const std::string& file)
|
||||
{
|
||||
if (type == "text") {
|
||||
std::ofstream f(absPath(file));
|
||||
std::ofstream f;
|
||||
f.exceptions(~std::ofstream::goodbit);
|
||||
f.open(absPath(file));
|
||||
|
||||
for (const auto& p : _keyLua) {
|
||||
std::string remoteScriptingInfo;
|
||||
@@ -430,6 +419,59 @@ void InteractionHandler::writeKeyboardDocumentation(const std::string& type, con
|
||||
p.second.first << remoteScriptingInfo << std::endl;
|
||||
}
|
||||
}
|
||||
else if (type == "html") {
|
||||
std::ofstream f;
|
||||
f.exceptions(~std::ofstream::goodbit);
|
||||
f.open(absPath(file));
|
||||
|
||||
#ifdef JSON
|
||||
std::stringstream json;
|
||||
json << "[";
|
||||
for (const auto& p : _keyLua) {
|
||||
json << "{";
|
||||
json << "\"key\": \"" << std::to_string(p.first) << "\",";
|
||||
json << "\"script\": \"" << p.second << "\",";
|
||||
json << "},";
|
||||
}
|
||||
json << "]";
|
||||
|
||||
std::string jsonText = json.str();
|
||||
|
||||
#else
|
||||
std::stringstream html;
|
||||
|
||||
html << "<html>\n"
|
||||
<< "\t<head>\n"
|
||||
<< "\t\t<title>Key Bindings</title>\n"
|
||||
<< "\t</head>\n"
|
||||
<< "<body>\n"
|
||||
<< "<table cellpadding=3 cellspacing=0 border=1>\n"
|
||||
<< "\t<caption>Key Bindings</caption>\n\n"
|
||||
<< "\t<thead>\n"
|
||||
<< "\t\t<tr>\n"
|
||||
<< "\t\t\t<td>Key</td>\n"
|
||||
<< "\t\t\t<td>Binding</td>\n"
|
||||
<< "\t\t\t<td>Remote scripting</td>\n"
|
||||
<< "\t\t</tr>\n"
|
||||
<< "\t</thead>\n"
|
||||
<< "\t<tbody>\n";
|
||||
|
||||
for (const auto& p : _keyLua) {
|
||||
html << "\t\t<tr>\n"
|
||||
<< "\t\t\t<td>" << std::to_string(p.first) << "</td>\n"
|
||||
<< "\t\t\t<td>" << p.second.first << "</td>\n"
|
||||
<< "\t\t\t<td>" << (p.second.second ? "Yes" : "No") << "</td>\n"
|
||||
<< "\t\t</tr>\n";
|
||||
}
|
||||
|
||||
html << "\t</tbody>\n"
|
||||
<< "</table>\n"
|
||||
<< "</html>";
|
||||
|
||||
f << html.str();
|
||||
#endif
|
||||
|
||||
}
|
||||
else {
|
||||
throw ghoul::RuntimeError(
|
||||
"Unsupported keyboard documentation type '" + type + "'",
|
||||
@@ -497,17 +539,5 @@ void InteractionHandler::clearKeyframes() {
|
||||
_inputState->clearKeyframes();
|
||||
}
|
||||
|
||||
void InteractionHandler::serialize(SyncBuffer* syncBuffer) {
|
||||
for (auto var : _interactionModes) {
|
||||
var.second->serialize(syncBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
void InteractionHandler::deserialize(SyncBuffer* syncBuffer) {
|
||||
for (auto var : _interactionModes) {
|
||||
var.second->deserialize(syncBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace interaction
|
||||
} // namespace openspace
|
||||
|
||||
@@ -335,55 +335,23 @@ void OrbitalInteractionMode::MouseStates::setVelocityScaleFactor(double scaleFac
|
||||
}
|
||||
|
||||
glm::dvec2 OrbitalInteractionMode::MouseStates::synchedGlobalRotationMouseVelocity() {
|
||||
return _synchedGlobalRotationMouseVelocity;
|
||||
return _globalRotationMouseState.velocity.get();
|
||||
}
|
||||
|
||||
glm::dvec2 OrbitalInteractionMode::MouseStates::synchedLocalRotationMouseVelocity() {
|
||||
return _synchedLocalRotationMouseVelocity;
|
||||
return _localRotationMouseState.velocity.get();
|
||||
}
|
||||
|
||||
glm::dvec2 OrbitalInteractionMode::MouseStates::synchedTruckMovementMouseVelocity() {
|
||||
return _synchedTruckMovementMouseVelocity;
|
||||
return _truckMovementMouseState.velocity.get();
|
||||
}
|
||||
|
||||
glm::dvec2 OrbitalInteractionMode::MouseStates::synchedLocalRollMouseVelocity() {
|
||||
return _synchedLocalRollMouseVelocity;
|
||||
return _localRollMouseState.velocity.get();
|
||||
}
|
||||
|
||||
glm::dvec2 OrbitalInteractionMode::MouseStates::synchedGlobalRollMouseVelocity() {
|
||||
return _synchedGlobalRollMouseVelocity;
|
||||
}
|
||||
|
||||
void OrbitalInteractionMode::MouseStates::preSynchronization() {
|
||||
_sharedGlobalRotationMouseVelocity = _globalRotationMouseState.velocity.get();
|
||||
_sharedLocalRotationMouseVelocity = _localRotationMouseState.velocity.get();
|
||||
_sharedTruckMovementMouseVelocity = _truckMovementMouseState.velocity.get();
|
||||
_sharedLocalRollMouseVelocity = _localRollMouseState.velocity.get();
|
||||
_sharedGlobalRollMouseVelocity = _globalRollMouseState.velocity.get();
|
||||
}
|
||||
|
||||
void OrbitalInteractionMode::MouseStates::postSynchronizationPreDraw() {
|
||||
_synchedGlobalRotationMouseVelocity = _sharedGlobalRotationMouseVelocity;
|
||||
_synchedLocalRotationMouseVelocity = _sharedLocalRotationMouseVelocity;
|
||||
_synchedTruckMovementMouseVelocity = _sharedTruckMovementMouseVelocity;
|
||||
_synchedLocalRollMouseVelocity = _sharedLocalRollMouseVelocity;
|
||||
_synchedGlobalRollMouseVelocity = _sharedGlobalRollMouseVelocity;
|
||||
}
|
||||
|
||||
void OrbitalInteractionMode::MouseStates::serialize(SyncBuffer* syncBuffer) {
|
||||
syncBuffer->encode(_sharedGlobalRotationMouseVelocity);
|
||||
syncBuffer->encode(_sharedLocalRotationMouseVelocity);
|
||||
syncBuffer->encode(_sharedTruckMovementMouseVelocity);
|
||||
syncBuffer->encode(_sharedLocalRollMouseVelocity);
|
||||
syncBuffer->encode(_sharedGlobalRollMouseVelocity);
|
||||
}
|
||||
|
||||
void OrbitalInteractionMode::MouseStates::deserialize(SyncBuffer* syncBuffer) {
|
||||
syncBuffer->decode(_sharedGlobalRotationMouseVelocity);
|
||||
syncBuffer->decode(_sharedLocalRotationMouseVelocity);
|
||||
syncBuffer->decode(_sharedTruckMovementMouseVelocity);
|
||||
syncBuffer->decode(_sharedLocalRollMouseVelocity);
|
||||
syncBuffer->decode(_sharedGlobalRollMouseVelocity);
|
||||
return _globalRollMouseState.velocity.get();
|
||||
}
|
||||
|
||||
OrbitalInteractionMode::OrbitalInteractionMode(std::shared_ptr<MouseStates> mouseStates)
|
||||
@@ -398,7 +366,6 @@ OrbitalInteractionMode::~OrbitalInteractionMode() {
|
||||
|
||||
void OrbitalInteractionMode::updateCameraStateFromMouseStates(Camera& camera) {
|
||||
// Update synched data
|
||||
_mouseStates->postSynchronizationPreDraw();
|
||||
|
||||
using namespace glm;
|
||||
if (_focusNode) {
|
||||
@@ -490,15 +457,6 @@ void OrbitalInteractionMode::updateCameraStateFromMouseStates(Camera& camera) {
|
||||
|
||||
void OrbitalInteractionMode::updateMouseStatesFromInput(const InputState& inputState, double deltaTime) {
|
||||
_mouseStates->updateMouseStatesFromInput(inputState, deltaTime);
|
||||
_mouseStates->preSynchronization();
|
||||
}
|
||||
|
||||
void OrbitalInteractionMode::serialize(SyncBuffer* syncBuffer) {
|
||||
_mouseStates->serialize(syncBuffer);
|
||||
}
|
||||
|
||||
void OrbitalInteractionMode::deserialize(SyncBuffer* syncBuffer) {
|
||||
_mouseStates->deserialize(syncBuffer);
|
||||
}
|
||||
|
||||
GlobeBrowsingInteractionMode::GlobeBrowsingInteractionMode(std::shared_ptr<MouseStates> mouseStates)
|
||||
@@ -527,9 +485,7 @@ void GlobeBrowsingInteractionMode::setFocusNode(SceneGraphNode* focusNode) {
|
||||
}
|
||||
|
||||
void GlobeBrowsingInteractionMode::updateCameraStateFromMouseStates(Camera& camera) {
|
||||
// Update synched data
|
||||
_mouseStates->postSynchronizationPreDraw();
|
||||
|
||||
|
||||
#ifdef OPENSPACE_MODULE_GLOBEBROWSING_ENABLED
|
||||
using namespace glm;
|
||||
if (_focusNode && _globe) {
|
||||
|
||||
@@ -95,8 +95,8 @@ void NetworkEngine::publishStatusMessage() {
|
||||
|
||||
uint16_t messageSize = 0;
|
||||
|
||||
double time = Time::ref().currentTime();
|
||||
std::string timeString = Time::ref().currentTimeUTC();
|
||||
double time = Time::ref().j2000Seconds();
|
||||
std::string timeString = Time::ref().UTC();
|
||||
double delta = Time::ref().deltaTime();
|
||||
|
||||
messageSize += sizeof(time);
|
||||
|
||||
@@ -994,7 +994,7 @@ void ParallelConnection::sendTimeKeyframe() {
|
||||
kf._dt = Time::ref().deltaTime();
|
||||
kf._paused = Time::ref().paused();
|
||||
kf._requiresTimeJump = _timeJumped;
|
||||
kf._time = Time::ref().currentTime();
|
||||
kf._time = Time::ref().j2000Seconds();
|
||||
|
||||
//timestamp as current runtime of OpenSpace instance
|
||||
kf._timestamp = OsEng.runTime();
|
||||
|
||||
@@ -173,6 +173,9 @@ PerformanceManager::~PerformanceManager() {
|
||||
|
||||
LINFO("Remove shared memory '" << _performanceMemory->name() << "'");
|
||||
ghoul::SharedMemory::remove(_performanceMemory->name());
|
||||
|
||||
_performanceMemory = nullptr;
|
||||
|
||||
}
|
||||
|
||||
PerformanceManager::destroyGlobalSharedMemory();
|
||||
|
||||
@@ -55,10 +55,8 @@ Property::Property(std::string identifier, std::string guiName)
|
||||
: _owner(nullptr)
|
||||
, _identifier(std::move(identifier))
|
||||
{
|
||||
if (_identifier.empty())
|
||||
LWARNING("Property identifier is empty");
|
||||
if (guiName.empty())
|
||||
LWARNING("Property GUI name is empty");
|
||||
ghoul_assert(!_identifier.empty(), "Identifier must not be empty");
|
||||
ghoul_assert(!guiName.empty(), "guiName must not be empty");
|
||||
|
||||
setVisible(true);
|
||||
_metaData.setValue(MetaDataKeyGuiName, std::move(guiName));
|
||||
@@ -75,8 +73,9 @@ std::string Property::fullyQualifiedIdentifier() const {
|
||||
PropertyOwner* currentOwner = owner();
|
||||
while (currentOwner) {
|
||||
std::string ownerId = currentOwner->name();
|
||||
if (!ownerId.empty())
|
||||
if (!ownerId.empty()) {
|
||||
identifier = ownerId + "." + identifier;
|
||||
}
|
||||
currentOwner = currentOwner->owner();
|
||||
}
|
||||
return identifier;
|
||||
@@ -162,19 +161,18 @@ void Property::onChange(std::function<void()> callback) {
|
||||
_onChangeCallback = std::move(callback);
|
||||
}
|
||||
|
||||
PropertyOwner* Property::owner() const
|
||||
{
|
||||
PropertyOwner* Property::owner() const {
|
||||
return _owner;
|
||||
}
|
||||
|
||||
void Property::setPropertyOwner(PropertyOwner* owner)
|
||||
{
|
||||
void Property::setPropertyOwner(PropertyOwner* owner) {
|
||||
_owner = owner;
|
||||
}
|
||||
|
||||
void Property::notifyListener() {
|
||||
if (_onChangeCallback)
|
||||
if (_onChangeCallback) {
|
||||
_onChangeCallback();
|
||||
}
|
||||
}
|
||||
|
||||
std::string Property::generateBaseDescription() const {
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <openspace/engine/openspaceengine.h>
|
||||
#include <openspace/engine/wrapper/windowwrapper.h>
|
||||
#include <openspace/rendering/renderengine.h>
|
||||
#include <openspace/rendering/renderable.h>
|
||||
#include <openspace/rendering/volumeraycaster.h>
|
||||
#include <openspace/scene/scene.h>
|
||||
#include <openspace/util/camera.h>
|
||||
@@ -260,7 +261,12 @@ void ABufferRenderer::render(float blackoutFactor, bool doPerformanceMeasurement
|
||||
glBindImageTexture(1, _fragmentTexture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32UI);
|
||||
|
||||
// Render the scene to the fragment buffer. Collect renderer tasks (active raycasters)
|
||||
RenderData data{ *_camera, psc(), doPerformanceMeasurements };
|
||||
int renderBinMask = static_cast<int>(Renderable::RenderBin::Background) |
|
||||
static_cast<int>(Renderable::RenderBin::Opaque) |
|
||||
static_cast<int>(Renderable::RenderBin::Transparent) |
|
||||
static_cast<int>(Renderable::RenderBin::Overlay);
|
||||
|
||||
RenderData data{ *_camera, psc(), doPerformanceMeasurements, renderBinMask };
|
||||
RendererTasks tasks;
|
||||
_scene->render(data, tasks);
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <openspace/scene/scene.h>
|
||||
#include <openspace/util/camera.h>
|
||||
#include <openspace/engine/openspaceengine.h>
|
||||
#include <openspace/rendering/renderable.h>
|
||||
#include <openspace/rendering/volumeraycaster.h>
|
||||
#include <openspace/rendering/raycastermanager.h>
|
||||
|
||||
@@ -329,7 +330,7 @@ void FramebufferRenderer::render(float blackoutFactor, bool doPerformanceMeasure
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
RenderData data = { *_camera, psc(), doPerformanceMeasurements };
|
||||
RenderData data = { *_camera, psc(), doPerformanceMeasurements, 0 };
|
||||
RendererTasks tasks;
|
||||
|
||||
// Capture standard fbo
|
||||
@@ -339,7 +340,13 @@ void FramebufferRenderer::render(float blackoutFactor, bool doPerformanceMeasure
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, _mainFramebuffer);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
// bind new fbo A with color and depth buffer.
|
||||
data.renderBinMask = static_cast<int>(Renderable::RenderBin::Background);
|
||||
_scene->render(data, tasks);
|
||||
data.renderBinMask = static_cast<int>(Renderable::RenderBin::Opaque);
|
||||
_scene->render(data, tasks);
|
||||
data.renderBinMask = static_cast<int>(Renderable::RenderBin::Transparent);
|
||||
_scene->render(data, tasks);
|
||||
data.renderBinMask = static_cast<int>(Renderable::RenderBin::Overlay);
|
||||
_scene->render(data, tasks);
|
||||
|
||||
for (const RaycasterTask& raycasterTask : tasks.raycasterTasks) {
|
||||
|
||||
@@ -22,14 +22,14 @@
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
// open space includes
|
||||
#include <openspace/rendering/renderable.h>
|
||||
#include <openspace/util/factorymanager.h>
|
||||
#include <openspace/util/updatestructures.h>
|
||||
#include <openspace/util/spicemanager.h>
|
||||
#include <openspace/scene/scenegraphnode.h>
|
||||
|
||||
// ghoul
|
||||
#include <openspace/documentation/verifier.h>
|
||||
|
||||
#include <ghoul/misc/dictionary.h>
|
||||
#include <ghoul/filesystem/filesystem.h>
|
||||
#include <ghoul/opengl/programobject.h>
|
||||
@@ -44,22 +44,37 @@ namespace {
|
||||
|
||||
namespace openspace {
|
||||
|
||||
Documentation Renderable::Documentation() {
|
||||
using namespace openspace::documentation;
|
||||
|
||||
return {
|
||||
"Renderable",
|
||||
"renderable",
|
||||
{
|
||||
{
|
||||
KeyType,
|
||||
new StringAnnotationVerifier("A valid Renderable created by a factory"),
|
||||
"This key specifies the type of Renderable that gets created. It has to be one"
|
||||
"of the valid Renderables that are available for creation (see the "
|
||||
"FactoryDocumentation for a list of possible Renderables), which depends on "
|
||||
"the configration of the application",
|
||||
Optional::No
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Renderable* Renderable::createFromDictionary(const ghoul::Dictionary& dictionary) {
|
||||
// The name is passed down from the SceneGraphNode
|
||||
std::string name;
|
||||
bool success = dictionary.getValue(SceneGraphNode::KeyName, name);
|
||||
assert(success);
|
||||
ghoul_assert(success, "The SceneGraphNode did not set the 'name' key");
|
||||
|
||||
std::string renderableType;
|
||||
success = dictionary.getValue(KeyType, renderableType);
|
||||
documentation::testSpecificationAndThrow(Documentation(), dictionary, "Renderable");
|
||||
|
||||
if (!success) {
|
||||
LERROR("Renderable '" << name << "' did not have key '" << KeyType << "'");
|
||||
return nullptr;
|
||||
}
|
||||
std::string renderableType = dictionary.value<std::string>(KeyType);
|
||||
|
||||
ghoul::TemplateFactory<Renderable>* factory
|
||||
= FactoryManager::ref().factory<Renderable>();
|
||||
auto factory = FactoryManager::ref().factory<Renderable>();
|
||||
Renderable* result = factory->create(renderableType, dictionary);
|
||||
if (result == nullptr) {
|
||||
LERROR("Failed to create a Renderable object of type '" << renderableType << "'");
|
||||
@@ -71,66 +86,55 @@ Renderable* Renderable::createFromDictionary(const ghoul::Dictionary& dictionary
|
||||
|
||||
Renderable::Renderable()
|
||||
: _enabled("enabled", "Is Enabled", true)
|
||||
, _renderBin(RenderBin::Opaque)
|
||||
, _startTime("")
|
||||
, _endTime("")
|
||||
, _hasTimeInterval(false)
|
||||
{
|
||||
|
||||
}
|
||||
{}
|
||||
|
||||
Renderable::Renderable(const ghoul::Dictionary& dictionary)
|
||||
: _enabled("enabled", "Is Enabled", true)
|
||||
, _renderBin(RenderBin::Opaque)
|
||||
, _startTime("")
|
||||
, _endTime("")
|
||||
, _hasTimeInterval(false)
|
||||
{
|
||||
setName("renderable");
|
||||
#ifndef NDEBUG
|
||||
std::string name;
|
||||
ghoul_assert(dictionary.getValue(SceneGraphNode::KeyName, name),
|
||||
"Scenegraphnode need to specify '" << SceneGraphNode::KeyName
|
||||
<< "' because renderables is going to use this for debugging!");
|
||||
#endif
|
||||
|
||||
ghoul_assert(
|
||||
dictionary.hasKeyAndValue<std::string>(SceneGraphNode::KeyName),
|
||||
"SceneGraphNode must specify '" << SceneGraphNode::KeyName << "'"
|
||||
);
|
||||
|
||||
dictionary.getValue(keyStart, _startTime);
|
||||
dictionary.getValue(keyEnd, _endTime);
|
||||
|
||||
if (_startTime != "" && _endTime != "")
|
||||
if (_startTime != "" && _endTime != "") {
|
||||
_hasTimeInterval = true;
|
||||
}
|
||||
|
||||
addProperty(_enabled);
|
||||
}
|
||||
|
||||
Renderable::~Renderable() {
|
||||
Renderable::~Renderable() {}
|
||||
|
||||
void Renderable::setBoundingSphere(PowerScaledScalar boundingSphere) {
|
||||
boundingSphere_ = std::move(boundingSphere);
|
||||
}
|
||||
|
||||
void Renderable::setBoundingSphere(const PowerScaledScalar& boundingSphere)
|
||||
{
|
||||
boundingSphere_ = boundingSphere;
|
||||
}
|
||||
|
||||
const PowerScaledScalar& Renderable::getBoundingSphere()
|
||||
{
|
||||
PowerScaledScalar Renderable::getBoundingSphere() {
|
||||
return boundingSphere_;
|
||||
}
|
||||
|
||||
void Renderable::update(const UpdateData&)
|
||||
{
|
||||
}
|
||||
void Renderable::update(const UpdateData&) {}
|
||||
|
||||
void Renderable::render(const RenderData& data, RendererTasks& tasks)
|
||||
{
|
||||
(void) tasks;
|
||||
void Renderable::render(const RenderData& data, RendererTasks&) {
|
||||
render(data);
|
||||
}
|
||||
|
||||
void Renderable::render(const RenderData& data)
|
||||
{
|
||||
}
|
||||
void Renderable::render(const RenderData& data) {}
|
||||
|
||||
void Renderable::postRender(const RenderData& data)
|
||||
{
|
||||
}
|
||||
void Renderable::postRender(const RenderData& data) {}
|
||||
|
||||
void Renderable::setPscUniforms(
|
||||
ghoul::opengl::ProgramObject& program,
|
||||
@@ -143,6 +147,18 @@ void Renderable::setPscUniforms(
|
||||
program.setUniform("scaling", camera.scaling());
|
||||
}
|
||||
|
||||
Renderable::RenderBin Renderable::renderBin() const {
|
||||
return _renderBin;
|
||||
}
|
||||
|
||||
void Renderable::setRenderBin(RenderBin bin) {
|
||||
_renderBin = bin;
|
||||
}
|
||||
|
||||
bool Renderable::matchesRenderBinMask(int binMask) {
|
||||
return binMask & static_cast<int>(renderBin());
|
||||
}
|
||||
|
||||
bool Renderable::isVisible() const {
|
||||
return _enabled;
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
|
||||
#include <openspace/performance/performancemanager.h>
|
||||
|
||||
#include <openspace/documentation/documentationengine.h>
|
||||
#include <openspace/engine/openspaceengine.h>
|
||||
#include <openspace/interaction/interactionhandler.h>
|
||||
#include <openspace/scene/scene.h>
|
||||
@@ -124,10 +125,12 @@ RenderEngine::RenderEngine()
|
||||
, _showInfo(true)
|
||||
, _showLog(true)
|
||||
, _takeScreenshot(false)
|
||||
, _showFrameNumber(false)
|
||||
, _globalBlackOutFactor(1.f)
|
||||
, _fadeDuration(2.f)
|
||||
, _currentFadeTime(0.f)
|
||||
, _fadeDirection(0)
|
||||
, _frameNumber(0)
|
||||
, _frametimeType(FrametimeType::DtTimeAvg)
|
||||
// , _sgctRenderStatisticsVisible(false)
|
||||
{
|
||||
@@ -180,6 +183,7 @@ void RenderEngine::setRendererFromString(const std::string& renderingMethod) {
|
||||
}
|
||||
|
||||
bool RenderEngine::initialize() {
|
||||
_frameNumber = 0;
|
||||
std::string renderingMethod = DefaultRenderingMethod;
|
||||
|
||||
// If the user specified a rendering method that he would like to use, use that
|
||||
@@ -228,6 +232,7 @@ bool RenderEngine::initialize() {
|
||||
MissionManager::initialize();
|
||||
#endif
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -240,6 +245,8 @@ bool RenderEngine::initializeGL() {
|
||||
OsEng.windowWrapper().setNearFarClippingPlane(0.001f, 1000.f);
|
||||
|
||||
try {
|
||||
const float fontSizeBig = 50.f;
|
||||
_fontBig = OsEng.fontManager().font(KeyFontMono, fontSizeBig);
|
||||
const float fontSizeTime = 15.f;
|
||||
_fontDate = OsEng.fontManager().font(KeyFontMono, fontSizeTime);
|
||||
const float fontSizeMono = 10.f;
|
||||
@@ -334,23 +341,69 @@ bool RenderEngine::initializeGL() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void RenderEngine::preSynchronization() {
|
||||
//if (_mainCamera)
|
||||
// _mainCamera->preSynchronization();
|
||||
void RenderEngine::updateSceneGraph() {
|
||||
_sceneGraph->update({
|
||||
glm::dvec3(0),
|
||||
glm::dmat3(1),
|
||||
1,
|
||||
Time::ref().j2000Seconds(),
|
||||
Time::ref().timeJumped(),
|
||||
Time::ref().deltaTime(),
|
||||
_performanceManager != nullptr
|
||||
});
|
||||
|
||||
_sceneGraph->evaluate(_mainCamera);
|
||||
|
||||
//Allow focus node to update camera (enables camera-following)
|
||||
//FIX LATER: THIS CAUSES MASTER NODE TO BE ONE FRAME AHEAD OF SLAVES
|
||||
//if (const SceneGraphNode* node = OsEng.ref().interactionHandler().focusNode()){
|
||||
//node->updateCamera(_mainCamera);
|
||||
//}
|
||||
}
|
||||
|
||||
void RenderEngine::postSynchronizationPreDraw() {
|
||||
void RenderEngine::updateShaderPrograms() {
|
||||
for (auto program : _programs) {
|
||||
try {
|
||||
if (program->isDirty()) {
|
||||
program->rebuildFromFile();
|
||||
}
|
||||
}
|
||||
catch (const ghoul::opengl::ShaderObject::ShaderCompileError& e) {
|
||||
LERRORC(e.component, e.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RenderEngine::updateRenderer() {
|
||||
bool windowResized = OsEng.windowWrapper().windowHasResized();
|
||||
|
||||
if (windowResized) {
|
||||
glm::ivec2 res = OsEng.windowWrapper().currentDrawBufferResolution();
|
||||
_renderer->setResolution(res);
|
||||
ghoul::fontrendering::FontRenderer::defaultRenderer().setFramebufferSize(glm::vec2(res));
|
||||
}
|
||||
|
||||
_renderer->update();
|
||||
}
|
||||
|
||||
void RenderEngine::updateScreenSpaceRenderables() {
|
||||
for (auto screenspacerenderable : _screenSpaceRenderables) {
|
||||
screenspacerenderable->update();
|
||||
}
|
||||
}
|
||||
|
||||
void RenderEngine::updateFade() {
|
||||
//temporary fade funtionality
|
||||
float fadedIn = 1.0;
|
||||
float fadedOut = 0.0;
|
||||
// Don't restart the fade if you've already done it in that direction
|
||||
if ( (_fadeDirection > 0 && _globalBlackOutFactor == fadedIn)
|
||||
|| (_fadeDirection < 0 && _globalBlackOutFactor == fadedOut)) {
|
||||
if ((_fadeDirection > 0 && _globalBlackOutFactor == fadedIn)
|
||||
|| (_fadeDirection < 0 && _globalBlackOutFactor == fadedOut)) {
|
||||
_fadeDirection = 0;
|
||||
}
|
||||
|
||||
if (_fadeDirection != 0) {
|
||||
if (_currentFadeTime > _fadeDuration){
|
||||
if (_currentFadeTime > _fadeDuration) {
|
||||
_globalBlackOutFactor = _fadeDirection > 0 ? fadedIn : fadedOut;
|
||||
_fadeDirection = 0;
|
||||
}
|
||||
@@ -362,52 +415,6 @@ void RenderEngine::postSynchronizationPreDraw() {
|
||||
_currentFadeTime += static_cast<float>(OsEng.windowWrapper().averageDeltaTime());
|
||||
}
|
||||
}
|
||||
|
||||
//if (_mainCamera)
|
||||
// _mainCamera->postSynchronizationPreDraw();
|
||||
|
||||
bool windowResized = OsEng.windowWrapper().windowHasResized();
|
||||
|
||||
if (windowResized) {
|
||||
glm::ivec2 res = OsEng.windowWrapper().currentDrawBufferResolution();
|
||||
_renderer->setResolution(res);
|
||||
ghoul::fontrendering::FontRenderer::defaultRenderer().setFramebufferSize(glm::vec2(res));
|
||||
}
|
||||
|
||||
// update and evaluate the scene starting from the root node
|
||||
_sceneGraph->update({
|
||||
glm::dvec3(0),
|
||||
glm::dmat3(1),
|
||||
1,
|
||||
Time::ref().currentTime(),
|
||||
Time::ref().timeJumped(),
|
||||
Time::ref().deltaTime(),
|
||||
_performanceManager != nullptr
|
||||
});
|
||||
_sceneGraph->evaluate(_mainCamera);
|
||||
|
||||
_renderer->update();
|
||||
|
||||
for (auto program : _programs) {
|
||||
try {
|
||||
if (program->isDirty()) {
|
||||
program->rebuildFromFile();
|
||||
}
|
||||
}
|
||||
catch (const ghoul::opengl::ShaderObject::ShaderCompileError& e) {
|
||||
LERRORC(e.component, e.what());
|
||||
}
|
||||
}
|
||||
|
||||
for (auto screenspacerenderable : _screenSpaceRenderables) {
|
||||
screenspacerenderable->update();
|
||||
}
|
||||
//Allow focus node to update camera (enables camera-following)
|
||||
//FIX LATER: THIS CAUSES MASTER NODE TO BE ONE FRAME AHEAD OF SLAVES
|
||||
//if (const SceneGraphNode* node = OsEng.ref().interactionHandler().focusNode()){
|
||||
//node->updateCamera(_mainCamera);
|
||||
//}
|
||||
|
||||
}
|
||||
|
||||
void RenderEngine::render(const glm::mat4& projectionMatrix, const glm::mat4& viewMatrix){
|
||||
@@ -420,10 +427,20 @@ void RenderEngine::render(const glm::mat4& projectionMatrix, const glm::mat4& vi
|
||||
|
||||
// Print some useful information on the master viewport
|
||||
if (OsEng.isMaster() && OsEng.windowWrapper().isSimpleRendering()) {
|
||||
if (_showInfo) {
|
||||
renderInformation();
|
||||
}
|
||||
renderInformation();
|
||||
}
|
||||
|
||||
glm::vec2 penPosition = glm::vec2(
|
||||
OsEng.windowWrapper().viewportPixelCoordinates().y / 2 - 50,
|
||||
OsEng.windowWrapper().viewportPixelCoordinates().w / 3
|
||||
);
|
||||
|
||||
if(_showFrameNumber) {
|
||||
RenderFontCr(*_fontBig, penPosition, "%i", _frameNumber);
|
||||
}
|
||||
|
||||
_frameNumber++;
|
||||
|
||||
|
||||
for (auto screenSpaceRenderable : _screenSpaceRenderables) {
|
||||
if (screenSpaceRenderable->isEnabled() && screenSpaceRenderable->isReady())
|
||||
@@ -462,7 +479,7 @@ void RenderEngine::postDraw() {
|
||||
}
|
||||
|
||||
if (_takeScreenshot) {
|
||||
OsEng.windowWrapper().takeScreenshot();
|
||||
OsEng.windowWrapper().takeScreenshot(_applyWarping);
|
||||
_takeScreenshot = false;
|
||||
}
|
||||
|
||||
@@ -471,8 +488,9 @@ void RenderEngine::postDraw() {
|
||||
}
|
||||
}
|
||||
|
||||
void RenderEngine::takeScreenshot() {
|
||||
void RenderEngine::takeScreenshot(bool applyWarping) {
|
||||
_takeScreenshot = true;
|
||||
_applyWarping = applyWarping;
|
||||
}
|
||||
|
||||
void RenderEngine::toggleInfoText(bool b) {
|
||||
@@ -495,8 +513,7 @@ void RenderEngine::toggleFrametimeType(int t) {
|
||||
}
|
||||
|
||||
Scene* RenderEngine::scene() {
|
||||
// TODO custom assert (ticket #5)
|
||||
assert(_sceneGraph);
|
||||
ghoul_assert(_sceneGraph, "Scenegraph not initialized");
|
||||
return _sceneGraph;
|
||||
}
|
||||
|
||||
@@ -508,29 +525,6 @@ void RenderEngine::setSceneGraph(Scene* sceneGraph) {
|
||||
_sceneGraph = sceneGraph;
|
||||
}
|
||||
|
||||
void RenderEngine::serialize(SyncBuffer* syncBuffer) {
|
||||
if (_mainCamera){
|
||||
_mainCamera->serialize(syncBuffer);
|
||||
}
|
||||
|
||||
|
||||
syncBuffer->encode(_onScreenInformation._node);
|
||||
syncBuffer->encode(_onScreenInformation._position.x);
|
||||
syncBuffer->encode(_onScreenInformation._position.y);
|
||||
syncBuffer->encode(_onScreenInformation._size);
|
||||
}
|
||||
|
||||
void RenderEngine::deserialize(SyncBuffer* syncBuffer) {
|
||||
if (_mainCamera){
|
||||
_mainCamera->deserialize(syncBuffer);
|
||||
}
|
||||
syncBuffer->decode(_onScreenInformation._node);
|
||||
syncBuffer->decode(_onScreenInformation._position.x);
|
||||
syncBuffer->decode(_onScreenInformation._position.y);
|
||||
syncBuffer->decode(_onScreenInformation._size);
|
||||
|
||||
}
|
||||
|
||||
Camera* RenderEngine::camera() const {
|
||||
return _mainCamera;
|
||||
}
|
||||
@@ -720,14 +714,16 @@ void RenderEngine::setNAaSamples(int nAaSamples) {
|
||||
}
|
||||
|
||||
scripting::LuaLibrary RenderEngine::luaLibrary() {
|
||||
return {
|
||||
return{
|
||||
"",
|
||||
{
|
||||
{
|
||||
"takeScreenshot",
|
||||
&luascriptfunctions::takeScreenshot,
|
||||
"",
|
||||
"Renders the current image to a file on disk"
|
||||
"(optional bool)",
|
||||
"Renders the current image to a file on disk. If the boolean parameter "
|
||||
"is set to 'true', the screenshot will include the blending and the "
|
||||
"meshes. If it is 'false', the straight FBO will be recorded."
|
||||
},
|
||||
{
|
||||
"setRenderer",
|
||||
@@ -739,7 +735,7 @@ scripting::LuaLibrary RenderEngine::luaLibrary() {
|
||||
"setNAaSamples",
|
||||
&luascriptfunctions::setNAaSamples,
|
||||
"int",
|
||||
"Sets the number of anti-aliasing (msaa) samples"
|
||||
"Sets the number of anti-aliasing (MSAA) samples"
|
||||
},
|
||||
{
|
||||
"showRenderInformation",
|
||||
@@ -1202,6 +1198,10 @@ void RenderEngine::changeViewPoint(std::string origin) {
|
||||
LFATAL("This function is being misused with an argument of '" << origin << "'");
|
||||
}
|
||||
|
||||
void RenderEngine::setShowFrameNumber(bool enabled){
|
||||
_showFrameNumber = enabled;
|
||||
}
|
||||
|
||||
void RenderEngine::setDisableRenderingOnMaster(bool enabled) {
|
||||
_disableMasterRendering = enabled;
|
||||
}
|
||||
@@ -1281,7 +1281,7 @@ void RenderEngine::renderInformation() {
|
||||
using Font = ghoul::fontrendering::Font;
|
||||
using ghoul::fontrendering::RenderFont;
|
||||
|
||||
if (_showInfo && _fontDate && _fontInfo) {
|
||||
if (_fontDate) {
|
||||
glm::vec2 penPosition = glm::vec2(
|
||||
10.f,
|
||||
OsEng.windowWrapper().viewportPixelCoordinates().w
|
||||
@@ -1291,45 +1291,46 @@ void RenderEngine::renderInformation() {
|
||||
RenderFontCr(*_fontDate,
|
||||
penPosition,
|
||||
"Date: %s",
|
||||
Time::ref().currentTimeUTC().c_str()
|
||||
Time::ref().UTC().c_str()
|
||||
);
|
||||
|
||||
RenderFontCr(*_fontInfo,
|
||||
penPosition,
|
||||
"Simulation increment (s): %.0f",
|
||||
Time::ref().deltaTime()
|
||||
if (_showInfo && _fontInfo) {
|
||||
RenderFontCr(*_fontInfo,
|
||||
penPosition,
|
||||
"Simulation increment (s): %.0f",
|
||||
Time::ref().deltaTime()
|
||||
);
|
||||
|
||||
switch (_frametimeType) {
|
||||
case FrametimeType::DtTimeAvg:
|
||||
RenderFontCr(*_fontInfo,
|
||||
penPosition,
|
||||
"Avg. Frametime: %.5f",
|
||||
OsEng.windowWrapper().averageDeltaTime()
|
||||
);
|
||||
break;
|
||||
case FrametimeType::FPS:
|
||||
RenderFontCr(*_fontInfo,
|
||||
penPosition,
|
||||
"FPS: %3.2f",
|
||||
1.0 / OsEng.windowWrapper().deltaTime()
|
||||
);
|
||||
break;
|
||||
case FrametimeType::FPSAvg:
|
||||
RenderFontCr(*_fontInfo,
|
||||
penPosition,
|
||||
"Avg. FPS: %3.2f",
|
||||
1.0 / OsEng.windowWrapper().averageDeltaTime()
|
||||
);
|
||||
break;
|
||||
default:
|
||||
RenderFontCr(*_fontInfo,
|
||||
penPosition,
|
||||
"Avg. Frametime: %.5f",
|
||||
OsEng.windowWrapper().averageDeltaTime()
|
||||
);
|
||||
break;
|
||||
}
|
||||
switch (_frametimeType) {
|
||||
case FrametimeType::DtTimeAvg:
|
||||
RenderFontCr(*_fontInfo,
|
||||
penPosition,
|
||||
"Avg. Frametime: %.5f",
|
||||
OsEng.windowWrapper().averageDeltaTime()
|
||||
);
|
||||
break;
|
||||
case FrametimeType::FPS:
|
||||
RenderFontCr(*_fontInfo,
|
||||
penPosition,
|
||||
"FPS: %3.2f",
|
||||
1.0 / OsEng.windowWrapper().deltaTime()
|
||||
);
|
||||
break;
|
||||
case FrametimeType::FPSAvg:
|
||||
RenderFontCr(*_fontInfo,
|
||||
penPosition,
|
||||
"Avg. FPS: %3.2f",
|
||||
1.0 / OsEng.windowWrapper().averageDeltaTime()
|
||||
);
|
||||
break;
|
||||
default:
|
||||
RenderFontCr(*_fontInfo,
|
||||
penPosition,
|
||||
"Avg. Frametime: %.5f",
|
||||
OsEng.windowWrapper().averageDeltaTime()
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
network::Status status = OsEng.parallelConnection().status();
|
||||
size_t nConnections = OsEng.parallelConnection().nConnections();
|
||||
@@ -1371,260 +1372,270 @@ void RenderEngine::renderInformation() {
|
||||
|
||||
|
||||
#ifdef OPENSPACE_MODULE_NEWHORIZONS_ENABLED
|
||||
//<<<<<<< HEAD
|
||||
bool hasNewHorizons = scene()->sceneGraphNode("NewHorizons");
|
||||
double currentTime = Time::ref().currentTime();
|
||||
double currentTime = Time::ref().j2000Seconds();
|
||||
|
||||
if (MissionManager::ref().hasCurrentMission()) {
|
||||
|
||||
const Mission& mission = MissionManager::ref().currentMission();
|
||||
//=======
|
||||
// bool hasNewHorizons = scene()->sceneGraphNode("NewHorizons");
|
||||
// double currentTime = Time::ref().currentTime();
|
||||
//>>>>>>> develop
|
||||
//
|
||||
// if (MissionManager::ref().hasCurrentMission()) {
|
||||
//
|
||||
// const Mission& mission = MissionManager::ref().currentMission();
|
||||
|
||||
if (mission.phases().size() > 0) {
|
||||
if (mission.phases().size() > 0) {
|
||||
|
||||
static const glm::vec4 nextMissionColor(0.7, 0.3, 0.3, 1);
|
||||
//static const glm::vec4 missionProgressColor(0.4, 1.0, 1.0, 1);
|
||||
static const glm::vec4 currentMissionColor(0.0, 0.5, 0.5, 1);
|
||||
static const glm::vec4 missionProgressColor = currentMissionColor;// (0.4, 1.0, 1.0, 1);
|
||||
static const glm::vec4 currentLeafMissionColor = missionProgressColor;
|
||||
static const glm::vec4 nonCurrentMissionColor(0.3, 0.3, 0.3, 1);
|
||||
static const glm::vec4 nextMissionColor(0.7, 0.3, 0.3, 1);
|
||||
//static const glm::vec4 missionProgressColor(0.4, 1.0, 1.0, 1);
|
||||
static const glm::vec4 currentMissionColor(0.0, 0.5, 0.5, 1);
|
||||
static const glm::vec4 missionProgressColor = currentMissionColor;// (0.4, 1.0, 1.0, 1);
|
||||
static const glm::vec4 currentLeafMissionColor = missionProgressColor;
|
||||
static const glm::vec4 nonCurrentMissionColor(0.3, 0.3, 0.3, 1);
|
||||
|
||||
// Add spacing
|
||||
RenderFontCr(*_fontInfo, penPosition, nonCurrentMissionColor, " ");
|
||||
// Add spacing
|
||||
RenderFontCr(*_fontInfo, penPosition, nonCurrentMissionColor, " ");
|
||||
|
||||
std::list<const MissionPhase*> phaseTrace = mission.phaseTrace(currentTime);
|
||||
std::list<const MissionPhase*> phaseTrace = mission.phaseTrace(currentTime);
|
||||
|
||||
if (phaseTrace.size()) {
|
||||
std::string title = "Current Mission Phase: " + phaseTrace.back()->name();
|
||||
RenderFontCr(*_fontInfo, penPosition, missionProgressColor, title.c_str());
|
||||
double remaining = phaseTrace.back()->timeRange().end - currentTime;
|
||||
float t = static_cast<float>(1.0 - remaining / phaseTrace.back()->timeRange().duration());
|
||||
std::string progress = progressToStr(25, t);
|
||||
//RenderFontCr(*_fontInfo, penPosition, missionProgressColor,
|
||||
// "%.0f s %s %.1f %%", remaining, progress.c_str(), t * 100);
|
||||
}
|
||||
else {
|
||||
RenderFontCr(*_fontInfo, penPosition, nextMissionColor, "Next Mission:");
|
||||
double remaining = mission.timeRange().start - currentTime;
|
||||
RenderFontCr(*_fontInfo, penPosition, nextMissionColor,
|
||||
"%.0f s", remaining);
|
||||
}
|
||||
|
||||
bool showAllPhases = false;
|
||||
|
||||
typedef std::pair<const MissionPhase*, int> PhaseWithDepth;
|
||||
std::stack<PhaseWithDepth> S;
|
||||
int pixelIndentation = 20;
|
||||
S.push({ &mission, 0 });
|
||||
while (!S.empty()) {
|
||||
const MissionPhase* phase = S.top().first;
|
||||
int depth = S.top().second;
|
||||
S.pop();
|
||||
|
||||
bool isCurrentPhase = phase->timeRange().includes(currentTime);
|
||||
|
||||
penPosition.x += depth * pixelIndentation;
|
||||
if (isCurrentPhase) {
|
||||
double remaining = phase->timeRange().end - currentTime;
|
||||
float t = static_cast<float>(1.0 - remaining / phase->timeRange().duration());
|
||||
if (phaseTrace.size()) {
|
||||
std::string title = "Current Mission Phase: " + phaseTrace.back()->name();
|
||||
RenderFontCr(*_fontInfo, penPosition, missionProgressColor, title.c_str());
|
||||
double remaining = phaseTrace.back()->timeRange().end - currentTime;
|
||||
float t = static_cast<float>(1.0 - remaining / phaseTrace.back()->timeRange().duration());
|
||||
std::string progress = progressToStr(25, t);
|
||||
RenderFontCr(*_fontInfo, penPosition, currentMissionColor,
|
||||
"%s %s %.1f %%",
|
||||
phase->name().c_str(),
|
||||
progress.c_str(),
|
||||
t * 100
|
||||
);
|
||||
//RenderFontCr(*_fontInfo, penPosition, missionProgressColor,
|
||||
// "%.0f s %s %.1f %%", remaining, progress.c_str(), t * 100);
|
||||
}
|
||||
else {
|
||||
RenderFontCr(*_fontInfo, penPosition, nonCurrentMissionColor, phase->name().c_str());
|
||||
RenderFontCr(*_fontInfo, penPosition, nextMissionColor, "Next Mission:");
|
||||
double remaining = mission.timeRange().start - currentTime;
|
||||
RenderFontCr(*_fontInfo, penPosition, nextMissionColor,
|
||||
"%.0f s", remaining);
|
||||
}
|
||||
penPosition.x -= depth * pixelIndentation;
|
||||
|
||||
if (isCurrentPhase || showAllPhases) {
|
||||
// phases are sorted increasingly by start time, and will be popped
|
||||
// last-in-first-out from the stack, so add them in reversed order.
|
||||
int indexLastPhase = phase->phases().size() - 1;
|
||||
for (int i = indexLastPhase; 0 <= i; --i) {
|
||||
S.push({ &phase->phase(i), depth + 1 });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
bool showAllPhases = false;
|
||||
|
||||
typedef std::pair<const MissionPhase*, int> PhaseWithDepth;
|
||||
std::stack<PhaseWithDepth> S;
|
||||
int pixelIndentation = 20;
|
||||
S.push({ &mission, 0 });
|
||||
while (!S.empty()) {
|
||||
const MissionPhase* phase = S.top().first;
|
||||
int depth = S.top().second;
|
||||
S.pop();
|
||||
|
||||
bool isCurrentPhase = phase->timeRange().includes(currentTime);
|
||||
|
||||
if (openspace::ImageSequencer::ref().isReady()) {
|
||||
penPosition.y -= 25.f;
|
||||
|
||||
glm::vec4 targetColor(0.00, 0.75, 1.00, 1);
|
||||
|
||||
if (hasNewHorizons) {
|
||||
try {
|
||||
double lt;
|
||||
glm::dvec3 p =
|
||||
SpiceManager::ref().targetPosition("PLUTO", "NEW HORIZONS", "GALACTIC", {}, currentTime, lt);
|
||||
psc nhPos = PowerScaledCoordinate::CreatePowerScaledCoordinate(p.x, p.y, p.z);
|
||||
float a, b, c;
|
||||
glm::dvec3 radii;
|
||||
SpiceManager::ref().getValue("PLUTO", "RADII", radii);
|
||||
a = radii.x;
|
||||
b = radii.y;
|
||||
float radius = (a + b) / 2.f;
|
||||
float distToSurf = glm::length(nhPos.vec3()) - radius;
|
||||
|
||||
RenderFont(*_fontInfo,
|
||||
penPosition,
|
||||
"Distance to Pluto: % .1f (KM)",
|
||||
distToSurf
|
||||
);
|
||||
penPosition.y -= _fontInfo->height();
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
}
|
||||
|
||||
double remaining = openspace::ImageSequencer::ref().getNextCaptureTime() - currentTime;
|
||||
float t = static_cast<float>(1.0 - remaining / openspace::ImageSequencer::ref().getIntervalLength());
|
||||
|
||||
std::string str = SpiceManager::ref().dateFromEphemerisTime(
|
||||
ImageSequencer::ref().getNextCaptureTime(),
|
||||
"YYYY MON DD HR:MN:SC"
|
||||
);
|
||||
|
||||
glm::vec4 active(0.6, 1, 0.00, 1);
|
||||
glm::vec4 brigther_active(0.9, 1, 0.75, 1);
|
||||
|
||||
if (remaining > 0) {
|
||||
|
||||
std::string progress = progressToStr(25, t);
|
||||
brigther_active *= (1 - t);
|
||||
|
||||
RenderFontCr(*_fontInfo,
|
||||
penPosition,
|
||||
active * t + brigther_active,
|
||||
"Next instrument activity:"
|
||||
);
|
||||
|
||||
RenderFontCr(*_fontInfo,
|
||||
penPosition,
|
||||
active * t + brigther_active,
|
||||
"%.0f s %s %.1f %%",
|
||||
remaining, progress.c_str(), t * 100
|
||||
);
|
||||
|
||||
RenderFontCr(*_fontInfo,
|
||||
penPosition,
|
||||
active,
|
||||
"Data acquisition time: %s",
|
||||
str.c_str()
|
||||
);
|
||||
}
|
||||
std::pair<double, std::string> nextTarget = ImageSequencer::ref().getNextTarget();
|
||||
std::pair<double, std::string> currentTarget = ImageSequencer::ref().getCurrentTarget();
|
||||
|
||||
if (currentTarget.first > 0.0) {
|
||||
int timeleft = static_cast<int>(nextTarget.first - currentTime);
|
||||
|
||||
int hour = timeleft / 3600;
|
||||
int second = timeleft % 3600;
|
||||
int minute = second / 60;
|
||||
second = second % 60;
|
||||
|
||||
std::string hh, mm, ss;
|
||||
|
||||
if (hour < 10)
|
||||
hh.append("0");
|
||||
if (minute < 10)
|
||||
mm.append("0");
|
||||
if (second < 10)
|
||||
ss.append("0");
|
||||
|
||||
hh.append(std::to_string(hour));
|
||||
mm.append(std::to_string(minute));
|
||||
ss.append(std::to_string(second));
|
||||
|
||||
RenderFontCr(*_fontInfo,
|
||||
penPosition,
|
||||
targetColor,
|
||||
"Data acquisition adjacency: [%s:%s:%s]",
|
||||
hh.c_str(), mm.c_str(), ss.c_str()
|
||||
);
|
||||
|
||||
#if 0
|
||||
// Why is it (2) in the original? ---abock
|
||||
//std::pair<double, std::vector<std::string>> incidentTargets = ImageSequencer::ref().getIncidentTargetList(0);
|
||||
//std::pair<double, std::vector<std::string>> incidentTargets = ImageSequencer::ref().getIncidentTargetList(2);
|
||||
std::string space;
|
||||
glm::vec4 color;
|
||||
size_t isize = incidentTargets.second.size();
|
||||
for (size_t p = 0; p < isize; p++) {
|
||||
double t = static_cast<double>(p + 1) / static_cast<double>(isize + 1);
|
||||
t = (p > isize / 2) ? 1 - t : t;
|
||||
t += 0.3;
|
||||
color = (p == isize / 2) ? targetColor : glm::vec4(t, t, t, 1);
|
||||
|
||||
RenderFont(*_fontInfo,
|
||||
penPosition,
|
||||
color,
|
||||
"%s%s",
|
||||
space.c_str(), incidentTargets.second[p].c_str()
|
||||
);
|
||||
|
||||
|
||||
for (int k = 0; k < incidentTargets.second[p].size() + 2; k++)
|
||||
space += " ";
|
||||
}
|
||||
#endif
|
||||
penPosition.y -= _fontInfo->height();
|
||||
|
||||
std::map<std::string, bool> activeMap = ImageSequencer::ref().getActiveInstruments();
|
||||
glm::vec4 firing(0.58 - t, 1 - t, 1 - t, 1);
|
||||
glm::vec4 notFiring(0.5, 0.5, 0.5, 1);
|
||||
|
||||
RenderFontCr(*_fontInfo,
|
||||
penPosition,
|
||||
active,
|
||||
"Active Instruments:"
|
||||
);
|
||||
|
||||
for (auto t : activeMap) {
|
||||
if (t.second == false) {
|
||||
RenderFont(*_fontInfo,
|
||||
penPosition,
|
||||
glm::vec4(0.3, 0.3, 0.3, 1),
|
||||
"| |"
|
||||
);
|
||||
RenderFontCr(*_fontInfo,
|
||||
penPosition,
|
||||
glm::vec4(0.3, 0.3, 0.3, 1),
|
||||
" %5s",
|
||||
t.first.c_str()
|
||||
);
|
||||
|
||||
}
|
||||
else {
|
||||
RenderFont(*_fontInfo,
|
||||
penPosition,
|
||||
glm::vec4(0.3, 0.3, 0.3, 1),
|
||||
"|"
|
||||
);
|
||||
if (t.first == "NH_LORRI") {
|
||||
RenderFont(*_fontInfo,
|
||||
penPosition,
|
||||
firing,
|
||||
" + "
|
||||
penPosition.x += depth * pixelIndentation;
|
||||
if (isCurrentPhase) {
|
||||
double remaining = phase->timeRange().end - currentTime;
|
||||
float t = static_cast<float>(1.0 - remaining / phase->timeRange().duration());
|
||||
std::string progress = progressToStr(25, t);
|
||||
RenderFontCr(*_fontInfo, penPosition, currentMissionColor,
|
||||
"%s %s %.1f %%",
|
||||
phase->name().c_str(),
|
||||
progress.c_str(),
|
||||
t * 100
|
||||
);
|
||||
}
|
||||
else {
|
||||
RenderFontCr(*_fontInfo, penPosition, nonCurrentMissionColor, phase->name().c_str());
|
||||
}
|
||||
penPosition.x -= depth * pixelIndentation;
|
||||
|
||||
if (isCurrentPhase || showAllPhases) {
|
||||
// phases are sorted increasingly by start time, and will be popped
|
||||
// last-in-first-out from the stack, so add them in reversed order.
|
||||
int indexLastPhase = phase->phases().size() - 1;
|
||||
for (int i = indexLastPhase; 0 <= i; --i) {
|
||||
S.push({ &phase->phase(i), depth + 1 });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (openspace::ImageSequencer::ref().isReady()) {
|
||||
penPosition.y -= 25.f;
|
||||
|
||||
glm::vec4 targetColor(0.00, 0.75, 1.00, 1);
|
||||
|
||||
if (hasNewHorizons) {
|
||||
try {
|
||||
double lt;
|
||||
glm::dvec3 p =
|
||||
SpiceManager::ref().targetPosition("PLUTO", "NEW HORIZONS", "GALACTIC", {}, currentTime, lt);
|
||||
psc nhPos = PowerScaledCoordinate::CreatePowerScaledCoordinate(p.x, p.y, p.z);
|
||||
float a, b, c;
|
||||
glm::dvec3 radii;
|
||||
SpiceManager::ref().getValue("PLUTO", "RADII", radii);
|
||||
a = radii.x;
|
||||
b = radii.y;
|
||||
float radius = (a + b) / 2.f;
|
||||
float distToSurf = glm::length(nhPos.vec3()) - radius;
|
||||
|
||||
RenderFont(*_fontInfo,
|
||||
penPosition,
|
||||
"Distance to Pluto: % .1f (KM)",
|
||||
distToSurf
|
||||
);
|
||||
penPosition.y -= _fontInfo->height();
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
}
|
||||
|
||||
double remaining = openspace::ImageSequencer::ref().getNextCaptureTime() - currentTime;
|
||||
float t = static_cast<float>(1.0 - remaining / openspace::ImageSequencer::ref().getIntervalLength());
|
||||
|
||||
std::string str = SpiceManager::ref().dateFromEphemerisTime(
|
||||
ImageSequencer::ref().getNextCaptureTime(),
|
||||
"YYYY MON DD HR:MN:SC"
|
||||
);
|
||||
|
||||
glm::vec4 active(0.6, 1, 0.00, 1);
|
||||
glm::vec4 brigther_active(0.9, 1, 0.75, 1);
|
||||
|
||||
if (remaining > 0) {
|
||||
|
||||
std::string progress = progressToStr(25, t);
|
||||
brigther_active *= (1 - t);
|
||||
|
||||
RenderFontCr(*_fontInfo,
|
||||
penPosition,
|
||||
active * t + brigther_active,
|
||||
"Next instrument activity:"
|
||||
);
|
||||
|
||||
RenderFontCr(*_fontInfo,
|
||||
penPosition,
|
||||
active * t + brigther_active,
|
||||
"%.0f s %s %.1f %%",
|
||||
remaining, progress.c_str(), t * 100
|
||||
);
|
||||
|
||||
RenderFontCr(*_fontInfo,
|
||||
penPosition,
|
||||
active,
|
||||
"Data acquisition time: %s",
|
||||
str.c_str()
|
||||
);
|
||||
}
|
||||
std::pair<double, std::string> nextTarget = ImageSequencer::ref().getNextTarget();
|
||||
std::pair<double, std::string> currentTarget = ImageSequencer::ref().getCurrentTarget();
|
||||
|
||||
if (currentTarget.first > 0.0) {
|
||||
int timeleft = static_cast<int>(nextTarget.first - currentTime);
|
||||
|
||||
int hour = timeleft / 3600;
|
||||
int second = timeleft % 3600;
|
||||
int minute = second / 60;
|
||||
second = second % 60;
|
||||
|
||||
std::string hh, mm, ss;
|
||||
|
||||
if (hour < 10)
|
||||
hh.append("0");
|
||||
if (minute < 10)
|
||||
mm.append("0");
|
||||
if (second < 10)
|
||||
ss.append("0");
|
||||
|
||||
hh.append(std::to_string(hour));
|
||||
mm.append(std::to_string(minute));
|
||||
ss.append(std::to_string(second));
|
||||
|
||||
RenderFontCr(*_fontInfo,
|
||||
penPosition,
|
||||
targetColor,
|
||||
"Data acquisition adjacency: [%s:%s:%s]",
|
||||
hh.c_str(), mm.c_str(), ss.c_str()
|
||||
);
|
||||
|
||||
#if 0
|
||||
// Why is it (2) in the original? ---abock
|
||||
//std::pair<double, std::vector<std::string>> incidentTargets = ImageSequencer::ref().getIncidentTargetList(0);
|
||||
//std::pair<double, std::vector<std::string>> incidentTargets = ImageSequencer::ref().getIncidentTargetList(2);
|
||||
std::string space;
|
||||
glm::vec4 color;
|
||||
size_t isize = incidentTargets.second.size();
|
||||
for (size_t p = 0; p < isize; p++) {
|
||||
double t = static_cast<double>(p + 1) / static_cast<double>(isize + 1);
|
||||
t = (p > isize / 2) ? 1 - t : t;
|
||||
t += 0.3;
|
||||
color = (p == isize / 2) ? targetColor : glm::vec4(t, t, t, 1);
|
||||
|
||||
RenderFont(*_fontInfo,
|
||||
penPosition,
|
||||
glm::vec4(0.3, 0.3, 0.3, 1),
|
||||
" |"
|
||||
);
|
||||
RenderFontCr(*_fontInfo,
|
||||
penPosition,
|
||||
active,
|
||||
" %5s",
|
||||
t.first.c_str()
|
||||
color,
|
||||
"%s%s",
|
||||
space.c_str(), incidentTargets.second[p].c_str()
|
||||
);
|
||||
|
||||
|
||||
for (int k = 0; k < incidentTargets.second[p].size() + 2; k++)
|
||||
space += " ";
|
||||
}
|
||||
#endif
|
||||
penPosition.y -= _fontInfo->height();
|
||||
|
||||
std::map<std::string, bool> activeMap = ImageSequencer::ref().getActiveInstruments();
|
||||
glm::vec4 firing(0.58 - t, 1 - t, 1 - t, 1);
|
||||
glm::vec4 notFiring(0.5, 0.5, 0.5, 1);
|
||||
|
||||
RenderFontCr(*_fontInfo,
|
||||
penPosition,
|
||||
active,
|
||||
"Active Instruments:"
|
||||
);
|
||||
|
||||
for (auto t : activeMap) {
|
||||
if (t.second == false) {
|
||||
RenderFont(*_fontInfo,
|
||||
penPosition,
|
||||
glm::vec4(0.3, 0.3, 0.3, 1),
|
||||
"| |"
|
||||
);
|
||||
RenderFontCr(*_fontInfo,
|
||||
penPosition,
|
||||
glm::vec4(0.3, 0.3, 0.3, 1),
|
||||
" %5s",
|
||||
t.first.c_str()
|
||||
);
|
||||
|
||||
}
|
||||
else {
|
||||
RenderFont(*_fontInfo,
|
||||
penPosition,
|
||||
glm::vec4(0.3, 0.3, 0.3, 1),
|
||||
"|"
|
||||
);
|
||||
if (t.first == "NH_LORRI") {
|
||||
RenderFont(*_fontInfo,
|
||||
penPosition,
|
||||
firing,
|
||||
" + "
|
||||
);
|
||||
}
|
||||
RenderFont(*_fontInfo,
|
||||
penPosition,
|
||||
glm::vec4(0.3, 0.3, 0.3, 1),
|
||||
" |"
|
||||
);
|
||||
RenderFontCr(*_fontInfo,
|
||||
penPosition,
|
||||
active,
|
||||
" %5s",
|
||||
t.first.c_str()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1723,6 +1734,12 @@ void RenderEngine::renderScreenLog() {
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<Syncable*> RenderEngine::getSyncables(){
|
||||
std::vector<Syncable*> syncables = _mainCamera->getSyncables();
|
||||
syncables.push_back(&_onScreenInformation);
|
||||
return syncables;
|
||||
}
|
||||
|
||||
void RenderEngine::sortScreenspaceRenderables() {
|
||||
std::sort(
|
||||
_screenSpaceRenderables.begin(),
|
||||
|
||||
@@ -33,11 +33,18 @@ namespace luascriptfunctions {
|
||||
*/
|
||||
int takeScreenshot(lua_State* L) {
|
||||
int nArguments = lua_gettop(L);
|
||||
if (nArguments != 0) {
|
||||
if (nArguments == 0) {
|
||||
OsEng.renderEngine().takeScreenshot();
|
||||
return 0;
|
||||
}
|
||||
else if (nArguments == 1) {
|
||||
bool b = lua_toboolean(L, -1) != 0;
|
||||
OsEng.renderEngine().takeScreenshot(b);
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
return luaL_error(L, "Expected %i arguments, got %i", 0, nArguments);
|
||||
}
|
||||
OsEng.renderEngine().takeScreenshot();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
#include <openspace/util/camera.h>
|
||||
#include <openspace/util/factorymanager.h>
|
||||
|
||||
#include <openspace/documentation/verifier.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#define _USE_MATH_DEFINES
|
||||
#include <math.h>
|
||||
@@ -50,16 +52,36 @@ namespace {
|
||||
|
||||
namespace openspace {
|
||||
|
||||
Documentation ScreenSpaceRenderable::Documentation() {
|
||||
using namespace openspace::documentation;
|
||||
|
||||
return {
|
||||
"Screenspace Renderable",
|
||||
"core_screenspacerenderable",
|
||||
{
|
||||
{
|
||||
KeyType,
|
||||
new StringAnnotationVerifier("Must name a valid Screenspace renderable"),
|
||||
"The type of the Screenspace renderable that is to be created. The "
|
||||
"available types of Screenspace renderable depend on the configuration of"
|
||||
"the application and can be written to disk on application startup into "
|
||||
"the FactoryDocumentation.",
|
||||
Optional::No
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
ScreenSpaceRenderable* ScreenSpaceRenderable::createFromDictionary(
|
||||
const ghoul::Dictionary& dictionary)
|
||||
{
|
||||
std::string renderableType;
|
||||
bool success = dictionary.getValue(KeyType, renderableType);
|
||||
documentation::testSpecificationAndThrow(
|
||||
Documentation(),
|
||||
dictionary,
|
||||
"ScreenSpaceRenderable"
|
||||
);
|
||||
|
||||
if (!success) {
|
||||
LERROR("ScreenSpaceRenderable did not have key '" << KeyType << "'");
|
||||
return nullptr;
|
||||
}
|
||||
std::string renderableType = dictionary.value<std::string>(KeyType);
|
||||
|
||||
auto factory = FactoryManager::ref().factory<ScreenSpaceRenderable>();
|
||||
ScreenSpaceRenderable* result = factory->create(renderableType, dictionary);
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
#include <openspace/util/factorymanager.h>
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
|
||||
#include <openspace/documentation/verifier.h>
|
||||
|
||||
namespace {
|
||||
const std::string _loggerCat = "Ephemeris";
|
||||
const std::string KeyType = "Type";
|
||||
@@ -33,6 +35,27 @@ namespace {
|
||||
|
||||
namespace openspace {
|
||||
|
||||
Documentation Ephemeris::Documentation() {
|
||||
using namespace openspace::documentation;
|
||||
|
||||
return{
|
||||
"Transformation Translation",
|
||||
"core_transform_translation",
|
||||
{
|
||||
{
|
||||
KeyType,
|
||||
new StringAnnotationVerifier("Must name a valid Translation type"),
|
||||
"The type of translation that is described in this element. "
|
||||
"The available types of translations depend on the "
|
||||
"configuration of the application and can be written to disk "
|
||||
"on application startup into the FactoryDocumentation.",
|
||||
Optional::No
|
||||
}
|
||||
},
|
||||
Exhaustive::No
|
||||
};
|
||||
}
|
||||
|
||||
Ephemeris* Ephemeris::createFromDictionary(const ghoul::Dictionary& dictionary) {
|
||||
if (!dictionary.hasValue<std::string>(KeyType)) {
|
||||
LERROR("Ephemeris did not have key '" << KeyType << "'");
|
||||
@@ -52,10 +75,6 @@ Ephemeris* Ephemeris::createFromDictionary(const ghoul::Dictionary& dictionary)
|
||||
return result;
|
||||
}
|
||||
|
||||
Ephemeris::Ephemeris() {}
|
||||
|
||||
Ephemeris::Ephemeris(const ghoul::Dictionary& dictionary) {}
|
||||
|
||||
Ephemeris::~Ephemeris() {}
|
||||
|
||||
bool Ephemeris::initialize() {
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
#include <openspace/util/factorymanager.h>
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
|
||||
#include <openspace/documentation/verifier.h>
|
||||
|
||||
namespace {
|
||||
const std::string _loggerCat = "Rotation";
|
||||
const std::string KeyType = "Type";
|
||||
@@ -33,16 +35,31 @@ namespace {
|
||||
|
||||
namespace openspace {
|
||||
|
||||
Rotation* Rotation::createFromDictionary(const ghoul::Dictionary& dictionary) {
|
||||
if (!dictionary.hasValue<std::string>(KeyType)) {
|
||||
LERROR("Ephemeris did not have key '" << KeyType << "'");
|
||||
return nullptr;
|
||||
}
|
||||
Documentation Rotation::Documentation() {
|
||||
using namespace openspace::documentation;
|
||||
|
||||
std::string rotationType;
|
||||
dictionary.getValue(KeyType, rotationType);
|
||||
ghoul::TemplateFactory<Rotation>* factory
|
||||
= FactoryManager::ref().factory<Rotation>();
|
||||
return {
|
||||
"Transformation Rotation",
|
||||
"core_transform_rotation",
|
||||
{
|
||||
{
|
||||
KeyType,
|
||||
new StringAnnotationVerifier("Must name a valid Rotation type."),
|
||||
"The type of the rotation that is described in this element. The "
|
||||
"available types of rotations depend on the configuration of the "
|
||||
"application and can be written to disk on application startup into the "
|
||||
"FactoryDocumentation.",
|
||||
Optional::No
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Rotation* Rotation::createFromDictionary(const ghoul::Dictionary& dictionary) {
|
||||
documentation::testSpecificationAndThrow(Documentation(), dictionary, "Rotation");
|
||||
|
||||
std::string rotationType = dictionary.value<std::string>(KeyType);
|
||||
auto factory = FactoryManager::ref().factory<Rotation>();
|
||||
Rotation* result = factory->create(rotationType, dictionary);
|
||||
if (result == nullptr) {
|
||||
LERROR("Failed creating Rotation object of type '" << rotationType << "'");
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
#include <openspace/util/factorymanager.h>
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
|
||||
#include <openspace/documentation/verifier.h>
|
||||
|
||||
namespace {
|
||||
const std::string _loggerCat = "Scale";
|
||||
const std::string KeyType = "Type";
|
||||
@@ -33,16 +35,34 @@ namespace {
|
||||
|
||||
namespace openspace {
|
||||
|
||||
Scale* Scale::createFromDictionary(const ghoul::Dictionary& dictionary) {
|
||||
if (!dictionary.hasValue<std::string>(KeyType)) {
|
||||
LERROR("Ephemeris did not have key '" << KeyType << "'");
|
||||
return nullptr;
|
||||
}
|
||||
Documentation Scale::Documentation() {
|
||||
using namespace openspace::documentation;
|
||||
|
||||
std::string scaleType;
|
||||
dictionary.getValue(KeyType, scaleType);
|
||||
ghoul::TemplateFactory<Scale>* factory
|
||||
= FactoryManager::ref().factory<Scale>();
|
||||
return {
|
||||
"Transformation Scaling",
|
||||
"core_transform_scaling",
|
||||
{
|
||||
{
|
||||
KeyType,
|
||||
new StringAnnotationVerifier("Must name a valid Scale type"),
|
||||
"The type of the scaling that is described in this element. "
|
||||
"The available types of scaling depend on the configuration "
|
||||
"of the application and can be written to disk on "
|
||||
"application startup into the FactoryDocumentation.",
|
||||
Optional::No
|
||||
}
|
||||
},
|
||||
Exhaustive::No
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Scale* Scale::createFromDictionary(const ghoul::Dictionary& dictionary) {
|
||||
documentation::testSpecificationAndThrow(Documentation(), dictionary, "Scale");
|
||||
|
||||
std::string scaleType = dictionary.value<std::string>(KeyType);
|
||||
|
||||
auto factory = FactoryManager::ref().factory<Scale>();
|
||||
Scale* result = factory->create(scaleType, dictionary);
|
||||
if (result == nullptr) {
|
||||
LERROR("Failed creating Scale object of type '" << scaleType << "'");
|
||||
@@ -52,10 +72,6 @@ Scale* Scale::createFromDictionary(const ghoul::Dictionary& dictionary) {
|
||||
return result;
|
||||
}
|
||||
|
||||
Scale::Scale() {}
|
||||
|
||||
Scale::Scale(const ghoul::Dictionary& dictionary) {}
|
||||
|
||||
Scale::~Scale() {}
|
||||
|
||||
bool Scale::initialize() {
|
||||
|
||||
@@ -55,12 +55,12 @@
|
||||
#include <modules/onscreengui/include/gui.h>
|
||||
#endif
|
||||
|
||||
#include "scene_doc.inl"
|
||||
#include "scene_lua.inl"
|
||||
|
||||
namespace {
|
||||
const std::string _loggerCat = "Scene";
|
||||
const std::string _moduleExtension = ".mod";
|
||||
const std::string _defaultCommonDirectory = "common";
|
||||
const std::string _commonModuleToken = "${COMMON_MODULE}";
|
||||
|
||||
const std::string KeyCamera = "Camera";
|
||||
@@ -98,15 +98,23 @@ void Scene::update(const UpdateData& data) {
|
||||
OsEng.interactionHandler().setInteractionMode("Orbital");
|
||||
|
||||
// After loading the scene, the keyboard bindings have been set
|
||||
|
||||
const std::string KeyboardShortcutsType =
|
||||
ConfigurationManager::KeyKeyboardShortcuts + "." +
|
||||
ConfigurationManager::PartType;
|
||||
|
||||
const std::string KeyboardShortcutsFile =
|
||||
ConfigurationManager::KeyKeyboardShortcuts + "." +
|
||||
ConfigurationManager::PartFile;
|
||||
|
||||
|
||||
std::string type;
|
||||
std::string file;
|
||||
bool hasType = OsEng.configurationManager().getValue(
|
||||
ConfigurationManager::KeyKeyboardShortcutsType, type
|
||||
KeyboardShortcutsType, type
|
||||
);
|
||||
|
||||
bool hasFile = OsEng.configurationManager().getValue(
|
||||
ConfigurationManager::KeyKeyboardShortcutsFile, file
|
||||
KeyboardShortcutsFile, file
|
||||
);
|
||||
|
||||
if (hasType && hasFile) {
|
||||
@@ -189,6 +197,14 @@ bool Scene::loadSceneInternal(const std::string& sceneDescriptionFilePath) {
|
||||
state
|
||||
);
|
||||
|
||||
// Perform testing against the documentation/specification
|
||||
openspace::documentation::testSpecificationAndThrow(
|
||||
Scene::Documentation(),
|
||||
dictionary,
|
||||
"Scene"
|
||||
);
|
||||
|
||||
|
||||
_graph.loadFromFile(sceneDescriptionFilePath);
|
||||
|
||||
// Initialize all nodes
|
||||
@@ -213,7 +229,7 @@ bool Scene::loadSceneInternal(const std::string& sceneDescriptionFilePath) {
|
||||
glm::dvec3(0),
|
||||
glm::dmat3(1),
|
||||
1,
|
||||
Time::ref().currentTime() });
|
||||
Time::ref().j2000Seconds() });
|
||||
}
|
||||
catch (const ghoul::RuntimeError& e) {
|
||||
LERRORC(e.component, e.message);
|
||||
@@ -230,13 +246,21 @@ bool Scene::loadSceneInternal(const std::string& sceneDescriptionFilePath) {
|
||||
}
|
||||
|
||||
// If a PropertyDocumentationFile was specified, generate it now
|
||||
const bool hasType = OsEng.configurationManager().hasKey(ConfigurationManager::KeyPropertyDocumentationType);
|
||||
const bool hasFile = OsEng.configurationManager().hasKey(ConfigurationManager::KeyPropertyDocumentationFile);
|
||||
const std::string KeyPropertyDocumentationType =
|
||||
ConfigurationManager::KeyPropertyDocumentation + '.' +
|
||||
ConfigurationManager::PartType;
|
||||
|
||||
const std::string KeyPropertyDocumentationFile =
|
||||
ConfigurationManager::KeyPropertyDocumentation + '.' +
|
||||
ConfigurationManager::PartFile;
|
||||
|
||||
const bool hasType = OsEng.configurationManager().hasKey(KeyPropertyDocumentationType);
|
||||
const bool hasFile = OsEng.configurationManager().hasKey(KeyPropertyDocumentationFile);
|
||||
if (hasType && hasFile) {
|
||||
std::string propertyDocumentationType;
|
||||
OsEng.configurationManager().getValue(ConfigurationManager::KeyPropertyDocumentationType, propertyDocumentationType);
|
||||
OsEng.configurationManager().getValue(KeyPropertyDocumentationType, propertyDocumentationType);
|
||||
std::string propertyDocumentationFile;
|
||||
OsEng.configurationManager().getValue(ConfigurationManager::KeyPropertyDocumentationFile, propertyDocumentationFile);
|
||||
OsEng.configurationManager().getValue(KeyPropertyDocumentationFile, propertyDocumentationFile);
|
||||
|
||||
propertyDocumentationFile = absPath(propertyDocumentationFile);
|
||||
writePropertyDocumentation(propertyDocumentationFile, propertyDocumentationType);
|
||||
@@ -414,13 +438,11 @@ SceneGraph& Scene::sceneGraph() {
|
||||
}
|
||||
|
||||
void Scene::writePropertyDocumentation(const std::string& filename, const std::string& type) {
|
||||
LDEBUG("Writing documentation for properties");
|
||||
if (type == "text") {
|
||||
LDEBUG("Writing documentation for properties");
|
||||
std::ofstream file(filename);
|
||||
if (!file.good()) {
|
||||
LERROR("Could not open file '" << filename << "' for writing property documentation");
|
||||
return;
|
||||
}
|
||||
std::ofstream file;
|
||||
file.exceptions(~std::ofstream::goodbit);
|
||||
file.open(filename);
|
||||
|
||||
using properties::Property;
|
||||
for (SceneGraphNode* node : _graph.nodes()) {
|
||||
@@ -429,13 +451,100 @@ void Scene::writePropertyDocumentation(const std::string& filename, const std::s
|
||||
file << node->name() << std::endl;
|
||||
|
||||
for (Property* p : properties) {
|
||||
file << p->fullyQualifiedIdentifier() << ": " << p->guiName() << std::endl;
|
||||
file << p->fullyQualifiedIdentifier() << ": " <<
|
||||
p->guiName() << std::endl;
|
||||
}
|
||||
|
||||
file << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (type == "html") {
|
||||
std::ofstream file;
|
||||
file.exceptions(~std::ofstream::goodbit);
|
||||
file.open(filename);
|
||||
|
||||
#ifdef JSON
|
||||
// Create JSON
|
||||
std::function<std::string(properties::PropertyOwner*)> createJson =
|
||||
[&createJson](properties::PropertyOwner* owner) -> std::string
|
||||
{
|
||||
std::stringstream json;
|
||||
json << "{";
|
||||
json << "\"name\": \"" << owner->name() << "\",";
|
||||
|
||||
json << "\"properties\": [";
|
||||
for (properties::Property* p : owner->properties()) {
|
||||
json << "{";
|
||||
json << "\"id\": \"" << p->identifier() << "\",";
|
||||
json << "\"type\": \"" << p->className() << "\",";
|
||||
json << "\"fullyQualifiedId\": \"" << p->fullyQualifiedIdentifier() << "\",";
|
||||
json << "\"guiName\": \"" << p->guiName() << "\",";
|
||||
json << "},";
|
||||
}
|
||||
json << "],";
|
||||
|
||||
json << "\"propertyOwner\": [";
|
||||
for (properties::PropertyOwner* o : owner->propertySubOwners()) {
|
||||
json << createJson(o);
|
||||
}
|
||||
json << "],";
|
||||
json << "},";
|
||||
|
||||
return json.str();
|
||||
};
|
||||
|
||||
|
||||
std::stringstream json;
|
||||
json << "[";
|
||||
for (SceneGraphNode* node : _graph.nodes()) {
|
||||
json << createJson(node);
|
||||
}
|
||||
|
||||
json << "]";
|
||||
|
||||
std::string jsonText = json.str();
|
||||
#else
|
||||
std::stringstream html;
|
||||
html << "<html>\n"
|
||||
<< "\t<head>\n"
|
||||
<< "\t\t<title>Properties</title>\n"
|
||||
<< "\t</head>\n"
|
||||
<< "<body>\n"
|
||||
<< "<table cellpadding=3 cellspacing=0 border=1>\n"
|
||||
<< "\t<caption>Properties</caption>\n\n"
|
||||
<< "\t<thead>\n"
|
||||
<< "\t\t<tr>\n"
|
||||
<< "\t\t\t<th>ID</th>\n"
|
||||
<< "\t\t\t<th>Type</th>\n"
|
||||
<< "\t\t\t<th>Description</th>\n"
|
||||
<< "\t\t</tr>\n"
|
||||
<< "\t</thead>\n"
|
||||
<< "\t<tbody>\n";
|
||||
|
||||
for (SceneGraphNode* node : _graph.nodes()) {
|
||||
for (properties::Property* p : node->propertiesRecursive()) {
|
||||
html << "\t\t<tr>\n"
|
||||
<< "\t\t\t<td>" << p->fullyQualifiedIdentifier() << "</td>\n"
|
||||
<< "\t\t\t<td>" << p->className() << "</td>\n"
|
||||
<< "\t\t\t<td>" << p->guiName() << "</td>\n"
|
||||
<< "\t\t</tr>\n";
|
||||
}
|
||||
|
||||
if (!node->propertiesRecursive().empty()) {
|
||||
html << "\t<tr><td style=\"line-height: 10px;\" colspan=3></td></tr>\n";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
html << "\t</tbody>\n"
|
||||
<< "</table>\n"
|
||||
<< "</html>;";
|
||||
|
||||
file << html.str();
|
||||
#endif
|
||||
|
||||
}
|
||||
else
|
||||
LERROR("Undefined type '" << type << "' for Property documentation");
|
||||
}
|
||||
@@ -455,6 +564,7 @@ scripting::LuaLibrary Scene::luaLibrary() {
|
||||
{
|
||||
"setPropertyValueRegex",
|
||||
&luascriptfunctions::property_setValueRegex,
|
||||
"string, *",
|
||||
"Sets all properties that pass the regular expression in the first "
|
||||
"argument. The second argument can be any type, but it has to match the "
|
||||
"type of the properties that matched the regular expression. The regular "
|
||||
|
||||
95
src/scene/scene_doc.inl
Normal file
95
src/scene/scene_doc.inl
Normal file
@@ -0,0 +1,95 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2016 *
|
||||
* *
|
||||
* 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/documentation/verifier.h>
|
||||
|
||||
namespace openspace {
|
||||
|
||||
Documentation Scene::Documentation() {
|
||||
using namespace documentation;
|
||||
|
||||
return {
|
||||
"Scene Description",
|
||||
{
|
||||
{
|
||||
"ScenePath",
|
||||
new StringVerifier,
|
||||
"The path to the base directory of the scene. The path is considered "
|
||||
"relative to the location of the scene description file.",
|
||||
Optional::Yes
|
||||
},
|
||||
{
|
||||
"CommonFolder",
|
||||
new StringAnnotationVerifier("A valid scene module folder"),
|
||||
"The path to the common folder that is loaded and will be bound to the "
|
||||
"${COMMON_MODULE} path token so that assets can be reused easily.",
|
||||
Optional::Yes
|
||||
},
|
||||
{
|
||||
"Camera",
|
||||
new TableVerifier({
|
||||
{
|
||||
"Focus",
|
||||
new StringAnnotationVerifier("A valid object in the scene"),
|
||||
"The initial focus node of the camera, i.e., the node around which "
|
||||
"the interaction will be performed."
|
||||
},
|
||||
{
|
||||
"Position",
|
||||
new DoubleVector3Verifier,
|
||||
"The initial camera positive relative to the focus object.",
|
||||
Optional::Yes
|
||||
},
|
||||
{
|
||||
"Rotation",
|
||||
new DoubleVector4Verifier,
|
||||
"The initial camera rotation expressed as a quaternion.",
|
||||
Optional::Yes
|
||||
}
|
||||
}),
|
||||
"Definitions of the camera starting parameters, such as focus, location, and "
|
||||
"orientation.",
|
||||
Optional::Yes
|
||||
},
|
||||
{
|
||||
"Modules",
|
||||
new TableVerifier({
|
||||
{ "*", new StringAnnotationVerifier(
|
||||
"Loadable module folders. This means that they either have to point "
|
||||
"to a folder that contains a ModuleFile or a folder which contains "
|
||||
"other folders that eventually contain ModuleFile. This second "
|
||||
"recursive approach is useful for grouping modules into logical "
|
||||
"units."
|
||||
)}
|
||||
}),
|
||||
"This is the list of modules that will be loaded into the initial scene. The "
|
||||
"values in this table have to correspond to folders relative to the "
|
||||
"ScenePath key. The order in which the modules are loaded is the same as the "
|
||||
"order in which they are specified in this table."
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
@@ -310,6 +310,7 @@ bool SceneGraph::loadFromFile(const std::string& sceneDescription) {
|
||||
element.getValue(SceneGraphNode::KeyParentName, parentName);
|
||||
|
||||
FileSys.setCurrentDirectory(modulePath);
|
||||
LDEBUGC("Create from dictionary", "Node name: " << nodeName << " Parent name:" << parentName << " Path: " << modulePath);
|
||||
SceneGraphNode* node = SceneGraphNode::createFromDictionary(element);
|
||||
if (node == nullptr) {
|
||||
LERROR("Error loading SceneGraphNode '" << nodeName << "' in module '" << moduleName << "'");
|
||||
@@ -344,7 +345,17 @@ bool SceneGraph::loadFromFile(const std::string& sceneDescription) {
|
||||
};
|
||||
|
||||
for (const ModuleInformation& i : moduleDictionaries) {
|
||||
addModule(i);
|
||||
try {
|
||||
LINFO("Adding module: " << i.moduleName);
|
||||
addModule(i);
|
||||
}
|
||||
catch (const documentation::SpecificationError& specError) {
|
||||
LERROR("Error loading module: " << i.moduleName);
|
||||
LERRORC(specError.component, specError.message);
|
||||
for (const auto& offense : specError.result.offenses) {
|
||||
LERRORC(offense.offender, std::to_string(offense.reason));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// ghoul::lua::destroyLuaState(state);
|
||||
|
||||
@@ -24,6 +24,9 @@
|
||||
|
||||
// open space includes
|
||||
#include <openspace/scene/scenegraphnode.h>
|
||||
|
||||
#include <openspace/documentation/documentation.h>
|
||||
|
||||
#include <openspace/query/query.h>
|
||||
#include <openspace/util/spicemanager.h>
|
||||
#include <openspace/util/time.h>
|
||||
@@ -46,6 +49,8 @@
|
||||
#include <cctype>
|
||||
#include <chrono>
|
||||
|
||||
#include "scenegraphnode_doc.inl"
|
||||
|
||||
namespace {
|
||||
const std::string _loggerCat = "SceneGraphNode";
|
||||
const std::string KeyRenderable = "Renderable";
|
||||
@@ -63,8 +68,13 @@ const std::string SceneGraphNode::KeyName = "Name";
|
||||
const std::string SceneGraphNode::KeyParentName = "Parent";
|
||||
const std::string SceneGraphNode::KeyDependencies = "Dependencies";
|
||||
|
||||
SceneGraphNode* SceneGraphNode::createFromDictionary(const ghoul::Dictionary& dictionary)
|
||||
{
|
||||
SceneGraphNode* SceneGraphNode::createFromDictionary(const ghoul::Dictionary& dictionary){
|
||||
openspace::documentation::testSpecificationAndThrow(
|
||||
SceneGraphNode::Documentation(),
|
||||
dictionary,
|
||||
"SceneGraphNode"
|
||||
);
|
||||
|
||||
SceneGraphNode* result = new SceneGraphNode;
|
||||
|
||||
if (!dictionary.hasValue<std::string>(KeyName)) {
|
||||
@@ -343,12 +353,20 @@ void SceneGraphNode::render(const RenderData& data, RendererTasks& tasks) {
|
||||
data.camera,
|
||||
thisPositionPSC,
|
||||
data.doPerformanceMeasurement,
|
||||
data.renderBinMask,
|
||||
_worldPositionCached,
|
||||
_worldRotationCached,
|
||||
_worldScaleCached};
|
||||
|
||||
_performanceRecord.renderTime = 0;
|
||||
if (_renderableVisible && _renderable->isVisible() && _renderable->isReady() && _renderable->isEnabled()) {
|
||||
|
||||
bool visible = _renderableVisible &&
|
||||
_renderable->isVisible() &&
|
||||
_renderable->isReady() &&
|
||||
_renderable->isEnabled() &&
|
||||
_renderable->matchesRenderBinMask(data.renderBinMask);
|
||||
|
||||
if (visible) {
|
||||
if (data.doPerformanceMeasurement) {
|
||||
glFinish();
|
||||
auto start = std::chrono::high_resolution_clock::now();
|
||||
@@ -371,7 +389,7 @@ void SceneGraphNode::render(const RenderData& data, RendererTasks& tasks) {
|
||||
|
||||
void SceneGraphNode::postRender(const RenderData& data) {
|
||||
const psc thisPosition = psc::CreatePowerScaledCoordinate(_worldPositionCached.x, _worldPositionCached.y, _worldPositionCached.z);
|
||||
RenderData newData = { data.camera, thisPosition, data.doPerformanceMeasurement, _worldPositionCached};
|
||||
RenderData newData = { data.camera, thisPosition, data.doPerformanceMeasurement, data.renderBinMask, _worldPositionCached};
|
||||
|
||||
_performanceRecord.renderTime = 0;
|
||||
if (_renderableVisible && _renderable->isVisible() && _renderable->isReady() && _renderable->isEnabled()) {
|
||||
@@ -584,7 +602,7 @@ SceneGraphNode* SceneGraphNode::childNode(const std::string& name)
|
||||
|
||||
void SceneGraphNode::updateCamera(Camera* camera) const{
|
||||
|
||||
psc origin = worldPosition();
|
||||
psc origin(worldPosition());
|
||||
//int i = 0;
|
||||
// the camera position
|
||||
|
||||
|
||||
102
src/scene/scenegraphnode_doc.inl
Normal file
102
src/scene/scenegraphnode_doc.inl
Normal file
@@ -0,0 +1,102 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2016 *
|
||||
* *
|
||||
* 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/documentation/verifier.h>
|
||||
|
||||
namespace openspace {
|
||||
|
||||
Documentation SceneGraphNode::Documentation() {
|
||||
using namespace documentation;
|
||||
|
||||
return {
|
||||
"Scenegraph Node",
|
||||
{
|
||||
{
|
||||
"Name",
|
||||
new StringVerifier,
|
||||
"The name of this scenegraph node. This name must be unique among all scene "
|
||||
"graph nodes that are loaded in a specific scene. If a duplicate is detected "
|
||||
"the loading of the node will fail, as will all childing that depend on the "
|
||||
"node."
|
||||
},
|
||||
{
|
||||
"Parent",
|
||||
new StringAnnotationVerifier(
|
||||
"Must be a name for another scenegraph node, or 'Root'"
|
||||
),
|
||||
"This names the parent of the currently specified scenegraph node. The "
|
||||
"parent must not have been defined earlier, but must exist at loading time, "
|
||||
"or the scenegraph node creation will fail. A special parent 'Root' is "
|
||||
"available that denotes the root of the scenegraph."
|
||||
},
|
||||
{
|
||||
"Renderable",
|
||||
new ReferencingVerifier("renderable"),
|
||||
"The renderable that is to be created for this scenegraph node. A renderable "
|
||||
"is a component of a scenegraph node that will lead to some visual result on "
|
||||
"the screen. The specifics heavily depend on the 'Type' of the renderable. "
|
||||
"If no Renderable is specified, this scenegraph node is an internal node and "
|
||||
"can be used for either group children, or apply common transformations to a "
|
||||
"group of children.",
|
||||
Optional::Yes
|
||||
},
|
||||
{
|
||||
"Transform",
|
||||
new TableVerifier({
|
||||
{
|
||||
"Translation",
|
||||
new ReferencingVerifier("core_transform_translation"),
|
||||
"This node describes a translation that is applied to the scenegraph "
|
||||
"node and all its children. Depending on the 'Type' of the "
|
||||
"translation, this can either be a static translation or a "
|
||||
"time-varying one.",
|
||||
Optional::Yes
|
||||
},
|
||||
{
|
||||
"Rotation",
|
||||
new ReferencingVerifier("core_transform_rotation"),
|
||||
"This nodes describes a rotation that is applied to the scenegraph "
|
||||
"node and all its children. Depending on the 'Type' of the rotation, "
|
||||
"this can either be a static rotation or a time-varying one.",
|
||||
Optional::Yes
|
||||
},
|
||||
{
|
||||
"Scale",
|
||||
new ReferencingVerifier("core_transform_scaling"),
|
||||
"This node describes a scaling that is applied to the scenegraph "
|
||||
"node and all its children. Depending on the 'Type' of the scaling, "
|
||||
"this can either be a static scaling or a time-varying one.",
|
||||
Optional::Yes
|
||||
}
|
||||
}),
|
||||
"This describes a set of transformations that are applied to this scenegraph "
|
||||
"node and all of its children. There are only three possible values "
|
||||
"corresponding to a 'Translation', a 'Rotation', and a 'Scale'.",
|
||||
Optional::Yes
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <ghoul/filesystem/filesystem.h>
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <ghoul/lua/lua_helper.h>
|
||||
#include <ghoul/misc/exception.h>
|
||||
|
||||
#include <openspace/engine/configurationmanager.h>
|
||||
#include <openspace/engine/openspaceengine.h>
|
||||
@@ -51,7 +52,6 @@ namespace {
|
||||
//const lua_CFunction _printFunctionReplacement = luascriptfunctions::printInfo;
|
||||
|
||||
const int _setTableOffset = -3; // -1 (top) -1 (first argument) -1 (second argument)
|
||||
|
||||
}
|
||||
|
||||
void ScriptEngine::initialize() {
|
||||
@@ -479,41 +479,36 @@ std::vector<std::string> ScriptEngine::allLuaFunctions() const {
|
||||
return result;
|
||||
}
|
||||
|
||||
bool ScriptEngine::writeDocumentation(const std::string& filename, const std::string& type) const {
|
||||
if (type == "text") {
|
||||
// The additional space between the longest function name and the descriptions
|
||||
LDEBUG("Writing Lua documentation of type '" << type <<
|
||||
"' to file '" << filename << "'");
|
||||
std::ofstream file(filename);
|
||||
if (!file.good()) {
|
||||
LERROR("Could not open file '" << filename << "' for writing documentation");
|
||||
return false;
|
||||
void ScriptEngine::writeDocumentation(const std::string& filename, const std::string& type) const {
|
||||
auto concatenate = [](std::string library, std::string function) {
|
||||
std::string total = "openspace.";
|
||||
if (!library.empty()) {
|
||||
total += std::move(library) + ".";
|
||||
}
|
||||
total += std::move(function);
|
||||
return total;
|
||||
};
|
||||
|
||||
auto concatenate = [](std::string library, std::string function) {
|
||||
std::string total = "openspace.";
|
||||
if (!library.empty())
|
||||
total += std::move(library) + ".";
|
||||
total += std::move(function);
|
||||
return total;
|
||||
};
|
||||
|
||||
LDEBUG("Writing Lua documentation of type '" << type <<
|
||||
"' to file '" << filename << "'");
|
||||
if (type == "text") {
|
||||
// Settings
|
||||
const unsigned int lineWidth = 80;
|
||||
static const std::string whitespace = " \t";
|
||||
static const std::string padding = " ";
|
||||
const bool commandListArguments = true;
|
||||
|
||||
// The additional space between the longest function name and the descriptions
|
||||
|
||||
std::ofstream file;
|
||||
file.exceptions(~std::ofstream::goodbit);
|
||||
file.open(filename);
|
||||
|
||||
file << "Available commands:\n";
|
||||
// Now write out the functions
|
||||
for (const LuaLibrary& library : _registeredLibraries) {
|
||||
for (const LuaLibrary::Function& function : library.functions) {
|
||||
|
||||
std::string functionName = concatenate(library.name, function.name);
|
||||
file << padding << functionName;
|
||||
if (commandListArguments)
|
||||
file << "(" << function.argumentText << ")";
|
||||
file << std::endl;
|
||||
for (const LuaLibrary& l : _registeredLibraries) {
|
||||
for (const LuaLibrary::Function& f : l.functions) {
|
||||
std::string name = concatenate(l.name, f.name);
|
||||
file << padding << name << "(" << f.argumentText << ")" << std::endl;
|
||||
}
|
||||
}
|
||||
file << std::endl;
|
||||
@@ -521,24 +516,32 @@ bool ScriptEngine::writeDocumentation(const std::string& filename, const std::st
|
||||
// Now write out the functions definitions
|
||||
for (const LuaLibrary& library : _registeredLibraries) {
|
||||
for (const LuaLibrary::Function& function : library.functions) {
|
||||
|
||||
std::string functionName = concatenate(library.name, function.name);
|
||||
file << functionName << "(" << function.argumentText << "):" << std::endl;
|
||||
std::string name = concatenate(library.name, function.name);
|
||||
file << name << "(" << function.argumentText << "):" << std::endl;
|
||||
|
||||
std::string remainingHelptext = function.helpText;
|
||||
|
||||
// @CLEANUP This needs to become a bit prettier ---abock
|
||||
while (!remainingHelptext.empty()) {
|
||||
const auto length = remainingHelptext.length();
|
||||
const auto paddingLength = padding.length();
|
||||
const size_t length = remainingHelptext.length();
|
||||
const size_t paddingLength = padding.length();
|
||||
|
||||
if ((length + paddingLength) > lineWidth) {
|
||||
auto lastSpace = remainingHelptext.find_last_of(whitespace, lineWidth - 1 - paddingLength);
|
||||
if (lastSpace == remainingHelptext.npos)
|
||||
size_t lastSpace = remainingHelptext.find_last_of(
|
||||
whitespace,
|
||||
lineWidth - 1 - paddingLength
|
||||
);
|
||||
if (lastSpace == remainingHelptext.npos) {
|
||||
lastSpace = lineWidth;
|
||||
file << padding << remainingHelptext.substr(0, lastSpace) << std::endl;
|
||||
auto firstNotSpace = remainingHelptext.find_first_not_of(whitespace, lastSpace);
|
||||
if (firstNotSpace == remainingHelptext.npos)
|
||||
}
|
||||
|
||||
file << padding << remainingHelptext.substr(0, lastSpace) << '\n';
|
||||
|
||||
size_t firstNotSpace = remainingHelptext.find_first_not_of(
|
||||
whitespace,
|
||||
lastSpace
|
||||
);
|
||||
if (firstNotSpace == remainingHelptext.npos) {
|
||||
firstNotSpace = lastSpace;
|
||||
}
|
||||
remainingHelptext = remainingHelptext.substr(firstNotSpace);
|
||||
}
|
||||
else {
|
||||
@@ -549,27 +552,115 @@ bool ScriptEngine::writeDocumentation(const std::string& filename, const std::st
|
||||
file << std::endl;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if (type == "html") {
|
||||
std::ofstream file;
|
||||
file.exceptions(~std::ofstream::goodbit);
|
||||
file.open(filename);
|
||||
|
||||
#ifdef JSON
|
||||
// Create JSON
|
||||
std::stringstream json;
|
||||
json << "[";
|
||||
|
||||
for (const LuaLibrary& l : _registeredLibraries) {
|
||||
json << "{";
|
||||
|
||||
json << "\"library\": \"" << l.name << "\",";
|
||||
json << "\"functions\": [";
|
||||
|
||||
for (const LuaLibrary::Function& f : l.functions) {
|
||||
json << "{";
|
||||
json << "\"name\": \"" << f.name << "\", ";
|
||||
json << "\"arguments\": \"" << f.argumentText << "\", ";
|
||||
json << "\"help\": \"" << f.helpText << "\"";
|
||||
json << "},";
|
||||
}
|
||||
json << "]},";
|
||||
}
|
||||
json << "]";
|
||||
|
||||
|
||||
std::string jsonText = json.str();
|
||||
#else
|
||||
std::stringstream html;
|
||||
|
||||
html << "<html>\n"
|
||||
<< "\t<head>\n"
|
||||
<< "\t\t<title>Script Log</title>\n"
|
||||
<< "\t</head>\n"
|
||||
<< "<body>\n"
|
||||
<< "<table cellpadding=3 cellspacing=0 border=1>\n"
|
||||
<< "\t<caption>Script Log</caption>\n\n"
|
||||
<< "\t<thead>\n"
|
||||
<< "\t\t<tr>\n"
|
||||
<< "\t\t\t<th rowspan=2>Library</th>\n"
|
||||
<< "\t\t\t<th colspan=3>Functions</th>\n"
|
||||
<< "\t\t</tr>\n"
|
||||
<< "\t\t<tr>\n"
|
||||
<< "\t\t\t<th>Name</th>\n"
|
||||
<< "\t\t\t<th>Arguments</th>\n"
|
||||
<< "\t\t\t<th>Help</th>\n"
|
||||
<< "\t\t</tr>\n"
|
||||
<< "\t</thead>\n"
|
||||
<< "\t<tbody>\n";
|
||||
|
||||
|
||||
|
||||
for (const LuaLibrary& l : _registeredLibraries) {
|
||||
html << "\t<tr>\n";
|
||||
|
||||
if (l.name.empty()) {
|
||||
html << "\t\t<td>openspace</td>\n";
|
||||
}
|
||||
else {
|
||||
html << "\t\t<td>openspace." << l.name << "</td>\n";
|
||||
}
|
||||
html << "\t\t<td></td><td></td><td></td>\n"
|
||||
<< "\t\</tr>";
|
||||
|
||||
for (const LuaLibrary::Function& f : l.functions) {
|
||||
html << "\t<tr>\n"
|
||||
<< "\t\t<td></td>\n"
|
||||
<< "\t\t<td>" << f.name << "</td>\n"
|
||||
<< "\t\t<td>" << f.argumentText << "</td>\n"
|
||||
<< "\t\t<td>" << f.helpText << "</td>\n"
|
||||
<< "\t</tr>\n";
|
||||
}
|
||||
|
||||
html << "\t<tr><td style=\"line-height: 10px;\" colspan=4></td></tr>\n";
|
||||
}
|
||||
|
||||
html << "\t</tbody>\n"
|
||||
<< "</table>\n"
|
||||
<< "</html>";
|
||||
|
||||
file << html.str();
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
LERROR("Undefined type '" << type << "' for Lua documentation");
|
||||
return false;
|
||||
throw ghoul::RuntimeError("Undefined type '" + type + "' for Lua documentation");
|
||||
}
|
||||
}
|
||||
|
||||
bool ScriptEngine::writeLog(const std::string& script) {
|
||||
const std::string KeyScriptLogType =
|
||||
ConfigurationManager::KeyScriptLog + '.' + ConfigurationManager::PartType;
|
||||
const std::string KeyScriptLogFile =
|
||||
ConfigurationManager::KeyScriptLog + '.' + ConfigurationManager::PartFile;
|
||||
|
||||
// Check that logging is enabled and initialize if necessary
|
||||
if (!_logFileExists) {
|
||||
// If a ScriptLogFile was specified, generate it now
|
||||
const bool hasType = OsEng.configurationManager()
|
||||
.hasKey(ConfigurationManager::KeyScriptLogType);
|
||||
.hasKey(KeyScriptLogType);
|
||||
const bool hasFile = OsEng.configurationManager()
|
||||
.hasKey(ConfigurationManager::KeyScriptLogFile);
|
||||
.hasKey(KeyScriptLogFile);
|
||||
if (hasType && hasFile) {
|
||||
OsEng.configurationManager()
|
||||
.getValue(ConfigurationManager::KeyScriptLogType, _logType);
|
||||
.getValue(KeyScriptLogType, _logType);
|
||||
OsEng.configurationManager()
|
||||
.getValue(ConfigurationManager::KeyScriptLogFile, _logFilename);
|
||||
.getValue(KeyScriptLogFile, _logFilename);
|
||||
|
||||
_logFilename = absPath(_logFilename);
|
||||
_logFileExists = true;
|
||||
@@ -588,8 +679,8 @@ bool ScriptEngine::writeLog(const std::string& script) {
|
||||
}
|
||||
} else {
|
||||
LDEBUG("No script log specified in 'openspace.cfg.' To log, set '"
|
||||
<< ConfigurationManager::KeyScriptLogType << " and "
|
||||
<< ConfigurationManager::KeyScriptLogFile
|
||||
<< KeyScriptLogType << " and "
|
||||
<< KeyScriptLogFile
|
||||
<< " in configuration table.");
|
||||
_logScripts = false;
|
||||
return false;
|
||||
@@ -616,51 +707,16 @@ bool ScriptEngine::writeLog(const std::string& script) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void ScriptEngine::serialize(SyncBuffer* syncBuffer){
|
||||
syncBuffer->encode(_currentSyncedScript);
|
||||
_currentSyncedScript.clear();
|
||||
}
|
||||
|
||||
void ScriptEngine::deserialize(SyncBuffer* syncBuffer){
|
||||
syncBuffer->decode(_currentSyncedScript);
|
||||
|
||||
if (!_currentSyncedScript.empty()){
|
||||
_mutex.lock();
|
||||
_receivedScripts.push_back(_currentSyncedScript);
|
||||
_mutex.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptEngine::postSynchronizationPreDraw() {
|
||||
std::vector<std::string> scripts;
|
||||
void ScriptEngine::presync(bool isMaster) {
|
||||
if (!isMaster) return;
|
||||
|
||||
_mutex.lock();
|
||||
scripts.assign(_receivedScripts.begin(), _receivedScripts.end());
|
||||
_receivedScripts.clear();
|
||||
_mutex.unlock();
|
||||
|
||||
while (!scripts.empty()) {
|
||||
try {
|
||||
runScript(scripts.back());
|
||||
}
|
||||
catch (const ghoul::RuntimeError& e) {
|
||||
LERRORC(e.component, e.message);
|
||||
}
|
||||
scripts.pop_back();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ScriptEngine::preSynchronization() {
|
||||
|
||||
_mutex.lock();
|
||||
|
||||
if (!_queuedScripts.empty()){
|
||||
if (!_queuedScripts.empty()) {
|
||||
_currentSyncedScript = _queuedScripts.back().first;
|
||||
bool remoteScripting = _queuedScripts.back().second;
|
||||
|
||||
|
||||
|
||||
//Not really a received script but the master also needs to run the script...
|
||||
_receivedScripts.push_back(_currentSyncedScript);
|
||||
_queuedScripts.pop_back();
|
||||
@@ -670,8 +726,43 @@ void ScriptEngine::preSynchronization() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
_mutex.unlock();
|
||||
|
||||
}
|
||||
|
||||
void ScriptEngine::encode(SyncBuffer* syncBuffer) {
|
||||
syncBuffer->encode(_currentSyncedScript);
|
||||
_currentSyncedScript.clear();
|
||||
}
|
||||
|
||||
void ScriptEngine::decode(SyncBuffer* syncBuffer) {
|
||||
syncBuffer->decode(_currentSyncedScript);
|
||||
|
||||
if (!_currentSyncedScript.empty()) {
|
||||
_mutex.lock();
|
||||
_receivedScripts.push_back(_currentSyncedScript);
|
||||
_mutex.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptEngine::postsync(bool isMaster) {
|
||||
std::vector<std::string> scripts;
|
||||
|
||||
_mutex.lock();
|
||||
scripts.assign(_receivedScripts.begin(), _receivedScripts.end());
|
||||
_receivedScripts.clear();
|
||||
_mutex.unlock();
|
||||
|
||||
while (!scripts.empty()) {
|
||||
try {
|
||||
runScript(scripts.back());
|
||||
}
|
||||
catch (const ghoul::RuntimeError& e) {
|
||||
LERRORC(e.component, e.message);
|
||||
}
|
||||
scripts.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptEngine::queueScript(const std::string &script, ScriptEngine::RemoteScripting remoteScripting){
|
||||
|
||||
197
src/scripting/scriptscheduler.cpp
Normal file
197
src/scripting/scriptscheduler.cpp
Normal file
@@ -0,0 +1,197 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2016 *
|
||||
* *
|
||||
* 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/scripting/scriptscheduler.h>
|
||||
|
||||
#include <openspace/engine/openspaceengine.h>
|
||||
|
||||
#include <openspace/scripting/scriptengine.h>
|
||||
#include <openspace/util/spicemanager.h> // parse time
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <ghoul/filesystem/filesystem>
|
||||
|
||||
|
||||
namespace openspace {
|
||||
namespace scripting {
|
||||
|
||||
namespace {
|
||||
const std::string _loggerCat = "ScriptScheduler";
|
||||
|
||||
const std::string KEY_TIME = "Time";
|
||||
const std::string KEY_FORWARD_SCRIPT = "ReversibleLuaScript.Forward";
|
||||
const std::string KEY_BACKWARD_SCRIPT = "ReversibleLuaScript.Backward";
|
||||
}
|
||||
|
||||
|
||||
ScheduledScript::ScheduledScript(const ghoul::Dictionary& dict)
|
||||
: ScheduledScript() // default init first
|
||||
{
|
||||
std::string timeStr;
|
||||
if (dict.getValue(KEY_TIME, timeStr)) {
|
||||
time = SpiceManager::ref().ephemerisTimeFromDate(timeStr);
|
||||
|
||||
if (!dict.getValue(KEY_FORWARD_SCRIPT, script.forwardScript)) {
|
||||
LERROR("Unable to read " << KEY_FORWARD_SCRIPT);
|
||||
}
|
||||
if (!dict.getValue(KEY_BACKWARD_SCRIPT, script.backwardScript)) {
|
||||
LERROR("Unable to read " << KEY_BACKWARD_SCRIPT);
|
||||
}
|
||||
}
|
||||
else {
|
||||
LERROR("Unable to read " << KEY_TIME);
|
||||
}
|
||||
}
|
||||
|
||||
bool ScheduledScript::CompareByTime(const ScheduledScript& s1, const ScheduledScript& s2){
|
||||
return s1.time < s2.time;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ScriptScheduler::loadScripts(const std::string& filepath, lua_State* L) {
|
||||
ghoul::Dictionary timedScriptsDict;
|
||||
try {
|
||||
ghoul::lua::loadDictionaryFromFile(absPath(filepath), timedScriptsDict, L);
|
||||
}
|
||||
catch (const ghoul::RuntimeError& e) {
|
||||
LERROR(e.what());
|
||||
return;
|
||||
}
|
||||
loadScripts(timedScriptsDict);
|
||||
}
|
||||
|
||||
void ScriptScheduler::loadScripts(const ghoul::Dictionary& dict) {
|
||||
for (size_t i = 0; i < dict.size(); ++i) {
|
||||
std::string id = std::to_string(i + 1);
|
||||
const ghoul::Dictionary& timedScriptDict = dict.value<ghoul::Dictionary>(id);
|
||||
_scheduledScripts.push_back(ScheduledScript(timedScriptDict));
|
||||
}
|
||||
|
||||
// Sort scripts by time
|
||||
std::stable_sort(_scheduledScripts.begin(), _scheduledScripts.end(), &ScheduledScript::CompareByTime);
|
||||
|
||||
// Ensure _currentIndex and _currentTime is accurate after new scripts was added
|
||||
double lastTime = _currentTime;
|
||||
rewind();
|
||||
progressTo(lastTime);
|
||||
}
|
||||
|
||||
void ScriptScheduler::rewind() {
|
||||
_currentIndex = 0;
|
||||
_currentTime = -DBL_MAX;
|
||||
}
|
||||
|
||||
|
||||
void ScriptScheduler::clearSchedule() {
|
||||
rewind();
|
||||
_scheduledScripts.clear();
|
||||
}
|
||||
|
||||
std::queue<std::string> ScriptScheduler::progressTo(double newTime) {
|
||||
std::queue<std::string> triggeredScripts;
|
||||
if (newTime > _currentTime) {
|
||||
while(_currentIndex < _scheduledScripts.size() && _scheduledScripts[_currentIndex].time <= newTime){
|
||||
triggeredScripts.push(_scheduledScripts[_currentIndex].script.forwardScript);
|
||||
_currentIndex++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
while (0 < _currentIndex && _scheduledScripts[_currentIndex - 1].time > newTime) {
|
||||
triggeredScripts.push(_scheduledScripts[_currentIndex - 1].script.backwardScript);
|
||||
_currentIndex--;
|
||||
}
|
||||
}
|
||||
|
||||
_currentTime = newTime;
|
||||
return triggeredScripts;
|
||||
}
|
||||
|
||||
std::queue<std::string> ScriptScheduler::progressTo(const std::string& timeStr) {
|
||||
return std::move(progressTo(SpiceManager::ref().ephemerisTimeFromDate(timeStr)));
|
||||
}
|
||||
|
||||
double ScriptScheduler::currentTime() const {
|
||||
return _currentTime;
|
||||
};
|
||||
|
||||
const std::vector<ScheduledScript>& ScriptScheduler::allScripts() const {
|
||||
return _scheduledScripts;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// Lua library functions //
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace luascriptfunctions {
|
||||
int loadTimedScripts(lua_State* L) {
|
||||
using ghoul::lua::luaTypeToString;
|
||||
int nArguments = lua_gettop(L);
|
||||
if (nArguments != 1)
|
||||
return luaL_error(L, "Expected %i arguments, got %i", 1, nArguments);
|
||||
|
||||
std::string missionFileName = luaL_checkstring(L, -1);
|
||||
if (missionFileName.empty()) {
|
||||
return luaL_error(L, "filepath string is empty");
|
||||
}
|
||||
|
||||
OsEng.scriptScheduler().loadScripts(missionFileName, L);
|
||||
}
|
||||
|
||||
int clear(lua_State* L) {
|
||||
using ghoul::lua::luaTypeToString;
|
||||
int nArguments = lua_gettop(L);
|
||||
if (nArguments != 0)
|
||||
return luaL_error(L, "Expected %i arguments, got %i", 0, nArguments);
|
||||
|
||||
OsEng.scriptScheduler().clearSchedule();
|
||||
}
|
||||
} // namespace luascriptfunction
|
||||
|
||||
|
||||
|
||||
LuaLibrary ScriptScheduler::luaLibrary() {
|
||||
return {
|
||||
"scriptScheduler",
|
||||
{
|
||||
{
|
||||
"load",
|
||||
&luascriptfunctions::loadTimedScripts,
|
||||
"string",
|
||||
"Load timed scripts from file"
|
||||
},
|
||||
{
|
||||
"clear",
|
||||
&luascriptfunctions::clear,
|
||||
"",
|
||||
"clears all scheduled scripts"
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace scripting
|
||||
|
||||
} // namespace openspace
|
||||
@@ -50,10 +50,11 @@ namespace openspace {
|
||||
: _maxFov(0.f)
|
||||
, _focusPosition()
|
||||
{
|
||||
_scaling.local = glm::vec2(1.f, 0.f);
|
||||
_position.local = Vec3(1.0, 1.0, 1.0);
|
||||
|
||||
_scaling = glm::vec2(1.f, 0.f);
|
||||
_position = Vec3(1.0, 1.0, 1.0);
|
||||
Vec3 eulerAngles(1.0, 1.0, 1.0);
|
||||
_rotation.local = Quat(eulerAngles);
|
||||
_rotation = Quat(eulerAngles);
|
||||
}
|
||||
|
||||
Camera::Camera(const Camera& o)
|
||||
@@ -61,9 +62,9 @@ namespace openspace {
|
||||
, _focusPosition(o._focusPosition)
|
||||
, _cachedViewDirection(o._cachedViewDirection)
|
||||
, _cachedLookupVector(o._cachedLookupVector)
|
||||
, _position(o._position)
|
||||
, _rotation(o._rotation)
|
||||
, _scaling(o._scaling)
|
||||
, _position(o._position)
|
||||
, _maxFov(o._maxFov)
|
||||
{ }
|
||||
|
||||
@@ -72,7 +73,7 @@ namespace openspace {
|
||||
// Mutators
|
||||
void Camera::setPositionVec3(Vec3 pos) {
|
||||
std::lock_guard<std::mutex> _lock(_mutex);
|
||||
_position.local = pos;
|
||||
_position = pos;
|
||||
|
||||
_cachedCombinedViewMatrix.isDirty = true;
|
||||
}
|
||||
@@ -84,7 +85,7 @@ namespace openspace {
|
||||
|
||||
void Camera::setRotation(Quat rotation) {
|
||||
std::lock_guard<std::mutex> _lock(_mutex);
|
||||
_rotation.local = rotation;
|
||||
_rotation = rotation;
|
||||
_cachedViewDirection.isDirty = true;
|
||||
_cachedLookupVector.isDirty = true;
|
||||
_cachedViewRotationMatrix.isDirty = true;
|
||||
@@ -93,7 +94,7 @@ namespace openspace {
|
||||
|
||||
void Camera::setScaling(glm::vec2 scaling) {
|
||||
std::lock_guard<std::mutex> _lock(_mutex);
|
||||
_scaling.local = std::move(scaling);
|
||||
_scaling = std::move(scaling);
|
||||
}
|
||||
|
||||
void Camera::setMaxFov(float fov) {
|
||||
@@ -105,7 +106,7 @@ namespace openspace {
|
||||
// Relative mutators
|
||||
void Camera::rotate(Quat rotation) {
|
||||
std::lock_guard<std::mutex> _lock(_mutex);
|
||||
_rotation.local = rotation * _rotation.local;
|
||||
_rotation = rotation * (glm::dquat)_rotation;
|
||||
|
||||
_cachedViewDirection.isDirty = true;
|
||||
_cachedLookupVector.isDirty = true;
|
||||
@@ -115,11 +116,11 @@ namespace openspace {
|
||||
|
||||
// Accessors
|
||||
const Camera::Vec3& Camera::positionVec3() const {
|
||||
return _position.synced;
|
||||
return _position;
|
||||
}
|
||||
|
||||
const Camera::Vec3& Camera::unsynchedPositionVec3() const {
|
||||
return _position.local;
|
||||
return _position;
|
||||
}
|
||||
|
||||
const Camera::Vec3& Camera::focusPositionVec3() const {
|
||||
@@ -129,7 +130,7 @@ namespace openspace {
|
||||
const Camera::Vec3& Camera::viewDirectionWorldSpace() const {
|
||||
if (_cachedViewDirection.isDirty) {
|
||||
_cachedViewDirection.datum =
|
||||
_rotation.synced * Vec3(_VIEW_DIRECTION_CAMERA_SPACE);
|
||||
(glm::dquat)_rotation * Vec3(_VIEW_DIRECTION_CAMERA_SPACE);
|
||||
_cachedViewDirection.datum = glm::normalize(_cachedViewDirection.datum);
|
||||
_cachedViewDirection.isDirty = true;
|
||||
}
|
||||
@@ -143,7 +144,7 @@ namespace openspace {
|
||||
const Camera::Vec3& Camera::lookUpVectorWorldSpace() const {
|
||||
if (_cachedLookupVector.isDirty) {
|
||||
_cachedLookupVector.datum =
|
||||
_rotation.synced * Vec3(_LOOKUP_VECTOR_CAMERA_SPACE);
|
||||
(glm::dquat)_rotation * Vec3(_LOOKUP_VECTOR_CAMERA_SPACE);
|
||||
_cachedLookupVector.datum = glm::normalize(_cachedLookupVector.datum);
|
||||
_cachedLookupVector.isDirty = true;
|
||||
}
|
||||
@@ -151,7 +152,7 @@ namespace openspace {
|
||||
}
|
||||
|
||||
const glm::vec2& Camera::scaling() const {
|
||||
return _scaling.synced;
|
||||
return _scaling;
|
||||
}
|
||||
|
||||
float Camera::maxFov() const {
|
||||
@@ -168,19 +169,19 @@ namespace openspace {
|
||||
|
||||
const Camera::Mat4& Camera::viewRotationMatrix() const {
|
||||
if (_cachedViewRotationMatrix.isDirty) {
|
||||
_cachedViewRotationMatrix.datum = glm::mat4_cast(glm::inverse(_rotation.synced));
|
||||
_cachedViewRotationMatrix.datum = glm::mat4_cast(glm::inverse((glm::dquat)_rotation));
|
||||
}
|
||||
return _cachedViewRotationMatrix.datum;
|
||||
}
|
||||
|
||||
const Camera::Quat& Camera::rotationQuaternion() const {
|
||||
return _rotation.synced;
|
||||
return _rotation;
|
||||
}
|
||||
|
||||
const Camera::Mat4& Camera::combinedViewMatrix() const {
|
||||
if (_cachedCombinedViewMatrix.isDirty) {
|
||||
Mat4 cameraTranslation =
|
||||
glm::inverse(glm::translate(Mat4(1.0), _position.synced));
|
||||
glm::inverse(glm::translate(Mat4(1.0), (Vec3)_position));
|
||||
_cachedCombinedViewMatrix.datum =
|
||||
Mat4(sgctInternal.viewMatrix()) *
|
||||
Mat4(viewRotationMatrix()) *
|
||||
@@ -190,30 +191,7 @@ namespace openspace {
|
||||
return _cachedCombinedViewMatrix.datum;
|
||||
}
|
||||
|
||||
// Synchronization
|
||||
void Camera::serialize(SyncBuffer* syncBuffer) {
|
||||
std::lock_guard<std::mutex> _lock(_mutex);
|
||||
|
||||
_rotation.serialize(syncBuffer);
|
||||
_position.serialize(syncBuffer);
|
||||
_scaling.serialize(syncBuffer);
|
||||
}
|
||||
|
||||
void Camera::deserialize(SyncBuffer* syncBuffer) {
|
||||
std::lock_guard<std::mutex> _lock(_mutex);
|
||||
|
||||
_rotation.deserialize(syncBuffer);
|
||||
_position.deserialize(syncBuffer);
|
||||
_scaling.deserialize(syncBuffer);
|
||||
}
|
||||
|
||||
void Camera::postSynchronizationPreDraw() {
|
||||
std::lock_guard<std::mutex> _lock(_mutex);
|
||||
|
||||
_rotation.postSynchronizationPreDraw();
|
||||
_position.postSynchronizationPreDraw();
|
||||
_scaling.postSynchronizationPreDraw();
|
||||
|
||||
void Camera::invalidateCache() {
|
||||
_cachedViewDirection.isDirty = true;
|
||||
_cachedLookupVector.isDirty = true;
|
||||
_cachedViewRotationMatrix.isDirty = true;
|
||||
@@ -237,14 +215,6 @@ namespace openspace {
|
||||
setRotation(q);
|
||||
}
|
||||
|
||||
void Camera::preSynchronization() {
|
||||
std::lock_guard<std::mutex> _lock(_mutex);
|
||||
|
||||
_rotation.preSynchronization();
|
||||
_position.preSynchronization();
|
||||
_scaling.preSynchronization();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
// SGCT INTERNAL //
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -287,7 +257,7 @@ namespace openspace {
|
||||
// Deprecated
|
||||
void Camera::setPosition(psc pos) {
|
||||
std::lock_guard<std::mutex> _lock(_mutex);
|
||||
_position.local = pos.dvec3();
|
||||
_position = pos.dvec3();
|
||||
}
|
||||
|
||||
void Camera::setFocusPosition(psc pos) {
|
||||
@@ -296,11 +266,11 @@ namespace openspace {
|
||||
}
|
||||
|
||||
psc Camera::position() const {
|
||||
return psc(_position.synced);
|
||||
return psc((Vec3)_position);
|
||||
}
|
||||
|
||||
psc Camera::unsynchedPosition() const {
|
||||
return psc(_position.local);
|
||||
return psc((Vec3)_position);
|
||||
}
|
||||
|
||||
psc Camera::focusPosition() const {
|
||||
@@ -318,4 +288,9 @@ namespace openspace {
|
||||
const glm::mat4& Camera::viewProjectionMatrix() const {
|
||||
return sgctInternal.viewProjectionMatrix();
|
||||
}
|
||||
|
||||
std::vector<Syncable*> Camera::getSyncables() {
|
||||
return{ &_position, &_rotation, &_scaling };
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
|
||||
#include <ghoul/misc/assert.h>
|
||||
|
||||
#include <fstream>
|
||||
|
||||
namespace openspace {
|
||||
|
||||
FactoryManager* FactoryManager::_manager = nullptr;
|
||||
@@ -57,9 +59,94 @@ FactoryManager& FactoryManager::ref() {
|
||||
return *_manager;
|
||||
}
|
||||
|
||||
void FactoryManager::addFactory(std::unique_ptr<ghoul::TemplateFactoryBase> factory) {
|
||||
void FactoryManager::addFactory(std::unique_ptr<ghoul::TemplateFactoryBase> factory,
|
||||
std::string name
|
||||
) {
|
||||
ghoul_assert(factory, "Factory must not be nullptr");
|
||||
_factories.push_back(std::move(factory));
|
||||
_factories.push_back({ std::move(factory), std::move(name) });
|
||||
}
|
||||
|
||||
void FactoryManager::writeDocumentation(const std::string& file, const std::string& type) {
|
||||
if (type == "text") {
|
||||
std::ofstream f;
|
||||
f.exceptions(~std::ofstream::goodbit);
|
||||
f.open(file);
|
||||
|
||||
for (const FactoryInfo& factoryInfo : _factories) {
|
||||
f << factoryInfo.name << '\n';
|
||||
|
||||
ghoul::TemplateFactoryBase* factory = factoryInfo.factory.get();
|
||||
for (const std::string& c : factory->registeredClasses()) {
|
||||
f << '\t' << c << '\n';
|
||||
}
|
||||
f << "\n\n";
|
||||
}
|
||||
|
||||
}
|
||||
else if (type == "html") {
|
||||
|
||||
#ifdef JSON
|
||||
std::stringstream json;
|
||||
|
||||
json << "[";
|
||||
for (const FactoryInfo& factoryInfo : _factories) {
|
||||
json << "{";
|
||||
json << "\"name\": \"" << factoryInfo.name << "\",";
|
||||
json << "\"classes\": [";
|
||||
|
||||
ghoul::TemplateFactoryBase* factory = factoryInfo.factory.get();
|
||||
for (const std::string& c : factory->registeredClasses()) {
|
||||
json << "\"" << c << "\",";
|
||||
}
|
||||
|
||||
json << "]},";
|
||||
}
|
||||
|
||||
json << "]";
|
||||
|
||||
// I did not check the output of this for correctness ---abock
|
||||
std::string jsonText = json.str();
|
||||
#else
|
||||
std::ofstream f;
|
||||
f.exceptions(~std::ofstream::goodbit);
|
||||
f.open(file);
|
||||
|
||||
std::stringstream html;
|
||||
html << "<html>\n"
|
||||
<< "\t<head>\n"
|
||||
<< "\t\t<title>Factories</title>\n"
|
||||
<< "\t</head>\n"
|
||||
<< "<body>\n"
|
||||
<< "<table cellpadding=3 cellspacing=0 border=1>\n"
|
||||
<< "\t<caption>Factories</caption>\n\n"
|
||||
<< "\t<thead>\n"
|
||||
<< "\t\t<tr>\n"
|
||||
<< "\t\t\t<th>Type</th>\n"
|
||||
<< "\t\t\t<th>Object</th>\n"
|
||||
<< "\t\t</tr>\n"
|
||||
<< "\t</thead>\n"
|
||||
<< "\t<tbody>\n";
|
||||
|
||||
for (const FactoryInfo& factoryInfo : _factories) {
|
||||
html << "\t\t<tr>\n"
|
||||
<< "\t\t\t<td colspan=2>" << factoryInfo.name << "</td>\n";
|
||||
|
||||
ghoul::TemplateFactoryBase* factory = factoryInfo.factory.get();
|
||||
for (const std::string& c : factory->registeredClasses()) {
|
||||
html << "\t\t\t<tr><td></td><td>" << c << "</td></tr>\n";
|
||||
}
|
||||
html << "\t<tr><td style=\"line-height: 10px;\" colspan=2></td></tr>\n";
|
||||
|
||||
}
|
||||
|
||||
html << "\t</tbody>\n"
|
||||
<< "</table>\n"
|
||||
<< "</html>;";
|
||||
|
||||
f << html.str();
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -63,6 +63,10 @@ void OpenSpaceModule::deinitialize() {
|
||||
internalDeinitialize();
|
||||
}
|
||||
|
||||
std::vector<Documentation> OpenSpaceModule::documentations() const {
|
||||
return {};
|
||||
}
|
||||
|
||||
std::string OpenSpaceModule::modulePath() const {
|
||||
std::string moduleName = name();
|
||||
std::transform(moduleName.begin(), moduleName.end(), moduleName.begin(), tolower);
|
||||
|
||||
@@ -44,8 +44,10 @@ SyncBuffer::~SyncBuffer() {
|
||||
}
|
||||
|
||||
void SyncBuffer::write() {
|
||||
_dataStream.resize(_encodeOffset);
|
||||
_synchronizationBuffer->setVal(_dataStream);
|
||||
sgct::SharedData::instance()->writeVector(_synchronizationBuffer.get());
|
||||
_dataStream.resize(_n);
|
||||
_encodeOffset = 0;
|
||||
_decodeOffset = 0;
|
||||
}
|
||||
|
||||
39
src/util/syncdata.cpp
Normal file
39
src/util/syncdata.cpp
Normal file
@@ -0,0 +1,39 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2016 *
|
||||
* *
|
||||
* 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/engine/openspaceengine.h>
|
||||
#include <openspace/engine/syncengine.h>
|
||||
#include <openspace/util/syncdata.h>
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
|
||||
namespace {
|
||||
const std::string _loggerCat = "SyncData";
|
||||
}
|
||||
|
||||
namespace openspace {
|
||||
|
||||
}
|
||||
@@ -44,38 +44,13 @@ Time* Time::_instance = nullptr;
|
||||
Time::Time(double secondsJ2000)
|
||||
: _time(secondsJ2000)
|
||||
, _dt(1.0)
|
||||
//local copies
|
||||
, _timeJumped(false)
|
||||
, _timePaused(false)
|
||||
, _jockeHasToFixThisLater(false)
|
||||
//shared copies
|
||||
, _sharedTime(-1.0)
|
||||
, _sharedDt(1.0)
|
||||
, _sharedTimeJumped(false)
|
||||
//synced copies
|
||||
, _syncedTime(-1.0)
|
||||
, _syncedDt(1.0)
|
||||
, _syncedTimeJumped(false)
|
||||
{
|
||||
|
||||
}
|
||||
{}
|
||||
|
||||
|
||||
Time::Time(const Time& other)
|
||||
: _time(other._time)
|
||||
, _dt(other._dt)
|
||||
//local copies
|
||||
, _timeJumped(other._timeJumped)
|
||||
, _timePaused(other._timePaused)
|
||||
, _jockeHasToFixThisLater(other._jockeHasToFixThisLater)
|
||||
//shared copies
|
||||
, _sharedTime(other._sharedTime)
|
||||
, _sharedDt(other._sharedDt)
|
||||
, _sharedTimeJumped(other._sharedTimeJumped)
|
||||
//synced copies
|
||||
, _syncedTime(other._syncedTime)
|
||||
, _syncedDt(other._syncedDt)
|
||||
, _syncedTimeJumped(other._syncedTimeJumped)
|
||||
{
|
||||
|
||||
}
|
||||
@@ -116,19 +91,18 @@ void Time::setTime(double value, bool requireJump) {
|
||||
_timeJumped = requireJump;
|
||||
}
|
||||
|
||||
double Time::currentTime() const {
|
||||
return _syncedTime;
|
||||
}
|
||||
|
||||
double Time::unsyncedJ2000Seconds() const {
|
||||
double Time::j2000Seconds() const {
|
||||
return _time;
|
||||
}
|
||||
|
||||
double Time::advanceTime(double tickTime) {
|
||||
if (_timePaused)
|
||||
if (_timePaused) {
|
||||
return _time;
|
||||
else
|
||||
return _time += _dt * tickTime;
|
||||
}
|
||||
else {
|
||||
_time += _dt * tickTime;
|
||||
}
|
||||
return _time;
|
||||
}
|
||||
|
||||
void Time::setDeltaTime(double deltaT) {
|
||||
@@ -136,11 +110,11 @@ void Time::setDeltaTime(double deltaT) {
|
||||
}
|
||||
|
||||
double Time::deltaTime() const {
|
||||
return _syncedDt;
|
||||
return _dt;
|
||||
}
|
||||
|
||||
void Time::setPause(bool pause) {
|
||||
_timePaused = pause;
|
||||
_timePaused = pause;
|
||||
}
|
||||
|
||||
bool Time::togglePause() {
|
||||
@@ -153,12 +127,12 @@ void Time::setTime(std::string time, bool requireJump) {
|
||||
_timeJumped = requireJump;
|
||||
}
|
||||
|
||||
std::string Time::currentTimeUTC() const {
|
||||
return SpiceManager::ref().dateFromEphemerisTime(_syncedTime);
|
||||
std::string Time::UTC() const {
|
||||
return SpiceManager::ref().dateFromEphemerisTime(_time);
|
||||
}
|
||||
|
||||
std::string Time::ISO8601() const {
|
||||
std::string datetime = SpiceManager::ref().dateFromEphemerisTime(_syncedTime);
|
||||
std::string datetime = SpiceManager::ref().dateFromEphemerisTime(_time);
|
||||
std::string month = datetime.substr(5, 3);
|
||||
|
||||
std::string MM = "";
|
||||
@@ -180,56 +154,8 @@ std::string Time::ISO8601() const {
|
||||
return datetime;
|
||||
}
|
||||
|
||||
void Time::serialize(SyncBuffer* syncBuffer) {
|
||||
_syncMutex.lock();
|
||||
|
||||
syncBuffer->encode(_sharedTime);
|
||||
syncBuffer->encode(_sharedDt);
|
||||
syncBuffer->encode(_sharedTimeJumped);
|
||||
|
||||
_syncMutex.unlock();
|
||||
}
|
||||
|
||||
void Time::deserialize(SyncBuffer* syncBuffer) {
|
||||
_syncMutex.lock();
|
||||
|
||||
syncBuffer->decode(_sharedTime);
|
||||
syncBuffer->decode(_sharedDt);
|
||||
syncBuffer->decode(_sharedTimeJumped);
|
||||
|
||||
if (_sharedTimeJumped)
|
||||
_jockeHasToFixThisLater = true;
|
||||
|
||||
_syncMutex.unlock();
|
||||
}
|
||||
|
||||
void Time::postSynchronizationPreDraw() {
|
||||
_syncMutex.lock();
|
||||
|
||||
_syncedTime = _sharedTime;
|
||||
_syncedDt = _sharedDt;
|
||||
_syncedTimeJumped = _sharedTimeJumped;
|
||||
|
||||
if (_jockeHasToFixThisLater) {
|
||||
_syncedTimeJumped = true;
|
||||
_jockeHasToFixThisLater = false;
|
||||
}
|
||||
|
||||
_syncMutex.unlock();
|
||||
}
|
||||
|
||||
void Time::preSynchronization() {
|
||||
_syncMutex.lock();
|
||||
|
||||
_sharedTime = _time;
|
||||
_sharedDt = _dt;
|
||||
_sharedTimeJumped = _timeJumped;
|
||||
|
||||
_syncMutex.unlock();
|
||||
}
|
||||
|
||||
bool Time::timeJumped() const {
|
||||
return _syncedTimeJumped;
|
||||
return _timeJumped;
|
||||
}
|
||||
|
||||
void Time::setTimeJumped(bool jumped) {
|
||||
@@ -240,6 +166,10 @@ bool Time::paused() const {
|
||||
return _timePaused;
|
||||
}
|
||||
|
||||
std::vector<Syncable*> Time::getSyncables() {
|
||||
return{ &_time, &_dt, &_timeJumped};
|
||||
}
|
||||
|
||||
scripting::LuaLibrary Time::luaLibrary() {
|
||||
return {
|
||||
"time",
|
||||
@@ -288,7 +218,7 @@ scripting::LuaLibrary Time::luaLibrary() {
|
||||
"the J2000 epoch"
|
||||
},
|
||||
{
|
||||
"currentTimeUTC",
|
||||
"UTC",
|
||||
&luascriptfunctions::time_currentTimeUTC,
|
||||
"",
|
||||
"Returns the current time as an ISO 8601 date string "
|
||||
|
||||
@@ -139,18 +139,18 @@ int time_setTime(lua_State* L) {
|
||||
* It is returned by calling the Time::currentTime method.
|
||||
*/
|
||||
int time_currentTime(lua_State* L) {
|
||||
lua_pushnumber(L, openspace::Time::ref().currentTime());
|
||||
lua_pushnumber(L, openspace::Time::ref().j2000Seconds());
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup LuaScripts
|
||||
* currentTimeUTC():
|
||||
* UTC():
|
||||
* Returns the current simulation time as a structured ISO 8601 string using the UTC
|
||||
* timezone by calling the Time::currentTimeUTC method
|
||||
* timezone by calling the Time::UTC method
|
||||
*/
|
||||
int time_currentTimeUTC(lua_State* L) {
|
||||
lua_pushstring(L, openspace::Time::ref().currentTimeUTC().c_str());
|
||||
lua_pushstring(L, openspace::Time::ref().UTC().c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -38,7 +38,6 @@ void TimeManager::preSynchronization(double dt) {
|
||||
} else {
|
||||
consumeKeyframes(dt);
|
||||
}
|
||||
Time::ref().preSynchronization();
|
||||
}
|
||||
|
||||
void TimeManager::consumeKeyframes(double dt) {
|
||||
@@ -85,7 +84,7 @@ void TimeManager::consumeKeyframes(double dt) {
|
||||
// Do not interpolate with time jumping keyframes.
|
||||
// Instead, wait until their timestamp and apply them directly.
|
||||
if (next._requiresTimeJump) {
|
||||
time.setTime(time.currentTime() + dt * time.deltaTime(), false);
|
||||
time.setTime(time.j2000Seconds() + dt * time.deltaTime(), false);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -99,7 +98,7 @@ void TimeManager::consumeKeyframes(double dt) {
|
||||
|
||||
double parameter = (t1 - t0) / (t2 - t0);
|
||||
|
||||
double y0 = time.currentTime();
|
||||
double y0 = time.j2000Seconds();
|
||||
double yPrime0 = time.deltaTime();
|
||||
|
||||
double y2 = next._time;
|
||||
|
||||
Reference in New Issue
Block a user