mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-05-04 18:11:01 -05:00
Merge branch 'feature/cef-update' into thesis/2021/skybrowser
This commit is contained in:
@@ -350,7 +350,7 @@ void AtmosphereDeferredcaster::preRaycast(const RenderData& data, const Deferred
|
||||
|
||||
// Shadow calculations..
|
||||
_shadowDataArrayCache.clear();
|
||||
for (const ShadowConfiguration& shadowConf : _shadowConfArray) {
|
||||
for (ShadowConfiguration& shadowConf : _shadowConfArray) {
|
||||
// TO REMEMBER: all distances and lengths in world coordinates are in
|
||||
// meters!!! We need to move this to view space...
|
||||
double lt;
|
||||
@@ -374,10 +374,19 @@ void AtmosphereDeferredcaster::preRaycast(const RenderData& data, const Deferred
|
||||
casterPos *= KM_TO_M; // converting to meters
|
||||
|
||||
SceneGraphNode* sourceNode = sceneGraphNode(shadowConf.source.first);
|
||||
if (!sourceNode) {
|
||||
if (!shadowConf.printedSourceError) {
|
||||
LERROR("Invalid scenegraph node for the shadow's receiver");
|
||||
shadowConf.printedSourceError = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
SceneGraphNode* casterNode = sceneGraphNode(shadowConf.caster.first);
|
||||
|
||||
if (!sourceNode || !casterNode) {
|
||||
LERROR("Invalid scenegraph node for the shadow's caster or receiver");
|
||||
if (!casterNode) {
|
||||
if (!shadowConf.printedCasterError) {
|
||||
LERROR("Invalid scenegraph node for the shadow's caster");
|
||||
shadowConf.printedCasterError = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -53,6 +53,10 @@ struct TransformData;
|
||||
struct ShadowConfiguration {
|
||||
std::pair<std::string, double> source;
|
||||
std::pair<std::string, double> caster;
|
||||
// Set to 'true' if we printed an error because we couldn't find the source or caster.
|
||||
// We only want to print a message once
|
||||
bool printedSourceError = false;
|
||||
bool printedCasterError = false;
|
||||
};
|
||||
|
||||
namespace documentation { struct Documentation; }
|
||||
|
||||
@@ -339,7 +339,8 @@ void RenderableSphere::render(const RenderData& data, RendererTasks&) {
|
||||
|
||||
ghoul::opengl::TextureUnit unit;
|
||||
unit.activate();
|
||||
_texture->bind();
|
||||
bindTexture();
|
||||
defer{ unbindTexture(); };
|
||||
_shader->setUniform(_uniformCache.colorTexture, unit);
|
||||
|
||||
// Setting these states should not be necessary,
|
||||
@@ -390,6 +391,12 @@ void RenderableSphere::update(const UpdateData&) {
|
||||
}
|
||||
}
|
||||
|
||||
void RenderableSphere::bindTexture() {
|
||||
_texture->bind();
|
||||
}
|
||||
|
||||
void RenderableSphere::unbindTexture() {}
|
||||
|
||||
void RenderableSphere::loadTexture() {
|
||||
if (!_texturePath.value().empty()) {
|
||||
std::unique_ptr<ghoul::opengl::Texture> texture =
|
||||
|
||||
@@ -60,6 +60,10 @@ public:
|
||||
|
||||
static documentation::Documentation Documentation();
|
||||
|
||||
protected:
|
||||
virtual void bindTexture();
|
||||
virtual void unbindTexture();
|
||||
|
||||
private:
|
||||
void loadTexture();
|
||||
|
||||
|
||||
@@ -136,18 +136,8 @@ scripting::LuaLibrary ScreenSpaceDashboard::luaLibrary() {
|
||||
return {
|
||||
"dashboard",
|
||||
{
|
||||
{
|
||||
"addDashboardItemToScreenSpace",
|
||||
&luascriptfunctions::addDashboardItemToScreenSpace,
|
||||
"string, table",
|
||||
"Adds a new dashboard item to an existing SceenSpaceDashboard."
|
||||
},
|
||||
{
|
||||
"removeDashboardItemsFromScreenSpace",
|
||||
&luascriptfunctions::removeDashboardItemsFromScreenSpace,
|
||||
"string",
|
||||
"Removes all dashboard items from an existing ScreenSpaceDashboard."
|
||||
}
|
||||
codegen::lua::AddDashboardItemToScreenSpace,
|
||||
codegen::lua::RemoveDashboardItemsFromScreenSpace
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -22,56 +22,48 @@
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
namespace openspace::luascriptfunctions {
|
||||
namespace {
|
||||
|
||||
/**
|
||||
* \ingroup LuaScripts
|
||||
* addDashboardItemToScreenSpace(string, table):
|
||||
*/
|
||||
int addDashboardItemToScreenSpace(lua_State* L) {
|
||||
ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::addDashboardItemToScreenSpace");
|
||||
auto [name, d] = ghoul::lua::values<std::string, ghoul::Dictionary>(L);
|
||||
//Adds a new dashboard item to an existing SceenSpaceDashboard.
|
||||
[[codegen::luawrap]] void addDashboardItemToScreenSpace(std::string identifier,
|
||||
ghoul::Dictionary dashboard)
|
||||
{
|
||||
using namespace openspace;
|
||||
|
||||
ScreenSpaceRenderable* ssr = global::renderEngine->screenSpaceRenderable(name);
|
||||
ScreenSpaceRenderable* ssr = global::renderEngine->screenSpaceRenderable(identifier);
|
||||
if (!ssr) {
|
||||
return ghoul::lua::luaError(L, "Provided name is not a ScreenSpace item");
|
||||
throw ghoul::lua::LuaError("Provided name is not a ScreenSpace item");
|
||||
}
|
||||
|
||||
ScreenSpaceDashboard* dash = dynamic_cast<ScreenSpaceDashboard*>(ssr);
|
||||
if (!dash) {
|
||||
return ghoul::lua::luaError(
|
||||
L,
|
||||
throw ghoul::lua::LuaError(
|
||||
"Provided name is a ScreenSpace item but not a dashboard"
|
||||
);
|
||||
}
|
||||
|
||||
dash->dashboard().addDashboardItem(DashboardItem::createFromDictionary(d));
|
||||
return 0;
|
||||
dash->dashboard().addDashboardItem(DashboardItem::createFromDictionary(dashboard));
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup LuaScripts
|
||||
* removeDashboardItemsFromScreenSpace(string):
|
||||
*/
|
||||
int removeDashboardItemsFromScreenSpace(lua_State* L) {
|
||||
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::removeDashboardItemsFromScreenSpace");
|
||||
const std::string name = ghoul::lua::value<std::string>(L);
|
||||
// Removes all dashboard items from an existing ScreenSpaceDashboard.
|
||||
[[codegen::luawrap]] void removeDashboardItemsFromScreenSpace(std::string identifier) {
|
||||
using namespace openspace;
|
||||
|
||||
ScreenSpaceRenderable* ssr = global::renderEngine->screenSpaceRenderable(name);
|
||||
ScreenSpaceRenderable* ssr = global::renderEngine->screenSpaceRenderable(identifier);
|
||||
if (!ssr) {
|
||||
return ghoul::lua::luaError(L, "Provided name is not a ScreenSpace item");
|
||||
throw ghoul::lua::LuaError("Provided identifier is not a ScreenSpace item");
|
||||
}
|
||||
|
||||
ScreenSpaceDashboard* dash = dynamic_cast<ScreenSpaceDashboard*>(ssr);
|
||||
if (!dash) {
|
||||
return ghoul::lua::luaError(
|
||||
L,
|
||||
"Provided name is a ScreenSpace item but not a dashboard"
|
||||
throw ghoul::lua::LuaError(
|
||||
"Provided identifier is a ScreenSpace item but not a dashboard"
|
||||
);
|
||||
}
|
||||
|
||||
dash->dashboard().clearDashboardItems();
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace openspace::luascriptfunctions
|
||||
#include "screenspacedashboard_lua_codegen.cpp"
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -26,9 +26,18 @@
|
||||
|
||||
#include <modules/debugging/rendering/renderabledebugplane.h>
|
||||
#include <openspace/documentation/documentation.h>
|
||||
#include <openspace/engine/globals.h>
|
||||
#include <openspace/navigation/navigationhandler.h>
|
||||
#include <openspace/navigation/path.h>
|
||||
#include <openspace/navigation/pathnavigator.h>
|
||||
#include <openspace/rendering/renderable.h>
|
||||
#include <openspace/rendering/renderengine.h>
|
||||
#include <openspace/scene/scene.h>
|
||||
#include <openspace/scene/scenegraphnode.h>
|
||||
#include <openspace/scripting/scriptengine.h>
|
||||
#include <openspace/scripting/lualibrary.h>
|
||||
#include <openspace/util/factorymanager.h>
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <ghoul/misc/assert.h>
|
||||
#include <ghoul/misc/templatefactory.h>
|
||||
|
||||
@@ -53,51 +62,16 @@ std::vector<documentation::Documentation> DebuggingModule::documentations() cons
|
||||
}
|
||||
|
||||
scripting::LuaLibrary DebuggingModule::luaLibrary() const {
|
||||
scripting::LuaLibrary res;
|
||||
res.name = "debugging";
|
||||
res.functions = {
|
||||
return {
|
||||
"debugging",
|
||||
{
|
||||
"renderCameraPath",
|
||||
&luascriptfunctions::renderCameraPath,
|
||||
"[number, bool, number]",
|
||||
"Render the current camera path from the path navigation system. The "
|
||||
"first optional argument is the number of samples to take along the path "
|
||||
"(defaults to 100). If a second optional argument is included and set to "
|
||||
"true, a line indicating the camera view direction along the path will "
|
||||
"also be rendered. This can be useful when debugging camera orientations. "
|
||||
"Finally, the third optional argument can be used to set the length "
|
||||
"(in meter) of the view direction lines"
|
||||
},
|
||||
{
|
||||
"removeRenderedCameraPath",
|
||||
&luascriptfunctions::removeRenderedCameraPath,
|
||||
"",
|
||||
"Removes the rendered camera path, if there is one"
|
||||
},
|
||||
{
|
||||
"renderPathControlPoints",
|
||||
&luascriptfunctions::renderPathControlPoints,
|
||||
"[number]",
|
||||
"Render the control points for the camera path spline as spheres. The "
|
||||
"optional argument can be used to set the radius of the created spheres. "
|
||||
},
|
||||
{
|
||||
"removePathControlPoints",
|
||||
&luascriptfunctions::removePathControlPoints,
|
||||
"",
|
||||
"Removes the rendered control points"
|
||||
},
|
||||
{
|
||||
"addCartesianAxes",
|
||||
&luascriptfunctions::addCartesianAxes,
|
||||
"string, [number]",
|
||||
"Adds a set of Cartesian axes to the scene graph node identified by the "
|
||||
"first string, to illustrate its local coordinate system. The second "
|
||||
"(optional) argument is a scale value, in meters."
|
||||
codegen::lua::RenderCameraPath,
|
||||
codegen::lua::RemoveRenderedCameraPath,
|
||||
codegen::lua::RenderPathControlPoints,
|
||||
codegen::lua::RemovePathControlPoints,
|
||||
codegen::lua::AddCartesianAxes
|
||||
}
|
||||
};
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -22,46 +22,39 @@
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#include <openspace/engine/globals.h>
|
||||
#include <openspace/navigation/navigationhandler.h>
|
||||
#include <openspace/navigation/path.h>
|
||||
#include <openspace/navigation/pathnavigator.h>
|
||||
#include <openspace/rendering/renderengine.h>
|
||||
#include <openspace/scene/scene.h>
|
||||
#include <openspace/scene/scenegraphnode.h>
|
||||
#include <openspace/scripting/scriptengine.h>
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
|
||||
namespace {
|
||||
constexpr const char _loggerCat[] = "Debugging";
|
||||
|
||||
constexpr const char RenderedPathIdentifier[] = "CurrentCameraPath";
|
||||
constexpr const char RenderedPointsIdentifier[] = "CurrentPathControlPoints";
|
||||
constexpr const char DebuggingGuiPath[] = "/Debugging";
|
||||
constexpr const char RenderedPathIdentifier[] = "CurrentCameraPath";
|
||||
constexpr const char RenderedPointsIdentifier[] = "CurrentPathControlPoints";
|
||||
constexpr const char DebuggingGuiPath[] = "/Debugging";
|
||||
|
||||
constexpr const glm::vec3 PathColor = { 1.0, 1.0, 0.0 };
|
||||
constexpr const glm::vec3 OrientationLineColor = { 0.0, 1.0, 1.0 };
|
||||
constexpr const glm::vec3 PathColor = { 1.0, 1.0, 0.0 };
|
||||
constexpr const glm::vec3 OrientationLineColor = { 0.0, 1.0, 1.0 };
|
||||
|
||||
// Conver the input string to a format that is valid as an identifier
|
||||
std::string makeIdentifier(std::string s) {
|
||||
std::replace(s.begin(), s.end(), ' ', '_');
|
||||
std::replace(s.begin(), s.end(), '.', '-');
|
||||
// Remove quotes and apostrophe, since they cause problems
|
||||
// when a string is translated to a script call
|
||||
s.erase(remove(s.begin(), s.end(), '\"'), s.end());
|
||||
s.erase(remove(s.begin(), s.end(), '\''), s.end());
|
||||
return s;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace openspace::luascriptfunctions {
|
||||
// Conver the input string to a format that is valid as an identifier
|
||||
std::string makeIdentifier(std::string s) {
|
||||
std::replace(s.begin(), s.end(), ' ', '_');
|
||||
std::replace(s.begin(), s.end(), '.', '-');
|
||||
// Remove quotes and apostrophe, since they cause problems
|
||||
// when a string is translated to a script call
|
||||
s.erase(remove(s.begin(), s.end(), '\"'), s.end());
|
||||
s.erase(remove(s.begin(), s.end(), '\''), s.end());
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* PathNavigation
|
||||
* Renders the current camera path
|
||||
* Render the current camera path from the path navigation system. The first optional
|
||||
* argument is the number of samples to take along the path (defaults to 100). If a second
|
||||
* optional argument is included and set to true, a line indicating the camera view
|
||||
* direction along the path will also be rendered. This can be useful when debugging
|
||||
* camera orientations. Finally, the third optional argument can be used to set the length
|
||||
* (in meter) of the view direction lines.
|
||||
*/
|
||||
int renderCameraPath(lua_State* L) {
|
||||
ghoul::lua::checkArgumentsAndThrow(L, { 0, 3 }, "lua::renderCameraPath");
|
||||
[[codegen::luawrap]] void renderCameraPath(int nSteps = 100,
|
||||
bool renderDirections = false,
|
||||
double directionLineLength = 6e7)
|
||||
{
|
||||
using namespace openspace;
|
||||
|
||||
if (!global::navigationHandler->pathNavigator().hasCurrentPath()) {
|
||||
LWARNINGC("Debugging: PathNavigation", "There is no current path to render");
|
||||
@@ -70,15 +63,7 @@ int renderCameraPath(lua_State* L) {
|
||||
const interaction::Path* currentPath =
|
||||
global::navigationHandler->pathNavigator().currentPath();
|
||||
|
||||
auto [nSteps, renderDirections, directionLineLength] = ghoul::lua::values<
|
||||
std::optional<int>, std::optional<bool>, std::optional<double>
|
||||
>(L);
|
||||
|
||||
nSteps = nSteps.value_or(100);
|
||||
renderDirections = renderDirections.value_or(false);
|
||||
directionLineLength = directionLineLength.value_or(6e7);
|
||||
|
||||
// Parent node. Note that we only render one path at a time, so remove the previously
|
||||
// Parent node. Note that we only render one path at a time, so remove the previously
|
||||
// rendered one, if any
|
||||
std::string addParentScript = fmt::format(
|
||||
"if openspace.hasSceneGraphNode('{0}') then "
|
||||
@@ -88,14 +73,14 @@ int renderCameraPath(lua_State* L) {
|
||||
RenderedPathIdentifier
|
||||
);
|
||||
|
||||
openspace::global::scriptEngine->queueScript(
|
||||
global::scriptEngine->queueScript(
|
||||
addParentScript,
|
||||
scripting::ScriptEngine::RemoteScripting::Yes
|
||||
);
|
||||
|
||||
// Get the poses along the path
|
||||
std::vector<CameraPose> poses;
|
||||
const double du = 1.0 / (*nSteps);
|
||||
const double du = 1.0 / nSteps;
|
||||
const double length = currentPath->pathLength();
|
||||
for (double u = 0.0; u < 1.0; u += du) {
|
||||
const CameraPose p = currentPath->interpolatedPose(u * length);
|
||||
@@ -120,7 +105,7 @@ int renderCameraPath(lua_State* L) {
|
||||
"}"
|
||||
"}";
|
||||
|
||||
openspace::global::scriptEngine->queueScript(
|
||||
global::scriptEngine->queueScript(
|
||||
fmt::format("openspace.addSceneGraphNode({})", pointNode),
|
||||
scripting::ScriptEngine::RemoteScripting::Yes
|
||||
);
|
||||
@@ -142,7 +127,7 @@ int renderCameraPath(lua_State* L) {
|
||||
"}"
|
||||
"}";
|
||||
|
||||
openspace::global::scriptEngine->queueScript(
|
||||
global::scriptEngine->queueScript(
|
||||
fmt::format("openspace.addSceneGraphNode({})", lineNode),
|
||||
scripting::ScriptEngine::RemoteScripting::Yes
|
||||
);
|
||||
@@ -162,43 +147,35 @@ int renderCameraPath(lua_State* L) {
|
||||
|
||||
// Add first point separately so that we can create first line in for loop
|
||||
addPoint(pointIdentifier(0), poses.front().position);
|
||||
if (*renderDirections) {
|
||||
addDirectionLine(pointIdentifier(0), poses.front(), *directionLineLength);
|
||||
if (renderDirections) {
|
||||
addDirectionLine(pointIdentifier(0), poses.front(), directionLineLength);
|
||||
}
|
||||
|
||||
for (int i = 1; i < static_cast<int>(poses.size()); i++) {
|
||||
addPoint(pointIdentifier(i), poses[i].position);
|
||||
addLineBetweenPoints(pointIdentifier(i), pointIdentifier(i - 1), PathColor, 4.f);
|
||||
|
||||
if (*renderDirections) {
|
||||
addDirectionLine(pointIdentifier(i), poses[i], *directionLineLength);
|
||||
if (renderDirections) {
|
||||
addDirectionLine(pointIdentifier(i), poses[i], directionLineLength);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* PathNavigation
|
||||
* Removes the currently rendered camera path if there is one
|
||||
*/
|
||||
int removeRenderedCameraPath(lua_State* L) {
|
||||
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::removeRenderedCameraPath");
|
||||
|
||||
openspace::global::scriptEngine->queueScript(
|
||||
fmt::format("openspace.removeSceneGraphNode('{}') ", RenderedPathIdentifier),
|
||||
// Removes the currently rendered camera path if there is one.
|
||||
[[codegen::luawrap]] void removeRenderedCameraPath() {
|
||||
using namespace openspace;
|
||||
global::scriptEngine->queueScript(
|
||||
fmt::format("openspace.removeSceneGraphNode('{}');", RenderedPathIdentifier),
|
||||
scripting::ScriptEngine::RemoteScripting::Yes
|
||||
);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* PathNavigation
|
||||
* Renders the control points of the current camera path
|
||||
* Render the control points for the camera path spline as spheres. The optional argument
|
||||
* can be used to set the radius of the created spheres.
|
||||
*/
|
||||
int renderPathControlPoints(lua_State* L) {
|
||||
ghoul::lua::checkArgumentsAndThrow(L, { 0, 1 }, "lua::renderPathControlPoints");
|
||||
[[codegen::luawrap]] void renderPathControlPoints(double radius = 2000000.0) {
|
||||
using namespace openspace;
|
||||
|
||||
if (!global::navigationHandler->pathNavigator().hasCurrentPath()) {
|
||||
LWARNINGC(
|
||||
@@ -209,20 +186,17 @@ int renderPathControlPoints(lua_State* L) {
|
||||
const interaction::Path* currentPath =
|
||||
global::navigationHandler->pathNavigator().currentPath();
|
||||
|
||||
auto [radius] = ghoul::lua::values<std::optional<double>>(L);
|
||||
radius = radius.value_or(2000000.0);
|
||||
|
||||
// Parent node. Note that we only render one set of points at a time,
|
||||
// so remove any previously rendered ones
|
||||
// Parent node. Note that we only render one set of points at a time, so remove any
|
||||
// previously rendered ones
|
||||
std::string addParentScript = fmt::format(
|
||||
"if openspace.hasSceneGraphNode('{0}') then "
|
||||
"openspace.removeSceneGraphNode('{0}') "
|
||||
"openspace.removeSceneGraphNode('{0}') "
|
||||
"end "
|
||||
"openspace.addSceneGraphNode( {{ Identifier = '{0}' }} )",
|
||||
RenderedPointsIdentifier
|
||||
);
|
||||
|
||||
openspace::global::scriptEngine->queueScript(
|
||||
global::scriptEngine->queueScript(
|
||||
addParentScript,
|
||||
scripting::ScriptEngine::RemoteScripting::Yes
|
||||
);
|
||||
@@ -234,74 +208,69 @@ int renderPathControlPoints(lua_State* L) {
|
||||
|
||||
const char* colorTexturePath = "openspace.absPath("
|
||||
"openspace.createSingleColorImage('point_color', { 0.0, 1.0, 0.0 })"
|
||||
")";
|
||||
")";
|
||||
|
||||
for (size_t i = 0; i < points.size(); i++) {
|
||||
const std::string& node = "{"
|
||||
"Identifier = 'ControlPoint_" + std::to_string(i) + "',"
|
||||
"Parent = '" + RenderedPointsIdentifier + "',"
|
||||
"Transform = { "
|
||||
"Translation = {"
|
||||
"Type = 'StaticTranslation',"
|
||||
"Position = " + ghoul::to_string(points[i]) + ""
|
||||
"},"
|
||||
"Translation = {"
|
||||
"Type = 'StaticTranslation',"
|
||||
"Position = " + ghoul::to_string(points[i]) + ""
|
||||
"},"
|
||||
"},"
|
||||
"Renderable = {"
|
||||
"Type = 'RenderableSphere',"
|
||||
"Enabled = true,"
|
||||
"Segments = 30,"
|
||||
"Size = " + std::to_string(*radius) + ","
|
||||
"Texture = " + colorTexturePath + ""
|
||||
"Type = 'RenderableSphere',"
|
||||
"Enabled = true,"
|
||||
"Segments = 30,"
|
||||
"Size = " + std::to_string(radius) + ","
|
||||
"Texture = " + colorTexturePath + ""
|
||||
"},"
|
||||
"GUI = {"
|
||||
"Name = 'Control Point " + std::to_string(i) + "',"
|
||||
"Path = '" + guiPath + "'"
|
||||
"Name = 'Control Point " + std::to_string(i) + "',"
|
||||
"Path = '" + guiPath + "'"
|
||||
"}"
|
||||
"}";
|
||||
"}";
|
||||
|
||||
openspace::global::scriptEngine->queueScript(
|
||||
global::scriptEngine->queueScript(
|
||||
fmt::format("openspace.addSceneGraphNode({})", node),
|
||||
scripting::ScriptEngine::RemoteScripting::Yes
|
||||
);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* PathNavigation
|
||||
* Removes the rendered control points
|
||||
*/
|
||||
int removePathControlPoints(lua_State* L) {
|
||||
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::removePathControlPoints");
|
||||
|
||||
openspace::global::scriptEngine->queueScript(
|
||||
fmt::format("openspace.removeSceneGraphNode('{}') ", RenderedPointsIdentifier),
|
||||
// Removes the rendered control points.
|
||||
[[codegen::luawrap]] void removePathControlPoints() {
|
||||
using namespace openspace;
|
||||
global::scriptEngine->queueScript(
|
||||
fmt::format("openspace.removeSceneGraphNode('{}');", RenderedPointsIdentifier),
|
||||
scripting::ScriptEngine::RemoteScripting::Yes
|
||||
);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a set of cartesian axes to the specified scene graph node
|
||||
* Adds a set of Cartesian axes to the scene graph node identified by the first string, to
|
||||
* illustrate its local coordinate system. The second (optional) argument is a scale
|
||||
* value, in meters.
|
||||
*/
|
||||
int addCartesianAxes(lua_State* L) {
|
||||
ghoul::lua::checkArgumentsAndThrow(L, { 1, 2 }, "lua::addCartesianAxes");
|
||||
|
||||
auto [nodeIdentifier, scale] =
|
||||
ghoul::lua::values<std::string, std::optional<double>>(L);
|
||||
|
||||
[[codegen::luawrap]] void addCartesianAxes(std::string nodeIdentifier,
|
||||
std::optional<double> scale)
|
||||
{
|
||||
using namespace openspace;
|
||||
SceneGraphNode* n = global::renderEngine->scene()->sceneGraphNode(nodeIdentifier);
|
||||
if (!n) {
|
||||
return ghoul::lua::luaError(L, "Unknown scene graph node: " + nodeIdentifier);
|
||||
throw ghoul::lua::LuaError("Unknown scene graph node: " + nodeIdentifier);
|
||||
}
|
||||
|
||||
if (!scale.has_value()) {
|
||||
scale = 2.0 * n->boundingSphere();
|
||||
if (n->boundingSphere() < 1E-3) {
|
||||
LWARNING("Using zero bounding sphere for scale of created axes. You might "
|
||||
"have to set the scale manually for them to be visible");
|
||||
if (n->boundingSphere() <= 0.0) {
|
||||
LWARNINGC(
|
||||
"Debugging: Cartesian Axes",
|
||||
"Using zero bounding sphere for scale of created axes. You need to set "
|
||||
"the scale manually for them to be visible"
|
||||
);
|
||||
scale = 1.0;
|
||||
}
|
||||
}
|
||||
@@ -311,31 +280,30 @@ int addCartesianAxes(lua_State* L) {
|
||||
"Identifier = '" + identifier + "',"
|
||||
"Parent = '" + nodeIdentifier + "',"
|
||||
"Transform = { "
|
||||
"Scale = {"
|
||||
"Type = 'StaticScale',"
|
||||
"Scale = " + std::to_string(*scale) + ""
|
||||
"}"
|
||||
"Scale = {"
|
||||
"Type = 'StaticScale',"
|
||||
"Scale = " + std::to_string(*scale) + ""
|
||||
"}"
|
||||
"},"
|
||||
"Renderable = {"
|
||||
"Type = 'RenderableCartesianAxes',"
|
||||
"Enabled = true,"
|
||||
"XColor = { 1.0, 0.0, 0.0 },"
|
||||
"YColor = { 0.0, 1.0, 0.0 },"
|
||||
"ZColor = { 0.0, 0.0, 1.0 }"
|
||||
"Type = 'RenderableCartesianAxes',"
|
||||
"Enabled = true,"
|
||||
"XColor = { 1.0, 0.0, 0.0 },"
|
||||
"YColor = { 0.0, 1.0, 0.0 },"
|
||||
"ZColor = { 0.0, 0.0, 1.0 }"
|
||||
"},"
|
||||
"GUI = {"
|
||||
"Name = '" + identifier + "',"
|
||||
"Path = '" + DebuggingGuiPath + "/Coordiante Systems'"
|
||||
"Name = '" + identifier + "',"
|
||||
"Path = '" + DebuggingGuiPath + "/Coordiante Systems'"
|
||||
"}"
|
||||
"}";
|
||||
|
||||
openspace::global::scriptEngine->queueScript(
|
||||
fmt::format("openspace.addSceneGraphNode({})", axes),
|
||||
global::scriptEngine->queueScript(
|
||||
fmt::format("openspace.addSceneGraphNode({});", axes),
|
||||
scripting::ScriptEngine::RemoteScripting::Yes
|
||||
);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace openspace::luascriptfunctions
|
||||
#include "debuggingmodule_lua_codegen.cpp"
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -24,15 +24,29 @@
|
||||
|
||||
#include <modules/exoplanets/exoplanetsmodule.h>
|
||||
|
||||
#include <modules/exoplanets/exoplanetshelper.h>
|
||||
#include <modules/exoplanets/rendering/renderableorbitdisc.h>
|
||||
#include <modules/exoplanets/tasks/exoplanetsdatapreparationtask.h>
|
||||
#include <openspace/engine/globals.h>
|
||||
#include <openspace/engine/globalscallbacks.h>
|
||||
#include <openspace/engine/moduleengine.h>
|
||||
#include <openspace/query/query.h>
|
||||
#include <openspace/rendering/renderengine.h>
|
||||
#include <openspace/scene/scenegraphnode.h>
|
||||
#include <openspace/scene/scene.h>
|
||||
#include <openspace/scripting/scriptengine.h>
|
||||
#include <openspace/util/distanceconstants.h>
|
||||
#include <openspace/util/factorymanager.h>
|
||||
#include <openspace/util/timeconversion.h>
|
||||
#include <openspace/util/timemanager.h>
|
||||
#include <ghoul/filesystem/filesystem.h>
|
||||
#include <ghoul/fmt.h>
|
||||
#include <ghoul/glm.h>
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <ghoul/misc/assert.h>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
#include "exoplanetsmodule_lua.inl"
|
||||
|
||||
@@ -256,41 +270,6 @@ float ExoplanetsModule::habitableZoneOpacity() const {
|
||||
return _habitableZoneOpacity;
|
||||
}
|
||||
|
||||
scripting::LuaLibrary ExoplanetsModule::luaLibrary() const {
|
||||
scripting::LuaLibrary res;
|
||||
res.name = "exoplanets";
|
||||
res.functions = {
|
||||
{
|
||||
"addExoplanetSystem",
|
||||
&exoplanets::luascriptfunctions::addExoplanetSystem,
|
||||
"string or list of strings",
|
||||
"Add one or multiple exoplanet systems to the scene, as specified by the "
|
||||
"input. An input string should be the name of the system host star"
|
||||
},
|
||||
{
|
||||
"removeExoplanetSystem",
|
||||
&exoplanets::luascriptfunctions::removeExoplanetSystem,
|
||||
"string",
|
||||
"Removes the nodes of the specified exoplanet system from the scene graph"
|
||||
},
|
||||
{
|
||||
"listAvailableExoplanetSystems",
|
||||
&exoplanets::luascriptfunctions::listAvailableExoplanetSystems,
|
||||
"",
|
||||
"Prints a list with the names of all exoplanet systems that can be added to "
|
||||
"the scene graph to the OpenSpace Log"
|
||||
},
|
||||
{
|
||||
"getListOfExoplanets",
|
||||
&exoplanets::luascriptfunctions::getListOfExoplanets,
|
||||
"",
|
||||
"Gets a list with the names of all exoplanet systems"
|
||||
}
|
||||
};
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void ExoplanetsModule::internalInitialize(const ghoul::Dictionary& dict) {
|
||||
const Parameters p = codegen::bake<Parameters>(dict);
|
||||
|
||||
@@ -343,4 +322,16 @@ std::vector<documentation::Documentation> ExoplanetsModule::documentations() con
|
||||
};
|
||||
}
|
||||
|
||||
scripting::LuaLibrary ExoplanetsModule::luaLibrary() const {
|
||||
return {
|
||||
"exoplanets",
|
||||
{
|
||||
codegen::lua::AddExoplanetSystem,
|
||||
codegen::lua::RemoveExoplanetSystem,
|
||||
codegen::lua::GetListOfExoplanets,
|
||||
codegen::lua::ListAvailableExoplanetSystems
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -22,44 +22,25 @@
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#include <modules/exoplanets/exoplanetshelper.h>
|
||||
#include <openspace/engine/globals.h>
|
||||
#include <openspace/engine/moduleengine.h>
|
||||
#include <openspace/query/query.h>
|
||||
#include <openspace/scene/scenegraphnode.h>
|
||||
#include <openspace/scripting/scriptengine.h>
|
||||
#include <openspace/util/distanceconstants.h>
|
||||
#include <openspace/util/timeconversion.h>
|
||||
#include <openspace/util/timemanager.h>
|
||||
#include <ghoul/filesystem/filesystem.h>
|
||||
#include <ghoul/fmt.h>
|
||||
#include <ghoul/glm.h>
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <ghoul/misc/assert.h>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
namespace {
|
||||
constexpr const char _loggerCat[] = "ExoplanetsModule";
|
||||
|
||||
constexpr const char ExoplanetsGuiPath[] = "/Milky Way/Exoplanets/Exoplanet Systems/";
|
||||
constexpr const char _loggerCat[] = "ExoplanetsModule";
|
||||
|
||||
// Lua cannot handle backslashes, so replace these with forward slashes
|
||||
std::string formatPathToLua(const std::string& path) {
|
||||
std::string resPath = path;
|
||||
std::replace(resPath.begin(), resPath.end(), '\\', '/');
|
||||
return resPath;
|
||||
}
|
||||
} // namespace
|
||||
constexpr const char ExoplanetsGuiPath[] = "/Milky Way/Exoplanets/Exoplanet Systems/";
|
||||
|
||||
namespace openspace::exoplanets::luascriptfunctions {
|
||||
// Lua cannot handle backslashes, so replace these with forward slashes
|
||||
std::string formatPathToLua(const std::string& path) {
|
||||
std::string resPath = path;
|
||||
std::replace(resPath.begin(), resPath.end(), '\\', '/');
|
||||
return resPath;
|
||||
}
|
||||
|
||||
constexpr const float AU = static_cast<float>(distanceconstants::AstronomicalUnit);
|
||||
constexpr const float SolarRadius = static_cast<float>(distanceconstants::SolarRadius);
|
||||
constexpr const float JupiterRadius =
|
||||
static_cast<float>(distanceconstants::JupiterRadius);
|
||||
openspace::exoplanets::ExoplanetSystem findExoplanetSystemInData(
|
||||
std::string_view starName)
|
||||
{
|
||||
using namespace openspace;
|
||||
using namespace exoplanets;
|
||||
|
||||
ExoplanetSystem findExoplanetSystemInData(std::string_view starName) {
|
||||
const ExoplanetsModule* module = global::moduleEngine->module<ExoplanetsModule>();
|
||||
|
||||
const std::string binPath = module->exoplanetsDataPath();
|
||||
@@ -135,6 +116,9 @@ ExoplanetSystem findExoplanetSystemInData(std::string_view starName) {
|
||||
}
|
||||
|
||||
void createExoplanetSystem(const std::string& starName) {
|
||||
using namespace openspace;
|
||||
using namespace exoplanets;
|
||||
|
||||
const std::string starIdentifier = createIdentifier(starName);
|
||||
|
||||
std::string sanitizedStarName = starName;
|
||||
@@ -173,7 +157,7 @@ void createExoplanetSystem(const std::string& starName) {
|
||||
const glm::dmat3 exoplanetSystemRotation = computeSystemRotation(starPos);
|
||||
|
||||
// Star
|
||||
float radiusInMeter = SolarRadius;
|
||||
double radiusInMeter = distanceconstants::SolarRadius;
|
||||
if (!std::isnan(system.starData.radius)) {
|
||||
radiusInMeter *= system.starData.radius;
|
||||
}
|
||||
@@ -242,7 +226,7 @@ void createExoplanetSystem(const std::string& starName) {
|
||||
"}"
|
||||
"}";
|
||||
|
||||
openspace::global::scriptEngine->queueScript(
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.addSceneGraphNode(" + starParent + ");",
|
||||
scripting::ScriptEngine::RemoteScripting::Yes
|
||||
);
|
||||
@@ -278,25 +262,25 @@ void createExoplanetSystem(const std::string& starName) {
|
||||
sEpoch = "2009-05-19T07:11:34.080";
|
||||
}
|
||||
|
||||
float planetRadius;
|
||||
double planetRadius;
|
||||
std::string enabled;
|
||||
if (std::isnan(planet.r)) {
|
||||
if (std::isnan(planet.rStar)) {
|
||||
planetRadius = planet.a * 0.001f * AU;
|
||||
planetRadius = planet.a * 0.001 * distanceconstants::AstronomicalUnit;
|
||||
}
|
||||
else {
|
||||
planetRadius = planet.rStar * 0.1f * SolarRadius;
|
||||
planetRadius = planet.rStar * 0.1 * distanceconstants::SolarRadius;
|
||||
}
|
||||
enabled = "false";
|
||||
}
|
||||
else {
|
||||
planetRadius = static_cast<float>(planet.r) * JupiterRadius;
|
||||
planetRadius = planet.r * distanceconstants::JupiterRadius;
|
||||
enabled = "true";
|
||||
}
|
||||
|
||||
const float periodInSeconds = static_cast<float>(planet.per * SecondsPerDay);
|
||||
const float semiMajorAxisInMeter = planet.a * AU;
|
||||
const float semiMajorAxisInKm = semiMajorAxisInMeter * 0.001f;
|
||||
float periodInSeconds = static_cast<float>(planet.per * SecondsPerDay);
|
||||
double semiMajorAxisInMeter = planet.a * distanceconstants::AstronomicalUnit;
|
||||
double semiMajorAxisInKm = semiMajorAxisInMeter * 0.001;
|
||||
|
||||
const std::string planetIdentifier = createIdentifier(planetName);
|
||||
|
||||
@@ -356,7 +340,7 @@ void createExoplanetSystem(const std::string& starName) {
|
||||
"}"
|
||||
"}";
|
||||
|
||||
openspace::global::scriptEngine->queueScript(
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.addSceneGraphNode(" + planetTrailNode + ");"
|
||||
"openspace.addSceneGraphNode(" + planetNode + ");",
|
||||
scripting::ScriptEngine::RemoteScripting::Yes
|
||||
@@ -406,7 +390,7 @@ void createExoplanetSystem(const std::string& starName) {
|
||||
"}"
|
||||
"}";
|
||||
|
||||
openspace::global::scriptEngine->queueScript(
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.addSceneGraphNode(" + discNode + ");",
|
||||
scripting::ScriptEngine::RemoteScripting::Yes
|
||||
);
|
||||
@@ -442,7 +426,7 @@ void createExoplanetSystem(const std::string& starName) {
|
||||
"},"
|
||||
"Scale = {"
|
||||
"Type = 'StaticScale',"
|
||||
"Scale = " + std::to_string(AU) + ""
|
||||
"Scale = " + std::to_string(distanceconstants::AstronomicalUnit) + ""
|
||||
"}"
|
||||
"},"
|
||||
"GUI = {"
|
||||
@@ -451,7 +435,7 @@ void createExoplanetSystem(const std::string& starName) {
|
||||
"}"
|
||||
"}";
|
||||
|
||||
openspace::global::scriptEngine->queueScript(
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.addSceneGraphNode(" + circle + ");",
|
||||
scripting::ScriptEngine::RemoteScripting::Yes
|
||||
);
|
||||
@@ -506,7 +490,7 @@ void createExoplanetSystem(const std::string& starName) {
|
||||
"}"
|
||||
"}";
|
||||
|
||||
openspace::global::scriptEngine->queueScript(
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.addSceneGraphNode(" + zoneDiscNode + ");",
|
||||
scripting::ScriptEngine::RemoteScripting::Yes
|
||||
);
|
||||
@@ -547,7 +531,7 @@ void createExoplanetSystem(const std::string& starName) {
|
||||
"}"
|
||||
"}";
|
||||
|
||||
openspace::global::scriptEngine->queueScript(
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.addSceneGraphNode(" + starGlare + ");",
|
||||
scripting::ScriptEngine::RemoteScripting::Yes
|
||||
);
|
||||
@@ -555,46 +539,9 @@ void createExoplanetSystem(const std::string& starName) {
|
||||
}
|
||||
}
|
||||
|
||||
int addExoplanetSystem(lua_State* L) {
|
||||
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::addExoplanetSystem");
|
||||
std::variant<std::string, ghoul::Dictionary> v =
|
||||
ghoul::lua::value<std::variant<std::string, ghoul::Dictionary>>(L);
|
||||
|
||||
if (std::holds_alternative<std::string>(v)) {
|
||||
// The user provided a single name
|
||||
std::string starName = std::get<std::string>(v);
|
||||
createExoplanetSystem(starName);
|
||||
}
|
||||
else {
|
||||
// A list of names was provided
|
||||
ghoul::Dictionary starNames = ghoul::lua::value<ghoul::Dictionary>(L);
|
||||
for (size_t i = 1; i <= starNames.size(); ++i) {
|
||||
if (!starNames.hasValue<std::string>(std::to_string(i))) {
|
||||
return ghoul::lua::luaError(
|
||||
L,
|
||||
fmt::format("List item {} is of invalid type", i)
|
||||
);
|
||||
}
|
||||
const std::string& starName = starNames.value<std::string>(std::to_string(i));
|
||||
createExoplanetSystem(starName);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int removeExoplanetSystem(lua_State* L) {
|
||||
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::removeExoplanetSystem");
|
||||
std::string starName = ghoul::lua::value<std::string>(L);
|
||||
|
||||
const std::string starIdentifier = createIdentifier(std::move(starName));
|
||||
openspace::global::scriptEngine->queueScript(
|
||||
"openspace.removeSceneGraphNode('" + starIdentifier + "');",
|
||||
scripting::ScriptEngine::RemoteScripting::Yes
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::vector<std::string> hostStarsWithSufficientData() {
|
||||
using namespace openspace;
|
||||
using namespace exoplanets;
|
||||
const ExoplanetsModule* module = global::moduleEngine->module<ExoplanetsModule>();
|
||||
|
||||
if (!module->hasDataFiles()) {
|
||||
@@ -657,23 +604,42 @@ std::vector<std::string> hostStarsWithSufficientData() {
|
||||
return names;
|
||||
}
|
||||
|
||||
int getListOfExoplanets(lua_State* L) {
|
||||
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::getListOfExoplanets");
|
||||
|
||||
std::vector<std::string> names = hostStarsWithSufficientData();
|
||||
lua_newtable(L);
|
||||
int number = 1;
|
||||
for (const std::string& s : names) {
|
||||
ghoul::lua::push(L, s);
|
||||
lua_rawseti(L, -2, number);
|
||||
++number;
|
||||
/**
|
||||
* Add one or multiple exoplanet systems to the scene, as specified by the input. An input
|
||||
* string should be the name of the system host star.
|
||||
*/
|
||||
[[codegen::luawrap]] void addExoplanetSystem(
|
||||
std::variant<std::string, std::vector<std::string>> starNames)
|
||||
{
|
||||
if (std::holds_alternative<std::string>(starNames)) {
|
||||
// The user provided a single name
|
||||
std::string starName = std::get<std::string>(starNames);
|
||||
createExoplanetSystem(starName);
|
||||
}
|
||||
else {
|
||||
std::vector<std::string> sns = std::get<std::vector<std::string>>(starNames);
|
||||
for (const std::string& starName : sns) {
|
||||
createExoplanetSystem(starName);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int listAvailableExoplanetSystems(lua_State* L) {
|
||||
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::listAvailableExoplanetSystems");
|
||||
[[codegen::luawrap]] void removeExoplanetSystem(std::string starName) {
|
||||
using namespace openspace;
|
||||
using namespace exoplanets;
|
||||
const std::string starIdentifier = createIdentifier(std::move(starName));
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.removeSceneGraphNode('" + starIdentifier + "');",
|
||||
scripting::ScriptEngine::RemoteScripting::Yes
|
||||
);
|
||||
}
|
||||
|
||||
[[codegen::luawrap]] std::vector<std::string> getListOfExoplanets() {
|
||||
std::vector<std::string> names = hostStarsWithSufficientData();
|
||||
return names;
|
||||
}
|
||||
|
||||
[[codegen::luawrap]] void listAvailableExoplanetSystems() {
|
||||
std::vector<std::string> names = hostStarsWithSufficientData();
|
||||
|
||||
std::string output;
|
||||
@@ -687,7 +653,8 @@ int listAvailableExoplanetSystems(lua_State* L) {
|
||||
"There is data available for the following {} exoplanet systems: {}",
|
||||
names.size(), output
|
||||
));
|
||||
return 0;
|
||||
}
|
||||
|
||||
} //namespace openspace::exoplanets::luascriptfunctions
|
||||
#include "exoplanetsmodule_lua_codegen.cpp"
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
openspace.gaia.documentation = {
|
||||
{
|
||||
Name = "addClippingBox",
|
||||
Arguments = "string, vec3, vec3",
|
||||
Arguments = { name = "String", size = "vec3", position = "vec3" },
|
||||
Documentation = "Creates a clipping box for the Gaia renderable in the first argument"
|
||||
},
|
||||
{
|
||||
Name = "removeClippingBox",
|
||||
Arguments = "",
|
||||
Arguments = {},
|
||||
Documentation = ""
|
||||
},
|
||||
{
|
||||
Name = "addClippingSphere",
|
||||
Arguments = "string, float",
|
||||
Arguments = { name = "String", radius = "Number" },
|
||||
Documentation = "Creates a clipping sphere for the Gaia renderable in the first argument"
|
||||
},
|
||||
{
|
||||
Name = "removeClippingBox",
|
||||
Arguments = "",
|
||||
Arguments = {},
|
||||
Documentation = ""
|
||||
}
|
||||
}
|
||||
@@ -104,4 +104,4 @@ openspace.gaia.removeClippingSphere = function()
|
||||
if openspace.hasSceneGraphNode(grid_identifier) then
|
||||
openspace.removeSceneGraphNode(grid_identifier)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -63,6 +63,7 @@ set(HEADER_FILES
|
||||
src/tileprovider/imagesequencetileprovider.h
|
||||
src/tileprovider/singleimagetileprovider.h
|
||||
src/tileprovider/sizereferencetileprovider.h
|
||||
src/tileprovider/spoutimageprovider.h
|
||||
src/tileprovider/temporaltileprovider.h
|
||||
src/tileprovider/texttileprovider.h
|
||||
src/tileprovider/tileindextileprovider.h
|
||||
@@ -102,6 +103,7 @@ set(SOURCE_FILES
|
||||
src/tileprovider/imagesequencetileprovider.cpp
|
||||
src/tileprovider/singleimagetileprovider.cpp
|
||||
src/tileprovider/sizereferencetileprovider.cpp
|
||||
src/tileprovider/spoutimageprovider.cpp
|
||||
src/tileprovider/temporaltileprovider.cpp
|
||||
src/tileprovider/texttileprovider.cpp
|
||||
src/tileprovider/tileindextileprovider.cpp
|
||||
|
||||
@@ -33,24 +33,36 @@
|
||||
#include <modules/globebrowsing/src/globerotation.h>
|
||||
#include <modules/globebrowsing/src/layer.h>
|
||||
#include <modules/globebrowsing/src/layeradjustment.h>
|
||||
#include <modules/globebrowsing/src/layergroup.h>
|
||||
#include <modules/globebrowsing/src/layermanager.h>
|
||||
#include <modules/globebrowsing/src/memoryawaretilecache.h>
|
||||
#include <modules/globebrowsing/src/renderableglobe.h>
|
||||
#include <modules/globebrowsing/src/tileprovider/defaulttileprovider.h>
|
||||
#include <modules/globebrowsing/src/tileprovider/imagesequencetileprovider.h>
|
||||
#include <modules/globebrowsing/src/tileprovider/singleimagetileprovider.h>
|
||||
#include <modules/globebrowsing/src/tileprovider/sizereferencetileprovider.h>
|
||||
#include <modules/globebrowsing/src/tileprovider/spoutimageprovider.h>
|
||||
#include <modules/globebrowsing/src/tileprovider/temporaltileprovider.h>
|
||||
#include <modules/globebrowsing/src/tileprovider/tileindextileprovider.h>
|
||||
#include <modules/globebrowsing/src/tileprovider/tileprovider.h>
|
||||
#include <modules/globebrowsing/src/tileprovider/tileproviderbyindex.h>
|
||||
#include <modules/globebrowsing/src/tileprovider/tileproviderbylevel.h>
|
||||
#include <openspace/camera/camera.h>
|
||||
#include <openspace/documentation/verifier.h>
|
||||
#include <openspace/engine/globals.h>
|
||||
#include <openspace/engine/globalscallbacks.h>
|
||||
#include <openspace/engine/moduleengine.h>
|
||||
#include <openspace/navigation/navigationhandler.h>
|
||||
#include <openspace/navigation/navigationstate.h>
|
||||
#include <openspace/navigation/orbitalnavigator.h>
|
||||
#include <openspace/query/query.h>
|
||||
#include <openspace/rendering/renderable.h>
|
||||
#include <openspace/rendering/renderengine.h>
|
||||
#include <openspace/scene/scene.h>
|
||||
#include <openspace/scene/scenegraphnode.h>
|
||||
#include <openspace/scripting/lualibrary.h>
|
||||
#include <openspace/util/factorymanager.h>
|
||||
#include <openspace/util/updatestructures.h>
|
||||
#include <ghoul/filesystem/filesystem.h>
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <ghoul/fmt.h>
|
||||
@@ -306,6 +318,9 @@ void GlobeBrowsingModule::internalInitialize(const ghoul::Dictionary& dict) {
|
||||
fTileProvider->registerClass<ImageSequenceTileProvider>(
|
||||
LAYER_TYPE_NAMES[static_cast<int>(TypeID::ImageSequenceTileLayer)]
|
||||
);
|
||||
fTileProvider->registerClass<SpoutImageProvider>(
|
||||
LAYER_TYPE_NAMES[static_cast<int>(TypeID::SpoutImageTileLayer)]
|
||||
);
|
||||
fTileProvider->registerClass<TemporalTileProvider>(
|
||||
LAYER_TYPE_NAMES[static_cast<int>(TypeID::TemporalTileLayer)]
|
||||
);
|
||||
@@ -334,141 +349,6 @@ globebrowsing::cache::MemoryAwareTileCache* GlobeBrowsingModule::tileCache() {
|
||||
return _tileCache.get();
|
||||
}
|
||||
|
||||
scripting::LuaLibrary GlobeBrowsingModule::luaLibrary() const {
|
||||
std::string listLayerGroups = layerGroupNamesList();
|
||||
|
||||
scripting::LuaLibrary res;
|
||||
res.name = "globebrowsing";
|
||||
res.functions = {
|
||||
{
|
||||
"addLayer",
|
||||
&globebrowsing::luascriptfunctions::addLayer,
|
||||
"string, string, table",
|
||||
"Adds a layer to the specified globe. The first argument specifies the "
|
||||
"name of the scene graph node of which to add the layer. The renderable "
|
||||
"of the specified scene graph node needs to be a renderable globe. "
|
||||
"The second argument is the layer group which can be any of "
|
||||
+ listLayerGroups + ". The third argument is the dictionary defining the "
|
||||
"layer."
|
||||
},
|
||||
{
|
||||
"deleteLayer",
|
||||
&globebrowsing::luascriptfunctions::deleteLayer,
|
||||
"string, string, (string, table)",
|
||||
"Removes a layer from the specified globe. The first argument specifies "
|
||||
"the name of the scene graph node of which to remove the layer. "
|
||||
"The renderable of the specified scene graph node needs to be a "
|
||||
"renderable globe. The second argument is the layer group which can be "
|
||||
"any of " + listLayerGroups + ". The third argument is either the identifier "
|
||||
"for the layer or a dictionary with the 'Identifier' key that is used instead"
|
||||
},
|
||||
{
|
||||
"getLayers",
|
||||
&globebrowsing::luascriptfunctions::getLayers,
|
||||
"string, string",
|
||||
"Returns the list of layers for the scene graph node specified in the first "
|
||||
"parameter. The second parameter specifies which layer type should be "
|
||||
"queried."
|
||||
},
|
||||
{
|
||||
"moveLayer",
|
||||
&globebrowsing::luascriptfunctions::moveLayer,
|
||||
"string, string, number, number",
|
||||
"Rearranges the order of a single layer on a globe. The first parameter"
|
||||
"is the identifier of the globe, the second parameter specifies "
|
||||
"the name of the layer group, the third parameter is the original position "
|
||||
"of the layer that should be moved and the last parameter is the new "
|
||||
"position in the list. The first position in the list has index 0, and the "
|
||||
"last position is given by the number of layers minus one. The new position "
|
||||
"may be -1 to place the layer at the top or any number bigger than the "
|
||||
"number of layers to place it at the bottom."
|
||||
},
|
||||
{
|
||||
"goToChunk",
|
||||
&globebrowsing::luascriptfunctions::goToChunk,
|
||||
"void",
|
||||
"Go to chunk with given index x, y, level"
|
||||
},
|
||||
{
|
||||
"goToGeo",
|
||||
&globebrowsing::luascriptfunctions::goToGeo,
|
||||
"[string], number, number, [number]",
|
||||
"Go to geographic coordinates of a globe. The first (optional) argument is "
|
||||
"the identifier of a scene graph node that has a RenderableGlobe attached. "
|
||||
"If no globe is passed in, the current anchor will be used. "
|
||||
"The second argument is latitude and the third is longitude (degrees). "
|
||||
"North and East are expressed as positive angles, while South and West are "
|
||||
"negative. The optional fourh argument is the altitude in meters. If no "
|
||||
"altitude is provided, the altitude will be kept as the current distance to "
|
||||
"the surface of the specified globe."
|
||||
},
|
||||
{
|
||||
// @TODO (2021-06-23, emmbr) Combine with the above function when the camera
|
||||
// paths work really well close to surfaces
|
||||
"flyToGeo",
|
||||
&globebrowsing::luascriptfunctions::flyToGeo,
|
||||
"[string], number, number, number [, bool, number]",
|
||||
"Fly the camera to geographic coordinates of a globe, using the path "
|
||||
"navigation system. The first (optional) argument is the identifier of a "
|
||||
"scene graph node with a RenderableGlobe. If no globe is passed in, the "
|
||||
"current anchor will be used. The second and third argument is latitude and "
|
||||
"longitude (degrees). The fourth argument is the altitude, in meters. The "
|
||||
"last two optional arguments are: a bool specifying whether the up vector "
|
||||
"at the target position should be set to the globe's North vector, and a "
|
||||
"duration for the motion, in seconds. Either of the two can be left out."
|
||||
},
|
||||
{
|
||||
"getLocalPositionFromGeo",
|
||||
&globebrowsing::luascriptfunctions::getLocalPositionFromGeo,
|
||||
"string, number, number, number",
|
||||
"Returns a position in the local Cartesian coordinate system of the globe "
|
||||
"identified by the first argument, that corresponds to the given geographic "
|
||||
"coordinates: latitude, longitude and altitude (in degrees and meters). In "
|
||||
"the local coordinate system, the position (0,0,0) corresponds to the "
|
||||
"globe's center."
|
||||
},
|
||||
{
|
||||
"getGeoPositionForCamera",
|
||||
&globebrowsing::luascriptfunctions::getGeoPositionForCamera,
|
||||
"void",
|
||||
"Get geographic coordinates of the camera position in latitude, "
|
||||
"longitude, and altitude (degrees and meters)."
|
||||
},
|
||||
{
|
||||
"loadWMSCapabilities",
|
||||
&globebrowsing::luascriptfunctions::loadWMSCapabilities,
|
||||
"string, string, string",
|
||||
"Loads and parses the WMS capabilities xml file from a remote server. "
|
||||
"The first argument is the name of the capabilities that can be used to "
|
||||
"later refer to the set of capabilities. The second argument is the "
|
||||
"globe for which this server is applicable. The third argument is the "
|
||||
"URL at which the capabilities file can be found."
|
||||
},
|
||||
{
|
||||
"removeWMSServer",
|
||||
&globebrowsing::luascriptfunctions::removeWMSServer,
|
||||
"string",
|
||||
"Removes the WMS server identified by the first argument from the list "
|
||||
"of available servers. The parameter corrsponds to the first argument in "
|
||||
"the loadWMSCapabilities call that was used to load the WMS server."
|
||||
},
|
||||
{
|
||||
"capabilitiesWMS",
|
||||
&globebrowsing::luascriptfunctions::capabilities,
|
||||
"string",
|
||||
"Returns an array of tables that describe the available layers that are "
|
||||
"supported by the WMS server identified by the provided name. The 'URL'"
|
||||
"component of the returned table can be used in the 'FilePath' argument "
|
||||
"for a call to the 'addLayer' function to add the value to a globe."
|
||||
}
|
||||
};
|
||||
res.scripts = {
|
||||
absPath("${MODULE_GLOBEBROWSING}/scripts/layer_support.lua")
|
||||
};
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
std::vector<documentation::Documentation> GlobeBrowsingModule::documentations() const {
|
||||
return {
|
||||
globebrowsing::Layer::Documentation(),
|
||||
@@ -817,4 +697,32 @@ uint64_t GlobeBrowsingModule::wmsCacheSize() const {
|
||||
return size * 1024 * 1024;
|
||||
}
|
||||
|
||||
scripting::LuaLibrary GlobeBrowsingModule::luaLibrary() const {
|
||||
std::string listLayerGroups = layerGroupNamesList();
|
||||
|
||||
scripting::LuaLibrary res;
|
||||
res.name = "globebrowsing";
|
||||
res.functions = {
|
||||
codegen::lua::AddLayer,
|
||||
codegen::lua::DeleteLayer,
|
||||
codegen::lua::GetLayers,
|
||||
codegen::lua::MoveLayer,
|
||||
codegen::lua::GoToChunk,
|
||||
codegen::lua::GoToGeo,
|
||||
// @TODO (2021-06-23, emmbr) Combine with the above function when the camera
|
||||
// paths work really well close to surfaces
|
||||
codegen::lua::FlyToGeo,
|
||||
codegen::lua::GetLocalPositionFromGeo,
|
||||
codegen::lua::GetGeoPositionForCamera,
|
||||
codegen::lua::LoadWMSCapabilities,
|
||||
codegen::lua::RemoveWMSServer,
|
||||
codegen::lua::Capabilities
|
||||
};
|
||||
res.scripts = {
|
||||
absPath("${MODULE_GLOBEBROWSING}/scripts/layer_support.lua")
|
||||
};
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -22,89 +22,78 @@
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#include <modules/globebrowsing/src/renderableglobe.h>
|
||||
|
||||
#include <modules/globebrowsing/src/layer.h>
|
||||
#include <modules/globebrowsing/src/layergroup.h>
|
||||
#include <modules/globebrowsing/src/layermanager.h>
|
||||
#include <openspace/camera/camera.h>
|
||||
#include <openspace/engine/globals.h>
|
||||
#include <openspace/engine/moduleengine.h>
|
||||
#include <openspace/navigation/navigationhandler.h>
|
||||
#include <openspace/rendering/renderable.h>
|
||||
#include <openspace/rendering/renderengine.h>
|
||||
#include <openspace/scene/scene.h>
|
||||
#include <openspace/scene/scenegraphnode.h>
|
||||
#include <openspace/query/query.h>
|
||||
#include <openspace/util/updatestructures.h>
|
||||
|
||||
namespace openspace::globebrowsing::luascriptfunctions {
|
||||
namespace {
|
||||
|
||||
/**
|
||||
* Adds a layer to the specified globe.
|
||||
* Adds a layer to the specified globe. The first argument specifies the name of the scene
|
||||
* graph node of which to add the layer. The renderable of the specified scene graph node
|
||||
* needs to be a renderable globe. The second argument is the layer group which can be any
|
||||
* of the supported layer groups. The third argument is the dictionary defining the layer.
|
||||
*/
|
||||
int addLayer(lua_State* L) {
|
||||
ZoneScoped
|
||||
|
||||
ghoul::lua::checkArgumentsAndThrow(L, 3, "lua::addLayer");
|
||||
auto [globeName, layerGroupName, layerDict] =
|
||||
ghoul::lua::values<std::string, std::string, ghoul::Dictionary>(L);
|
||||
[[codegen::luawrap]] void addLayer(std::string globeName, std::string layerGroupName,
|
||||
ghoul::Dictionary layer)
|
||||
{
|
||||
using namespace openspace;
|
||||
using namespace globebrowsing;
|
||||
|
||||
// Get the node and make sure it exists
|
||||
SceneGraphNode* n = global::renderEngine->scene()->sceneGraphNode(globeName);
|
||||
if (!n) {
|
||||
return ghoul::lua::luaError(L, "Unknown globe name: " + globeName);
|
||||
throw ghoul::lua::LuaError("Unknown globe name: " + globeName);
|
||||
}
|
||||
|
||||
// Get the renderable globe
|
||||
RenderableGlobe* globe = dynamic_cast<RenderableGlobe*>(n->renderable());
|
||||
if (!globe) {
|
||||
return ghoul::lua::luaError(L, "Renderable is not a globe: " + globeName);
|
||||
throw ghoul::lua::LuaError("Renderable is not a globe: " + globeName);
|
||||
}
|
||||
|
||||
// Get the layer group
|
||||
layergroupid::GroupID groupID = ghoul::from_string<layergroupid::GroupID>(
|
||||
layerGroupName
|
||||
);
|
||||
);
|
||||
if (groupID == layergroupid::GroupID::Unknown) {
|
||||
return ghoul::lua::luaError(L, "Unknown layer group: " + layerGroupName);
|
||||
throw ghoul::lua::LuaError("Unknown layer group: " + layerGroupName);
|
||||
}
|
||||
|
||||
// Get the dictionary defining the layer
|
||||
Layer* layer = globe->layerManager().addLayer(groupID, layerDict);
|
||||
if (layer) {
|
||||
layer->initialize();
|
||||
Layer* l = globe->layerManager().addLayer(groupID, layer);
|
||||
if (l) {
|
||||
l->initialize();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a layer from the specified globe.
|
||||
* Removes a layer from the specified globe. The first argument specifies the name of the
|
||||
* scene graph node of which to remove the layer. The renderable of the specified scene
|
||||
* graph node needs to be a renderable globe. The second argument is the layer group which
|
||||
* can be any of the supported layer groups. The third argument is either the identifier
|
||||
* for the layer or a dictionary with the 'Identifier' key that is used instead.
|
||||
*/
|
||||
int deleteLayer(lua_State* L) {
|
||||
ghoul::lua::checkArgumentsAndThrow(L, 3, "lua::deleteLayer");
|
||||
auto [globeName, layerGroupName, layerOrName] = ghoul::lua::values<
|
||||
std::string, std::string, std::variant<std::string, ghoul::Dictionary>
|
||||
>(L);
|
||||
[[codegen::luawrap]] void deleteLayer(std::string globeName, std::string layerGroupName,
|
||||
std::variant<std::string, ghoul::Dictionary> layerOrName)
|
||||
{
|
||||
using namespace openspace;
|
||||
using namespace globebrowsing;
|
||||
|
||||
// Get the node and make sure it exists
|
||||
SceneGraphNode* n = global::renderEngine->scene()->sceneGraphNode(globeName);
|
||||
if (!n) {
|
||||
return ghoul::lua::luaError(L, "Unknown globe name: " + globeName);
|
||||
throw ghoul::lua::LuaError("Unknown globe name: " + globeName);
|
||||
}
|
||||
|
||||
// Get the renderable globe
|
||||
RenderableGlobe* globe = dynamic_cast<RenderableGlobe*>(n->renderable());
|
||||
if (!globe) {
|
||||
return ghoul::lua::luaError(L, "Renderable is not a globe: " + globeName);
|
||||
throw ghoul::lua::LuaError("Renderable is not a globe: " + globeName);
|
||||
}
|
||||
|
||||
// Get the layer group
|
||||
layergroupid::GroupID groupID = ghoul::from_string<layergroupid::GroupID>(
|
||||
layerGroupName
|
||||
);
|
||||
);
|
||||
if (groupID == layergroupid::GroupID::Unknown) {
|
||||
return ghoul::lua::luaError(L, "Unknown layer group: " + layerGroupName);
|
||||
throw ghoul::lua::LuaError("Unknown layer group: " + layerGroupName);
|
||||
}
|
||||
|
||||
std::string layerName;
|
||||
@@ -112,15 +101,9 @@ int deleteLayer(lua_State* L) {
|
||||
layerName = std::get<std::string>(layerOrName);
|
||||
}
|
||||
else {
|
||||
ghoul_assert(
|
||||
std::holds_alternative<ghoul::Dictionary>(layerOrName),
|
||||
"Missing case"
|
||||
);
|
||||
|
||||
ghoul::Dictionary d = std::get<ghoul::Dictionary>(layerOrName);
|
||||
if (!d.hasValue<std::string>("Identifier")) {
|
||||
return ghoul::lua::luaError(
|
||||
L,
|
||||
throw ghoul::lua::LuaError(
|
||||
"Table passed to deleteLayer does not contain an Identifier"
|
||||
);
|
||||
}
|
||||
@@ -128,131 +111,144 @@ int deleteLayer(lua_State* L) {
|
||||
}
|
||||
|
||||
globe->layerManager().deleteLayer(groupID, layerName);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int getLayers(lua_State* L) {
|
||||
ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::getLayers");
|
||||
auto [globeIdentifier, layer] = ghoul::lua::values<std::string, std::string>(L);
|
||||
/**
|
||||
* Returns the list of layers for the scene graph node specified in the first parameter.
|
||||
* The second parameter specifies which layer type should be queried.
|
||||
*/
|
||||
[[codegen::luawrap]] std::vector<std::string> getLayers(std::string globeIdentifier,
|
||||
std::string layer)
|
||||
{
|
||||
using namespace openspace;
|
||||
using namespace globebrowsing;
|
||||
|
||||
SceneGraphNode* n = sceneGraphNode(globeIdentifier);
|
||||
if (!n) {
|
||||
return ghoul::lua::luaError(L, "Unknown globe name: " + globeIdentifier);
|
||||
throw ghoul::lua::LuaError("Unknown globe name: " + globeIdentifier);
|
||||
}
|
||||
|
||||
const RenderableGlobe* globe = dynamic_cast<const RenderableGlobe*>(n->renderable());
|
||||
if (!globe) {
|
||||
return ghoul::lua::luaError(L, "Identifier must be a RenderableGlobe");
|
||||
throw ghoul::lua::LuaError("Identifier must be a RenderableGlobe");
|
||||
}
|
||||
|
||||
globebrowsing::layergroupid::GroupID group =
|
||||
ghoul::from_string<globebrowsing::layergroupid::GroupID>(layer);
|
||||
if (group == globebrowsing::layergroupid::GroupID::Unknown) {
|
||||
return ghoul::lua::luaError(L, "Unknown layer groupd: " + layer);
|
||||
throw ghoul::lua::LuaError("Unknown layer groupd: " + layer);
|
||||
}
|
||||
|
||||
const globebrowsing::LayerGroup& lg = globe->layerManager().layerGroup(group);
|
||||
std::vector<globebrowsing::Layer*> layers = lg.layers();
|
||||
|
||||
lua_newtable(L);
|
||||
int key = 1;
|
||||
std::vector<std::string> res;
|
||||
res.reserve(layers.size());
|
||||
for (globebrowsing::Layer* l : layers) {
|
||||
ghoul::lua::push(L, key, l->identifier());
|
||||
lua_settable(L, -3);
|
||||
key++;
|
||||
res.push_back(l->identifier());
|
||||
}
|
||||
return 1;
|
||||
return res;
|
||||
}
|
||||
|
||||
int moveLayer(lua_State* L) {
|
||||
ghoul::lua::checkArgumentsAndThrow(L, 4, "lua::moveLayer");
|
||||
auto [globeIdentifier, layer, oldPosition, newPosition] =
|
||||
ghoul::lua::values<std::string, std::string, int, int>(L);
|
||||
/**
|
||||
* Rearranges the order of a single layer on a globe. The first parameter is the
|
||||
* identifier of the globe, the second parameter specifies the name of the layer group,
|
||||
* the third parameter is the original position of the layer that should be moved and the
|
||||
* last parameter is the new position in the list. The first position in the list has
|
||||
* index 0, and the last position is given by the number of layers minus one. The new
|
||||
* position may be -1 to place the layer at the top or any number bigger than the number
|
||||
* of layers to place it at the bottom.
|
||||
*/
|
||||
[[codegen::luawrap]] void moveLayer(std::string globeIdentifier, std::string layer,
|
||||
int oldPosition, int newPosition)
|
||||
{
|
||||
using namespace openspace;
|
||||
using namespace globebrowsing;
|
||||
|
||||
if (oldPosition == newPosition) {
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
SceneGraphNode* n = sceneGraphNode(globeIdentifier);
|
||||
if (!n) {
|
||||
return ghoul::lua::luaError(L, "Unknown globe name: " + globeIdentifier);
|
||||
throw ghoul::lua::LuaError("Unknown globe name: " + globeIdentifier);
|
||||
}
|
||||
|
||||
RenderableGlobe* globe = dynamic_cast<RenderableGlobe*>(n->renderable());
|
||||
if (!globe) {
|
||||
return ghoul::lua::luaError(L, "Identifier must be a RenderableGlobe");
|
||||
throw ghoul::lua::LuaError("Identifier must be a RenderableGlobe");
|
||||
}
|
||||
|
||||
globebrowsing::layergroupid::GroupID group =
|
||||
ghoul::from_string<globebrowsing::layergroupid::GroupID>(layer);
|
||||
if (group == globebrowsing::layergroupid::GroupID::Unknown) {
|
||||
return ghoul::lua::luaError(L, "Unknown layer groupd: " + layer);
|
||||
throw ghoul::lua::LuaError("Unknown layer groupd: " + layer);
|
||||
}
|
||||
|
||||
globebrowsing::LayerGroup& lg = globe->layerManager().layerGroup(group);
|
||||
lg.moveLayer(oldPosition, newPosition);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int goToChunk(lua_State* L) {
|
||||
ghoul::lua::checkArgumentsAndThrow(L, 4, "lua::goToChunk");
|
||||
auto [identifier, x, y, level] = ghoul::lua::values<std::string, int, int, int>(L);
|
||||
/**
|
||||
* Go to the chunk on a globe with given index x, y, level.
|
||||
*/
|
||||
[[codegen::luawrap]] void goToChunk(std::string identifier, int x, int y, int level) {
|
||||
using namespace openspace;
|
||||
using namespace globebrowsing;
|
||||
|
||||
SceneGraphNode* n = sceneGraphNode(identifier);
|
||||
if (!n) {
|
||||
return ghoul::lua::luaError(L, "Unknown globe name: " + identifier);
|
||||
throw ghoul::lua::LuaError("Unknown globe name: " + identifier);
|
||||
}
|
||||
|
||||
const RenderableGlobe* globe = dynamic_cast<const RenderableGlobe*>(n->renderable());
|
||||
if (!globe) {
|
||||
return ghoul::lua::luaError(L, "Identifier must be a RenderableGlobe");
|
||||
throw ghoul::lua::LuaError("Identifier must be a RenderableGlobe");
|
||||
}
|
||||
|
||||
global::moduleEngine->module<GlobeBrowsingModule>()->goToChunk(*globe, x, y, level);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int goToGeo(lua_State* L) {
|
||||
ghoul::lua::checkArgumentsAndThrow(L, { 2, 4 }, "lua::goToGeo");
|
||||
/**
|
||||
* Go to geographic coordinates of a globe. The first (optional) argument is the
|
||||
* identifier of a scene graph node that has a RenderableGlobe attached. If no globe is
|
||||
* passed in, the current anchor will be used. The second argument is latitude and the
|
||||
* third is longitude (degrees). North and East are expressed as positive angles, while
|
||||
* South and West are negative. The optional fourh argument is the altitude in meters. If
|
||||
* no altitude is provided, the altitude will be kept as the current distance to the
|
||||
* surface of the specified globe.
|
||||
*/
|
||||
[[codegen::luawrap]] void goToGeo(std::optional<std::string> globe, double latitude,
|
||||
double longitude, std::optional<double> altitude)
|
||||
{
|
||||
using namespace openspace;
|
||||
using namespace globebrowsing;
|
||||
|
||||
// Check if the user provided a Scene graph node identifier as the first argument.
|
||||
// lua_isstring returns true for both numbers and strings, so better use !lua_isnumber
|
||||
const bool providedGlobeIdentifier = !lua_isnumber(L, 1);
|
||||
const SceneGraphNode* n;
|
||||
if (providedGlobeIdentifier) {
|
||||
const std::string& globeIdentifier = ghoul::lua::value<std::string>(L);
|
||||
n = sceneGraphNode(globeIdentifier);
|
||||
if (globe.has_value()) {
|
||||
n = sceneGraphNode(*globe);
|
||||
if (!n) {
|
||||
return ghoul::lua::luaError(L, "Unknown globe name: " + globeIdentifier);
|
||||
throw ghoul::lua::LuaError("Unknown globe name: " + *globe);
|
||||
}
|
||||
}
|
||||
else {
|
||||
n = global::navigationHandler->orbitalNavigator().anchorNode();
|
||||
if (!n) {
|
||||
return ghoul::lua::luaError(L, "No anchor node is set.");
|
||||
throw ghoul::lua::LuaError("No anchor node is set.");
|
||||
}
|
||||
}
|
||||
|
||||
auto [latitude, longitude, altitude] =
|
||||
ghoul::lua::values<double, double, std::optional<double>>(L);
|
||||
|
||||
const RenderableGlobe* globe = dynamic_cast<const RenderableGlobe*>(n->renderable());
|
||||
if (!globe) {
|
||||
if (providedGlobeIdentifier) {
|
||||
return ghoul::lua::luaError(L, "Identifier must be a RenderableGlobe");
|
||||
}
|
||||
else {
|
||||
return ghoul::lua::luaError(
|
||||
L,
|
||||
"Current anchor node is not a RenderableGlobe. Either change the anchor "
|
||||
"to a globe, or specify a globe identifier as the first argument"
|
||||
);
|
||||
}
|
||||
const RenderableGlobe* gl = dynamic_cast<const RenderableGlobe*>(n->renderable());
|
||||
if (!gl) {
|
||||
throw ghoul::lua::LuaError(
|
||||
"Current anchor node is not a RenderableGlobe. Either change the anchor "
|
||||
"to a globe, or specify a globe identifier as the first argument"
|
||||
);
|
||||
}
|
||||
|
||||
if (altitude.has_value()) {
|
||||
global::moduleEngine->module<GlobeBrowsingModule>()->goToGeo(
|
||||
*globe,
|
||||
*gl,
|
||||
latitude,
|
||||
longitude,
|
||||
*altitude
|
||||
@@ -260,63 +256,52 @@ int goToGeo(lua_State* L) {
|
||||
}
|
||||
else {
|
||||
global::moduleEngine->module<GlobeBrowsingModule>()->goToGeo(
|
||||
*globe,
|
||||
*gl,
|
||||
latitude,
|
||||
longitude
|
||||
);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int flyToGeo(lua_State* L) {
|
||||
int nArguments = ghoul::lua::checkArgumentsAndThrow(L, { 3, 6 }, "lua::flyToGeo");
|
||||
|
||||
// Check if the user provided a Scene graph node identifier as the first argument.
|
||||
// lua_isstring returns true for both numbers and strings, so better use !lua_isnumber
|
||||
const bool providedGlobeIdentifier = !lua_isnumber(L, 1);
|
||||
const int parameterOffset = providedGlobeIdentifier ? 1 : 0;
|
||||
/**
|
||||
* Fly the camera to geographic coordinates of a globe, using the path navigation system.
|
||||
* The first (optional) argument is the identifier of a scene graph node with a
|
||||
* RenderableGlobe. If no globe is passed in, the current anchor will be used. The second
|
||||
* and third argument is latitude and longitude (degrees). The fourth argument is the
|
||||
* altitude, in meters. The last two optional arguments are: a bool specifying whether the
|
||||
* up vector at the target position should be set to the globe's North vector, and a
|
||||
* duration for the motion, in seconds. Either of the two can be left out.
|
||||
*/
|
||||
[[codegen::luawrap]] void flyToGeo(std::optional<std::string> globe, double latitude,
|
||||
double longitude, double altitude,
|
||||
std::optional<double> duration,
|
||||
std::optional<bool> shouldUseUpVector)
|
||||
{
|
||||
using namespace openspace;
|
||||
using namespace globebrowsing;
|
||||
|
||||
const SceneGraphNode* n;
|
||||
if (providedGlobeIdentifier) {
|
||||
const std::string& globeIdentifier =
|
||||
ghoul::lua::value<std::string>(L, 1, ghoul::lua::PopValue::No);
|
||||
n = sceneGraphNode(globeIdentifier);
|
||||
if (globe.has_value()) {
|
||||
n = sceneGraphNode(*globe);
|
||||
if (!n) {
|
||||
return ghoul::lua::luaError(L, "Unknown globe name: " + globeIdentifier);
|
||||
throw ghoul::lua::LuaError("Unknown globe name: " + *globe);
|
||||
}
|
||||
}
|
||||
else {
|
||||
n = global::navigationHandler->orbitalNavigator().anchorNode();
|
||||
if (!n) {
|
||||
return ghoul::lua::luaError(L, "No anchor node is set.");
|
||||
throw ghoul::lua::LuaError("No anchor node is set.");
|
||||
}
|
||||
}
|
||||
|
||||
const RenderableGlobe* globe = dynamic_cast<const RenderableGlobe*>(n->renderable());
|
||||
if (!globe) {
|
||||
if (providedGlobeIdentifier) {
|
||||
return ghoul::lua::luaError(L, "Identifier must be a RenderableGlobe");
|
||||
}
|
||||
else {
|
||||
return ghoul::lua::luaError(L,
|
||||
"Current anchor node is not a RenderableGlobe. "
|
||||
"Either change the anchor to a globe, or specify a globe identifier "
|
||||
"as the first argument"
|
||||
);
|
||||
}
|
||||
const RenderableGlobe* gl = dynamic_cast<const RenderableGlobe*>(n->renderable());
|
||||
if (!gl) {
|
||||
throw ghoul::lua::LuaError("Current anchor node is not a RenderableGlobe");
|
||||
}
|
||||
|
||||
const double latitude =
|
||||
ghoul::lua::value<double>(L, parameterOffset + 1, ghoul::lua::PopValue::No);
|
||||
const double longitude =
|
||||
ghoul::lua::value<double>(L, parameterOffset + 2, ghoul::lua::PopValue::No);
|
||||
const double altitude =
|
||||
ghoul::lua::value<double>(L, parameterOffset + 3, ghoul::lua::PopValue::No);
|
||||
|
||||
// Compute the relative position based on the input values
|
||||
auto module = global::moduleEngine->module<GlobeBrowsingModule>();
|
||||
const glm::dvec3 positionModelCoords = module->cartesianCoordinatesFromGeo(
|
||||
*globe,
|
||||
*gl,
|
||||
latitude,
|
||||
longitude,
|
||||
altitude
|
||||
@@ -324,12 +309,12 @@ int flyToGeo(lua_State* L) {
|
||||
|
||||
const glm::dvec3 currentPosW = global::navigationHandler->camera()->positionVec3();
|
||||
const glm::dvec3 currentPosModelCoords =
|
||||
glm::inverse(globe->modelTransform()) * glm::dvec4(currentPosW, 1.0);
|
||||
glm::inverse(gl->modelTransform()) * glm::dvec4(currentPosW, 1.0);
|
||||
|
||||
constexpr const double LengthEpsilon = 10.0; // meters
|
||||
if (glm::distance(currentPosModelCoords, positionModelCoords) < LengthEpsilon) {
|
||||
LINFOC("GlobeBrowsing", "flyToGeo: Already at the requested position");
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
ghoul::Dictionary instruction;
|
||||
@@ -338,83 +323,63 @@ int flyToGeo(lua_State* L) {
|
||||
instruction.setValue("Position", positionModelCoords);
|
||||
instruction.setValue("PathType", std::string("ZoomOutOverview"));
|
||||
|
||||
// Handle the two optional arguments: duration and use target's up direction argument
|
||||
// The user can either provide both, or one of them
|
||||
if (nArguments >= parameterOffset + 4) {
|
||||
const int firstLocation = parameterOffset + 4;
|
||||
const bool firstIsNumber = (lua_isnumber(L, firstLocation) != 0);
|
||||
const bool firstIsBool = (lua_isboolean(L, firstLocation) != 0);
|
||||
|
||||
if (!(firstIsNumber || firstIsBool)) {
|
||||
const char* msg = lua_pushfstring(
|
||||
L,
|
||||
"%s or %s expected, got %s",
|
||||
lua_typename(L, LUA_TNUMBER),
|
||||
lua_typename(L, LUA_TBOOLEAN),
|
||||
luaL_typename(L, -1)
|
||||
);
|
||||
return ghoul::lua::luaError(
|
||||
L, fmt::format("bad argument #{} ({})", firstLocation, msg)
|
||||
);
|
||||
if (duration.has_value()) {
|
||||
constexpr const double Epsilon = 1e-5;
|
||||
if (*duration <= Epsilon) {
|
||||
throw ghoul::lua::LuaError("Duration must be larger than zero");
|
||||
}
|
||||
instruction.setValue("Duration", *duration);
|
||||
}
|
||||
|
||||
int location = firstLocation;
|
||||
if (firstIsBool) {
|
||||
const bool useUpFromTarget = (lua_toboolean(L, location) == 1);
|
||||
instruction.setValue("UseTargetUpDirection", useUpFromTarget);
|
||||
if (shouldUseUpVector.has_value()) {
|
||||
instruction.setValue("UseTargetUpDirection", *shouldUseUpVector);
|
||||
|
||||
if (nArguments > location) {
|
||||
location++;
|
||||
}
|
||||
}
|
||||
|
||||
if (firstIsNumber || nArguments > firstLocation) {
|
||||
double duration =
|
||||
ghoul::lua::value<double>(L, location, ghoul::lua::PopValue::No);
|
||||
constexpr const double Epsilon = 1e-5;
|
||||
if (duration <= Epsilon) {
|
||||
return ghoul::lua::luaError(L, "Duration must be larger than zero");
|
||||
}
|
||||
instruction.setValue("Duration", duration);
|
||||
}
|
||||
}
|
||||
|
||||
global::navigationHandler->pathNavigator().createPath(instruction);
|
||||
global::navigationHandler->pathNavigator().startPath();
|
||||
|
||||
lua_settop(L, 0);
|
||||
|
||||
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int getLocalPositionFromGeo(lua_State* L) {
|
||||
ghoul::lua::checkArgumentsAndThrow(L, 4, "lua::getLocalPositionFromGeo");
|
||||
auto [globeIdentifier, latitude, longitude, altitude] =
|
||||
ghoul::lua::values<std::string, double, double, double>(L);
|
||||
|
||||
/**
|
||||
* Returns a position in the local Cartesian coordinate system of the globe identified by
|
||||
* the first argument, that corresponds to the given geographic coordinates: latitude,
|
||||
* longitude and altitude (in degrees and meters). In the local coordinate system, the
|
||||
* position (0,0,0) corresponds to the globe's center.
|
||||
*/
|
||||
[[codegen::luawrap]]
|
||||
std::tuple<double, double, double>
|
||||
getLocalPositionFromGeo(std::string globeIdentifier, double latitude, double longitude,
|
||||
double altitude)
|
||||
{
|
||||
using namespace openspace;
|
||||
using namespace globebrowsing;
|
||||
|
||||
SceneGraphNode* n = sceneGraphNode(globeIdentifier);
|
||||
if (!n) {
|
||||
return ghoul::lua::luaError(L, "Unknown globe identifier: " + globeIdentifier);
|
||||
throw ghoul::lua::LuaError("Unknown globe identifier: " + globeIdentifier);
|
||||
}
|
||||
const RenderableGlobe* globe = dynamic_cast<const RenderableGlobe*>(n->renderable());
|
||||
if (!globe) {
|
||||
return ghoul::lua::luaError(L, "Identifier must be a RenderableGlobe");
|
||||
throw ghoul::lua::LuaError("Identifier must be a RenderableGlobe");
|
||||
}
|
||||
|
||||
GlobeBrowsingModule& mod = *(global::moduleEngine->module<GlobeBrowsingModule>());
|
||||
glm::vec3 p = mod.cartesianCoordinatesFromGeo(*globe, latitude, longitude, altitude);
|
||||
ghoul::lua::push(L, p.x, p.y, p.z);
|
||||
return 3;
|
||||
return { p.x, p.y, p.z };
|
||||
}
|
||||
|
||||
int getGeoPositionForCamera(lua_State* L) {
|
||||
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::getGeoPositionForCamera");
|
||||
/**
|
||||
* Get geographic coordinates of the camera position in latitude, longitude, and altitude
|
||||
* (degrees and meters).
|
||||
*/
|
||||
[[codegen::luawrap]] std::tuple<double, double, double> getGeoPositionForCamera() {
|
||||
using namespace openspace;
|
||||
using namespace globebrowsing;
|
||||
|
||||
GlobeBrowsingModule* module = global::moduleEngine->module<GlobeBrowsingModule>();
|
||||
const RenderableGlobe* globe = module->castFocusNodeRenderableToGlobe();
|
||||
if (!globe) {
|
||||
return ghoul::lua::luaError(L, "Focus node must be a RenderableGlobe");
|
||||
throw ghoul::lua::LuaError("Focus node must be a RenderableGlobe");
|
||||
}
|
||||
|
||||
const glm::dvec3 cameraPosition = global::navigationHandler->camera()->positionVec3();
|
||||
@@ -430,53 +395,66 @@ int getGeoPositionForCamera(lua_State* L) {
|
||||
const Geodetic2 geo2 = globe->ellipsoid().cartesianToGeodetic2(
|
||||
posHandle.centerToReferenceSurface
|
||||
);
|
||||
const double altitude = glm::length(cameraPositionModelSpace -
|
||||
posHandle.centerToReferenceSurface);
|
||||
const double altitude = glm::length(
|
||||
cameraPositionModelSpace - posHandle.centerToReferenceSurface
|
||||
);
|
||||
|
||||
ghoul::lua::push(L, glm::degrees(geo2.lat), glm::degrees(geo2.lon), altitude);
|
||||
return 3;
|
||||
return { glm::degrees(geo2.lat), glm::degrees(geo2.lon), altitude };
|
||||
}
|
||||
|
||||
int loadWMSCapabilities(lua_State* L) {
|
||||
ghoul::lua::checkArgumentsAndThrow(L, 3, "lua::loadWMSCapabilities");
|
||||
auto [name, globe, url] =
|
||||
ghoul::lua::values<std::string, std::string, std::string>(L);
|
||||
|
||||
/**
|
||||
* Loads and parses the WMS capabilities xml file from a remote server. The first argument
|
||||
* is the name of the capabilities that can be used to later refer to the set of
|
||||
* capabilities. The second argument is the globe for which this server is applicable. The
|
||||
* third argument is the URL at which the capabilities file can be found.
|
||||
*/
|
||||
[[codegen::luawrap]] void loadWMSCapabilities(std::string name, std::string globe,
|
||||
std::string url)
|
||||
{
|
||||
using namespace openspace;
|
||||
using namespace globebrowsing;
|
||||
global::moduleEngine->module<GlobeBrowsingModule>()->loadWMSCapabilities(
|
||||
std::move(name),
|
||||
std::move(globe),
|
||||
std::move(url)
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int removeWMSServer(lua_State* L) {
|
||||
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::removeWMSServer");
|
||||
const std::string name = ghoul::lua::value<std::string>(L);
|
||||
|
||||
/**
|
||||
* Removes the WMS server identified by the first argument from the list of available
|
||||
* servers. The parameter corrsponds to the first argument in the loadWMSCapabilities call
|
||||
* that was used to load the WMS server.
|
||||
*/
|
||||
[[codegen::luawrap]] void removeWMSServer(std::string name) {
|
||||
using namespace openspace;
|
||||
using namespace globebrowsing;
|
||||
global::moduleEngine->module<GlobeBrowsingModule>()->removeWMSServer(name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int capabilities(lua_State* L) {
|
||||
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::capabilities");
|
||||
const std::string name = ghoul::lua::value<std::string>(L);
|
||||
/**
|
||||
* Returns an array of tables that describe the available layers that are supported by the
|
||||
* WMS server identified by the provided name. The 'URL' component of the returned table
|
||||
* can be used in the 'FilePath' argument for a call to the 'addLayer' function to add the
|
||||
* value to a globe.
|
||||
*/
|
||||
[[codegen::luawrap]] std::vector<ghoul::Dictionary> capabilities(std::string name) {
|
||||
using namespace openspace;
|
||||
using namespace globebrowsing;
|
||||
|
||||
GlobeBrowsingModule::Capabilities cap =
|
||||
global::moduleEngine->module<GlobeBrowsingModule>()->capabilities(name);
|
||||
|
||||
lua_newtable(L);
|
||||
std::vector<ghoul::Dictionary> res;
|
||||
res.reserve(cap.size());
|
||||
for (size_t i = 0; i < cap.size(); ++i) {
|
||||
const GlobeBrowsingModule::Layer& l = cap[i];
|
||||
|
||||
lua_newtable(L);
|
||||
ghoul::lua::push(L, "Name", l.name);
|
||||
lua_settable(L, -3);
|
||||
ghoul::lua::push(L, "URL", l.url);
|
||||
lua_settable(L, -3);
|
||||
lua_rawseti(L, -2, i + 1);
|
||||
ghoul::Dictionary c;
|
||||
c.setValue("Name", cap[i].name);
|
||||
c.setValue("URL", cap[i].url);
|
||||
res.push_back(c);
|
||||
}
|
||||
return 1;
|
||||
return res;
|
||||
}
|
||||
|
||||
} // namespace openspace::globebrowsing::luascriptfunctions
|
||||
#include "globebrowsingmodule_lua_codegen.cpp"
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -2,4 +2,9 @@ set (OPENSPACE_DEPENDENCIES
|
||||
debugging
|
||||
)
|
||||
|
||||
# Don't **actually** add it as a dependency. Only mark it as a dependency if it was already enabled anyway. We need to do this as the GlobeBrowsing partially depends on being able to detect if OpenSpace was compiled with Spout support or not
|
||||
if (OPENSPACE_MODULE_SPOUT)
|
||||
set(OPENSPACE_DEPENDENCIES ${OPENSPACE_DEPENDENCIES} spout)
|
||||
endif (OPENSPACE_MODULE_SPOUT)
|
||||
|
||||
set (DEFAULT_MODULE ON)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
openspace.globebrowsing.documentation = {
|
||||
{
|
||||
Name = "createTemporalGibsGdalXml",
|
||||
Arguments = "string, string, string",
|
||||
Arguments = { layerName = "String", resolution = "String", format = "String" },
|
||||
Documentation = [[
|
||||
Creates an XML configuration for a temporal GIBS dataset to be used in
|
||||
a TemporalTileprovider
|
||||
@@ -9,7 +9,7 @@ openspace.globebrowsing.documentation = {
|
||||
},
|
||||
{
|
||||
Name = "createGibsGdalXml",
|
||||
Arguments = "string, string, string, string",
|
||||
Arguments = { layerName = "String", date = "String", resolution = "String", format = "String" },
|
||||
Documentation =
|
||||
"Creates an XML configuration for a GIBS dataset." ..
|
||||
"Arguments are: layerName, date, resolution, format." ..
|
||||
@@ -32,7 +32,7 @@ openspace.globebrowsing.documentation = {
|
||||
},
|
||||
{
|
||||
Name = "addGibsLayer",
|
||||
Arguments = "string, string, string, string, string",
|
||||
Arguments = { layer = "String", resolution = "String", format = "String", startDate = "String", endDate = "String" },
|
||||
Documentation = "Adds a new layer from NASA GIBS to the Earth globe. Arguments " ..
|
||||
"are: imagery layer name, imagery resolution, start date, end date, format. " ..
|
||||
"For all specifications, see " ..
|
||||
@@ -42,7 +42,7 @@ openspace.globebrowsing.documentation = {
|
||||
},
|
||||
{
|
||||
Name = "parseInfoFile",
|
||||
Arguments = "string",
|
||||
Arguments = { file = "String" },
|
||||
Documentation =
|
||||
"Parses the passed info file and return the table with the information " ..
|
||||
"provided in the info file. The return table contains the optional keys: " ..
|
||||
@@ -53,7 +53,7 @@ openspace.globebrowsing.documentation = {
|
||||
},
|
||||
{
|
||||
Name = "addBlendingLayersFromDirectory",
|
||||
Arguments = "string, string",
|
||||
Arguments = { directory = "String", nodeName = "String" },
|
||||
Documentation =
|
||||
"Retrieves all info files recursively in the directory passed as the first " ..
|
||||
"argument to this function. The color and height tables retrieved from these " ..
|
||||
@@ -63,7 +63,7 @@ openspace.globebrowsing.documentation = {
|
||||
},
|
||||
{
|
||||
Name = "addFocusNodesFromDirectory",
|
||||
Arguments = "string, string",
|
||||
Arguments = { directory = "String", nodeName = "String" },
|
||||
Documentation =
|
||||
"Retrieves all info files recursively in the directory passed as the first " ..
|
||||
"argument to this function. The name and location retrieved from these info " ..
|
||||
@@ -73,7 +73,7 @@ openspace.globebrowsing.documentation = {
|
||||
},
|
||||
{
|
||||
Name = "addFocusNodeFromLatLong",
|
||||
Arguments = "string, string, number, number, number",
|
||||
Arguments = { name = "String", globeIdentifier = "String", latitude = "Number", longitude = "Number", altitude = "Number" },
|
||||
Documentation =
|
||||
"Creates a new SceneGraphNode that can be used as focus node. " ..
|
||||
"Usage: openspace.globebrowsing.addFocusNodeFromLatLong(" ..
|
||||
@@ -81,7 +81,7 @@ openspace.globebrowsing.documentation = {
|
||||
},
|
||||
{
|
||||
Name = "loadWMSServersFromFile",
|
||||
Arguments = "string",
|
||||
Arguments = { filePath = "String" },
|
||||
Documentation =
|
||||
"Loads all WMS servers from the provided file and passes them to the " ..
|
||||
"'openspace.globebrowsing.loadWMSCapabilities' file."
|
||||
|
||||
@@ -163,7 +163,8 @@ vec4 getSample#{layerGroup}#{i}(vec2 uv, vec3 levelWeights,
|
||||
c = getTexVal(#{layerGroup}[#{i}].pile, levelWeights, uv, #{layerGroup}[#{i}].padding);
|
||||
#elif (#{#{layerGroup}#{i}LayerType} == 8) // SolidColor
|
||||
c.rgb = #{layerGroup}[#{i}].color;
|
||||
|
||||
#elif (#{#{layerGroup}#{i}LayerType} == 9) // SpoutImageTileLayer
|
||||
c = getTexVal(#{layerGroup}[#{i}].pile, levelWeights, uv, #{layerGroup}[#{i}].padding);
|
||||
#endif
|
||||
|
||||
return c;
|
||||
|
||||
@@ -68,6 +68,7 @@ void GPULayerGroup::setValue(ghoul::opengl::ProgramObject& program,
|
||||
// Intentional fall through. Same for all tile layers
|
||||
case layergroupid::TypeID::DefaultTileLayer:
|
||||
case layergroupid::TypeID::SingleImageTileLayer:
|
||||
case layergroupid::TypeID::SpoutImageTileLayer:
|
||||
case layergroupid::TypeID::ImageSequenceTileLayer:
|
||||
case layergroupid::TypeID::SizeReferenceTileLayer:
|
||||
case layergroupid::TypeID::TemporalTileLayer:
|
||||
@@ -149,6 +150,7 @@ void GPULayerGroup::bind(ghoul::opengl::ProgramObject& p,
|
||||
// Intentional fall through. Same for all tile layers
|
||||
case layergroupid::TypeID::DefaultTileLayer:
|
||||
case layergroupid::TypeID::SingleImageTileLayer:
|
||||
case layergroupid::TypeID::SpoutImageTileLayer:
|
||||
case layergroupid::TypeID::ImageSequenceTileLayer:
|
||||
case layergroupid::TypeID::SizeReferenceTileLayer:
|
||||
case layergroupid::TypeID::TemporalTileLayer:
|
||||
|
||||
@@ -115,7 +115,7 @@ namespace {
|
||||
std::optional<std::string> type [[codegen::inlist("DefaultTileLayer",
|
||||
"SingleImageTileLayer", "ImageSequenceTileLayer", "SizeReferenceTileLayer",
|
||||
"TemporalTileLayer", "TileIndexTileLayer", "ByIndexTileLayer",
|
||||
"ByLevelTileLayer", "SolidColor")]];
|
||||
"ByLevelTileLayer", "SolidColor", "SpoutImageTileLayer")]];
|
||||
|
||||
// Determine whether the layer is enabled or not. If this value is not specified,
|
||||
// the layer is disabled
|
||||
@@ -302,6 +302,7 @@ Layer::Layer(layergroupid::GroupID id, const ghoul::Dictionary& layerDict,
|
||||
// Intentional fall through. Same for all tile layers
|
||||
case layergroupid::TypeID::DefaultTileLayer:
|
||||
case layergroupid::TypeID::SingleImageTileLayer:
|
||||
case layergroupid::TypeID::SpoutImageTileLayer:
|
||||
case layergroupid::TypeID::ImageSequenceTileLayer:
|
||||
case layergroupid::TypeID::SizeReferenceTileLayer:
|
||||
case layergroupid::TypeID::TemporalTileLayer:
|
||||
@@ -470,6 +471,7 @@ void Layer::initializeBasedOnType(layergroupid::TypeID id, ghoul::Dictionary ini
|
||||
// Intentional fall through. Same for all tile layers
|
||||
case layergroupid::TypeID::DefaultTileLayer:
|
||||
case layergroupid::TypeID::SingleImageTileLayer:
|
||||
case layergroupid::TypeID::SpoutImageTileLayer:
|
||||
case layergroupid::TypeID::ImageSequenceTileLayer:
|
||||
case layergroupid::TypeID::SizeReferenceTileLayer:
|
||||
case layergroupid::TypeID::TemporalTileLayer:
|
||||
@@ -502,6 +504,7 @@ void Layer::addVisibleProperties() {
|
||||
// Intentional fall through. Same for all tile layers
|
||||
case layergroupid::TypeID::DefaultTileLayer:
|
||||
case layergroupid::TypeID::SingleImageTileLayer:
|
||||
case layergroupid::TypeID::SpoutImageTileLayer:
|
||||
case layergroupid::TypeID::ImageSequenceTileLayer:
|
||||
case layergroupid::TypeID::SizeReferenceTileLayer:
|
||||
case layergroupid::TypeID::TemporalTileLayer:
|
||||
|
||||
@@ -56,7 +56,7 @@ enum GroupID {
|
||||
Unknown
|
||||
};
|
||||
|
||||
static constexpr const int NUM_LAYER_TYPES = 9;
|
||||
static constexpr const int NUM_LAYER_TYPES = 10;
|
||||
static constexpr const char* LAYER_TYPE_NAMES[NUM_LAYER_TYPES] = {
|
||||
"DefaultTileLayer",
|
||||
"SingleImageTileLayer",
|
||||
@@ -66,7 +66,8 @@ static constexpr const char* LAYER_TYPE_NAMES[NUM_LAYER_TYPES] = {
|
||||
"TileIndexTileLayer",
|
||||
"ByIndexTileLayer",
|
||||
"ByLevelTileLayer",
|
||||
"SolidColor"
|
||||
"SolidColor",
|
||||
"SpoutImageTileLayer"
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -82,7 +83,8 @@ enum class TypeID {
|
||||
TileIndexTileLayer = 5,
|
||||
ByIndexTileLayer = 6,
|
||||
ByLevelTileLayer = 7,
|
||||
SolidColor = 8
|
||||
SolidColor = 8,
|
||||
SpoutImageTileLayer = 9
|
||||
};
|
||||
|
||||
static constexpr int NUM_ADJUSTMENT_TYPES = 3;
|
||||
|
||||
@@ -195,6 +195,11 @@ void DefaultTileProvider::reset() {
|
||||
_asyncTextureDataProvider->prepareToBeDeleted();
|
||||
}
|
||||
|
||||
int DefaultTileProvider::minLevel() {
|
||||
ghoul_assert(_asyncTextureDataProvider, "No data provider");
|
||||
return 1;
|
||||
}
|
||||
|
||||
int DefaultTileProvider::maxLevel() {
|
||||
ghoul_assert(_asyncTextureDataProvider, "No data provider");
|
||||
return _asyncTextureDataProvider->rawTileDataReader().maxChunkLevel();
|
||||
|
||||
@@ -41,6 +41,7 @@ public:
|
||||
TileDepthTransform depthTransform() override final;
|
||||
void update() override final;
|
||||
void reset() override final;
|
||||
int minLevel() override final;
|
||||
int maxLevel() override final;
|
||||
float noDataValueAsFloat() override final;
|
||||
|
||||
|
||||
@@ -149,6 +149,10 @@ void ImageSequenceTileProvider::reset() {
|
||||
}
|
||||
}
|
||||
|
||||
int ImageSequenceTileProvider::minLevel() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ImageSequenceTileProvider::maxLevel() {
|
||||
return _currentTileProvider ? _currentTileProvider->maxLevel() : 0;
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@ public:
|
||||
TileDepthTransform depthTransform() override final;
|
||||
void update() override final;
|
||||
void reset() override final;
|
||||
int minLevel() override final;
|
||||
int maxLevel() override final;
|
||||
float noDataValueAsFloat() override final;
|
||||
|
||||
|
||||
@@ -93,6 +93,10 @@ void SingleImageProvider::reset() {
|
||||
_tile = Tile{ _tileTexture.get(), std::nullopt, Tile::Status::OK };
|
||||
}
|
||||
|
||||
int SingleImageProvider::minLevel() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int SingleImageProvider::maxLevel() {
|
||||
return 1337; // unlimited
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@ public:
|
||||
TileDepthTransform depthTransform() override final;
|
||||
void update() override final;
|
||||
void reset() override final;
|
||||
int minLevel() override final;
|
||||
int maxLevel() override final;
|
||||
float noDataValueAsFloat() override final;
|
||||
|
||||
|
||||
@@ -114,6 +114,10 @@ TileDepthTransform SizeReferenceTileProvider::depthTransform() {
|
||||
|
||||
void SizeReferenceTileProvider::update() {}
|
||||
|
||||
int SizeReferenceTileProvider::minLevel() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int SizeReferenceTileProvider::maxLevel() {
|
||||
return 1337; // unlimited
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ public:
|
||||
Tile::Status tileStatus(const TileIndex& index) override final;
|
||||
TileDepthTransform depthTransform() override final;
|
||||
void update() override final;
|
||||
int minLevel() override final;
|
||||
int maxLevel() override final;
|
||||
float noDataValueAsFloat() override final;
|
||||
|
||||
|
||||
@@ -0,0 +1,223 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2022 *
|
||||
* *
|
||||
* 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 <modules/globebrowsing/src/tileprovider/spoutimageprovider.h>
|
||||
|
||||
#include <openspace/documentation/documentation.h>
|
||||
|
||||
#ifdef OPENSPACE_HAS_SPOUT
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif // WIN32_LEAN_AND_MEAN
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#endif // NOMINMAX
|
||||
#include <modules/spout/spoutwrapper.h>
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
struct [[codegen::Dictionary(SpoutImageProvider)]] Parameters {
|
||||
std::optional<std::string> spoutName;
|
||||
};
|
||||
#include "spoutimageprovider_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace::globebrowsing {
|
||||
|
||||
documentation::Documentation SpoutImageProvider::Documentation() {
|
||||
return codegen::doc<Parameters>("globebrowsing_spoutimageprovider");
|
||||
}
|
||||
|
||||
SpoutImageProvider::SpoutImageProvider(const ghoul::Dictionary& dictionary) {
|
||||
ZoneScoped
|
||||
|
||||
#ifdef OPENSPACE_HAS_SPOUT
|
||||
spoutReceiver = std::make_unique<spout::SpoutReceiverPropertyProxy>(
|
||||
*this,
|
||||
dictionary
|
||||
);
|
||||
|
||||
spoutReceiver->onUpdateTexture([this](int width, int height) {
|
||||
for (int i = 0; i < 2; i++) {
|
||||
if (!fbo[i]) {
|
||||
glGenFramebuffers(1, &fbo[i]);
|
||||
}
|
||||
tileTexture[i].release();
|
||||
tileTexture[i] = std::make_unique<ghoul::opengl::Texture>(
|
||||
glm::uvec3(width / 2, height, 1),
|
||||
GL_TEXTURE_2D,
|
||||
ghoul::opengl::Texture::Format::RGBA,
|
||||
GL_RGBA,
|
||||
GL_UNSIGNED_BYTE,
|
||||
ghoul::opengl::Texture::FilterMode::Linear,
|
||||
ghoul::opengl::Texture::WrappingMode::Repeat,
|
||||
ghoul::opengl::Texture::AllocateData::No,
|
||||
ghoul::opengl::Texture::TakeOwnership::No
|
||||
);
|
||||
|
||||
if (!tileTexture[i]) {
|
||||
return false;
|
||||
}
|
||||
tileTexture[i]->uploadTexture();
|
||||
tiles[i] = Tile{ tileTexture[i].get(), std::nullopt, Tile::Status::OK };
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
|
||||
spoutReceiver->onReleaseTexture([this]() {
|
||||
for (int i = 0; i < 2; i++) {
|
||||
if (fbo[i]) {
|
||||
glDeleteFramebuffers(1, &fbo[i]);
|
||||
}
|
||||
tileTexture[i].release();
|
||||
fbo[i] = 0;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
spoutReceiver->onUpdateReceiver([this](int width, int height, unsigned int texture) {
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo[0]);
|
||||
glFramebufferTexture2D(
|
||||
GL_READ_FRAMEBUFFER,
|
||||
GL_COLOR_ATTACHMENT0,
|
||||
GL_TEXTURE_2D,
|
||||
static_cast<GLuint>(texture),
|
||||
0
|
||||
);
|
||||
glReadBuffer(GL_COLOR_ATTACHMENT0);
|
||||
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo[1]);
|
||||
glFramebufferTexture2D(
|
||||
GL_DRAW_FRAMEBUFFER,
|
||||
GL_COLOR_ATTACHMENT1,
|
||||
GL_TEXTURE_2D,
|
||||
static_cast<GLuint>(*tileTexture[0]),
|
||||
0
|
||||
);
|
||||
glDrawBuffer(GL_COLOR_ATTACHMENT1);
|
||||
|
||||
glBlitFramebuffer(
|
||||
width / 2,
|
||||
0,
|
||||
width,
|
||||
height,
|
||||
0,
|
||||
0,
|
||||
width / 2,
|
||||
height,
|
||||
GL_COLOR_BUFFER_BIT,
|
||||
GL_NEAREST
|
||||
);
|
||||
glFramebufferTexture2D(
|
||||
GL_DRAW_FRAMEBUFFER,
|
||||
GL_COLOR_ATTACHMENT1,
|
||||
GL_TEXTURE_2D,
|
||||
static_cast<GLuint>(*tileTexture[1]),
|
||||
0
|
||||
);
|
||||
glBlitFramebuffer(
|
||||
0,
|
||||
0,
|
||||
width / 2,
|
||||
height,
|
||||
0,
|
||||
0,
|
||||
width / 2,
|
||||
height,
|
||||
GL_COLOR_BUFFER_BIT,
|
||||
GL_NEAREST
|
||||
);
|
||||
return true;
|
||||
});
|
||||
#endif
|
||||
|
||||
reset();
|
||||
}
|
||||
|
||||
void SpoutImageProvider::internalInitialize() {
|
||||
ZoneScoped
|
||||
|
||||
#ifdef OPENSPACE_HAS_SPOUT
|
||||
spoutReceiver->updateReceiver();
|
||||
#endif // OPENSPACE_HAS_SPOUT
|
||||
}
|
||||
|
||||
void SpoutImageProvider::internalDeinitialize() {
|
||||
#ifdef OPENSPACE_HAS_SPOUT
|
||||
spoutReceiver->release();
|
||||
#endif // OPENSPACE_HAS_SPOUT
|
||||
}
|
||||
|
||||
Tile SpoutImageProvider::tile(const TileIndex& tileIndex) {
|
||||
ZoneScoped
|
||||
|
||||
spoutUpdate = true;
|
||||
return tiles[tileIndex.x];
|
||||
}
|
||||
|
||||
Tile::Status SpoutImageProvider::tileStatus(const TileIndex&) {
|
||||
return Tile::Status::OK;
|
||||
}
|
||||
|
||||
TileDepthTransform SpoutImageProvider::depthTransform() {
|
||||
return { 0.f, 1.f };
|
||||
}
|
||||
|
||||
void SpoutImageProvider::update() {
|
||||
#ifdef OPENSPACE_HAS_SPOUT
|
||||
if (!spoutUpdate) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!spoutReceiver->isCreated()) {
|
||||
reset();
|
||||
if (!spoutReceiver->isCreated()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
spoutReceiver->updateReceiver();
|
||||
#endif // OPENSPACE_HAS_SPOUT
|
||||
}
|
||||
|
||||
void SpoutImageProvider::reset() {
|
||||
#ifdef OPENSPACE_HAS_SPOUT
|
||||
spoutReceiver->updateReceiver();
|
||||
#endif // OPENSPACE_HAS_SPOUT
|
||||
}
|
||||
|
||||
int SpoutImageProvider::minLevel() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SpoutImageProvider::maxLevel() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
float SpoutImageProvider::noDataValueAsFloat() {
|
||||
return std::numeric_limits<float>::min();
|
||||
}
|
||||
|
||||
} // namespace openspace::globebrowsing
|
||||
@@ -0,0 +1,66 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2022 *
|
||||
* *
|
||||
* 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. *
|
||||
****************************************************************************************/
|
||||
|
||||
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___TILEPROVIDER__SPOUTIMAGEPROVIDER___H__
|
||||
#define __OPENSPACE_MODULE_GLOBEBROWSING___TILEPROVIDER__SPOUTIMAGEPROVIDER___H__
|
||||
|
||||
#include <modules/globebrowsing/src/tileprovider/tileprovider.h>
|
||||
|
||||
namespace openspace::spout { class SpoutReceiverPropertyProxy; }
|
||||
|
||||
namespace openspace::globebrowsing {
|
||||
|
||||
class SpoutImageProvider : public TileProvider {
|
||||
public:
|
||||
SpoutImageProvider(const ghoul::Dictionary& dictionary);
|
||||
|
||||
Tile tile(const TileIndex& tileIndex) override final;
|
||||
Tile::Status tileStatus(const TileIndex& index) override final;
|
||||
TileDepthTransform depthTransform() override final;
|
||||
void update() override final;
|
||||
void reset() override final;
|
||||
int minLevel() override final;
|
||||
int maxLevel() override final;
|
||||
float noDataValueAsFloat() override final;
|
||||
|
||||
static documentation::Documentation Documentation();
|
||||
|
||||
private:
|
||||
void internalInitialize() override final;
|
||||
void internalDeinitialize() override final;
|
||||
|
||||
std::array<std::unique_ptr<ghoul::opengl::Texture>, 2> tileTexture;
|
||||
std::array<GLuint, 2> fbo = { 0, 0 };
|
||||
std::array<Tile, 2> tiles;
|
||||
|
||||
#ifdef OPENSPACE_HAS_SPOUT
|
||||
std::unique_ptr<spout::SpoutReceiverPropertyProxy> spoutReceiver;
|
||||
#endif
|
||||
|
||||
bool spoutUpdate = false;
|
||||
};
|
||||
|
||||
} // namespace openspace::globebrowsing
|
||||
|
||||
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___TILEPROVIDER__SPOUTIMAGEPROVIDER___H__
|
||||
@@ -371,6 +371,10 @@ void TemporalTileProvider::reset() {
|
||||
}
|
||||
}
|
||||
|
||||
int TemporalTileProvider::minLevel() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int TemporalTileProvider::maxLevel() {
|
||||
if (!_currentTileProvider) {
|
||||
update();
|
||||
@@ -833,6 +837,10 @@ void TemporalTileProvider::InterpolateTileProvider::reset() {
|
||||
future->reset();
|
||||
}
|
||||
|
||||
int TemporalTileProvider::InterpolateTileProvider::minLevel() {
|
||||
return glm::max(t1->minLevel(), t2->minLevel());
|
||||
}
|
||||
|
||||
int TemporalTileProvider::InterpolateTileProvider::maxLevel() {
|
||||
return glm::min(t1->maxLevel(), t2->maxLevel());
|
||||
}
|
||||
|
||||
@@ -51,6 +51,7 @@ public:
|
||||
TileDepthTransform depthTransform() override final;
|
||||
void update() override final;
|
||||
void reset() override final;
|
||||
int minLevel() override final;
|
||||
int maxLevel() override final;
|
||||
float noDataValueAsFloat() override final;
|
||||
|
||||
@@ -71,6 +72,7 @@ private:
|
||||
TileDepthTransform depthTransform() override final;
|
||||
void update() override final;
|
||||
void reset() override final;
|
||||
int minLevel() override final;
|
||||
int maxLevel() override final;
|
||||
float noDataValueAsFloat() override final;
|
||||
|
||||
|
||||
@@ -54,6 +54,10 @@ TileDepthTransform TileIndexTileProvider::depthTransform() {
|
||||
|
||||
void TileIndexTileProvider::update() {}
|
||||
|
||||
int TileIndexTileProvider::minLevel() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int TileIndexTileProvider::maxLevel() {
|
||||
return 1337; // unlimited
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ public:
|
||||
Tile::Status tileStatus(const TileIndex& index) override final;
|
||||
TileDepthTransform depthTransform() override final;
|
||||
void update() override final;
|
||||
int minLevel() override final;
|
||||
int maxLevel() override final;
|
||||
float noDataValueAsFloat() override final;
|
||||
};
|
||||
|
||||
@@ -190,7 +190,8 @@ ChunkTile TileProvider::chunkTile(TileIndex tileIndex, int parents, int maxParen
|
||||
|
||||
// Step 3. Traverse 0 or more parents up the chunkTree until we find a chunk that
|
||||
// has a loaded tile ready to use.
|
||||
while (tileIndex.level > 1) {
|
||||
int minimumLevel = minLevel();
|
||||
while (tileIndex.level > minimumLevel) {
|
||||
Tile t = tile(tileIndex);
|
||||
if (t.status != Tile::Status::OK) {
|
||||
if (--maxParents < 0) {
|
||||
|
||||
@@ -114,6 +114,12 @@ struct TileProvider : public properties::PropertyOwner {
|
||||
*/
|
||||
virtual void reset() = 0;
|
||||
|
||||
/**
|
||||
* \return The minimum level as defined by the <code>TileIndex</code> that this
|
||||
* TileProvider is capable of providing.
|
||||
*/
|
||||
virtual int minLevel() = 0;
|
||||
|
||||
/**
|
||||
* \return The maximum level as defined by <code>TileIndex</code> that this
|
||||
* TileProvider is able provide.
|
||||
|
||||
@@ -142,6 +142,10 @@ void TileProviderByIndex::reset() {
|
||||
_defaultTileProvider->reset();
|
||||
}
|
||||
|
||||
int TileProviderByIndex::minLevel() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int TileProviderByIndex::maxLevel() {
|
||||
return _defaultTileProvider->maxLevel();
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ public:
|
||||
TileDepthTransform depthTransform() override final;
|
||||
void update() override final;
|
||||
void reset() override final;
|
||||
int minLevel() override final;
|
||||
int maxLevel() override final;
|
||||
float noDataValueAsFloat() override final;
|
||||
|
||||
|
||||
@@ -156,6 +156,10 @@ void TileProviderByLevel::reset() {
|
||||
}
|
||||
}
|
||||
|
||||
int TileProviderByLevel::minLevel() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int TileProviderByLevel::maxLevel() {
|
||||
return static_cast<int>(_providerIndices.size() - 1);
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ public:
|
||||
TileDepthTransform depthTransform() override final;
|
||||
void update() override final;
|
||||
void reset() override final;
|
||||
int minLevel() override final;
|
||||
int maxLevel() override final;
|
||||
float noDataValueAsFloat() override final;
|
||||
|
||||
|
||||
@@ -35,6 +35,8 @@
|
||||
#include <modules/kameleon/include/kameleonwrapper.h>
|
||||
#include <openspace/json.h>
|
||||
#include <openspace/engine/globals.h>
|
||||
#include <openspace/rendering/renderengine.h>
|
||||
#include <openspace/rendering/screenspacerenderable.h>
|
||||
#include <openspace/scene/scene.h>
|
||||
#include <openspace/scripting/scriptengine.h>
|
||||
#include <openspace/util/spicemanager.h>
|
||||
@@ -753,54 +755,14 @@ scripting::LuaLibrary IswaManager::luaLibrary() {
|
||||
return {
|
||||
"iswa",
|
||||
{
|
||||
{
|
||||
"addCygnet",
|
||||
&luascriptfunctions::iswa_addCygnet,
|
||||
"int, string, string",
|
||||
"Adds a IswaCygnet",
|
||||
},
|
||||
{
|
||||
"addScreenSpaceCygnet",
|
||||
&luascriptfunctions::iswa_addScreenSpaceCygnet,
|
||||
"int, string, string",
|
||||
"Adds a Screen Space Cygnets",
|
||||
},
|
||||
{
|
||||
"addKameleonPlanes",
|
||||
&luascriptfunctions::iswa_addKameleonPlanes,
|
||||
"string, int",
|
||||
"Adds KameleonPlanes from cdf file.",
|
||||
},
|
||||
{
|
||||
"addCdfFiles",
|
||||
&luascriptfunctions::iswa_addCdfFiles,
|
||||
"string",
|
||||
"Adds a cdf files to choose from.",
|
||||
},
|
||||
{
|
||||
"removeCygnet",
|
||||
&luascriptfunctions::iswa_removeCygnet,
|
||||
"string",
|
||||
"Remove a Cygnets",
|
||||
},
|
||||
{
|
||||
"removeScreenSpaceCygnet",
|
||||
&luascriptfunctions::iswa_removeScrenSpaceCygnet,
|
||||
"int",
|
||||
"Remove a Screen Space Cygnets",
|
||||
},
|
||||
{
|
||||
"removeGroup",
|
||||
&luascriptfunctions::iswa_removeGroup,
|
||||
"int",
|
||||
"Remove a group of Cygnets",
|
||||
},
|
||||
{
|
||||
"setBaseUrl",
|
||||
&luascriptfunctions::iswa_setBaseUrl,
|
||||
"string",
|
||||
"sets the base url",
|
||||
}
|
||||
codegen::lua::AddCygnet,
|
||||
codegen::lua::AddScreenSpaceCygnet,
|
||||
codegen::lua::RemoveCygnet,
|
||||
codegen::lua::RemoveScreenSpaceCygnet,
|
||||
codegen::lua::RemoveGroup,
|
||||
codegen::lua::AddCdfFiles,
|
||||
codegen::lua::AddKameleonPlanes,
|
||||
codegen::lua::SetBaseUrl
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -22,63 +22,26 @@
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#include <openspace/engine/globals.h>
|
||||
#include <openspace/rendering/renderengine.h>
|
||||
#include <openspace/rendering/screenspacerenderable.h>
|
||||
namespace {
|
||||
|
||||
namespace openspace::luascriptfunctions {
|
||||
|
||||
int iswa_addCygnet(lua_State* L) {
|
||||
int nArguments = lua_gettop(L);
|
||||
|
||||
int id = -1;
|
||||
std::string type = "Texture";
|
||||
std::string group = "";
|
||||
|
||||
if (nArguments > 0) {
|
||||
id = static_cast<int>(lua_tonumber(L, 1));
|
||||
}
|
||||
|
||||
if (nArguments > 1) {
|
||||
type = luaL_checkstring(L, 2);
|
||||
}
|
||||
|
||||
if (nArguments > 2) {
|
||||
group = luaL_checkstring(L, 3);
|
||||
}
|
||||
|
||||
IswaManager::ref().addIswaCygnet(id, type, group);
|
||||
|
||||
return 0;
|
||||
// Adds a IswaCygnet.
|
||||
[[codegen::luawrap]] void addCygnet(int id = -1, std::string type = "Texture",
|
||||
std::string group = "")
|
||||
{
|
||||
openspace::IswaManager::ref().addIswaCygnet(id, type, group);
|
||||
}
|
||||
|
||||
int iswa_addScreenSpaceCygnet(lua_State* L) {
|
||||
static const std::string _loggerCat = "addScreenSpaceCygnet";
|
||||
using ghoul::lua::errorLocation;
|
||||
|
||||
int nArguments = lua_gettop(L);
|
||||
if (nArguments != 1) {
|
||||
return ghoul::lua::luaError(L, fmt::format(
|
||||
"Expected {} argumemts, got {}", 1, nArguments
|
||||
));
|
||||
}
|
||||
|
||||
ghoul::Dictionary d;
|
||||
try {
|
||||
ghoul::lua::luaDictionaryFromState(L, d);
|
||||
}
|
||||
catch (const ghoul::lua::LuaFormatException& e) {
|
||||
LERROR(e.what());
|
||||
return 0;
|
||||
}
|
||||
// Adds a Screen Space Cygnets.
|
||||
[[codegen::luawrap]] void addScreenSpaceCygnet(ghoul::Dictionary d) {
|
||||
using namespace openspace;
|
||||
|
||||
int id = static_cast<int>(d.value<double>("CygnetId"));
|
||||
|
||||
std::map<int, std::shared_ptr<CygnetInfo>> cygnetInformation =
|
||||
IswaManager::ref().cygnetInformation();
|
||||
if (cygnetInformation.find(id) == cygnetInformation.end()) {
|
||||
LWARNING("Could not find Cygnet with id = " + std::to_string(id));
|
||||
return 0;
|
||||
throw ghoul::lua::LuaError(
|
||||
"Could not find Cygnet with id = " + std::to_string(id)
|
||||
);
|
||||
}
|
||||
|
||||
std::shared_ptr<CygnetInfo> info = cygnetInformation[id];
|
||||
@@ -87,8 +50,9 @@ int iswa_addScreenSpaceCygnet(lua_State* L) {
|
||||
info->selected = true;
|
||||
|
||||
if (global::renderEngine->screenSpaceRenderable(name)) {
|
||||
LERROR("A cygnet with the name \"" + name +"\" already exist");
|
||||
return 0;
|
||||
throw ghoul::lua::LuaError(fmt::format(
|
||||
"A cygnet with the name \"{}\" already exist", name
|
||||
));
|
||||
}
|
||||
else {
|
||||
d.setValue("Name", name);
|
||||
@@ -100,99 +64,68 @@ int iswa_addScreenSpaceCygnet(lua_State* L) {
|
||||
);
|
||||
global::renderEngine->addScreenSpaceRenderable(std::move(s));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// int iswa_addKameleonPlane(lua_State* L){
|
||||
// int nArguments = lua_gettop(L);
|
||||
|
||||
// std::string kwPath = "";
|
||||
// std::string type = "x";
|
||||
// std::string group = "";
|
||||
|
||||
// if (nArguments > 0) {
|
||||
// kwPath = luaL_checkstring(L, 1);
|
||||
// }
|
||||
|
||||
// if (nArguments > 1) {
|
||||
// type = luaL_checkstring(L, 2);
|
||||
// }
|
||||
|
||||
// if (nArguments > 2) {
|
||||
// group = luaL_checkstring(L, 3);
|
||||
// }
|
||||
|
||||
// IswaManager::ref().createKameleonPlane(kwPath, type, group);
|
||||
// return 0;
|
||||
// }
|
||||
|
||||
int iswa_removeCygnet(lua_State* L) {
|
||||
std::string name = luaL_checkstring(L, -1);
|
||||
// Remove a Cygnets.
|
||||
[[codegen::luawrap]] void removeCygnet(std::string name) {
|
||||
using namespace openspace;
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.removeSceneGraphNode('" + name + "')",
|
||||
scripting::ScriptEngine::RemoteScripting::Yes
|
||||
);
|
||||
// IswaManager::ref().deleteIswaCygnet(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iswa_removeScrenSpaceCygnet(lua_State* L) {
|
||||
static const std::string _loggerCat = "removeScreenSpaceCygnet";
|
||||
|
||||
int id = static_cast<int>(lua_tonumber(L, 1));
|
||||
|
||||
// Remove a Screen Space Cygnets.
|
||||
[[codegen::luawrap]] void removeScreenSpaceCygnet(int id) {
|
||||
using namespace openspace;
|
||||
|
||||
std::map<int, std::shared_ptr<CygnetInfo>> cygnetInformation =
|
||||
IswaManager::ref().cygnetInformation();
|
||||
if (cygnetInformation.find(id) == cygnetInformation.end()) {
|
||||
LWARNING("Could not find Cygnet with id = " + std::to_string(id));
|
||||
return 0;
|
||||
throw ghoul::lua::LuaError(
|
||||
"Could not find Cygnet with id = " + std::to_string(id)
|
||||
);
|
||||
}
|
||||
|
||||
std::shared_ptr<CygnetInfo> info = cygnetInformation[id];
|
||||
info->selected = false;
|
||||
|
||||
std::string script =
|
||||
"openspace.unregisterScreenSpaceRenderable('" +
|
||||
cygnetInformation[id]->name + "');";
|
||||
std::string script = fmt::format(
|
||||
"openspace.unregisterScreenSpaceRenderable('{}');", cygnetInformation[id]->name
|
||||
);
|
||||
|
||||
global::scriptEngine->queueScript(
|
||||
script,
|
||||
scripting::ScriptEngine::RemoteScripting::Yes
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iswa_removeGroup(lua_State* L) {
|
||||
std::string name = luaL_checkstring(L, -1);
|
||||
// IswaManager::ref().unregisterGroup(id);
|
||||
|
||||
// Remove a group of Cygnets.
|
||||
[[codegen::luawrap]] void removeGroup(std::string name) {
|
||||
using namespace openspace;
|
||||
|
||||
std::map<std::string, std::shared_ptr<IswaBaseGroup>> groups =
|
||||
IswaManager::ref().groups();
|
||||
if (groups.find(name) != groups.end()) {
|
||||
groups[name]->clearGroup();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iswa_addCdfFiles(lua_State* L) {
|
||||
std::string path = luaL_checkstring(L, 1);
|
||||
IswaManager::ref().addCdfFiles(path);
|
||||
|
||||
return 0;
|
||||
// Adds a cdf files to choose from.
|
||||
[[codegen::luawrap]] void addCdfFiles(std::string path) {
|
||||
openspace::IswaManager::ref().addCdfFiles(path);
|
||||
}
|
||||
|
||||
int iswa_addKameleonPlanes(lua_State* L) {
|
||||
std::string group = luaL_checkstring(L, 1);
|
||||
int pos = static_cast<int>(lua_tonumber(L, 2));
|
||||
IswaManager::ref().addKameleonCdf(group, pos);
|
||||
return 0;
|
||||
// Adds KameleonPlanes from cdf file.
|
||||
[[codegen::luawrap]] void addKameleonPlanes(std::string group, int pos) {
|
||||
openspace::IswaManager::ref().addKameleonCdf(group, pos);
|
||||
}
|
||||
|
||||
int iswa_setBaseUrl(lua_State* L) {
|
||||
std::string url = luaL_checkstring(L, 1);
|
||||
IswaManager::ref().setBaseUrl(url);
|
||||
return 0;
|
||||
// Sets the base url.
|
||||
[[codegen::luawrap]] void setBaseUrl(std::string url) {
|
||||
openspace::IswaManager::ref().setBaseUrl(url);
|
||||
}
|
||||
|
||||
} // namespace openspace::luascriptfunctions
|
||||
#include "iswamanager_lua_codegen.cpp"
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
#include <openspace/rendering/renderable.h>
|
||||
#include <openspace/rendering/screenspacerenderable.h>
|
||||
#include <openspace/scripting/lualibrary.h>
|
||||
#include <openspace/util/coordinateconversion.h>
|
||||
#include <openspace/util/factorymanager.h>
|
||||
#include <openspace/util/spicemanager.h>
|
||||
#include <ghoul/misc/assert.h>
|
||||
@@ -140,28 +141,13 @@ std::vector<documentation::Documentation> SpaceModule::documentations() const {
|
||||
}
|
||||
|
||||
scripting::LuaLibrary SpaceModule::luaLibrary() const {
|
||||
scripting::LuaLibrary res;
|
||||
res.name = "space";
|
||||
res.functions = {
|
||||
return {
|
||||
"space",
|
||||
{
|
||||
"convertFromRaDec",
|
||||
&space::luascriptfunctions::convertFromRaDec,
|
||||
"string/double, string/double, double",
|
||||
"Returns the cartesian world position of a ra dec coordinate with distance. "
|
||||
"If the coordinate is given as strings the format should be ra 'XhYmZs' and "
|
||||
"dec 'XdYmZs'. If the coordinate is given as numbers the values should be "
|
||||
"in degrees."
|
||||
},
|
||||
{
|
||||
"convertToRaDec",
|
||||
&space::luascriptfunctions::convertToRaDec,
|
||||
"double, double, double",
|
||||
"Returns the formatted ra, dec strings and distance for a given cartesian "
|
||||
"world coordinate."
|
||||
codegen::lua::ConvertFromRaDec,
|
||||
codegen::lua::ConvertToRaDec
|
||||
}
|
||||
};
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -22,47 +22,61 @@
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#include <openspace/util/coordinateconversion.h>
|
||||
namespace {
|
||||
|
||||
namespace openspace::space::luascriptfunctions {
|
||||
|
||||
int convertFromRaDec(lua_State* L) {
|
||||
ghoul::lua::checkArgumentsAndThrow(L, 3, "lua::convertFromRaDec");
|
||||
/**
|
||||
* Returns the cartesian world position of a ra dec coordinate with distance. If the
|
||||
* coordinate is given as strings the format should be ra 'XhYmZs' and dec 'XdYmZs'. If
|
||||
* the coordinate is given as numbers the values should be in degrees.
|
||||
*/
|
||||
[[codegen::luawrap]] glm::dvec3 convertFromRaDec(
|
||||
std::variant<double, std::string> rightAscension,
|
||||
std::variant<double, std::string> declination,
|
||||
double distance)
|
||||
{
|
||||
using namespace openspace;
|
||||
|
||||
glm::dvec2 degrees = glm::dvec2(0.0);
|
||||
if (ghoul::lua::hasValue<std::string>(L, 1) &&
|
||||
ghoul::lua::hasValue<std::string>(L, 2))
|
||||
if (std::holds_alternative<double>(rightAscension) &&
|
||||
std::holds_alternative<double>(declination))
|
||||
{
|
||||
auto [ra, dec] = ghoul::lua::values<std::string, std::string>(L);
|
||||
degrees = icrsToDecimalDegrees(ra, dec);
|
||||
degrees = glm::dvec2(
|
||||
std::get<double>(rightAscension),
|
||||
std::get<double>(declination)
|
||||
);
|
||||
}
|
||||
else if (ghoul::lua::hasValue<double>(L, 1) && ghoul::lua::hasValue<double>(L, 2)) {
|
||||
auto [x, y] = ghoul::lua::values<double, double>(L);
|
||||
degrees.x = x;
|
||||
degrees.y = y;
|
||||
else if (std::holds_alternative<std::string>(rightAscension) &&
|
||||
std::holds_alternative<std::string>(declination))
|
||||
{
|
||||
degrees = icrsToDecimalDegrees(
|
||||
std::get<std::string>(rightAscension),
|
||||
std::get<std::string>(declination)
|
||||
);
|
||||
}
|
||||
else {
|
||||
throw ghoul::lua::LuaRuntimeException(
|
||||
throw ghoul::lua::LuaError(
|
||||
"Ra and Dec have to be of the same type, either String or Number"
|
||||
);
|
||||
}
|
||||
|
||||
double distance = ghoul::lua::value<double>(L);
|
||||
glm::dvec3 pos = icrsToGalacticCartesian(degrees.x, degrees.y, distance);
|
||||
ghoul::lua::push(L, pos);
|
||||
return 1;
|
||||
return pos;
|
||||
}
|
||||
|
||||
int convertToRaDec(lua_State* L) {
|
||||
ghoul::lua::checkArgumentsAndThrow(L, 3, "lua::convertToRaDec");
|
||||
auto [x, y, z] = ghoul::lua::values<double, double, double>(L);
|
||||
|
||||
/**
|
||||
* Returns the formatted ra, dec strings and distance for a given cartesian world
|
||||
* coordinate.
|
||||
*/
|
||||
[[codegen::luawrap]] std::tuple<std::string, std::string, double> convertToRaDec(double x,
|
||||
double y,
|
||||
double z)
|
||||
{
|
||||
using namespace openspace;
|
||||
glm::dvec3 deg = galacticCartesianToIcrs(x, y, z);
|
||||
std::pair<std::string, std::string> raDecPair = decimalDegreesToIcrs(deg.x, deg.y);
|
||||
|
||||
// Ra, Dec, Distance
|
||||
ghoul::lua::push(L, raDecPair.first, raDecPair.second, deg.z);
|
||||
return 3;
|
||||
return { raDecPair.first, raDecPair.second, deg.z };
|
||||
}
|
||||
|
||||
} // namespace openspace::space::luascriptfunctions
|
||||
#include "spacemodule_lua_codegen.cpp"
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -315,10 +315,27 @@ Dataset loadFile(std::filesystem::path path, SkipAllZeroLines skipAllZeroLines)
|
||||
str >> entry.position.x >> entry.position.y >> entry.position.z;
|
||||
allZero &= (entry.position == glm::vec3(0.0));
|
||||
|
||||
if (!str.good()) {
|
||||
throw ghoul::RuntimeError(fmt::format(
|
||||
"Error loading position information out of data line {} in file {}. "
|
||||
"Value was not a number",
|
||||
res.entries.size(), path
|
||||
));
|
||||
}
|
||||
|
||||
entry.data.resize(nDataValues);
|
||||
for (int i = 0; i < nDataValues; i += 1) {
|
||||
str >> entry.data[i];
|
||||
bool isGood = str.good();
|
||||
allZero &= (entry.data[i] == 0.0);
|
||||
|
||||
if (!str.good()) {
|
||||
throw ghoul::RuntimeError(fmt::format(
|
||||
"Error loading data value {} out of data line {} in file {}. "
|
||||
"Value was not a number",
|
||||
i, res.entries.size(), path
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
if (skipAllZeroLines && allZero) {
|
||||
|
||||
@@ -26,14 +26,18 @@ include(${OPENSPACE_CMAKE_EXT_DIR}/module_definition.cmake)
|
||||
|
||||
set(HEADER_FILES
|
||||
renderableplanespout.h
|
||||
renderablespherespout.h
|
||||
screenspacespout.h
|
||||
spoutlibrary.h
|
||||
spoutwrapper.h
|
||||
)
|
||||
source_group("Header Files" FILES ${HEADER_FILES})
|
||||
|
||||
set(SOURCE_FILES
|
||||
renderableplanespout.cpp
|
||||
renderablespherespout.cpp
|
||||
screenspacespout.cpp
|
||||
spoutwrapper.cpp
|
||||
)
|
||||
source_group("Source Files" FILES ${SOURCE_FILES})
|
||||
|
||||
|
||||
@@ -5,7 +5,9 @@
|
||||
//
|
||||
|
||||
#include <windows.h>
|
||||
#ifndef SPOUT_NO_GL_INCLUDE
|
||||
#include <GL/GL.h>
|
||||
#endif
|
||||
|
||||
#define SPOUTLIBRARY_EXPORTS // defined for this DLL. The application imports rather than exports
|
||||
|
||||
|
||||
@@ -71,10 +71,7 @@ documentation::Documentation RenderablePlaneSpout::Documentation() {
|
||||
|
||||
RenderablePlaneSpout::RenderablePlaneSpout(const ghoul::Dictionary& dictionary)
|
||||
: RenderablePlane(dictionary)
|
||||
, _spoutName(NameInfo)
|
||||
, _spoutSelection(SelectionInfo)
|
||||
, _updateSelection(UpdateInfo)
|
||||
, _receiver(GetSpout())
|
||||
, _spoutReceiver(*this, dictionary)
|
||||
{
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
@@ -96,115 +93,36 @@ RenderablePlaneSpout::RenderablePlaneSpout(const ghoul::Dictionary& dictionary)
|
||||
// Adding an extra space to the user-facing name as it looks nicer
|
||||
setGuiName("RenderablePlaneSpout " + std::to_string(iIdentifier));
|
||||
}
|
||||
|
||||
_spoutName = p.spoutName.value_or(_spoutName);
|
||||
_spoutName.onChange([this]() {
|
||||
_isSpoutDirty = true;
|
||||
_isErrorMessageDisplayed = false;
|
||||
|
||||
_receiver->SetActiveSender(_spoutName.value().c_str());
|
||||
});
|
||||
addProperty(_spoutName);
|
||||
|
||||
_spoutSelection.onChange([this](){
|
||||
_spoutName = _spoutSelection.option().description;
|
||||
});
|
||||
_spoutSelection.addOption(0, "");
|
||||
addProperty(_spoutSelection);
|
||||
|
||||
_updateSelection.onChange([this]() {
|
||||
const std::string& currentValue = _spoutSelection.options().empty() ?
|
||||
"" :
|
||||
_spoutSelection.option().description;
|
||||
|
||||
_spoutSelection.clearOptions();
|
||||
_spoutSelection.addOption(0, "");
|
||||
|
||||
const int nSenders = _receiver->GetSenderCount();
|
||||
int idx = 0;
|
||||
|
||||
for (int i = 0; i < nSenders; ++i) {
|
||||
char Name[256];
|
||||
_receiver->GetSenderName(i, Name, 256);
|
||||
|
||||
_spoutSelection.addOption(i + 1, Name);
|
||||
|
||||
if (currentValue == Name) {
|
||||
idx = i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
_spoutSelection = idx;
|
||||
});
|
||||
addProperty(_updateSelection);
|
||||
}
|
||||
|
||||
void RenderablePlaneSpout::deinitializeGL() {
|
||||
_receiver->ReleaseReceiver();
|
||||
_receiver->Release();
|
||||
_spoutReceiver.release();
|
||||
|
||||
RenderablePlane::deinitializeGL();
|
||||
}
|
||||
|
||||
void RenderablePlaneSpout::update(const UpdateData& data) {
|
||||
RenderablePlane::update(data);
|
||||
|
||||
if (_isFirstUpdate) {
|
||||
// Trigger an update; the value is a dummy that is ignored
|
||||
_updateSelection.set(0);
|
||||
|
||||
// #0 is the empty string and we just pick the first one after that (if it exists)
|
||||
if (_spoutSelection.options().size() > 1) {
|
||||
_spoutSelection = 1;
|
||||
}
|
||||
|
||||
_isFirstUpdate = false;
|
||||
}
|
||||
|
||||
if (_spoutName.value().empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_isSpoutDirty) {
|
||||
defer { _isSpoutDirty = false; };
|
||||
|
||||
std::memset(_currentSenderName, 0, 256);
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
|
||||
_receiver->ReleaseReceiver();
|
||||
|
||||
_receiver->GetActiveSender(_currentSenderName);
|
||||
|
||||
bool hasCreated = _receiver->CreateReceiver(_currentSenderName, width, height);
|
||||
if (!hasCreated) {
|
||||
LWARNINGC(
|
||||
LoggerCat,
|
||||
fmt::format("Could not create receiver for {}", _currentSenderName)
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
const bool hasReceived = _receiver->ReceiveTexture(_currentSenderName, width, height);
|
||||
|
||||
if (!hasReceived && !_isErrorMessageDisplayed) {
|
||||
LWARNINGC(
|
||||
LoggerCat,
|
||||
fmt::format("Could not receive texture for {}", _currentSenderName)
|
||||
);
|
||||
_isErrorMessageDisplayed = true;
|
||||
}
|
||||
_spoutReceiver.updateReceiver();
|
||||
}
|
||||
|
||||
void RenderablePlaneSpout::bindTexture() {
|
||||
_receiver->BindSharedTexture();
|
||||
if (_spoutReceiver.isReceiving()) {
|
||||
_spoutReceiver.saveGLTextureState();
|
||||
glBindTexture(GL_TEXTURE_2D, static_cast<GLuint>(_spoutReceiver.spoutTexture()));
|
||||
}
|
||||
else {
|
||||
RenderablePlane::bindTexture();
|
||||
}
|
||||
}
|
||||
|
||||
void RenderablePlaneSpout::unbindTexture() {
|
||||
_receiver->UnBindSharedTexture();
|
||||
if (_spoutReceiver.isReceiving()) {
|
||||
_spoutReceiver.restoreGLTextureState();
|
||||
}
|
||||
else {
|
||||
RenderablePlane::unbindTexture();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -29,10 +29,7 @@
|
||||
|
||||
#include <modules/base/rendering/renderableplane.h>
|
||||
|
||||
#include <modules/spout/spoutlibrary.h>
|
||||
#include <openspace/properties/stringproperty.h>
|
||||
#include <openspace/properties/optionproperty.h>
|
||||
#include <openspace/properties/triggerproperty.h>
|
||||
#include <modules/spout/spoutwrapper.h>
|
||||
|
||||
namespace openspace {
|
||||
|
||||
@@ -51,16 +48,7 @@ private:
|
||||
void bindTexture() override;
|
||||
void unbindTexture() override;
|
||||
|
||||
properties::StringProperty _spoutName;
|
||||
properties::OptionProperty _spoutSelection;
|
||||
properties::TriggerProperty _updateSelection;
|
||||
|
||||
SPOUTHANDLE _receiver;
|
||||
|
||||
bool _isSpoutDirty = true;
|
||||
char _currentSenderName[256] = {};
|
||||
bool _isFirstUpdate = true;
|
||||
bool _isErrorMessageDisplayed = false;
|
||||
spout::SpoutReceiverPropertyProxy _spoutReceiver;
|
||||
};
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2022 *
|
||||
* *
|
||||
* 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. *
|
||||
****************************************************************************************/
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
#include <modules/spout/renderablespherespout.h>
|
||||
|
||||
#include <openspace/documentation/documentation.h>
|
||||
#include <openspace/documentation/verifier.h>
|
||||
#include <openspace/util/sphere.h>
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <ghoul/opengl/texture.h>
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation RenderableSphereSpout::Documentation() {
|
||||
using namespace openspace::documentation;
|
||||
return {
|
||||
"Renderable Sphere Spout",
|
||||
"spout_sphere_spout",
|
||||
{
|
||||
{
|
||||
"Name",
|
||||
new StringVerifier,
|
||||
Optional::Yes,
|
||||
"Specifies the GUI name of the RenderableSphereSpout"
|
||||
},
|
||||
{
|
||||
spout::SpoutReceiverPropertyProxy::NameInfoProperty().identifier,
|
||||
new StringVerifier,
|
||||
Optional::Yes,
|
||||
spout::SpoutReceiverPropertyProxy::NameInfoProperty().description
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
RenderableSphereSpout::RenderableSphereSpout(const ghoul::Dictionary& dictionary)
|
||||
: RenderableSphere(dictionary)
|
||||
, _spoutReceiver(*this, dictionary)
|
||||
{
|
||||
documentation::testSpecificationAndThrow(
|
||||
Documentation(),
|
||||
dictionary,
|
||||
"RenderableSphereSpout"
|
||||
);
|
||||
|
||||
int iIdentifier = 0;
|
||||
if (_identifier.empty()) {
|
||||
static int id = 0;
|
||||
iIdentifier = id;
|
||||
|
||||
if (iIdentifier == 0) {
|
||||
setIdentifier("RenderableSphereSpout");
|
||||
}
|
||||
else {
|
||||
setIdentifier("RenderableSphereSpout" + std::to_string(iIdentifier));
|
||||
}
|
||||
++id;
|
||||
}
|
||||
|
||||
if (_guiName.empty()) {
|
||||
// Adding an extra space to the user-facing name as it looks nicer
|
||||
setGuiName("RenderableSphereSpout " + std::to_string(iIdentifier));
|
||||
}
|
||||
}
|
||||
|
||||
void RenderableSphereSpout::deinitializeGL() {
|
||||
_spoutReceiver.release();
|
||||
RenderableSphere::deinitializeGL();
|
||||
}
|
||||
|
||||
void RenderableSphereSpout::update(const UpdateData& data) {
|
||||
RenderableSphere::update(data);
|
||||
_spoutReceiver.updateReceiver();
|
||||
}
|
||||
|
||||
void RenderableSphereSpout::bindTexture() {
|
||||
if (_spoutReceiver.isReceiving()) {
|
||||
_spoutReceiver.saveGLTextureState();
|
||||
glBindTexture(GL_TEXTURE_2D, _spoutReceiver.spoutTexture());
|
||||
}
|
||||
else {
|
||||
RenderableSphere::bindTexture();
|
||||
}
|
||||
}
|
||||
|
||||
void RenderableSphereSpout::unbindTexture() {
|
||||
if (_spoutReceiver.isReceiving()) {
|
||||
_spoutReceiver.restoreGLTextureState();
|
||||
}
|
||||
else {
|
||||
RenderableSphere::unbindTexture();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
#endif // WIN32
|
||||
@@ -0,0 +1,58 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2022 *
|
||||
* *
|
||||
* 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. *
|
||||
****************************************************************************************/
|
||||
|
||||
#ifndef __OPENSPACE_MODULE_SPOUT___RENDERABLESPHERESPOUT___H__
|
||||
#define __OPENSPACE_MODULE_SPOUT___RENDERABLESPHERESPOUT___H__
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
#include <modules/base/rendering/renderablesphere.h>
|
||||
|
||||
#include <modules/spout/spoutwrapper.h>
|
||||
|
||||
namespace openspace {
|
||||
|
||||
namespace documentation { struct Documentation; }
|
||||
|
||||
class RenderableSphereSpout : public RenderableSphere {
|
||||
public:
|
||||
RenderableSphereSpout(const ghoul::Dictionary& dictionary);
|
||||
|
||||
void deinitializeGL() override;
|
||||
void update(const UpdateData& data) override;
|
||||
|
||||
static documentation::Documentation Documentation();
|
||||
|
||||
private:
|
||||
void bindTexture() override;
|
||||
void unbindTexture() override;
|
||||
|
||||
spout::SpoutReceiverPropertyProxy _spoutReceiver;
|
||||
};
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
#endif // WIN32
|
||||
|
||||
#endif // __OPENSPACE_MODULE_SPOUT___RENDERABLESPHERESPOUT___H__
|
||||
@@ -69,13 +69,8 @@ documentation::Documentation ScreenSpaceSpout::Documentation() {
|
||||
|
||||
ScreenSpaceSpout::ScreenSpaceSpout(const ghoul::Dictionary& dictionary)
|
||||
: ScreenSpaceRenderable(dictionary)
|
||||
, _spoutName(NameInfo)
|
||||
, _spoutSelection(SelectionInfo)
|
||||
, _updateSelection(UpdateInfo)
|
||||
, _receiver(GetSpout())
|
||||
, _spoutReceiver(*this, dictionary)
|
||||
{
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
std::string identifier;
|
||||
if (dictionary.hasValue<std::string>(KeyIdentifier)) {
|
||||
identifier = dictionary.value<std::string>(KeyIdentifier);
|
||||
@@ -85,127 +80,30 @@ ScreenSpaceSpout::ScreenSpaceSpout(const ghoul::Dictionary& dictionary)
|
||||
}
|
||||
identifier = makeUniqueIdentifier(identifier);
|
||||
setIdentifier(std::move(identifier));
|
||||
|
||||
_spoutName = p.spoutName.value_or(_spoutName);
|
||||
_spoutName.onChange([this]() {
|
||||
_isSpoutDirty = true;
|
||||
_isErrorMessageDisplayed = false;
|
||||
|
||||
_receiver->SetActiveSender(_spoutName.value().c_str());
|
||||
});
|
||||
addProperty(_spoutName);
|
||||
|
||||
_spoutSelection.onChange([this]() {
|
||||
_spoutName = _spoutSelection.option().description;
|
||||
});
|
||||
_spoutSelection.addOption(0, "");
|
||||
addProperty(_spoutSelection);
|
||||
|
||||
_updateSelection.onChange([this]() {
|
||||
const std::string& currentValue = _spoutSelection.options().empty() ?
|
||||
"" :
|
||||
_spoutSelection.option().description;
|
||||
|
||||
_spoutSelection.clearOptions();
|
||||
_spoutSelection.addOption(0, "");
|
||||
|
||||
int nSenders = _receiver->GetSenderCount();
|
||||
|
||||
int idx = 0;
|
||||
|
||||
for (int i = 0; i < nSenders; ++i) {
|
||||
char Name[256];
|
||||
_receiver->GetSenderName(i, Name, 256);
|
||||
|
||||
_spoutSelection.addOption(i + 1, Name);
|
||||
|
||||
if (currentValue == Name) {
|
||||
idx = i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
_spoutSelection = idx;
|
||||
});
|
||||
addProperty(_updateSelection);
|
||||
}
|
||||
|
||||
bool ScreenSpaceSpout::deinitializeGL() {
|
||||
_receiver->ReleaseReceiver();
|
||||
_receiver->Release();
|
||||
_spoutReceiver.release();
|
||||
|
||||
return ScreenSpaceRenderable::deinitializeGL();
|
||||
}
|
||||
|
||||
bool ScreenSpaceSpout::isReady() const {
|
||||
return ScreenSpaceRenderable::isReady() && !_spoutName.value().empty();
|
||||
return ScreenSpaceRenderable::isReady() && !_spoutReceiver.isReceiving();
|
||||
}
|
||||
|
||||
void ScreenSpaceSpout::update() {
|
||||
if (_isFirstUpdate) {
|
||||
defer { _isFirstUpdate = false; };
|
||||
|
||||
// Trigger an update; the value is a dummy that is ignored
|
||||
_updateSelection.set(0);
|
||||
|
||||
// #0 is the empty string and we just pick the first one after that (if it exists)
|
||||
if (_spoutSelection.options().size() > 1) {
|
||||
_spoutSelection = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (_spoutName.value().empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_isSpoutDirty) {
|
||||
defer { _isSpoutDirty = false; };
|
||||
|
||||
std::memset(_currentSenderName, 0, 256);
|
||||
|
||||
_receiver->ReleaseReceiver();
|
||||
_receiver->GetActiveSender(_currentSenderName);
|
||||
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
const bool hasCreated = _receiver->CreateReceiver(
|
||||
_currentSenderName,
|
||||
width,
|
||||
height
|
||||
);
|
||||
_objectSize = { width, height };
|
||||
|
||||
if (!hasCreated) {
|
||||
LWARNINGC(
|
||||
"ScreenSpaceSpout",
|
||||
fmt::format("Could not create receiver for {}", _currentSenderName)
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
const bool receiveSuccess = _receiver->ReceiveTexture(
|
||||
_currentSenderName,
|
||||
width,
|
||||
height
|
||||
);
|
||||
|
||||
if (!receiveSuccess && !_isErrorMessageDisplayed) {
|
||||
LWARNINGC(
|
||||
"ScreenSpaceSpout",
|
||||
fmt::format("Could not receive texture for {}", _currentSenderName)
|
||||
);
|
||||
_isErrorMessageDisplayed = true;
|
||||
}
|
||||
ScreenSpaceRenderable::update();
|
||||
_spoutReceiver.updateReceiver();
|
||||
}
|
||||
|
||||
void ScreenSpaceSpout::bindTexture() {
|
||||
_receiver->BindSharedTexture();
|
||||
_spoutReceiver.saveGLTextureState();
|
||||
glBindTexture(GL_TEXTURE_2D, _spoutReceiver.spoutTexture());
|
||||
}
|
||||
|
||||
void ScreenSpaceSpout::unbindTexture() {
|
||||
_receiver->UnBindSharedTexture();
|
||||
_spoutReceiver.restoreGLTextureState();
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -29,11 +29,7 @@
|
||||
|
||||
#include <openspace/rendering/screenspacerenderable.h>
|
||||
|
||||
#include <modules/spout/spoutlibrary.h>
|
||||
|
||||
#include <openspace/properties/stringproperty.h>
|
||||
#include <openspace/properties/optionproperty.h>
|
||||
#include <openspace/properties/triggerproperty.h>
|
||||
#include <modules/spout/spoutwrapper.h>
|
||||
|
||||
namespace openspace {
|
||||
|
||||
@@ -54,17 +50,8 @@ public:
|
||||
private:
|
||||
void bindTexture() override;
|
||||
void unbindTexture() override;
|
||||
|
||||
properties::StringProperty _spoutName;
|
||||
properties::OptionProperty _spoutSelection;
|
||||
properties::TriggerProperty _updateSelection;
|
||||
|
||||
SPOUTHANDLE _receiver;
|
||||
|
||||
bool _isSpoutDirty = true;
|
||||
char _currentSenderName[256] = {};
|
||||
bool _isFirstUpdate = true;
|
||||
bool _isErrorMessageDisplayed = false;
|
||||
|
||||
spout::SpoutReceiverPropertyProxy _spoutReceiver;
|
||||
};
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <modules/spout/spoutmodule.h>
|
||||
|
||||
#include <modules/spout/renderableplanespout.h>
|
||||
#include <modules/spout/renderablespherespout.h>
|
||||
#include <modules/spout/screenspacespout.h>
|
||||
#include <openspace/util/factorymanager.h>
|
||||
#include <ghoul/misc/templatefactory.h>
|
||||
@@ -46,6 +47,7 @@ void SpoutModule::internalInitialize(const ghoul::Dictionary&) {
|
||||
FactoryManager::ref().factory<Renderable>();
|
||||
ghoul_assert(fRenderable, "Renderable factory was not created");
|
||||
fRenderable->registerClass<RenderablePlaneSpout>("RenderablePlaneSpout");
|
||||
fRenderable->registerClass<RenderableSphereSpout>("RenderableSphereSpout");
|
||||
#endif // WIN32
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,613 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2022 *
|
||||
* *
|
||||
* 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 "modules/spout/spoutwrapper.h"
|
||||
|
||||
#include <ghoul/fmt.h>
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <ghoul/opengl/ghoul_gl.h>
|
||||
#include <ghoul/opengl/texture.h>
|
||||
#define SPOUT_NO_GL_INCLUDE
|
||||
#include <SpoutLibrary.h>
|
||||
|
||||
namespace {
|
||||
constexpr const char _loggerCat[] = "Spout";
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo NameSenderInfo = {
|
||||
"SpoutName",
|
||||
"Spout Sender Name",
|
||||
"This value sets the Spout sender to use a specific name."
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo NameReceiverInfo = {
|
||||
"SpoutName",
|
||||
"Spout Receiver Name",
|
||||
"This value explicitly sets the Spout receiver to use a specific name. If this "
|
||||
"is not a valid name, an empty image is used."
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo SelectionInfo = {
|
||||
"SpoutSelection",
|
||||
"Spout Selection",
|
||||
"This property displays all available Spout sender on the system. If one them is "
|
||||
"selected, its value is stored in the 'SpoutName' property, overwriting its "
|
||||
"previous value."
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo UpdateInfo = {
|
||||
"UpdateSelection",
|
||||
"Update Selection",
|
||||
"If this property is trigged, the 'SpoutSelection' options will be refreshed."
|
||||
};
|
||||
} // namespace
|
||||
|
||||
namespace openspace::spout {
|
||||
|
||||
SpoutMain::SpoutMain() {
|
||||
_spoutHandle = GetSpout();
|
||||
}
|
||||
|
||||
SpoutMain::~SpoutMain() {}
|
||||
|
||||
void SpoutMain::release() {
|
||||
if (_spoutHandle) {
|
||||
_spoutHandle->Release();
|
||||
}
|
||||
}
|
||||
|
||||
void SpoutMain::saveGLState() {
|
||||
GLint buf;
|
||||
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &buf);
|
||||
_defaultFBO = static_cast<unsigned int>(buf);
|
||||
|
||||
glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &buf);
|
||||
_defaultReadFBO = static_cast<unsigned int>(buf);
|
||||
|
||||
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &buf);
|
||||
_defaultDrawFBO = static_cast<unsigned int>(buf);
|
||||
|
||||
glGetIntegerv(GL_READ_BUFFER, &buf);
|
||||
_defaultReadBuffer = static_cast<unsigned int>(buf);
|
||||
|
||||
glGetIntegerv(GL_DRAW_BUFFER0, &buf);
|
||||
_defaultReadBuffer = static_cast<unsigned int>(buf);
|
||||
|
||||
saveGLTextureState();
|
||||
}
|
||||
|
||||
void SpoutMain::restoreGLState() {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, static_cast<GLuint>(_defaultFBO));
|
||||
if (_defaultFBO) {
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, static_cast<GLuint>(_defaultReadFBO));
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, static_cast<GLuint>(_defaultDrawFBO));
|
||||
glReadBuffer(static_cast<GLenum>(_defaultReadBuffer));
|
||||
GLenum buf[1];
|
||||
buf[0] = static_cast<GLenum>(_defaultDrawBuffer[0]);
|
||||
glDrawBuffers(1, buf);
|
||||
}
|
||||
restoreGLTextureState();
|
||||
}
|
||||
|
||||
void SpoutMain::saveGLTextureState() {
|
||||
GLint buf;
|
||||
glGetIntegerv(GL_TEXTURE_BINDING_2D, &buf);
|
||||
_defaultTexture = static_cast<unsigned int>(buf);
|
||||
}
|
||||
|
||||
void SpoutMain::restoreGLTextureState() {
|
||||
glBindTexture(GL_TEXTURE_2D, static_cast<GLuint>(_defaultTexture));
|
||||
}
|
||||
|
||||
SpoutReceiver::SpoutReceiver() {}
|
||||
|
||||
SpoutReceiver::~SpoutReceiver() {}
|
||||
|
||||
const std::vector<std::string> &SpoutReceiver::spoutReceiverList() {
|
||||
if (!_spoutHandle) {
|
||||
return _receiverList;
|
||||
}
|
||||
|
||||
const int nSenders = _spoutHandle->GetSenderCount();
|
||||
_receiverList.clear();
|
||||
|
||||
for (int i = 0; i < nSenders; ++i) {
|
||||
char Name[256];
|
||||
_spoutHandle->GetSenderName(i, Name, 256);
|
||||
_receiverList.push_back(Name);
|
||||
}
|
||||
|
||||
return _receiverList;
|
||||
}
|
||||
|
||||
bool SpoutReceiver::isCreated() const {
|
||||
return _isCreated;
|
||||
}
|
||||
|
||||
bool SpoutReceiver::isReceiving() const {
|
||||
return _isReceiving;
|
||||
}
|
||||
|
||||
bool SpoutReceiver::updateReceiver() {
|
||||
unsigned int width = 10;
|
||||
unsigned int height = 10;
|
||||
|
||||
if (!_spoutHandle || !_isCreated) {
|
||||
return false;
|
||||
}
|
||||
|
||||
char currentSpoutName[256] = { 0 };
|
||||
std::memcpy(currentSpoutName, _currentSpoutName.data(), _currentSpoutName.size());
|
||||
_spoutHandle->CheckReceiver(currentSpoutName, width, height, _isReceiving);
|
||||
|
||||
// if spout is not connected a 10x10 texture is created
|
||||
if (updateTexture(width, height) && _isReceiving) {
|
||||
saveGLState();
|
||||
|
||||
_spoutHandle->ReceiveTexture(
|
||||
currentSpoutName,
|
||||
width,
|
||||
height,
|
||||
static_cast<GLuint>(*_spoutTexture),
|
||||
static_cast<GLuint>(GL_TEXTURE_2D),
|
||||
true
|
||||
);
|
||||
|
||||
if (_onUpdateReceiverCallback) {
|
||||
const GLuint t = static_cast<GLuint>(*_spoutTexture);
|
||||
if (!_onUpdateReceiverCallback(width, height, t)) {
|
||||
restoreGLState();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
restoreGLState();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SpoutReceiver::updateReceiverName(const std::string& name) {
|
||||
unsigned int width = 0;
|
||||
unsigned int height = 0;
|
||||
|
||||
if (!_spoutHandle) {
|
||||
return false;
|
||||
}
|
||||
|
||||
releaseReceiver();
|
||||
|
||||
if (_onUpdateReceiverNameCallback) {
|
||||
if (!_onUpdateReceiverNameCallback(name)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
char nameBuf[256] = { 0 };
|
||||
std::memcpy(nameBuf, name.data(), name.size());
|
||||
bool hasCreated = _spoutHandle->CreateReceiver(nameBuf, width, height);
|
||||
if (!hasCreated) {
|
||||
if (!_isErrorMessageDisplayed) {
|
||||
LWARNING(fmt::format(
|
||||
"Could not create receiver for {} -> {}x{}", name, width, height
|
||||
));
|
||||
_isErrorMessageDisplayed = true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
_currentSpoutName = name;
|
||||
_isErrorMessageDisplayed = false;
|
||||
_isCreated = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SpoutReceiver::releaseReceiver() {
|
||||
if (!_isCreated) {
|
||||
return;
|
||||
}
|
||||
|
||||
_isReceiving = false;
|
||||
_isCreated = false;
|
||||
_isErrorMessageDisplayed = false;
|
||||
_currentSpoutName.clear();
|
||||
if (_onReleaseReceiverCallback) {
|
||||
_onReleaseReceiverCallback();
|
||||
}
|
||||
releaseTexture();
|
||||
if (_spoutHandle) {
|
||||
_spoutHandle->ReleaseReceiver();
|
||||
}
|
||||
}
|
||||
|
||||
void SpoutReceiver::release() {
|
||||
releaseReceiver();
|
||||
SpoutMain::release();
|
||||
}
|
||||
|
||||
void SpoutReceiver::onUpdateReceiverName(std::function<bool(const std::string&)> callback)
|
||||
{
|
||||
_onUpdateReceiverNameCallback = std::move(callback);
|
||||
}
|
||||
|
||||
void SpoutReceiver::onUpdateReceiver(std::function<bool(int, int, unsigned int)> callback)
|
||||
{
|
||||
_onUpdateReceiverCallback = std::move(callback);
|
||||
}
|
||||
|
||||
void SpoutReceiver::onReleaseReceiver(std::function<void()> callback) {
|
||||
_onReleaseReceiverCallback = std::move(callback);
|
||||
}
|
||||
|
||||
void SpoutReceiver::onUpdateTexture(std::function<bool(int, int)> callback) {
|
||||
_onUpdateTextureCallback = std::move(callback);
|
||||
}
|
||||
|
||||
void SpoutReceiver::onReleaseTexture(std::function<void()> callback) {
|
||||
_onReleaseTextureCallback = std::move(callback);
|
||||
}
|
||||
|
||||
unsigned int SpoutReceiver::spoutTexture() const {
|
||||
return _spoutTexture ? static_cast<unsigned int>(*_spoutTexture) : 0;
|
||||
}
|
||||
|
||||
bool SpoutReceiver::updateTexture(unsigned int width, unsigned int height) {
|
||||
if (width != _spoutWidth || height != _spoutHeight) {
|
||||
releaseTexture();
|
||||
_spoutTexture = std::make_unique<ghoul::opengl::Texture>(
|
||||
glm::uvec3(width, height, 1),
|
||||
GL_TEXTURE_2D,
|
||||
ghoul::opengl::Texture::Format::RGBA,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
ghoul::opengl::Texture::FilterMode::Linear,
|
||||
ghoul::opengl::Texture::WrappingMode::Repeat,
|
||||
ghoul::opengl::Texture::AllocateData::No,
|
||||
ghoul::opengl::Texture::TakeOwnership::No
|
||||
);
|
||||
|
||||
if (_spoutTexture) {
|
||||
_spoutTexture->uploadTexture();
|
||||
if (_onUpdateTextureCallback && !_onUpdateTextureCallback(width, height)) {
|
||||
LWARNING(fmt::format(
|
||||
"Could not create callback texture for {} -> {}x{}",
|
||||
_currentSpoutName, width, height
|
||||
));
|
||||
return false;
|
||||
}
|
||||
_spoutWidth = width;
|
||||
_spoutHeight = height;
|
||||
}
|
||||
else {
|
||||
LWARNING(fmt::format(
|
||||
"Could not create texture for {} -> {}x{}",
|
||||
_currentSpoutName, width, height
|
||||
));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void SpoutReceiver::releaseTexture() {
|
||||
_spoutWidth = 0;
|
||||
_spoutHeight = 0;
|
||||
if (_onReleaseTextureCallback) {
|
||||
_onReleaseTextureCallback();
|
||||
}
|
||||
_spoutTexture.release();
|
||||
}
|
||||
|
||||
const properties::Property::PropertyInfo& SpoutReceiverPropertyProxy::NameInfoProperty() {
|
||||
return NameReceiverInfo;
|
||||
}
|
||||
|
||||
const properties::Property::PropertyInfo&
|
||||
SpoutReceiverPropertyProxy::SelectionInfoProperty()
|
||||
{
|
||||
return SelectionInfo;
|
||||
}
|
||||
|
||||
const properties::Property::PropertyInfo& SpoutReceiverPropertyProxy::UpdateInfoProperty()
|
||||
{
|
||||
return UpdateInfo;
|
||||
}
|
||||
|
||||
SpoutReceiverPropertyProxy::SpoutReceiverPropertyProxy(properties::PropertyOwner& owner,
|
||||
const ghoul::Dictionary& dictionary)
|
||||
: _spoutName(NameReceiverInfo)
|
||||
, _spoutSelection(SelectionInfo)
|
||||
, _updateSelection(UpdateInfo)
|
||||
{
|
||||
if (dictionary.hasKey(NameReceiverInfo.identifier)) {
|
||||
_spoutName = dictionary.value<std::string>(NameReceiverInfo.identifier);
|
||||
}
|
||||
else {
|
||||
_isSelectAny = true;
|
||||
}
|
||||
|
||||
_spoutName.onChange([this]() { _isSpoutDirty = true; });
|
||||
owner.addProperty(_spoutName);
|
||||
|
||||
_spoutSelection.onChange([this]() {
|
||||
if (_spoutName.value().empty() && _spoutSelection.value() == 0) {
|
||||
if (_spoutSelection.options().size() > 1) {
|
||||
_spoutSelection = 1;
|
||||
}
|
||||
}
|
||||
_spoutName = "";
|
||||
_spoutName = _spoutSelection.option().description;
|
||||
});
|
||||
_spoutSelection.addOption(0, "");
|
||||
owner.addProperty(_spoutSelection);
|
||||
|
||||
_updateSelection.onChange([this]() {
|
||||
const std::vector<std::string> receiverList = spoutReceiverList();
|
||||
|
||||
_spoutSelection.clearOptions();
|
||||
_spoutSelection.addOption(0, "");
|
||||
|
||||
int idx = 0;
|
||||
for (int i = 0; i < static_cast<int>(receiverList.size()); ++i) {
|
||||
_spoutSelection.addOption(i + 1, receiverList[i]);
|
||||
|
||||
LWARNING(fmt::format("List {}", receiverList[i]));
|
||||
|
||||
if (!_isSelectAny && _spoutName.value() == receiverList[i]) {
|
||||
idx = i + 1;
|
||||
}
|
||||
}
|
||||
_spoutSelection = idx;
|
||||
|
||||
});
|
||||
owner.addProperty(_updateSelection);
|
||||
|
||||
_updateSelection.set(0);
|
||||
}
|
||||
|
||||
SpoutReceiverPropertyProxy::~SpoutReceiverPropertyProxy() {}
|
||||
|
||||
bool SpoutReceiverPropertyProxy::updateReceiver() {
|
||||
if (_isSpoutDirty) {
|
||||
if (!updateReceiverName(_spoutName.value())) {
|
||||
return false;
|
||||
}
|
||||
_isSpoutDirty = false;
|
||||
}
|
||||
return SpoutReceiver::updateReceiver();
|
||||
}
|
||||
|
||||
void SpoutReceiverPropertyProxy::releaseReceiver() {
|
||||
_isSpoutDirty = true;
|
||||
SpoutReceiver::releaseReceiver();
|
||||
}
|
||||
|
||||
|
||||
SpoutSender::SpoutSender() {}
|
||||
|
||||
SpoutSender::~SpoutSender() {}
|
||||
|
||||
bool SpoutSender::isCreated() const {
|
||||
return _isCreated;
|
||||
}
|
||||
|
||||
bool SpoutSender::isSending() const {
|
||||
return _isSending;
|
||||
}
|
||||
|
||||
bool SpoutSender::updateSenderStatus() {
|
||||
if (!_isSending) {
|
||||
if (_spoutWidth == 0 || _spoutHeight == 0) {
|
||||
if (!_isErrorMessageDisplayed) {
|
||||
LWARNING(fmt::format(
|
||||
"Could not create sender for {}, dimensions invalid {}x{}",
|
||||
_currentSpoutName, _spoutWidth, _spoutHeight
|
||||
));
|
||||
_isErrorMessageDisplayed = true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_currentSpoutName.empty()) {
|
||||
if (!_isErrorMessageDisplayed) {
|
||||
LWARNING(fmt::format("Could not create sender, invalid name"));
|
||||
_isErrorMessageDisplayed = true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
ghoul_assert(_currentSpoutName.size() < 256, "Spout name must be < 256");
|
||||
char name[256] = { 0 };
|
||||
std::memcpy(name, _currentSpoutName.data(), _currentSpoutName.size());
|
||||
|
||||
bool hasCreated = _spoutHandle->CreateSender(name, _spoutWidth, _spoutHeight);
|
||||
if (!hasCreated) {
|
||||
if (!_isErrorMessageDisplayed) {
|
||||
LWARNING(fmt::format(
|
||||
"Could not create sender for {} -> {}x{}",
|
||||
_currentSpoutName, _spoutWidth, _spoutHeight
|
||||
));
|
||||
_isErrorMessageDisplayed = true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
_isErrorMessageDisplayed = false;
|
||||
_isSending = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SpoutSender::updateSender(unsigned int texture, unsigned int textureType) {
|
||||
if (!_spoutHandle || !updateSenderStatus()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
_spoutHandle->SendTexture(texture, textureType, _spoutWidth, _spoutHeight);
|
||||
|
||||
if (_onUpdateSenderCallback) {
|
||||
bool s = _onUpdateSenderCallback(
|
||||
_currentSpoutName,
|
||||
texture,
|
||||
textureType,
|
||||
_spoutWidth,
|
||||
_spoutHeight
|
||||
);
|
||||
if (!s) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SpoutSender::updateSenderName(const std::string& name) {
|
||||
if (!_spoutHandle) {
|
||||
return false;
|
||||
}
|
||||
if (name == _currentSpoutName) {
|
||||
return true;
|
||||
}
|
||||
|
||||
releaseSender();
|
||||
|
||||
if (_onUpdateSenderNameCallback) {
|
||||
if (!_onUpdateSenderNameCallback(name)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
_currentSpoutName = name;
|
||||
_isCreated = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SpoutSender::updateSenderSize(int width, int height) {
|
||||
if (!_spoutHandle) {
|
||||
return false;
|
||||
}
|
||||
if (width == static_cast<int>(_spoutWidth) &&
|
||||
height == static_cast<int>(_spoutHeight))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
releaseSender();
|
||||
|
||||
if (_onUpdateSenderSizeCallback) {
|
||||
if (!_onUpdateSenderSizeCallback(width, height)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
_spoutWidth = width;
|
||||
_spoutHeight = height;
|
||||
_isCreated = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SpoutSender::releaseSender() {
|
||||
if (!_isSending) {
|
||||
return;
|
||||
}
|
||||
|
||||
_isCreated = false;
|
||||
_isSending = false;
|
||||
_isErrorMessageDisplayed = false;
|
||||
_currentSpoutName.clear();
|
||||
_spoutWidth = 0;
|
||||
_spoutHeight = 0;
|
||||
if (_onReleaseSenderCallback) {
|
||||
_onReleaseSenderCallback();
|
||||
}
|
||||
if (_spoutHandle) {
|
||||
_spoutHandle->ReleaseReceiver();
|
||||
}
|
||||
}
|
||||
|
||||
void SpoutSender::release() {
|
||||
releaseSender();
|
||||
SpoutMain::release();
|
||||
}
|
||||
|
||||
void SpoutSender::onUpdateSenderName(std::function<bool(const std::string&)> callback) {
|
||||
_onUpdateSenderNameCallback = std::move(callback);
|
||||
}
|
||||
|
||||
void SpoutSender::onUpdateSenderSize(std::function<bool(int, int)> callback) {
|
||||
_onUpdateSenderSizeCallback = std::move(callback);
|
||||
}
|
||||
|
||||
void SpoutSender::onUpdateSender(std::function<bool(const std::string&, unsigned int,
|
||||
unsigned int, int, int)> callback)
|
||||
{
|
||||
_onUpdateSenderCallback = std::move(callback);
|
||||
}
|
||||
|
||||
void SpoutSender::onReleaseSender(std::function<void()> callback) {
|
||||
_onReleaseSenderCallback = std::move(callback);
|
||||
}
|
||||
|
||||
const properties::Property::PropertyInfo& SpoutSenderPropertyProxy::NameInfoProperty() {
|
||||
return NameSenderInfo;
|
||||
}
|
||||
|
||||
SpoutSenderPropertyProxy::SpoutSenderPropertyProxy(properties::PropertyOwner& owner,
|
||||
const ghoul::Dictionary& dictionary)
|
||||
: _spoutName(NameSenderInfo)
|
||||
{
|
||||
if (dictionary.hasKey(NameSenderInfo.identifier)) {
|
||||
_spoutName = dictionary.value<std::string>(NameSenderInfo.identifier);
|
||||
}
|
||||
else {
|
||||
LWARNING(fmt::format("Sender does not have a name"));
|
||||
}
|
||||
|
||||
_spoutName.onChange([this]() { _isSpoutDirty = true; });
|
||||
owner.addProperty(_spoutName);
|
||||
}
|
||||
|
||||
SpoutSenderPropertyProxy::~SpoutSenderPropertyProxy() {}
|
||||
|
||||
bool SpoutSenderPropertyProxy::updateSender(unsigned int texture,
|
||||
unsigned int textureType)
|
||||
{
|
||||
if (_isSpoutDirty) {
|
||||
if (!updateSenderName(_spoutName)) {
|
||||
return false;
|
||||
}
|
||||
_isSpoutDirty = false;
|
||||
}
|
||||
return SpoutSender::updateSender(texture, textureType);
|
||||
}
|
||||
|
||||
void SpoutSenderPropertyProxy::releaseSender() {
|
||||
_isSpoutDirty = true;
|
||||
SpoutSender::releaseSender();
|
||||
}
|
||||
|
||||
} // namespace openspace::spout
|
||||
@@ -0,0 +1,190 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2022 *
|
||||
* *
|
||||
* 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. *
|
||||
****************************************************************************************/
|
||||
|
||||
#ifndef __OPENSPACE_MODULE_SPOUT___SPOUTWRAPPER___H__
|
||||
#define __OPENSPACE_MODULE_SPOUT___SPOUTWRAPPER___H__
|
||||
|
||||
#include <openspace/properties/optionproperty.h>
|
||||
#include <openspace/properties/propertyowner.h>
|
||||
#include <openspace/properties/stringproperty.h>
|
||||
#include <openspace/properties/triggerproperty.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
struct SPOUTLIBRARY;
|
||||
typedef SPOUTLIBRARY* SPOUTHANDLE;
|
||||
|
||||
namespace ghoul::opengl { class Texture; }
|
||||
|
||||
namespace openspace::spout {
|
||||
|
||||
// @TODO(abock, 2022-03-02) This class should probably be outsourced into a stand-alone
|
||||
// library that the SGCT version of this class then can also use
|
||||
class SpoutMain {
|
||||
public:
|
||||
SpoutMain();
|
||||
virtual ~SpoutMain();
|
||||
|
||||
virtual void release();
|
||||
|
||||
void saveGLState();
|
||||
void restoreGLState();
|
||||
|
||||
void saveGLTextureState();
|
||||
void restoreGLTextureState();
|
||||
|
||||
protected:
|
||||
unsigned int _defaultTexture;
|
||||
unsigned int _defaultFBO;
|
||||
unsigned int _defaultReadFBO;
|
||||
unsigned int _defaultDrawFBO;
|
||||
unsigned int _defaultReadBuffer;
|
||||
unsigned int _defaultDrawBuffer[1] = { 0 };
|
||||
|
||||
SPOUTHANDLE _spoutHandle = nullptr;
|
||||
|
||||
std::string _currentSpoutName;
|
||||
unsigned int _spoutWidth = 0;
|
||||
unsigned int _spoutHeight = 0;
|
||||
};
|
||||
|
||||
class SpoutReceiver : public SpoutMain {
|
||||
public:
|
||||
SpoutReceiver();
|
||||
virtual ~SpoutReceiver();
|
||||
|
||||
void release() override;
|
||||
|
||||
virtual bool updateReceiverName(const std::string& name);
|
||||
virtual bool updateReceiver();
|
||||
virtual void releaseReceiver();
|
||||
|
||||
void onUpdateReceiverName(std::function<bool(const std::string&)> callback);
|
||||
void onUpdateReceiver(std::function<bool(int, int, unsigned int)> callback);
|
||||
void onReleaseReceiver(std::function<void()> callback);
|
||||
void onUpdateTexture(std::function<bool(int, int)> callback);
|
||||
void onReleaseTexture(std::function<void()> callback);
|
||||
|
||||
const std::vector<std::string>& spoutReceiverList();
|
||||
bool isCreated() const;
|
||||
bool isReceiving() const;
|
||||
unsigned int spoutTexture() const;
|
||||
|
||||
private:
|
||||
bool updateTexture(unsigned int width, unsigned int height);
|
||||
void releaseTexture();
|
||||
|
||||
bool _isErrorMessageDisplayed = false;
|
||||
bool _isCreated = false;
|
||||
bool _isReceiving = false;
|
||||
std::vector<std::string> _receiverList;
|
||||
|
||||
std::unique_ptr<ghoul::opengl::Texture> _spoutTexture;
|
||||
|
||||
std::function<bool(const std::string&)> _onUpdateReceiverNameCallback = nullptr;
|
||||
std::function<bool(int, int, unsigned int)> _onUpdateReceiverCallback = nullptr;
|
||||
std::function<void()> _onReleaseReceiverCallback = nullptr;
|
||||
std::function<bool(int, int)> _onUpdateTextureCallback = nullptr;
|
||||
std::function<void()> _onReleaseTextureCallback = nullptr;
|
||||
};
|
||||
|
||||
|
||||
class SpoutReceiverPropertyProxy : public SpoutReceiver {
|
||||
public:
|
||||
static const properties::Property::PropertyInfo& NameInfoProperty();
|
||||
static const properties::Property::PropertyInfo& SelectionInfoProperty();
|
||||
static const properties::Property::PropertyInfo& UpdateInfoProperty();
|
||||
|
||||
SpoutReceiverPropertyProxy(properties::PropertyOwner& owner,
|
||||
const ghoul::Dictionary& dictionary);
|
||||
virtual ~SpoutReceiverPropertyProxy();
|
||||
|
||||
bool updateReceiver() override;
|
||||
void releaseReceiver() override;
|
||||
|
||||
private:
|
||||
properties::StringProperty _spoutName;
|
||||
properties::OptionProperty _spoutSelection;
|
||||
properties::TriggerProperty _updateSelection;
|
||||
|
||||
bool _isSpoutDirty = true;
|
||||
bool _isSelectAny = false;
|
||||
};
|
||||
|
||||
|
||||
class SpoutSender : public SpoutMain {
|
||||
public:
|
||||
SpoutSender();
|
||||
virtual ~SpoutSender();
|
||||
|
||||
void release() override;
|
||||
|
||||
virtual bool updateSenderName(const std::string& name);
|
||||
virtual bool updateSenderSize(int width, int height);
|
||||
virtual bool updateSender(unsigned int texture, unsigned int textureType);
|
||||
virtual void releaseSender();
|
||||
|
||||
void onUpdateSenderName(std::function<bool(const std::string&)> callback);
|
||||
void onUpdateSenderSize(std::function<bool(int, int)> callback);
|
||||
void onUpdateSender(std::function<bool(const std::string&, unsigned int,
|
||||
unsigned int, int, int)> callback);
|
||||
void onReleaseSender(std::function<void()> callback);
|
||||
|
||||
bool isCreated() const;
|
||||
bool isSending() const;
|
||||
|
||||
private:
|
||||
bool updateSenderStatus();
|
||||
|
||||
bool _isErrorMessageDisplayed = false;
|
||||
bool _isCreated = false;
|
||||
bool _isSending = false;
|
||||
|
||||
std::function<bool(const std::string&)> _onUpdateSenderNameCallback = nullptr;
|
||||
std::function<bool(int, int)> _onUpdateSenderSizeCallback = nullptr;
|
||||
std::function<bool(const std::string&, unsigned int,
|
||||
unsigned int, int, int)> _onUpdateSenderCallback = nullptr;
|
||||
std::function<void()> _onReleaseSenderCallback = nullptr;
|
||||
};
|
||||
|
||||
class SpoutSenderPropertyProxy : public SpoutSender {
|
||||
public:
|
||||
static const properties::Property::PropertyInfo& NameInfoProperty();
|
||||
|
||||
SpoutSenderPropertyProxy(properties::PropertyOwner& owner,
|
||||
const ghoul::Dictionary& dictionary);
|
||||
virtual ~SpoutSenderPropertyProxy();
|
||||
|
||||
bool updateSender(unsigned int texture, unsigned int textureType) override;
|
||||
void releaseSender() override;
|
||||
|
||||
private:
|
||||
properties::StringProperty _spoutName;
|
||||
|
||||
bool _isSpoutDirty = true;
|
||||
};
|
||||
|
||||
} // namespace openspace::spout
|
||||
|
||||
#endif // __OPENSPACE_MODULE_SPOUT___SPOUTWRAPPER___H__
|
||||
@@ -28,10 +28,15 @@
|
||||
#include <modules/statemachine/include/statemachine.h>
|
||||
#include <modules/statemachine/include/transition.h>
|
||||
#include <openspace/documentation/documentation.h>
|
||||
#include <openspace/engine/globals.h>
|
||||
#include <openspace/engine/moduleengine.h>
|
||||
#include <openspace/scripting/lualibrary.h>
|
||||
#include <openspace/scripting/scriptengine.h>
|
||||
#include <ghoul/filesystem/filesystem.h>
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <ghoul/misc/misc.h>
|
||||
#include <string>
|
||||
#include <optional>
|
||||
|
||||
#include "statemachinemodule_lua.inl"
|
||||
|
||||
@@ -140,78 +145,20 @@ void StateMachineModule::saveToFile(const std::string& filename,
|
||||
}
|
||||
|
||||
scripting::LuaLibrary StateMachineModule::luaLibrary() const {
|
||||
scripting::LuaLibrary res;
|
||||
res.name = "statemachine";
|
||||
res.functions = {
|
||||
{
|
||||
"createStateMachine",
|
||||
&luascriptfunctions::createStateMachine,
|
||||
"table, table, [string]",
|
||||
"Creates a state machine from a list of states and transitions. See State "
|
||||
"and Transition documentation for details. The optional thrid argument is "
|
||||
"the identifier of the desired initial state. If left out, the first state "
|
||||
"in the list will be used."
|
||||
},
|
||||
return {
|
||||
"statemachine",
|
||||
{
|
||||
"destroyStateMachine",
|
||||
&luascriptfunctions::destroyStateMachine,
|
||||
"",
|
||||
"Destroys the current state machine and deletes all the memory."
|
||||
},
|
||||
{
|
||||
"goToState",
|
||||
&luascriptfunctions::goToState,
|
||||
"string",
|
||||
"Triggers a transition from the current state to the state with the given "
|
||||
"identifier. Requires that the specified string corresponds to an existing "
|
||||
"state, and that a transition between the two states exists."
|
||||
},
|
||||
{
|
||||
"setInitialState",
|
||||
&luascriptfunctions::setInitialState,
|
||||
"string",
|
||||
"Immediately sets the current state to the state with the given name, if "
|
||||
"it exists. This is done without doing a transition and completely ignores "
|
||||
"the previous state."
|
||||
},
|
||||
{
|
||||
"currentState",
|
||||
&luascriptfunctions::currentState,
|
||||
"",
|
||||
"Returns the string name of the current state that the statemachine is in."
|
||||
},
|
||||
{
|
||||
"possibleTransitions",
|
||||
&luascriptfunctions::possibleTransitions,
|
||||
"",
|
||||
"Returns a list with the identifiers of all the states that can be "
|
||||
"transitioned to from the current state."
|
||||
},
|
||||
{
|
||||
"canGoToState",
|
||||
&luascriptfunctions::canGoToState,
|
||||
"string",
|
||||
"Returns true if there is a defined transition between the current state and "
|
||||
"the given string name of a state, otherwise false"
|
||||
},
|
||||
{
|
||||
"printCurrentStateInfo",
|
||||
&luascriptfunctions::printCurrentStateInfo,
|
||||
"",
|
||||
"Prints information about the current state and possible transitions to the "
|
||||
"log."
|
||||
},
|
||||
{
|
||||
"saveToDotFile",
|
||||
&luascriptfunctions::saveToDotFile,
|
||||
"string, [string]",
|
||||
"Saves the current state machine to a .dot file as a directed graph. The "
|
||||
"resulting graph can be rendered using external tools such as Graphviz. "
|
||||
"The first parameter is the name of the file, and the second is an optional "
|
||||
"directory. If no directory is given, the file is saved to the temp folder."
|
||||
codegen::lua::CreateStateMachine,
|
||||
codegen::lua::DestroyStateMachine,
|
||||
codegen::lua::GoToState,
|
||||
codegen::lua::SetInitialState,
|
||||
codegen::lua::CurrentState,
|
||||
codegen::lua::PossibleTransitions,
|
||||
codegen::lua::CanGoToState,
|
||||
codegen::lua::PrintCurrentStateInfo,
|
||||
codegen::lua::SaveToDotFile
|
||||
}
|
||||
};
|
||||
return res;
|
||||
}
|
||||
|
||||
std::vector<documentation::Documentation> StateMachineModule::documentations() const {
|
||||
|
||||
@@ -22,90 +22,91 @@
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#include <modules/statemachine/statemachinemodule.h>
|
||||
#include <openspace/engine/globals.h>
|
||||
#include <openspace/engine/moduleengine.h>
|
||||
#include <openspace/scripting/scriptengine.h>
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <ghoul/misc/misc.h>
|
||||
#include <optional>
|
||||
|
||||
namespace openspace::luascriptfunctions {
|
||||
|
||||
int createStateMachine(lua_State* L) {
|
||||
ghoul::lua::checkArgumentsAndThrow(L, { 2, 3 }, "lua::createStateMachine");
|
||||
auto [states, transitions, startState] = ghoul::lua::values<
|
||||
ghoul::Dictionary, ghoul::Dictionary, std::optional<std::string>
|
||||
>(L);
|
||||
namespace {
|
||||
|
||||
/**
|
||||
* Creates a state machine from a list of states and transitions. See State and Transition
|
||||
* documentation for details. The optional thrid argument is the identifier of the desired
|
||||
* initial state. If left out, the first state in the list will be used.
|
||||
*/
|
||||
[[codegen::luawrap]] void createStateMachine(ghoul::Dictionary states,
|
||||
ghoul::Dictionary transitions,
|
||||
std::optional<std::string> startState)
|
||||
{
|
||||
using namespace openspace;
|
||||
StateMachineModule* module = global::moduleEngine->module<StateMachineModule>();
|
||||
module->initializeStateMachine(
|
||||
std::move(states),
|
||||
std::move(transitions),
|
||||
std::move(startState)
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int destroyStateMachine(lua_State* L) {
|
||||
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::destroyStateMachine");
|
||||
|
||||
// Destroys the current state machine and deletes all the memory.
|
||||
[[codegen::luawrap]] void destroyStateMachine() {
|
||||
using namespace openspace;
|
||||
StateMachineModule* module = global::moduleEngine->module<StateMachineModule>();
|
||||
module->deinitializeStateMachine();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int goToState(lua_State* L) {
|
||||
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::goToState");
|
||||
std::string newState = ghoul::lua::value<std::string>(L);
|
||||
|
||||
/**
|
||||
* Triggers a transition from the current state to the state with the given identifier.
|
||||
* Requires that the specified string corresponds to an existing state, and that a
|
||||
* transition between the two states exists.
|
||||
*/
|
||||
[[codegen::luawrap]] void goToState(std::string newState) {
|
||||
using namespace openspace;
|
||||
StateMachineModule* module = global::moduleEngine->module<StateMachineModule>();
|
||||
module->transitionTo(newState);
|
||||
LINFOC("StateMachine", "Transitioning to " + newState);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int setInitialState(lua_State* L) {
|
||||
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::setStartState");
|
||||
std::string startState = ghoul::lua::value<std::string>(L);
|
||||
|
||||
/**
|
||||
* Immediately sets the current state to the state with the given name, if it exists. This
|
||||
* is done without doing a transition and completely ignores the previous state.
|
||||
*/
|
||||
[[codegen::luawrap]] void setInitialState(std::string startState) {
|
||||
using namespace openspace;
|
||||
StateMachineModule* module = global::moduleEngine->module<StateMachineModule>();
|
||||
module->setInitialState(startState);
|
||||
LINFOC("StateMachine", "Initial state set to: " + startState);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int currentState(lua_State* L) {
|
||||
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::currentState");
|
||||
|
||||
// Returns the string name of the current state that the statemachine is in.
|
||||
[[codegen::luawrap]] std::string currentState() {
|
||||
using namespace openspace;
|
||||
StateMachineModule* module = global::moduleEngine->module<StateMachineModule>();
|
||||
std::string currentState = module->currentState();
|
||||
ghoul::lua::push(L, std::move(currentState));
|
||||
return 1;
|
||||
return currentState;
|
||||
}
|
||||
|
||||
int possibleTransitions(lua_State* L) {
|
||||
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::possibleTransitions");
|
||||
|
||||
/**
|
||||
* Returns a list with the identifiers of all the states that can be transitioned to from
|
||||
* the current state.
|
||||
*/
|
||||
[[codegen::luawrap]] std::vector<std::string> possibleTransitions() {
|
||||
using namespace openspace;
|
||||
StateMachineModule* module = global::moduleEngine->module<StateMachineModule>();
|
||||
std::vector<std::string> transitions = module->possibleTransitions();
|
||||
ghoul::lua::push(L, transitions);
|
||||
return 1;
|
||||
return transitions;
|
||||
}
|
||||
|
||||
int canGoToState(lua_State* L) {
|
||||
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::canGoToState");
|
||||
std::string state = ghoul::lua::value<std::string>(L);
|
||||
|
||||
/**
|
||||
* Returns true if there is a defined transition between the current state and the given
|
||||
* string name of a state, otherwise false.
|
||||
*/
|
||||
[[codegen::luawrap]] bool canGoToState(std::string state) {
|
||||
using namespace openspace;
|
||||
StateMachineModule* module = global::moduleEngine->module<StateMachineModule>();
|
||||
ghoul::lua::push(L, module->canGoToState(state));
|
||||
return 1;
|
||||
bool canTransition = module->canGoToState(state);
|
||||
return canTransition;
|
||||
}
|
||||
|
||||
int printCurrentStateInfo(lua_State* L) {
|
||||
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::printCurrentStateInfo");
|
||||
|
||||
/**
|
||||
* Prints information about the current state and possible transitions to the log.
|
||||
*/
|
||||
[[codegen::luawrap]] void printCurrentStateInfo() {
|
||||
using namespace openspace;
|
||||
StateMachineModule* module = global::moduleEngine->module<StateMachineModule>();
|
||||
if (module->hasStateMachine()) {
|
||||
std::string currentState = module->currentState();
|
||||
@@ -119,24 +120,27 @@ int printCurrentStateInfo(lua_State* L) {
|
||||
else {
|
||||
LINFOC("StateMachine", "No state machine has been created");
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int saveToDotFile(lua_State* L) {
|
||||
ghoul::lua::checkArgumentsAndThrow(L, { 1, 2 }, "lua::saveToDotFile");
|
||||
auto [filename, directory] =
|
||||
ghoul::lua::values<std::string, std::optional<std::string>>(L);
|
||||
|
||||
/**
|
||||
* Saves the current state machine to a .dot file as a directed graph. The resulting graph
|
||||
* can be rendered using external tools such as Graphviz. The first parameter is the name
|
||||
* of the file, and the second is an optional directory. If no directory is given, the
|
||||
* file is saved to the temp folder.
|
||||
*/
|
||||
[[codegen::luawrap]] void saveToDotFile(std::string filename,
|
||||
std::optional<std::string> directory)
|
||||
{
|
||||
using namespace openspace;
|
||||
StateMachineModule* module = global::moduleEngine->module<StateMachineModule>();
|
||||
|
||||
if (directory.has_value()) {
|
||||
module->saveToFile(filename, *directory);
|
||||
}
|
||||
else {
|
||||
module->saveToFile(filename);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
} //namespace openspace::luascriptfunctions
|
||||
#include "statemachinemodule_lua_codegen.cpp"
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -27,7 +27,9 @@
|
||||
#include <modules/sync/syncs/httpsynchronization.h>
|
||||
#include <modules/sync/syncs/urlsynchronization.h>
|
||||
#include <openspace/documentation/documentation.h>
|
||||
#include <openspace/engine/globals.h>
|
||||
#include <openspace/engine/globalscallbacks.h>
|
||||
#include <openspace/engine/moduleengine.h>
|
||||
#include <openspace/rendering/renderable.h>
|
||||
#include <openspace/rendering/screenspacerenderable.h>
|
||||
#include <openspace/scripting/lualibrary.h>
|
||||
@@ -119,30 +121,13 @@ std::vector<documentation::Documentation> SyncModule::documentations() const {
|
||||
}
|
||||
|
||||
scripting::LuaLibrary SyncModule::luaLibrary() const {
|
||||
scripting::LuaLibrary res;
|
||||
res.name = "sync";
|
||||
res.functions = {
|
||||
return {
|
||||
"sync",
|
||||
{
|
||||
"syncResource",
|
||||
&luascriptfunctions::syncResource,
|
||||
"string, number",
|
||||
"Synchronizes the http resource identified by the name passed as the "
|
||||
"first parameter and the version provided as the second parameter. The "
|
||||
"application will hang while the data is being downloaded"
|
||||
},
|
||||
{
|
||||
"unsyncResource",
|
||||
&luascriptfunctions::unsyncResource,
|
||||
"string [, number]",
|
||||
"Unsynchronizes the http resources identified by the name passed as the "
|
||||
"first parameter by removing all data that was downloaded as part of the "
|
||||
"original synchronization. If the second parameter is provided, is it "
|
||||
"the version of the resources that is unsynchronized, if the parameter "
|
||||
"is not provided, all versions for the specified http resource are "
|
||||
"removed."
|
||||
codegen::lua::SyncResource,
|
||||
codegen::lua::UnsyncResource
|
||||
}
|
||||
};
|
||||
return res;
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -22,14 +22,15 @@
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#include <openspace/engine/globals.h>
|
||||
#include <openspace/engine/moduleengine.h>
|
||||
namespace {
|
||||
|
||||
namespace openspace::luascriptfunctions {
|
||||
|
||||
int syncResource(lua_State* L) {
|
||||
ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::syncResource");
|
||||
auto [identifier, version] = ghoul::lua::values<std::string, double>(L);
|
||||
/**
|
||||
* Synchronizes the http resource identified by the name passed as the first parameter and
|
||||
* the version provided as the second parameter. The application will hang while the data
|
||||
* is being downloaded.
|
||||
*/
|
||||
[[codegen::luawrap]] bool syncResource(std::string identifier, int version) {
|
||||
using namespace openspace;
|
||||
|
||||
ghoul::Dictionary dict;
|
||||
dict.setValue("Type", std::string("HttpSynchronization"));
|
||||
@@ -45,14 +46,20 @@ int syncResource(lua_State* L) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(20));
|
||||
}
|
||||
|
||||
ghoul::lua::push(L, sync->isResolved());
|
||||
return 1;
|
||||
bool isResolved = sync->isResolved();
|
||||
return isResolved;
|
||||
}
|
||||
|
||||
int unsyncResource(lua_State* L) {
|
||||
ghoul::lua::checkArgumentsAndThrow(L, { 1, 2 }, "lua::unsyncResource");
|
||||
auto [identifier, version] = ghoul::lua::values<std::string, std::optional<int>>(L);
|
||||
|
||||
/**
|
||||
* Unsynchronizes the http resources identified by the name passed as the first parameter
|
||||
* by removing all data that was downloaded as part of the original synchronization. If
|
||||
* the second parameter is provided, is it the version of the resources that is
|
||||
* unsynchronized, if the parameter is not provided, all versions for the specified http
|
||||
* resource are removed.
|
||||
*/
|
||||
[[codegen::luawrap]] void unsyncResource(std::string identifier, std::optional<int> version) {
|
||||
using namespace openspace;
|
||||
|
||||
const SyncModule* module = global::moduleEngine->module<SyncModule>();
|
||||
std::filesystem::path sync = absPath(module->synchronizationRoot());
|
||||
std::filesystem::path base = sync / "http" / identifier;
|
||||
@@ -70,8 +77,8 @@ int unsyncResource(lua_State* L) {
|
||||
std::filesystem::remove_all(folder);
|
||||
std::filesystem::remove(base / syncFile);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace openspace::luascriptfunctions
|
||||
#include "syncmodule_lua_codegen.cpp"
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -55,14 +55,15 @@ cmake_policy(SET CMP0074 NEW)
|
||||
|
||||
# Specify the CEF distribution version.
|
||||
|
||||
# Release from 04/24/2019 verified to work on Windows.
|
||||
set(CEF_VERSION "73.1.13+g6e3c989+chromium-73.0.3683.75")
|
||||
# Release from 03/21/2022 verified to work on Windows.
|
||||
set(CEF_VERSION "99.2.12+g2977b3a+chromium-99.0.4844.74")
|
||||
|
||||
# Removing - micahnyc 03/21/2022
|
||||
# 73.1.13 has an issue on MacOS: The GUI freezing upon interaction.
|
||||
# Therefore, we fall back to 3.3578.1867 from 01/29/2019
|
||||
if (APPLE)
|
||||
set(CEF_VERSION "3.3578.1867.g0f6d65a")
|
||||
endif ()
|
||||
#if (APPLE)
|
||||
# set(CEF_VERSION "3.3578.1867.g0f6d65a")
|
||||
#endif ()
|
||||
|
||||
# CEF Sandbox is not working with the latest Visual Studio, so we disable it for now.
|
||||
if (WIN32)
|
||||
|
||||
@@ -456,12 +456,10 @@ if(OS_WINDOWS)
|
||||
# List of CEF binary files.
|
||||
set(CEF_BINARY_FILES
|
||||
chrome_elf.dll
|
||||
d3dcompiler_43.dll
|
||||
d3dcompiler_47.dll
|
||||
libcef.dll
|
||||
libEGL.dll
|
||||
libGLESv2.dll
|
||||
natives_blob.bin
|
||||
snapshot_blob.bin
|
||||
v8_context_snapshot.bin
|
||||
#swiftshader
|
||||
@@ -469,11 +467,9 @@ if(OS_WINDOWS)
|
||||
|
||||
# List of CEF resource files.
|
||||
set(CEF_RESOURCE_FILES
|
||||
cef.pak
|
||||
cef_100_percent.pak
|
||||
cef_200_percent.pak
|
||||
cef_extensions.pak
|
||||
devtools_resources.pak
|
||||
chrome_100_percent.pak
|
||||
chrome_200_percent.pak
|
||||
resources.pak
|
||||
icudtl.dat
|
||||
locales
|
||||
)
|
||||
|
||||
@@ -41,11 +41,17 @@ namespace openspace {
|
||||
|
||||
class DefaultBrowserLauncher : public CefLifeSpanHandler, public CefRequestHandler {
|
||||
public:
|
||||
bool OnBeforePopup(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame,
|
||||
const CefString& targetUrl, const CefString& targetFrameName,
|
||||
CefLifeSpanHandler::WindowOpenDisposition targetDisposition, bool userGesture,
|
||||
const CefPopupFeatures& popupFeatures, CefWindowInfo& windowInfo,
|
||||
CefRefPtr<CefClient>& client, CefBrowserSettings& settings,
|
||||
bool OnBeforePopup(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
const CefString& targetUrl,
|
||||
const CefString& targetFrameName,
|
||||
CefLifeSpanHandler::WindowOpenDisposition targetDisposition,
|
||||
bool userGesture,
|
||||
const CefPopupFeatures& popupFeatures,
|
||||
CefWindowInfo& windowInfo,
|
||||
CefRefPtr<CefClient>& client,
|
||||
CefBrowserSettings& settings,
|
||||
CefRefPtr<CefDictionaryValue>& extra_info,
|
||||
bool* noJavascriptAccess) override;
|
||||
|
||||
//bool OnOpenURLFromTab(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame,
|
||||
|
||||
@@ -48,7 +48,7 @@ BrowserInstance::BrowserInstance(WebRenderHandler* renderer,
|
||||
: _renderHandler(renderer)
|
||||
, _keyboardHandler(keyboardHandler)
|
||||
{
|
||||
_client = new BrowserClient(_renderHandler, _keyboardHandler);
|
||||
_client = new BrowserClient(_renderHandler.get(), _keyboardHandler.get());
|
||||
|
||||
CefWindowInfo windowInfo;
|
||||
windowInfo.SetAsWindowless(nullptr);
|
||||
@@ -62,6 +62,7 @@ BrowserInstance::BrowserInstance(WebRenderHandler* renderer,
|
||||
_client.get(),
|
||||
url,
|
||||
browserSettings,
|
||||
nullptr,
|
||||
nullptr
|
||||
);
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@ bool DefaultBrowserLauncher::OnBeforePopup(CefRefPtr<CefBrowser>, CefRefPtr<CefF
|
||||
CefLifeSpanHandler::WindowOpenDisposition,
|
||||
bool, const CefPopupFeatures&, CefWindowInfo&,
|
||||
CefRefPtr<CefClient>&, CefBrowserSettings&,
|
||||
CefRefPtr<CefDictionaryValue>&,
|
||||
bool*)
|
||||
{
|
||||
// never permit CEF popups, always launch in default browser
|
||||
|
||||
@@ -94,8 +94,8 @@ ScreenSpaceBrowser::ScreenSpaceBrowser(const ghoul::Dictionary& dictionary)
|
||||
_renderHandler = new ScreenSpaceRenderHandler;
|
||||
_keyboardHandler = new WebKeyboardHandler();
|
||||
_browserInstance = std::make_unique<BrowserInstance>(
|
||||
_renderHandler,
|
||||
_keyboardHandler
|
||||
_renderHandler.get(),
|
||||
_keyboardHandler.get()
|
||||
);
|
||||
|
||||
_url.onChange([this]() { _isUrlDirty = true; });
|
||||
|
||||
@@ -42,8 +42,10 @@ void WebBrowserApp::OnContextCreated(CefRefPtr<CefBrowser>, CefRefPtr<CefFrame>,
|
||||
void WebBrowserApp::OnBeforeCommandLineProcessing(const CefString&,
|
||||
CefRefPtr<CefCommandLine> commandLine)
|
||||
{
|
||||
commandLine->AppendSwitch("disable-gpu");
|
||||
commandLine->AppendSwitch("disable-gpu-compositing");
|
||||
commandLine->AppendSwitch("use-gl=desktop");
|
||||
commandLine->AppendSwitch("ignore-gpu-blacklist");
|
||||
commandLine->AppendSwitch("log-gpu-control-list-decisions");
|
||||
|
||||
commandLine->AppendSwitch("enable-begin-frame-scheduling");
|
||||
commandLine->AppendSwitchWithValue("autoplay-policy", "no-user-gesture-required");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user