Merge branch 'master' into feature/profileOverScene

This commit is contained in:
GPayne
2021-09-12 21:11:12 -06:00
105 changed files with 1953 additions and 2385 deletions
+32 -7
View File
@@ -64,11 +64,7 @@ set(SOURCE_FILES
src/profile/propertiesdialog.cpp
)
find_package(Qt5 COMPONENTS Widgets REQUIRED)
set(MOC_FILES "")
qt5_wrap_cpp(
MOC_FILES
set(HEADER_SOURCE
include/launcherwindow.h
include/profile/actiondialog.h
include/profile/additionalscriptsdialog.h
@@ -85,13 +81,42 @@ qt5_wrap_cpp(
include/profile/propertiesdialog.h
)
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Widgets REQUIRED)
set(MOC_FILES "")
set(RESOURCE_FILES "")
qt5_add_resources(RESOURCE_FILES resources/resources.qrc)
set(LIBRARIES "")
if (${QT_VERSION_MAJOR} EQUAL 5)
find_package(Qt5 COMPONENTS Widgets)
qt5_wrap_cpp(
MOC_FILES
${HEADER_SOURCE}
)
qt5_add_resources(RESOURCE_FILES resources/resources.qrc)
set(LIBRARIES )
elseif (${QT_VERSION_MAJOR} EQUAL 6)
find_package(Qt6 COMPONENTS Widgets REQUIRED)
qt6_wrap_cpp(
MOC_FILES
${HEADER_SOURCE}
)
qt6_add_resources(RESOURCE_FILES resources/resources.qrc)
elseif (NOT DEFINED QT_VERSION_MAJOR)
message(FATAL_ERROR "Unable to find Qt version")
else ()
message(FATAL_ERROR "Unsupported Qt version")
endif()
add_library(openspace-ui-launcher STATIC ${HEADER_FILES} ${SOURCE_FILES} ${MOC_FILES} ${RESOURCE_FILES})
set_openspace_compile_settings(openspace-ui-launcher)
target_include_directories(openspace-ui-launcher PUBLIC include)
target_link_libraries(openspace-ui-launcher PUBLIC Qt5::Core Qt5::Gui Qt5::Widgets openspace-core)
target_link_libraries(
openspace-ui-launcher
PUBLIC
openspace-core
Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Gui Qt${QT_VERSION_MAJOR}::Widgets
)
if (MSVC)
set(MSVC_WARNINGS
@@ -38,7 +38,7 @@ class QListWidget;
class QPushButton;
class QTextEdit;
class ActionDialog : public QDialog {
class ActionDialog final : public QDialog {
Q_OBJECT
public:
ActionDialog(QWidget* parent,
@@ -29,7 +29,7 @@
class QTextEdit;
class AdditionalScriptsDialog : public QDialog {
class AdditionalScriptsDialog final : public QDialog {
Q_OBJECT
public:
/**
@@ -32,7 +32,7 @@
class QTextEdit;
class QTreeView;
class AssetsDialog : public QDialog {
class AssetsDialog final : public QDialog {
Q_OBJECT
public:
/**
@@ -31,7 +31,7 @@
#include "openspace/scene/profile.h"
#include <memory>
class AssetTreeModel : public QAbstractItemModel {
class AssetTreeModel final : public QAbstractItemModel {
Q_OBJECT
public:
@@ -45,7 +45,7 @@ public:
* function (can be multiple times)
* \return QVariant data object
*/
QVariant data(const QModelIndex& index, int role) const override;
QVariant data(const QModelIndex& index, int role) const final;
/**
* Returns the header data of the tree view
@@ -57,7 +57,7 @@ public:
* \return QVariant data object in the header
*/
QVariant headerData(int section, Qt::Orientation orientation,
int role = Qt::DisplayRole) const override;
int role = Qt::DisplayRole) const final;
/**
* Returns the index of item in #QModelIndex object form
@@ -68,7 +68,7 @@ public:
* \return #QModelIndex index of the item at specified position
*/
QModelIndex index(int row, int column,
const QModelIndex& parent = QModelIndex()) const override;
const QModelIndex& parent = QModelIndex()) const final;
/**
* Returns the index of the parent of the item specified by input param
@@ -76,7 +76,7 @@ public:
* \param index of item that is a child of the parent
* \return #QModelIndex index of the parent
*/
QModelIndex parent(const QModelIndex& index) const override;
QModelIndex parent(const QModelIndex& index) const final;
/**
* Returns the index of the parent of the item specified by the input params
@@ -103,7 +103,7 @@ public:
* \param parent #QModelIndex of the parent item
* \return number of children/rows of this parent
*/
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
int rowCount(const QModelIndex& parent = QModelIndex()) const final;
/**
* Returns the number of columns of data in each item of the tree
@@ -111,7 +111,7 @@ public:
* \param parent specified by the #QModelIndex index
* \return the number of data columns
*/
int columnCount(const QModelIndex& parent = QModelIndex()) const override;
int columnCount(const QModelIndex& parent = QModelIndex()) const final;
/**
* Return the Qt flags of the item specified by index, which can include
@@ -120,7 +120,7 @@ public:
* \param index specified by the #QModelIndex index
* \return the Qt flags
*/
Qt::ItemFlags flags(const QModelIndex& index) const override;
Qt::ItemFlags flags(const QModelIndex& index) const final;
/**
* Set data at index \p index
@@ -131,7 +131,7 @@ public:
* \return true if the data set was successful
*/
bool setData(const QModelIndex& index, const QVariant& value,
int role = Qt::EditRole) override;
int role = Qt::EditRole) final;
/**
* Returns a vector of all #Assets selected in the tree view
@@ -34,7 +34,7 @@ class QLabel;
class QLineEdit;
class QTabWidget;
class CameraDialog : public QDialog {
class CameraDialog final : public QDialog {
Q_OBJECT
public:
/**
@@ -33,7 +33,7 @@ class QListWidget;
class QLineEdit;
class QPushButton;
class DeltaTimesDialog : public QDialog {
class DeltaTimesDialog final : public QDialog {
Q_OBJECT
public:
/**
@@ -32,7 +32,7 @@ class QListWidget;
class QListWidgetItem;
class QPushButton;
class MarkNodesDialog : public QDialog {
class MarkNodesDialog final : public QDialog {
Q_OBJECT
public:
/**
@@ -33,7 +33,7 @@
class QLineEdit;
class QTextEdit;
class MetaDialog : public QDialog {
class MetaDialog final : public QDialog {
Q_OBJECT
public:
/**
@@ -35,7 +35,7 @@ class QLineEdit;
class QListWidget;
class QPushButton;
class ModulesDialog : public QDialog {
class ModulesDialog final : public QDialog {
Q_OBJECT
public:
/**
@@ -36,7 +36,7 @@ class QLabel;
class QLineEdit;
class QTextEdit;
class ProfileEdit : public QDialog {
class ProfileEdit final : public QDialog {
Q_OBJECT
public:
/**
@@ -36,7 +36,7 @@ class QLineEdit;
class QListWidget;
class QPushButton;
class PropertiesDialog : public QDialog {
class PropertiesDialog final : public QDialog {
Q_OBJECT
public:
/**
@@ -28,7 +28,7 @@
#include <QDialog>
#include <QListWidget>
class ScriptlogDialog : public QDialog {
class ScriptlogDialog final : public QDialog {
Q_OBJECT
public:
/**
@@ -34,7 +34,7 @@ class QDateTimeEdit;
class QLabel;
class QLineEdit;
class TimeDialog : public QDialog {
class TimeDialog final : public QDialog {
Q_OBJECT
public:
/**
@@ -65,8 +65,8 @@ ActionDialog::ActionDialog(QWidget* parent,
std::vector<openspace::Profile::Keybinding>* keybindings)
: QDialog(parent)
, _actions(actions)
, _keybindings(keybindings)
, _actionData(*_actions)
, _keybindings(keybindings)
, _keybindingsData(*_keybindings)
{
setWindowTitle("Actions and Keybindings");
@@ -512,9 +512,7 @@ void ActionDialog::actionSaved() {
const auto it = std::find_if(
_actionData.begin(), _actionData.end(),
[id = newIdentifier](const Profile::Action& action) {
return action.identifier == id;
}
[id = newIdentifier](const Profile::Action& a) { return a.identifier == id; }
);
if (it != _actionData.end()) {
QMessageBox::critical(
+3 -3
View File
@@ -960,7 +960,7 @@ void checkCommandLineForSettings(int& argc, char** argv, bool& hasSGCT, bool& ha
}
std::string setWindowConfigPresetForGui(const std::string labelFromCfgFile,
const std::string xmlExt, bool haveCliSGCTConfig,
bool haveCliSGCTConfig,
const std::string& sgctFunctionName)
{
configuration::Configuration& config = *global::configuration;
@@ -1046,8 +1046,9 @@ int main(int argc, char* argv[]) {
//
// Parse commandline arguments
//
char* prgName = argv[0];
ghoul::cmdparser::CommandlineParser parser(
std::string(argv[0]),
std::string(prgName),
ghoul::cmdparser::CommandlineParser::AllowUnknownCommands::Yes
);
@@ -1159,7 +1160,6 @@ int main(int argc, char* argv[]) {
const std::string xmlExt = ".xml";
std::string windowCfgPreset = setWindowConfigPresetForGui(
labelFromCfgFile,
xmlExt,
hasSGCTConfig,
sgctFunctionName
);
+1 -1
View File
@@ -129,4 +129,4 @@ int main(int argc, char** argv) {
LINFO("Server stopped");
return 0;
};
}
+47
View File
@@ -0,0 +1,47 @@
local assetHelper = asset.require('util/asset_helper')
local earth = asset.require('scene/solarsystem/planets/earth/earth')
local sunTransforms = asset.require('scene/solarsystem/sun/transforms')
local models = asset.syncedResource({
Name = "New Horizons Model",
Type = "HttpSynchronization",
Identifier = "newhorizons_model",
Version = 2
})
local lat = 40.7306
local long = -73.9352
local Example_GlobeRotation = {
Identifier = "Example_GlobeRotation",
Parent = earth.Earth.Identifier,
Transform = {
Translation = {
Type = "GlobeTranslation",
Globe = earth.Earth.Identifier,
Latitude = lat,
Longitude = long,
Altitude = 6,
UseHeightmap = true
},
Rotation = {
Type = "GlobeRotation",
Globe = earth.Earth.Identifier,
Latitude = lat,
Longitude = long
-- Can be used to to put flat on leaning surfaces, but also leads to updating
-- the rotation every frame
--UseHeightmap = true
}
},
Renderable = {
Type = "RenderableModel",
Body = "NEW HORIZONS",
GeometryFile = models .. "/NewHorizonsCleanModel.obj"
},
GUI = {
Path = "/Example"
}
}
assetHelper.registerSceneGraphNodesAndExport(asset, { Example_GlobeRotation })
+2 -2
View File
@@ -16,8 +16,8 @@ local Example_Fixed_Height = {
Translation = {
Type = "GlobeTranslation",
Globe = earth.Earth.Identifier,
Longitude = -74.006,
Latitude = 40.7128,
Longitude = -74.006,
Altitude = 100000.0
}
},
@@ -38,8 +38,8 @@ local Example_Adaptive_Height = {
Translation = {
Type = "GlobeTranslation",
Globe = earth.Earth.Identifier,
Longitude = -74.006,
Latitude = 40.7128,
Longitude = -74.006,
UseHeightmap = true
}
},
@@ -0,0 +1,75 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* *
* 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 "fragment.glsl"
in vec2 vs_st;
in vec3 vs_normalViewSpace;
in vec4 vs_positionCameraSpace;
in float vs_screenSpaceDepth;
in mat3 TBN;
uniform float ambientIntensity = 0.2;
uniform float diffuseIntensity = 1.0;
uniform float specularIntensity = 1.0;
uniform bool performShading = true;
uniform bool use_forced_color = false;
uniform bool has_texture_diffuse;
uniform bool has_texture_normal;
uniform bool has_texture_specular;
uniform bool has_color_specular;
uniform bool opacityBlending = false;
uniform sampler2D texture_diffuse;
uniform sampler2D texture_normal;
uniform sampler2D texture_specular;
uniform vec3 color_diffuse;
uniform vec3 color_specular;
uniform int nLightSources;
uniform vec3 lightDirectionsViewSpace[8];
uniform float lightIntensities[8];
uniform float opacity = 1.0;
Fragment getFragment() {
Fragment frag;
if (has_texture_normal) {
vec3 normalAlbedo = texture(texture_normal, vs_st).rgb;
normalAlbedo = normalize(normalAlbedo * 2.0 - 1.0);
frag.color.rgb = normalize(TBN * normalAlbedo);
}
else {
frag.color.rgb = normalize(vs_normalViewSpace);
}
frag.color.a = 1.0;
frag.gPosition = vs_positionCameraSpace;
frag.gNormal = vec4(vs_normalViewSpace, 0.0);
frag.disableLDR2HDR = true;
return frag;
}
@@ -0,0 +1,68 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* *
* 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. *
****************************************************************************************/
#version __CONTEXT__
#include "PowerScaling/powerScaling_vs.hglsl"
layout(location = 0) in vec4 in_position;
layout(location = 1) in vec2 in_st;
layout(location = 2) in vec3 in_normal;
layout(location = 3) in vec3 in_tangent;
out vec2 vs_st;
out vec3 vs_normalViewSpace;
out float vs_screenSpaceDepth;
out vec4 vs_positionCameraSpace;
out mat3 TBN;
uniform mat4 modelViewTransform;
uniform mat4 projectionTransform;
uniform mat4 normalTransform;
uniform mat4 meshTransform;
uniform mat4 meshNormalTransform;
void main() {
vs_positionCameraSpace = modelViewTransform * (meshTransform * in_position);
vec4 positionClipSpace = projectionTransform * vs_positionCameraSpace;
vec4 positionScreenSpace = z_normalization(positionClipSpace);
gl_Position = positionScreenSpace;
vs_st = in_st;
vs_screenSpaceDepth = positionScreenSpace.w;
vs_normalViewSpace = normalize(mat3(normalTransform) * (mat3(meshNormalTransform) * in_normal));
// TBN matrix for normal mapping
vec3 T = normalize(mat3(normalTransform) * (mat3(meshNormalTransform) * in_tangent));
vec3 N = normalize(mat3(normalTransform) * (mat3(meshNormalTransform) * in_normal));
// Re-orthogonalize T with respect to N
T = normalize(T - dot(T, N) * N);
// Retrieve perpendicular vector B with cross product of T and N
vec3 B = normalize(cross(N, T));
TBN = mat3(T, B, N);
}
@@ -0,0 +1,45 @@
local assetHelper = asset.require('util/asset_helper')
local sunTransforms = asset.require('scene/solarsystem/sun/transforms')
local transforms = asset.require('scene/solarsystem/planets/earth/transforms')
local model = asset.syncedResource({
Name = "Animated Box",
Type = "HttpSynchronization",
Identifier = "animated_box",
Version = 1
})
local model = {
Identifier = "modelshader",
Parent = transforms.EarthCenter.Identifier,
Transform = {
Translation = {
Type = "StaticTranslation",
Position = { 11E7, 0.0, 0.0 }
}
},
Renderable = {
Type = "RenderableModel",
GeometryFile = model .. "/BoxAnimated.glb",
ModelScale = 3E7,
LightSources = {
{
Type = "SceneGraphLightSource",
Identifier = "Sun",
Node = sunTransforms.SolarSystemBarycenter.Identifier,
Intensity = 1.0
}
},
PerformShading = true,
DisableFaceCulling = true,
VertexShader = asset.localResource("model_vs.glsl"),
FragmentShader = asset.localResource("model_fs.glsl"),
},
GUI = {
Name = "Model Shader",
Path = "/Example",
Description = "Simple box model with a custom shader",
}
}
assetHelper.registerSceneGraphNodesAndExport(asset, { model })
@@ -50,6 +50,7 @@ local Apollo15 = {
Renderable = {
Type = "RenderableModel",
GeometryFile = models .. "/ApolloCSM.osmodel",
ModelScale = 0.0001,
LightSources = {
{
Type = "SceneGraphLightSource",
@@ -38,11 +38,6 @@ local Apollo8LaunchModel = {
End = "1968 DEC 22"
},
Transform = {
Scale = {
Type = "StaticScale",
-- The scale of the model is in cm; OpenSpace is in m
Scale = 0.01
},
Rotation = {
Type = "StaticRotation",
Rotation = {0.0, 0.0, -3.1415 / 2}
@@ -51,6 +46,7 @@ local Apollo8LaunchModel = {
Renderable = {
Type = "RenderableModel",
GeometryFile = models .. "/ApolloCSM.osmodel",
ModelScale = 0.0001,
LightSources = {
{
Type = "SceneGraphLightSource",
@@ -50,11 +50,6 @@ local Apollo8Model = {
End = "1968 DEC 28"
},
Transform = {
Scale = {
Type = "StaticScale",
-- The scale of the model is in cm; OpenSpace is in m
Scale = 0.01
},
Rotation = {
Type = "StaticRotation",
Rotation = {0.0, 0.0, -3.1415 / 2}
@@ -63,6 +58,7 @@ local Apollo8Model = {
Renderable = {
Type = "RenderableModel",
GeometryFile = models .. "/ApolloCSM.osmodel",
ModelScale = 0.0001,
LightSources = {
{
Type = "SceneGraphLightSource",
@@ -1,8 +1,17 @@
<GDAL_WMS>
<Service name="TiledWMS">
<ServerUrl>http://198.102.45.23/arcgis/rest/services/worldelevation3d/terrain3d?</ServerUrl>
<TiledGroupName>GCS_Elevation</TiledGroupName>
<Service name="TMS">
<ServerUrl>http://earthlive.maptiles.arcgis.com/arcgis/rest/services/GCS_Elevation3D/ImageServer/tile/${z}/${y}/${x}</ServerUrl>
</Service>
<Timeout>2</Timeout>
<DataWindow>
<UpperLeftX>-180</UpperLeftX> <UpperLeftY>90</UpperLeftY>
<LowerRightX>180</LowerRightX> <LowerRightY>-90</LowerRightY>
<SizeX>16777216</SizeX> <SizeY>8388608</SizeY>
<TileLevel>14</TileLevel> <YOrigin>top</YOrigin>
</DataWindow>
<Projection>EPSG:4326</Projection>
<BlockSizeX>512</BlockSizeX> <BlockSizeY>512</BlockSizeY>
<BandsCount>1</BandsCount> <DataType>Float32</DataType>
<DataValues NoData="0" Min="-11000" Max="8500"/>
<MaxConnections>5</MaxConnections>
<ZeroBlockHttpCodes>404,400</ZeroBlockHttpCodes>
</GDAL_WMS>
+1 -1
View File
@@ -3,7 +3,7 @@ asset.require('./static_server')
local guiCustomization = asset.require('customization/gui')
-- Select which commit hashes to use for the frontend and backend
local frontendHash = "829260614bb95e236d23cb500f6ec0fb2e3bdf51"
local frontendHash = "b777c48280801e3b54cf77c1231f949fe6e69ace"
local dataProvider = "data.openspaceproject.com/files/webgui"
local frontend = asset.syncedResource({
@@ -28,6 +28,7 @@
#include <ghoul/misc/assert.h>
#include <ghoul/misc/exception.h>
#include <ghoul/misc/stringconversion.h>
#include <ghoul/fmt.h>
#include <array>
#include <memory>
#include <string>
@@ -126,18 +127,18 @@ inline std::string to_string(const openspace::interaction::JoystickAction& value
case openspace::interaction::JoystickAction::Press: return "Press";
case openspace::interaction::JoystickAction::Repeat: return "Repeat";
case openspace::interaction::JoystickAction::Release: return "Release";
default: throw MissingCaseException();
default: throw MissingCaseException();
}
}
template <>
constexpr openspace::interaction::JoystickAction from_string(std::string_view string) {
if (string == "Idle") { return openspace::interaction::JoystickAction::Idle; }
if (string == "Press") { return openspace::interaction::JoystickAction::Press; }
if (string == "Repeat") { return openspace::interaction::JoystickAction::Repeat; }
if (string == "Idle") { return openspace::interaction::JoystickAction::Idle; }
if (string == "Press") { return openspace::interaction::JoystickAction::Press; }
if (string == "Repeat") { return openspace::interaction::JoystickAction::Repeat; }
if (string == "Release") { return openspace::interaction::JoystickAction::Release; }
throw RuntimeError("Unknown action '" + std::string(string) + "'");
throw RuntimeError(fmt::format("Unknown action '{}'", string));
}
} // namespace ghoul
@@ -199,7 +199,8 @@ private:
struct IdleBehavior : public properties::PropertyOwner {
enum Behavior {
Orbit = 0,
OrbitAtConstantLat
OrbitAtConstantLat,
OrbitAroundUp
};
IdleBehavior();
@@ -369,20 +370,36 @@ private:
glm::dquat& localRotation, glm::dquat& globalRotation);
/**
* IdleBehavior::Behavior::Orbit
* Orbit the current anchor node, in a right-bound orbit, by updating the position
* and global rotation of the camera
* and global rotation of the camera.
*
* Used for IdleBehavior::Behavior::Orbit
*
* \param deltaTime The time step to use for the motion. Controls the rotation angle
* \param position The position of the camera. Will be changed by the function
* \param globalRotation The camera's global rotation. Will be changed by the function
* \param speedScale A speed scale that controls the speed of the motion
*/
void orbitAnchor(double deltaTime, glm::dvec3& position,
glm::dquat& globalRotation, double speedScale);
/**
* IdleBehavior::Behavior::OrbitAtConstantLat
* Orbit the current anchor node, but stay on the current latitude band. Note that
* this creates a rolling motion if looking at any of the anchor's poles, and should
* be used with care
* Orbit the current anchor node, by adding a rotation around the given axis. For
* example, when the axis is the north vector, the camera will stay on the current
* latitude band. Note that this creates a rolling motion if the camera's forward
* vector coincides with the axis, and should be used with care.
*
* Used for:
* IdleBehavior::Behavior::OrbitAtConstantLat ( axis = north = z-axis ) and
* IdleBehavior::Behavior::OrbitAroundUp ( axis = up = y-axis )
*
* \param axis The axis to arbit around, given in model coordinates of the anchor
* \param deltaTime The time step to use for the motion. Controls the rotation angle
* \param position The position of the camera. Will be changed by the function
* \param globalRotation The camera's global rotation. Will be changed by the function
* \param speedScale A speed scale that controls the speed of the motion
*/
void orbitAtConstantLatitude(double deltaTime, glm::dvec3& position,
void orbitAroundAxis(const glm::dvec3 axis, double deltaTime, glm::dvec3& position,
glm::dquat& globalRotation, double speedScale);
};
-7
View File
@@ -57,12 +57,6 @@ public:
Waypoint startPoint() const;
Waypoint endPoint() const;
/**
* Return the specified duration for the path, in seconds. Note that the time it
* takes to actually traverse the path will not exactly match the provided duration
*/
double duration() const;
/**
* Return the total length of the the curve for the path, in meters
*/
@@ -128,7 +122,6 @@ private:
Waypoint _start;
Waypoint _end;
double _duration; // seconds
Type _type;
std::unique_ptr<PathCurve> _curve;
@@ -87,7 +87,7 @@ public:
*
* \param value The value that is used to set this Property
*/
virtual void set(std::any value) override;
virtual void set(std::any value) final;
/**
* Returns the <code>std::type_info</code> describing the template parameter
@@ -94,9 +94,9 @@ public:
virtual void updateRendererData();
virtual void raycastersChanged(VolumeRaycaster& raycaster,
RaycasterListener::IsAttached attached);
RaycasterListener::IsAttached attached) override;
virtual void deferredcastersChanged(Deferredcaster& deferredcaster,
DeferredcasterListener::IsAttached isAttached);
DeferredcasterListener::IsAttached isAttached) override;
private:
using RaycasterProgObjMap = std::map<
@@ -32,6 +32,7 @@
#include <openspace/properties/scalar/intproperty.h>
#include <openspace/properties/scalar/floatproperty.h>
#include <openspace/properties/vector/vec3property.h>
#include <openspace/properties/vector/vec4property.h>
#include <openspace/properties/triggerproperty.h>
#include <openspace/rendering/framebufferrenderer.h>
#include <chrono>
@@ -219,6 +220,9 @@ private:
} _cameraButtonLocations;
std::string _versionString;
properties::Vec4Property _enabledFontColor;
properties::Vec4Property _disabledFontColor;
};
} // namespace openspace
+2 -2
View File
@@ -41,7 +41,7 @@ public:
virtual bool isInitializing() const = 0;
};
class SingleThreadedSceneInitializer : public SceneInitializer {
class SingleThreadedSceneInitializer final : public SceneInitializer {
public:
void initializeNode(SceneGraphNode* node) override;
std::vector<SceneGraphNode*> takeInitializedNodes() override;
@@ -51,7 +51,7 @@ private:
std::vector<SceneGraphNode*> _initializedNodes;
};
class MultiThreadedSceneInitializer : public SceneInitializer {
class MultiThreadedSceneInitializer final : public SceneInitializer {
public:
MultiThreadedSceneInitializer(unsigned int nThreads);
+1
View File
@@ -108,6 +108,7 @@ set(SOURCE_FILES
rendering/renderabletrailorbit.cpp
rendering/renderabletrailtrajectory.cpp
rendering/screenspacedashboard.cpp
rendering/screenspacedashboard_lua.inl
rendering/screenspaceframebuffer.cpp
rendering/screenspaceimagelocal.cpp
rendering/screenspaceimageonline.cpp
+48 -9
View File
@@ -249,6 +249,14 @@ namespace {
// [[codegen::verbatim(EnableOpacityBlendingInfo.description)]]
std::optional<bool> enableOpacityBlending;
// The path to the vertex shader program that is used instead of the default
// shader.
std::optional<std::filesystem::path> vertexShader;
// The path to the fragment shader program that is used instead of the default
// shader.
std::optional<std::filesystem::path> fragmentShader;
};
#include "renderablemodel_codegen.cpp"
} // namespace
@@ -335,7 +343,7 @@ RenderableModel::RenderableModel(const ghoul::Dictionary& dictionary)
distanceUnit = DistanceUnit::Kilometer;
break;
// Weired units
// Weird units
case Parameters::ScaleUnit::Thou:
distanceUnit = DistanceUnit::Thou;
break;
@@ -472,6 +480,13 @@ RenderableModel::RenderableModel(const ghoul::Dictionary& dictionary)
_disableDepthTest = p.disableDepthTest.value_or(_disableDepthTest);
_disableFaceCulling = p.disableFaceCulling.value_or(_disableFaceCulling);
if (p.vertexShader.has_value()) {
_vertexShaderPath = p.vertexShader->string();
}
if (p.fragmentShader.has_value()) {
_fragmentShaderPath = p.fragmentShader->string();
}
if (p.lightSources.has_value()) {
std::vector<ghoul::Dictionary> lightsources = *p.lightSources;
@@ -560,16 +575,33 @@ void RenderableModel::initialize() {
void RenderableModel::initializeGL() {
ZoneScoped
std::string program = ProgramName;
if (!_vertexShaderPath.empty()) {
program += "|vs=" + _vertexShaderPath;
}
if (!_fragmentShaderPath.empty()) {
program += "|fs=" + _fragmentShaderPath;
}
_program = BaseModule::ProgramObjectManager.request(
ProgramName,
[]() -> std::unique_ptr<ghoul::opengl::ProgramObject> {
return global::renderEngine->buildRenderProgram(
ProgramName,
absPath("${MODULE_BASE}/shaders/model_vs.glsl"),
absPath("${MODULE_BASE}/shaders/model_fs.glsl")
);
program,
[&]() -> std::unique_ptr<ghoul::opengl::ProgramObject> {
std::filesystem::path vs =
_vertexShaderPath.empty() ?
absPath("${MODULE_BASE}/shaders/model_vs.glsl") :
_vertexShaderPath;
std::filesystem::path fs =
_fragmentShaderPath.empty() ?
absPath("${MODULE_BASE}/shaders/model_fs.glsl") :
_fragmentShaderPath;
return global::renderEngine->buildRenderProgram(ProgramName, vs, fs);
}
);
// We don't really know what kind of shader the user provides us with, so we can't
// make the assumption that we are going to use all uniforms
_program->setIgnoreUniformLocationError(
ghoul::opengl::ProgramObject::IgnoreError::Yes
);
ghoul::opengl::updateUniformLocations(*_program, _uniformCache, UniformNames);
@@ -581,8 +613,15 @@ void RenderableModel::deinitializeGL() {
_geometry->deinitialize();
_geometry.reset();
std::string program = ProgramName;
if (!_vertexShaderPath.empty()) {
program += "|vs=" + _vertexShaderPath;
}
if (!_fragmentShaderPath.empty()) {
program += "|fs=" + _fragmentShaderPath;
}
BaseModule::ProgramObjectManager.release(
ProgramName,
program,
[](ghoul::opengl::ProgramObject* p) {
global::renderEngine->removeRenderProgram(p);
}
+2
View File
@@ -101,6 +101,8 @@ private:
properties::BoolProperty _enableOpacityBlending;
properties::OptionProperty _blendingFuncOption;
std::string _vertexShaderPath;
std::string _fragmentShaderPath;
ghoul::opengl::ProgramObject* _program = nullptr;
UniformCache(opacity, nLightSources, lightDirectionsViewSpace, lightIntensities,
modelViewTransform, normalTransform, projectionTransform,
@@ -338,7 +338,6 @@ void RenderableTrail::internalRender(bool renderLines, bool renderPoints,
_programObject->setUniform(_uniformCache.nVertices, nVertices);
#if !defined(__APPLE__)
glm::ivec2 resolution = global::renderEngine->renderingResolution();
GLint viewport[4];
global::renderEngine->openglStateCache().viewport(viewport);
_programObject->setUniform(
@@ -54,79 +54,10 @@ namespace {
#include "screenspacedashboard_codegen.cpp"
} // namespace
#include "screenspacedashboard_lua.inl"
namespace openspace {
namespace luascriptfunctions {
/**
* \ingroup LuaScripts
* addDashboardItemToScreenSpace(string, table):
*/
int addDashboardItemToScreenSpace(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::addDashboardItemToScreenSpace");
const std::string& name = ghoul::lua::value<std::string>(L, 1);
const int type = lua_type(L, 2);
if (type != LUA_TTABLE) {
return ghoul::lua::luaError(L, "Expected argument of type 'table'");
}
ghoul::Dictionary d;
try {
ghoul::lua::luaDictionaryFromState(L, d);
}
catch (const ghoul::lua::LuaFormatException& e) {
LERRORC("addDashboardItem", e.what());
return 0;
}
ScreenSpaceRenderable* ssr = global::renderEngine->screenSpaceRenderable(name);
if (!ssr) {
return ghoul::lua::luaError(L, "Provided name 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"
);
}
dash->dashboard().addDashboardItem(DashboardItem::createFromDictionary(d));
lua_settop(L, 0);
return 0;
}
/**
* \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, 1);
ScreenSpaceRenderable* ssr = global::renderEngine->screenSpaceRenderable(name);
if (!ssr) {
return ghoul::lua::luaError(L, "Provided name 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"
);
}
dash->dashboard().clearDashboardItems();
return 0;
}
} // namespace luascriptfunctions
documentation::Documentation ScreenSpaceDashboard::Documentation() {
return codegen::doc<Parameters>("base_screenspace_dashboard");
}
@@ -0,0 +1,77 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
namespace openspace::luascriptfunctions {
/**
* \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);
ScreenSpaceRenderable* ssr = global::renderEngine->screenSpaceRenderable(name);
if (!ssr) {
return ghoul::lua::luaError(L, "Provided name 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"
);
}
dash->dashboard().addDashboardItem(DashboardItem::createFromDictionary(d));
return 0;
}
/**
* \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);
ScreenSpaceRenderable* ssr = global::renderEngine->screenSpaceRenderable(name);
if (!ssr) {
return ghoul::lua::luaError(L, "Provided name 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"
);
}
dash->dashboard().clearDashboardItems();
return 0;
}
} // namespace openspace::luascriptfunctions
+7 -7
View File
@@ -44,15 +44,15 @@ uniform mat4 meshTransform;
uniform mat4 meshNormalTransform;
void main() {
vs_positionCameraSpace = modelViewTransform * (meshTransform * in_position);
vec4 positionClipSpace = projectionTransform * vs_positionCameraSpace;
vec4 positionScreenSpace = z_normalization(positionClipSpace);
vs_positionCameraSpace = modelViewTransform * (meshTransform * in_position);
vec4 positionClipSpace = projectionTransform * vs_positionCameraSpace;
vec4 positionScreenSpace = z_normalization(positionClipSpace);
gl_Position = positionScreenSpace;
vs_st = in_st;
vs_screenSpaceDepth = positionScreenSpace.w;
gl_Position = positionScreenSpace;
vs_st = in_st;
vs_screenSpaceDepth = positionScreenSpace.w;
vs_normalViewSpace = normalize(mat3(normalTransform) * (mat3(meshNormalTransform) * in_normal));
vs_normalViewSpace = normalize(mat3(normalTransform) * (mat3(meshNormalTransform) * in_normal));
// TBN matrix for normal mapping
vec3 T = normalize(mat3(normalTransform) * (mat3(meshNormalTransform) * in_tangent));
+3 -4
View File
@@ -94,11 +94,10 @@ scripting::LuaLibrary DebuggingModule::luaLibrary() const {
"addCartesianAxes",
&luascriptfunctions::addCartesianAxes,
{},
"string, string [,number]",
"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 string "
"will be used to set the identifier of the axes. The third (optional) "
"argument is a scale value, in meters."
"first string, to illustrate its local coordinate system. The second "
"(optional) argument is a scale value, in meters."
}
};
+31 -45
View File
@@ -61,11 +61,7 @@ namespace openspace::luascriptfunctions {
* Renders the current camera path
*/
int renderCameraPath(lua_State* L) {
int nArguments = ghoul::lua::checkArgumentsAndThrow(
L,
{ 0, 3 },
"lua::renderCameraPath"
);
ghoul::lua::checkArgumentsAndThrow(L, { 0, 3 }, "lua::renderCameraPath");
if (!global::navigationHandler->pathNavigator().hasCurrentPath()) {
LWARNINGC("Debugging: PathNavigation", "There is no current path to render");
@@ -74,12 +70,13 @@ int renderCameraPath(lua_State* L) {
const interaction::Path* currentPath =
global::navigationHandler->pathNavigator().currentPath();
const int nSteps = (nArguments > 0) ? ghoul::lua::value<int>(L, 1) : 100;
bool renderDirections = (nArguments > 1) ? ghoul::lua::value<bool>(L, 2) : false;
auto [nSteps, renderDirections, directionLineLength] = ghoul::lua::values<
std::optional<int>, std::optional<bool>, std::optional<double>
>(L);
constexpr const double defaultLineLength = 6e7;
const double directionLineLength =
(nArguments > 2) ? ghoul::lua::value<double>(L, 3) : defaultLineLength;
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
// rendered one, if any
@@ -98,7 +95,7 @@ int renderCameraPath(lua_State* L) {
// 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);
@@ -153,11 +150,12 @@ int renderCameraPath(lua_State* L) {
);
};
auto addDirectionLine = [addPoint, addLineBetweenPoints, directionLineLength]
(const std::string& pointId, const CameraPose& p)
auto addDirectionLine = [addPoint, addLineBetweenPoints]
(const std::string& pointId, const CameraPose& p,
double lineLength)
{
const glm::dvec3 dir = glm::normalize(p.rotation * glm::dvec3(0.0, 0.0, -1.0));
const glm::dvec3 pointPosition = p.position + directionLineLength * dir;
const glm::dvec3 pointPosition = p.position + lineLength * dir;
const std::string id = fmt::format("{}_orientation", pointId);
addPoint(id, pointPosition);
@@ -166,20 +164,19 @@ 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());
if (*renderDirections) {
addDirectionLine(pointIdentifier(0), poses.front(), *directionLineLength);
}
for (int i = 1; i < poses.size(); i++) {
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]);
if (*renderDirections) {
addDirectionLine(pointIdentifier(i), poses[i], *directionLineLength);
}
}
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
@@ -195,7 +192,6 @@ int removeRenderedCameraPath(lua_State* L) {
scripting::ScriptEngine::RemoteScripting::Yes
);
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
@@ -204,11 +200,7 @@ int removeRenderedCameraPath(lua_State* L) {
* Renders the control points of the current camera path
*/
int renderPathControlPoints(lua_State* L) {
int nArguments = ghoul::lua::checkArgumentsAndThrow(
L,
{ 0, 1 },
"lua::renderPathControlPoints"
);
ghoul::lua::checkArgumentsAndThrow(L, { 0, 1 }, "lua::renderPathControlPoints");
if (!global::navigationHandler->pathNavigator().hasCurrentPath()) {
LWARNINGC(
@@ -219,7 +211,8 @@ int renderPathControlPoints(lua_State* L) {
const interaction::Path* currentPath =
global::navigationHandler->pathNavigator().currentPath();
const double radius = (nArguments > 0) ? ghoul::lua::value<int>(L, 1) : 2000000;
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
@@ -259,7 +252,7 @@ int renderPathControlPoints(lua_State* L) {
"Type = 'RenderableSphere',"
"Enabled = true,"
"Segments = 30,"
"Size = " + std::to_string(radius) + ","
"Size = " + std::to_string(*radius) + ","
"Texture = " + colorTexturePath + ""
"},"
"GUI = {"
@@ -274,7 +267,6 @@ int renderPathControlPoints(lua_State* L) {
);
}
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
@@ -290,7 +282,6 @@ int removePathControlPoints(lua_State* L) {
scripting::ScriptEngine::RemoteScripting::Yes
);
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
@@ -298,37 +289,33 @@ int removePathControlPoints(lua_State* L) {
* Add a set of cartesian axes to the specified scene graph node
*/
int addCartesianAxes(lua_State* L) {
int nArgs = ghoul::lua::checkArgumentsAndThrow(L, { 2, 3 }, "lua::addCartesianAxes");
ghoul::lua::checkArgumentsAndThrow(L, { 1, 2 }, "lua::addCartesianAxes");
const std::string& nodeName = ghoul::lua::value<std::string>(L, 1);
const std::string& axesIdentifier = ghoul::lua::value<std::string>(L, 2);
auto [nodeIdentifier, scale] =
ghoul::lua::values<std::string, std::optional<double>>(L);
SceneGraphNode* n = global::renderEngine->scene()->sceneGraphNode(nodeName);
SceneGraphNode* n = global::renderEngine->scene()->sceneGraphNode(nodeIdentifier);
if (!n) {
return ghoul::lua::luaError(L, "Unknown scene graph node: " + nodeName);
return ghoul::lua::luaError(L, "Unknown scene graph node: " + nodeIdentifier);
}
double scale;
if (nArgs > 2) {
scale = ghoul::lua::value<double>(L, 3);
}
else {
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");
scale += 1.0;
scale = 1.0;
}
}
const std::string identifier = makeIdentifier(axesIdentifier);
const std::string identifier = makeIdentifier(nodeIdentifier + "_AxesXYZ");
const std::string& axes = "{"
"Identifier = '" + identifier + "',"
"Parent = '" + nodeName + "',"
"Parent = '" + nodeIdentifier + "',"
"Transform = { "
"Scale = {"
"Type = 'StaticScale',"
"Scale = " + std::to_string(scale) + ""
"Scale = " + std::to_string(*scale) + ""
"}"
"},"
"Renderable = {"
@@ -349,7 +336,6 @@ int addCartesianAxes(lua_State* L) {
scripting::ScriptEngine::RemoteScripting::Yes
);
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
+2 -2
View File
@@ -200,13 +200,13 @@ std::string ExoplanetsModule::exoplanetsDataPath() const {
return absPath(
fmt::format("{}/{}", _exoplanetsDataFolder.value(), ExoplanetsDataFileName)
).string();
};
}
std::string ExoplanetsModule::lookUpTablePath() const {
return absPath(
fmt::format("{}/{}", _exoplanetsDataFolder, LookupTableFileName)
).string();
};
}
std::string ExoplanetsModule::bvColormapPath() const {
return _bvColorMapPath;
+51 -63
View File
@@ -88,43 +88,45 @@ ExoplanetSystem findExoplanetSystemInData(std::string_view starName) {
std::string name;
std::getline(ss, name, ',');
if (name.substr(0, name.length() - 2) == starName) {
std::string location_s;
std::getline(ss, location_s);
long location = std::stol(location_s.c_str());
if (name.substr(0, name.length() - 2) != starName) {
continue;
}
data.seekg(location);
data.read(reinterpret_cast<char*>(&p), sizeof(ExoplanetDataEntry));
std::string location_s;
std::getline(ss, location_s);
long location = std::stol(location_s.c_str());
sanitizeNameString(name);
data.seekg(location);
data.read(reinterpret_cast<char*>(&p), sizeof(ExoplanetDataEntry));
if (!hasSufficientData(p)) {
LWARNING(fmt::format("Insufficient data for exoplanet: '{}'", name));
continue;
}
sanitizeNameString(name);
system.planetNames.push_back(name);
system.planetsData.push_back(p);
if (!hasSufficientData(p)) {
LWARNING(fmt::format("Insufficient data for exoplanet: '{}'", name));
continue;
}
// Star data - Should not vary between planets, but one data entry might
// lack data for the host star while another does not. So for every planet,
// update star data if needed
const glm::vec3 pos{ p.positionX, p.positionY, p.positionZ };
if (system.starData.position != pos && isValidPosition(pos)) {
system.starData.position = pos;
}
if (system.starData.radius != p.rStar && !std::isnan(p.rStar)) {
system.starData.radius = p.rStar;
}
if (system.starData.bv != p.bmv && !std::isnan(p.bmv)) {
system.starData.bv = p.bmv;
}
if (system.starData.teff != p.teff && !std::isnan(p.teff)) {
system.starData.teff = p.teff;
}
if (system.starData.luminosity != p.luminosity && !std::isnan(p.luminosity)) {
system.starData.luminosity = p.luminosity;
}
system.planetNames.push_back(name);
system.planetsData.push_back(p);
// Star data - Should not vary between planets, but one data entry might lack data
// for the host star while another does not. So for every planet, update star data
// if needed
const glm::vec3 pos = glm::vec3(p.positionX, p.positionY, p.positionZ);
if (system.starData.position != pos && isValidPosition(pos)) {
system.starData.position = pos;
}
if (system.starData.radius != p.rStar && !std::isnan(p.rStar)) {
system.starData.radius = p.rStar;
}
if (system.starData.bv != p.bmv && !std::isnan(p.bmv)) {
system.starData.bv = p.bmv;
}
if (system.starData.teff != p.teff && !std::isnan(p.teff)) {
system.starData.teff = p.teff;
}
if (system.starData.luminosity != p.luminosity && !std::isnan(p.luminosity)) {
system.starData.luminosity = p.luminosity;
}
}
@@ -555,50 +557,40 @@ 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);
const int t = lua_type(L, 1);
if (t == LUA_TSTRING) {
if (std::holds_alternative<std::string>(v)) {
// The user provided a single name
const std::string& starName = ghoul::lua::value<std::string>(L, 1);
std::string starName = std::get<std::string>(v);
createExoplanetSystem(starName);
}
else if (t == LUA_TTABLE) {
else {
// A list of names was provided
ghoul::Dictionary d;
ghoul::lua::luaDictionaryFromState(L, d);
for (size_t i = 1; i <= d.size(); ++i) {
if (!d.hasValue<std::string>(std::to_string(i))) {
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)
L,
fmt::format("List item {} is of invalid type", i)
);
}
const std::string& starName = d.value<std::string>(std::to_string(i));
const std::string& starName = starNames.value<std::string>(std::to_string(i));
createExoplanetSystem(starName);
}
lua_pop(L, 1);
}
else {
return ghoul::lua::luaError(L, "Invalid input");
}
lua_settop(L, 0);
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
int removeExoplanetSystem(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::removeExoplanetSystem");
std::string starName = ghoul::lua::value<std::string>(L);
const int StringLocation = -1;
const std::string starName = luaL_checkstring(L, StringLocation);
const std::string starIdentifier = createIdentifier(starName);
const std::string starIdentifier = createIdentifier(std::move(starName));
openspace::global::scriptEngine->queueScript(
"openspace.removeSceneGraphNode('" + starIdentifier + "');",
scripting::ScriptEngine::RemoteScripting::Yes
);
return 0;
}
@@ -656,7 +648,6 @@ std::vector<std::string> hostStarsWithSufficientData() {
// For easier read, sort by names and remove duplicates
std::sort(names.begin(), names.end());
names.erase(std::unique(names.begin(), names.end()), names.end());
return names;
}
@@ -664,15 +655,13 @@ 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) {
lua_pushstring(L, s.c_str());
ghoul::lua::push(L, s);
lua_rawseti(L, -2, number);
++number;
}
return 1;
}
@@ -683,16 +672,15 @@ int listAvailableExoplanetSystems(lua_State* L) {
std::string output;
for (auto it = names.begin(); it != names.end(); ++it) {
if (it != names.end()) {
output += *it + ", ";
}
output += *it + ", ";
}
output.pop_back();
output.pop_back();
LINFO(fmt::format(
"There is data available for the following {} exoplanet systems: {}",
names.size(), output
));
return 0;
}
+2
View File
@@ -34,6 +34,7 @@ set(HEADER_FILES
src/geodeticpatch.h
src/globelabelscomponent.h
src/globetranslation.h
src/globerotation.h
src/gpulayergroup.h
src/layer.h
src/layeradjustment.h
@@ -71,6 +72,7 @@ set(SOURCE_FILES
src/geodeticpatch.cpp
src/globelabelscomponent.cpp
src/globetranslation.cpp
src/globerotation.cpp
src/gpulayergroup.cpp
src/layer.cpp
src/layeradjustment.cpp
@@ -30,6 +30,7 @@
#include <modules/globebrowsing/src/geodeticpatch.h>
#include <modules/globebrowsing/src/globelabelscomponent.h>
#include <modules/globebrowsing/src/globetranslation.h>
#include <modules/globebrowsing/src/globerotation.h>
#include <modules/globebrowsing/src/layer.h>
#include <modules/globebrowsing/src/layeradjustment.h>
#include <modules/globebrowsing/src/layermanager.h>
@@ -274,6 +275,10 @@ void GlobeBrowsingModule::internalInitialize(const ghoul::Dictionary& dict) {
ghoul_assert(fTranslation, "Translation factory was not created");
fTranslation->registerClass<globebrowsing::GlobeTranslation>("GlobeTranslation");
auto fRotation = FactoryManager::ref().factory<Rotation>();
ghoul_assert(fRotation, "Rotation factory was not created");
fRotation->registerClass<globebrowsing::GlobeRotation>("GlobeRotation");
auto fTileProvider =
std::make_unique<ghoul::TemplateFactory<tileprovider::TileProvider>>();
ghoul_assert(fTileProvider, "TileProvider factory was not created");
+47 -118
View File
@@ -47,10 +47,8 @@ int addLayer(lua_State* L) {
ZoneScoped
ghoul::lua::checkArgumentsAndThrow(L, 3, "lua::addLayer");
// String arguments
const std::string& globeName = ghoul::lua::value<std::string>(L, 1);
const std::string& layerGroupName = ghoul::lua::value<std::string>(L, 2);
auto [globeName, layerGroupName, layerDict] =
ghoul::lua::values<std::string, std::string, ghoul::Dictionary>(L);
// Get the node and make sure it exists
SceneGraphNode* n = global::renderEngine->scene()->sceneGraphNode(globeName);
@@ -73,23 +71,10 @@ int addLayer(lua_State* L) {
}
// Get the dictionary defining the layer
ghoul::Dictionary d;
try {
ghoul::lua::luaDictionaryFromState(L, d);
}
catch (const ghoul::lua::LuaFormatException& e) {
LERRORC("addLayerFromDictionary", e.what());
lua_settop(L, 0);
return 0;
}
lua_settop(L, 0);
Layer* layer = globe->layerManager().addLayer(groupID, d);
Layer* layer = globe->layerManager().addLayer(groupID, layerDict);
if (layer) {
layer->initialize();
}
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
@@ -98,11 +83,8 @@ int addLayer(lua_State* L) {
*/
int deleteLayer(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 3, "lua::deleteLayer");
const std::string& globeName = luaL_checkstring(L, 1);
const std::string& layerGroupName = luaL_checkstring(L, 2);
const std::string& layerName = luaL_checkstring(L, 3);
lua_pop(L, 3);
auto [globeName, layerGroupName, layerName] =
ghoul::lua::values<std::string, std::string, std::string>(L);
// Get the node and make sure it exists
SceneGraphNode* n = global::renderEngine->scene()->sceneGraphNode(globeName);
@@ -125,17 +107,12 @@ int deleteLayer(lua_State* L) {
}
globe->layerManager().deleteLayer(groupID, layerName);
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
int getLayers(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::getLayers");
const std::string& globeIdentifier = ghoul::lua::value<std::string>(L, 1);
const std::string& layer = ghoul::lua::value<std::string>(L, 2);
lua_pop(L, 2);
auto [globeIdentifier, layer] = ghoul::lua::values<std::string, std::string>(L);
SceneGraphNode* n = sceneGraphNode(globeIdentifier);
if (!n) {
@@ -168,12 +145,8 @@ int getLayers(lua_State* L) {
int moveLayer(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 4, "lua::moveLayer");
const std::string& globeIdentifier = ghoul::lua::value<std::string>(L, 1);
const std::string& layer = ghoul::lua::value<std::string>(L, 2);
int oldPosition = ghoul::lua::value<int>(L, 3);
int newPosition = ghoul::lua::value<int>(L, 4);
lua_pop(L, 4);
auto [globeIdentifier, layer, oldPosition, newPosition] =
ghoul::lua::values<std::string, std::string, int, int>(L);
if (oldPosition == newPosition) {
return 0;
@@ -197,22 +170,16 @@ int moveLayer(lua_State* L) {
globebrowsing::LayerGroup& lg = globe->layerManager().layerGroup(group);
lg.moveLayers(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);
const std::string& globeIdentifier = ghoul::lua::value<std::string>(L, 1);
const int x = ghoul::lua::value<int>(L, 2);
const int y = ghoul::lua::value<int>(L, 3);
const int level = ghoul::lua::value<int>(L, 4);
lua_pop(L, 4);
SceneGraphNode* n = sceneGraphNode(globeIdentifier);
SceneGraphNode* n = sceneGraphNode(identifier);
if (!n) {
return ghoul::lua::luaError(L, "Unknown globe name: " + globeIdentifier);
return ghoul::lua::luaError(L, "Unknown globe name: " + identifier);
}
const RenderableGlobe* globe = dynamic_cast<const RenderableGlobe*>(n->renderable());
@@ -221,22 +188,18 @@ int goToChunk(lua_State* L) {
}
global::moduleEngine->module<GlobeBrowsingModule>()->goToChunk(*globe, x, y, level);
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
int goToGeo(lua_State* L) {
int nArguments = ghoul::lua::checkArgumentsAndThrow(L, { 2, 4 }, "lua::goToGeo");
ghoul::lua::checkArgumentsAndThrow(L, { 2, 4 }, "lua::goToGeo");
// 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;
const SceneGraphNode* n;
if (providedGlobeIdentifier) {
const std::string& globeIdentifier = ghoul::lua::value<std::string>(L, 1);
const std::string& globeIdentifier = ghoul::lua::value<std::string>(L);
n = sceneGraphNode(globeIdentifier);
if (!n) {
return ghoul::lua::luaError(L, "Unknown globe name: " + globeIdentifier);
@@ -249,8 +212,8 @@ int goToGeo(lua_State* L) {
}
}
const double latitude = ghoul::lua::value<double>(L, parameterOffset + 1);
const double longitude = ghoul::lua::value<double>(L, parameterOffset + 2);
auto [latitude, longitude, altitude] =
ghoul::lua::values<double, double, std::optional<double>>(L);
const RenderableGlobe* globe = dynamic_cast<const RenderableGlobe*>(n->renderable());
if (!globe) {
@@ -258,32 +221,29 @@ int goToGeo(lua_State* L) {
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"
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"
);
}
}
if (nArguments == parameterOffset + 2) {
global::moduleEngine->module<GlobeBrowsingModule>()->goToGeo(
*globe, latitude, longitude
);
}
else if (nArguments == parameterOffset + 3) {
const double altitude = ghoul::lua::value<double>(L, parameterOffset + 3);
if (altitude.has_value()) {
global::moduleEngine->module<GlobeBrowsingModule>()->goToGeo(
*globe,
latitude,
longitude,
altitude
*altitude
);
}
else {
global::moduleEngine->module<GlobeBrowsingModule>()->goToGeo(
*globe,
latitude,
longitude
);
}
lua_settop(L, 0);
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
@@ -297,7 +257,8 @@ int flyToGeo(lua_State* L) {
const SceneGraphNode* n;
if (providedGlobeIdentifier) {
const std::string& globeIdentifier = ghoul::lua::value<std::string>(L, 1);
const std::string& globeIdentifier =
ghoul::lua::value<std::string>(L, 1, ghoul::lua::PopValue::No);
n = sceneGraphNode(globeIdentifier);
if (!n) {
return ghoul::lua::luaError(L, "Unknown globe name: " + globeIdentifier);
@@ -324,9 +285,12 @@ int flyToGeo(lua_State* L) {
}
}
const double latitude = ghoul::lua::value<double>(L, parameterOffset + 1);
const double longitude = ghoul::lua::value<double>(L, parameterOffset + 2);
const double altitude = ghoul::lua::value<double>(L, parameterOffset + 3);
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>();
@@ -374,7 +338,8 @@ int flyToGeo(lua_State* L) {
}
if (firstIsNumber || nArguments > firstLocation) {
double duration = ghoul::lua::value<double>(L, location);
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");
@@ -394,12 +359,8 @@ int flyToGeo(lua_State* L) {
int getLocalPositionFromGeo(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 4, "lua::getLocalPositionFromGeo");
const std::string& globeIdentifier = ghoul::lua::value<std::string>(L, 1);
const double latitude = ghoul::lua::value<double>(L, 2);
const double longitude = ghoul::lua::value<double>(L, 3);
const double altitude = ghoul::lua::value<double>(L, 4);
lua_pop(L, 4);
auto [globeIdentifier, latitude, longitude, altitude] =
ghoul::lua::values<std::string, double, double, double>(L);
SceneGraphNode* n = sceneGraphNode(globeIdentifier);
if (!n) {
@@ -411,16 +372,8 @@ int getLocalPositionFromGeo(lua_State* L) {
}
GlobeBrowsingModule& mod = *(global::moduleEngine->module<GlobeBrowsingModule>());
glm::vec3 pos = mod.cartesianCoordinatesFromGeo(
*globe,
latitude,
longitude,
altitude
);
ghoul::lua::push(L, pos.x, pos.y, pos.z);
ghoul_assert(lua_gettop(L) == 3, "Incorrect number of items left on stack");
glm::vec3 p = mod.cartesianCoordinatesFromGeo(*globe, latitude, longitude, altitude);
ghoul::lua::push(L, p.x, p.y, p.z);
return 3;
}
@@ -450,72 +403,48 @@ int getGeoPositionForCamera(lua_State* L) {
posHandle.centerToReferenceSurface);
ghoul::lua::push(L, glm::degrees(geo2.lat), glm::degrees(geo2.lon), altitude);
ghoul_assert(lua_gettop(L) == 3, "Incorrect number of items left on stack");
return 3;
}
int loadWMSCapabilities(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 3, "lua::loadWMSCapabilities");
std::string name = ghoul::lua::value<std::string>(L, 1);
std::string globe = ghoul::lua::value<std::string>(L, 2);
std::string url = ghoul::lua::value<std::string>(L, 3);
auto [name, globe, url] =
ghoul::lua::values<std::string, std::string, std::string>(L);
global::moduleEngine->module<GlobeBrowsingModule>()->loadWMSCapabilities(
std::move(name),
std::move(globe),
std::move(url)
);
lua_pop(L, 3);
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
int removeWMSServer(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::removeWMSServer");
const std::string& name = ghoul::lua::value<std::string>(
L,
1,
ghoul::lua::PopValue::Yes
);
const std::string name = ghoul::lua::value<std::string>(L);
global::moduleEngine->module<GlobeBrowsingModule>()->removeWMSServer(name);
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
int capabilities(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::capabilities");
const std::string name = ghoul::lua::value<std::string>(L);
const std::string& name = ghoul::lua::value<std::string>(
L,
1,
ghoul::lua::PopValue::Yes
);
GlobeBrowsingModule::Capabilities cap =
global::moduleEngine->module<GlobeBrowsingModule>()->capabilities(name);
lua_newtable(L);
for (unsigned long i = 0; i < cap.size(); ++i) {
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_assert(lua_gettop(L) == 1, "Incorrect number of items left on stack");
return 1;
}
+2 -2
View File
@@ -43,8 +43,8 @@ struct AABB3 {
struct Geodetic2 {
double lat = 0.0;
double lon = 0.0;
double lat = 0.0; // in radians
double lon = 0.0; // in radians
};
+238
View File
@@ -0,0 +1,238 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* *
* 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/globerotation.h>
#include <modules/globebrowsing/globebrowsingmodule.h>
#include <modules/globebrowsing/src/renderableglobe.h>
#include <openspace/documentation/documentation.h>
#include <openspace/documentation/verifier.h>
#include <openspace/engine/globals.h>
#include <openspace/engine/moduleengine.h>
#include <openspace/scene/scenegraphnode.h>
#include <openspace/query/query.h>
#include <openspace/util/updatestructures.h>
#include <ghoul/logging/logmanager.h>
#include <glm/gtx/quaternion.hpp>
namespace {
constexpr openspace::properties::Property::PropertyInfo GlobeInfo = {
"Globe",
"Attached Globe",
"The globe on which the longitude/latitude is specified"
};
constexpr openspace::properties::Property::PropertyInfo LatitudeInfo = {
"Latitude",
"Latitude",
"The latitude of the location on the globe's surface. The value can range from "
"-90 to 90, with negative values representing the southern hemisphere of the "
"globe. The default value is 0.0."
};
constexpr openspace::properties::Property::PropertyInfo LongitudeInfo = {
"Longitude",
"Longitude",
"The longitude of the location on the globe's surface. The value can range from "
"-180 to 180, with negative values representing the western hemisphere of the "
"globe. The default value is 0.0."
};
constexpr openspace::properties::Property::PropertyInfo AngleInfo = {
"Angle",
"Angle",
"A rotation angle that can be used to rotate the object around its own y-axis, "
"which will be pointing out of the globe's surface."
};
constexpr openspace::properties::Property::PropertyInfo UseHeightmapInfo = {
"UseHeightmap",
"Use Heightmap",
"If set to true, the heightmap will be used when computing the surface normal. "
"This means that the object will be rotated to lay flat on the surface at the "
"given coordinate and follow the shape of the landscape."
};
struct [[codegen::Dictionary(GlobeRotation)]] Parameters {
// [[codegen::verbatim(GlobeInfo.description)]]
std::string globe
[[codegen::annotation("A valid scene graph node with a RenderableGlobe")]];
// [[codegen::verbatim(LatitudeInfo.description)]]
std::optional<double> latitude;
// [[codegen::verbatim(LongitudeInfo.description)]]
std::optional<double> longitude;
// [[codegen::verbatim(AngleInfo.description)]]
std::optional<double> angle;
// [[codegen::verbatim(UseHeightmapInfo.description)]]
std::optional<bool> useHeightmap;
};
#include "globerotation_codegen.cpp"
} // namespace
namespace openspace::globebrowsing {
documentation::Documentation GlobeRotation::Documentation() {
return codegen::doc<Parameters>("globebrowsing_rotation_globerotation");
}
GlobeRotation::GlobeRotation(const ghoul::Dictionary& dictionary)
: _globe(GlobeInfo)
, _latitude(LatitudeInfo, 0.0, -90.0, 90.0)
, _longitude(LongitudeInfo, 0.0, -180.0, 180.0)
, _angle(AngleInfo, 0.0, 0.0, 360.0)
, _useHeightmap(UseHeightmapInfo, false)
{
const Parameters p = codegen::bake<Parameters>(dictionary);
_globe = p.globe;
_latitude = p.latitude.value_or(_latitude);
_latitude.onChange([this]() { setUpdateVariables(); });
addProperty(_latitude);
_longitude = p.longitude.value_or(_longitude);
_longitude.onChange([this]() { setUpdateVariables(); });
addProperty(_longitude);
_useHeightmap = p.useHeightmap.value_or(_useHeightmap);
_useHeightmap.onChange([this]() { setUpdateVariables(); });
addProperty(_useHeightmap);
_angle = p.angle.value_or(_angle);
_angle.onChange([this]() { setUpdateVariables(); });
addProperty(_angle);
}
void GlobeRotation::findGlobe() {
SceneGraphNode* n = sceneGraphNode(_globe);
if (n->renderable() && dynamic_cast<RenderableGlobe*>(n->renderable())) {
_globeNode = dynamic_cast<RenderableGlobe*>(n->renderable());
}
else {
LERRORC(
"GlobeRotation",
"Could not set attached node as it does not have a RenderableGlobe"
);
if (_globeNode) {
// Reset the globe name to it's previous name
_globe = _globeNode->identifier();
}
}
}
void GlobeRotation::setUpdateVariables() {
_matrixIsDirty = true;
requireUpdate();
}
glm::vec3 GlobeRotation::computeSurfacePosition(double latitude, double longitude) const
{
ghoul_assert(_globeNode, "Globe cannot be nullptr");
GlobeBrowsingModule* mod = global::moduleEngine->module<GlobeBrowsingModule>();
glm::vec3 groundPos = mod->cartesianCoordinatesFromGeo(
*_globeNode,
latitude,
longitude,
0.0
);
SurfacePositionHandle h =
_globeNode->calculateSurfacePositionHandle(groundPos);
// Compute position including heightmap
return mod->cartesianCoordinatesFromGeo(
*_globeNode,
latitude,
longitude,
h.heightToSurface
);
}
glm::dmat3 GlobeRotation::matrix(const UpdateData&) const {
if (!_globeNode) {
// @TODO(abock): The const cast should be removed on a redesign of the rotation
// to make the matrix function not constant. Const casting this
// away is fine as the factories that create the rotations don't
// create them as constant objects
const_cast<GlobeRotation*>(this)->findGlobe();
_matrixIsDirty = true;
}
if (_useHeightmap) {
// If we use the heightmap, we have to compute the height every frame
_matrixIsDirty = true;
}
if (!_matrixIsDirty) {
return _matrix;
}
// Compute vector that points out of globe surface
glm::dvec3 yAxis = glm::dvec3(0.0);
if (_useHeightmap) {
const double angleDiff = 0.00001; // corresponds to a meter-ish
const glm::vec3 posCenter = computeSurfacePosition(_latitude, _longitude);
const glm::vec3 pos1 = computeSurfacePosition(_latitude, _longitude + angleDiff);
const glm::vec3 pos2 = computeSurfacePosition(_latitude + angleDiff, _longitude);
const glm::vec3 v1 = pos1 - posCenter;
const glm::vec3 v2 = pos2 - posCenter;
yAxis = glm::dvec3(glm::cross(v1, v2));
}
else {
float latitudeRad = glm::radians(static_cast<float>(_latitude));
float longitudeRad = glm::radians(static_cast<float>(_longitude));
yAxis = _globeNode->ellipsoid().geodeticSurfaceNormal(
{ latitudeRad, longitudeRad }
);
}
yAxis = glm::normalize(yAxis);
constexpr const glm::dvec3 n = glm::dvec3(0.0, 0.0, 1.0);
glm::dvec3 zAxis = glm::dvec3(
zAxis.x = yAxis.y * n.z - yAxis.z * n.y,
zAxis.y = yAxis.z * n.x - yAxis.x * n.z,
zAxis.z = yAxis.x * n.y - yAxis.y * n.x
);
zAxis = glm::normalize(zAxis);
const glm::dvec3 xAxis = glm::normalize(glm::cross(yAxis, zAxis));
const glm::dmat3 mat = {
xAxis.x, xAxis.y, xAxis.z,
yAxis.x, yAxis.y, yAxis.z,
zAxis.x, zAxis.y, zAxis.z
};
const glm::dquat q = glm::angleAxis(glm::radians(_angle.value()), yAxis);
_matrix = glm::toMat3(q) * mat;
_matrixIsDirty = false;
return _matrix;
}
} // namespace openspace::globebrowsing
+65
View File
@@ -0,0 +1,65 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* *
* 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___GLOBEROTATION___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___GLOBEROTATION___H__
#include <openspace/scene/rotation.h>
#include <openspace/properties/stringproperty.h>
#include <openspace/properties/scalar/boolproperty.h>
#include <openspace/properties/scalar/doubleproperty.h>
namespace openspace::globebrowsing {
class RenderableGlobe;
class GlobeRotation : public Rotation {
public:
GlobeRotation(const ghoul::Dictionary& dictionary);
glm::dmat3 matrix(const UpdateData& data) const override;
static documentation::Documentation Documentation();
private:
void findGlobe();
void setUpdateVariables();
glm::vec3 computeSurfacePosition(double latitude, double longitude) const;
properties::StringProperty _globe;
properties::DoubleProperty _latitude;
properties::DoubleProperty _longitude;
properties::DoubleProperty _angle;
properties::BoolProperty _useHeightmap;
RenderableGlobe* _globeNode = nullptr;
mutable bool _matrixIsDirty = true;
mutable glm::dmat3 _matrix = glm::dmat3(0.0);
};
} // namespace openspace::globebrowsing
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___GLOBEROTATION___H__
+28 -27
View File
@@ -42,14 +42,6 @@ namespace {
"The globe on which the longitude/latitude is specified"
};
constexpr openspace::properties::Property::PropertyInfo LongitudeInfo = {
"Longitude",
"Longitude",
"The longitude of the location on the globe's surface. The value can range from "
"-180 to 180, with negative values representing the western hemisphere of the "
"globe. The default value is 0.0"
};
constexpr openspace::properties::Property::PropertyInfo LatitudeInfo = {
"Latitude",
"Latitude",
@@ -58,6 +50,14 @@ namespace {
"globe. The default value is 0.0"
};
constexpr openspace::properties::Property::PropertyInfo LongitudeInfo = {
"Longitude",
"Longitude",
"The longitude of the location on the globe's surface. The value can range from "
"-180 to 180, with negative values representing the western hemisphere of the "
"globe. The default value is 0.0"
};
constexpr openspace::properties::Property::PropertyInfo AltitudeInfo = {
"Altitude",
"Altitude",
@@ -80,12 +80,12 @@ namespace {
std::string globe
[[codegen::annotation("A valid scene graph node with a RenderableGlobe")]];
// [[codegen::verbatim(LongitudeInfo.description)]]
std::optional<double> longitude;
// [[codegen::verbatim(LatitudeInfo.description)]]
std::optional<double> latitude;
// [[codegen::verbatim(LongitudeInfo.description)]]
std::optional<double> longitude;
// [[codegen::verbatim(AltitudeInfo.description)]]
std::optional<double> altitude;
@@ -103,34 +103,30 @@ documentation::Documentation GlobeTranslation::Documentation() {
GlobeTranslation::GlobeTranslation(const ghoul::Dictionary& dictionary)
: _globe(GlobeInfo)
, _longitude(LongitudeInfo, 0.0, -180.0, 180.0)
, _latitude(LatitudeInfo, 0.0, -90.0, 90.0)
, _longitude(LongitudeInfo, 0.0, -180.0, 180.0)
, _altitude(AltitudeInfo, 0.0, 0.0, 1e12)
, _useHeightmap(UseHeightmapInfo, false)
{
const Parameters p = codegen::bake<Parameters>(dictionary);
_globe = p.globe;
_globe.onChange([this]() {
fillAttachedNode();
_positionIsDirty = true;
});
_longitude = p.longitude.value_or(_longitude);
_longitude.onChange([this]() { _positionIsDirty = true; });
addProperty(_longitude);
_latitude = p.latitude.value_or(_latitude);
_latitude.onChange([this]() { _positionIsDirty = true; });
_latitude.onChange([this]() { setUpdateVariables(); });
addProperty(_latitude);
_longitude = p.longitude.value_or(_longitude);
_longitude.onChange([this]() { setUpdateVariables(); });
addProperty(_longitude);
_altitude = p.altitude.value_or(_altitude);
_altitude.setExponent(8.f);
_altitude.onChange([this]() { _positionIsDirty = true; });
_altitude.onChange([this]() { setUpdateVariables(); });
addProperty(_altitude);
_useHeightmap = p.useHeightmap.value_or(_useHeightmap);
_useHeightmap.onChange([this]() { _positionIsDirty = true; });
_useHeightmap.onChange([this]() { setUpdateVariables(); });
addProperty(_useHeightmap);
}
@@ -151,6 +147,11 @@ void GlobeTranslation::fillAttachedNode() {
}
}
void GlobeTranslation::setUpdateVariables() {
_positionIsDirty = true;
requireUpdate();
}
glm::dvec3 GlobeTranslation::position(const UpdateData&) const {
if (!_attachedNode) {
// @TODO(abock): The const cast should be removed on a redesign of the translation
@@ -170,10 +171,10 @@ glm::dvec3 GlobeTranslation::position(const UpdateData&) const {
return _position;
}
GlobeBrowsingModule& mod = *(global::moduleEngine->module<GlobeBrowsingModule>());
GlobeBrowsingModule* mod = global::moduleEngine->module<GlobeBrowsingModule>();
if (_useHeightmap) {
glm::vec3 groundPos = mod.cartesianCoordinatesFromGeo(
glm::vec3 groundPos = mod->cartesianCoordinatesFromGeo(
*_attachedNode,
_latitude,
_longitude,
@@ -183,7 +184,7 @@ glm::dvec3 GlobeTranslation::position(const UpdateData&) const {
SurfacePositionHandle h =
_attachedNode->calculateSurfacePositionHandle(groundPos);
_position = mod.cartesianCoordinatesFromGeo(
_position = mod->cartesianCoordinatesFromGeo(
*_attachedNode,
_latitude,
_longitude,
@@ -192,7 +193,7 @@ glm::dvec3 GlobeTranslation::position(const UpdateData&) const {
return _position;
}
else {
_position = mod.cartesianCoordinatesFromGeo(
_position = mod->cartesianCoordinatesFromGeo(
*_attachedNode,
_latitude,
_longitude,
+2 -1
View File
@@ -45,10 +45,11 @@ public:
private:
void fillAttachedNode();
void setUpdateVariables();
properties::StringProperty _globe;
properties::DoubleProperty _longitude;
properties::DoubleProperty _latitude;
properties::DoubleProperty _longitude;
properties::DoubleProperty _altitude;
properties::BoolProperty _useHeightmap;
@@ -188,7 +188,8 @@ int calculateTileLevelDifference(GDALDataset* dataset, int minimumPixelSize) {
}
const int sizeLevel0 = maxOverview->GetXSize();
const double diff = log2(minimumPixelSize) - log2(sizeLevel0);
return static_cast<int>(diff);
const double intdiff = diff >= 0 ? ceil(diff) : floor(diff);
return static_cast<int>(intdiff);
}
/**
+2 -3
View File
@@ -370,8 +370,8 @@ void TimeQuantizer::setResolution(const std::string& resolutionString) {
}
void TimeQuantizer::verifyStartTimeRestrictions() {
//If monthly time resolution then restrict to 28 days so every month is consistent
unsigned int dayUpperLimit;
// If monthly time resolution then restrict to 28 days so every month is consistent
int dayUpperLimit;
std::string helpfulDescription = "the selected month";
if (_resolutionUnit == 'M') {
dayUpperLimit = 28;
@@ -631,7 +631,6 @@ std::vector<std::string> TimeQuantizer::quantized(Time& start, Time& end) {
const double startSeconds = s.J2000();
const double endSeconds = e.J2000();
const double delta = endSeconds - startSeconds;
ghoul_assert(
static_cast<int>(delta) % static_cast<int>(_resolution) == 0,
"Quantization error"
+2 -5
View File
@@ -47,6 +47,7 @@ std::vector<nlohmann::json> ShortcutTopic::shortcutsJson() const {
std::vector<nlohmann::json> json;
for (const interaction::Action& action : global::actionManager->actions()) {
nlohmann::json shortcutJson = {
{ "identifier", action.identifier },
{ "name", action.name },
{ "script", action.command },
{ "synchronization", static_cast<bool>(action.synchronization) },
@@ -77,11 +78,7 @@ std::vector<nlohmann::json> ShortcutTopic::shortcutsJson() const {
{ "super" , hasKeyModifier(k.modifier, KeyModifier::Super) }
}
},
{ "name", action.name },
{ "script", action.command },
{ "synchronization", static_cast<bool>(action.synchronization) },
{ "documentation", action.documentation },
{ "guiPath", action.guiPath },
{ "action", action.name },
};
json.push_back(shortcutJson);
}
@@ -134,8 +134,7 @@ RenderableSmallBody::RenderableSmallBody(const ghoul::Dictionary& dictionary)
}
if (dictionary.hasValue<bool>(ContiguousModeInfo.identifier)) {
_contiguousMode = static_cast<bool>(
dictionary.value<bool>(ContiguousModeInfo.identifier));
_contiguousMode = dictionary.value<bool>(ContiguousModeInfo.identifier);
}
else {
_contiguousMode = false;
+16 -26
View File
@@ -30,48 +30,38 @@ int convertFromRaDec(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 3, "lua::convertFromRaDec");
glm::dvec2 degrees = glm::dvec2(0.0);
if (lua_type(L, 1) == LUA_TSTRING && lua_type(L, 2) == LUA_TSTRING) {
std::string ra = ghoul::lua::value<std::string>(L, 1);
std::string dec = ghoul::lua::value<std::string>(L, 2);
if (ghoul::lua::hasValue<std::string>(L, 1) &&
ghoul::lua::hasValue<std::string>(L, 2))
{
auto [ra, dec] = ghoul::lua::values<std::string, std::string>(L);
degrees = icrsToDecimalDegrees(ra, dec);
}
else if (lua_type(L, 1) == LUA_TNUMBER && lua_type(L, 2) == LUA_TNUMBER) {
degrees.x = ghoul::lua::value<double>(L, 1);
degrees.y = ghoul::lua::value<double>(L, 2);
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 {
throw ghoul::lua::LuaRuntimeException("lua::convertFromRaDec: Ra and Dec have to "
"be of the same type, either String or Number"
throw ghoul::lua::LuaRuntimeException(
"Ra and Dec have to be of the same type, either String or Number"
);
}
double distance = ghoul::lua::value<double>(L, 3);
lua_settop(L, 0);
double distance = ghoul::lua::value<double>(L);
glm::dvec3 pos = icrsToGalacticCartesian(degrees.x, degrees.y, distance);
ghoul::lua::push(L, pos);
ghoul_assert(lua_gettop(L) == 1, "Incorrect number of items left on stack");
return 1;
}
int convertToRaDec(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 3, "lua::convertToRaDec");
auto [x, y, z] = ghoul::lua::values<double, double, double>(L);
double x = ghoul::lua::value<double>(L, 1);
double y = ghoul::lua::value<double>(L, 2);
double z = ghoul::lua::value<double>(L, 3);
lua_settop(L, 0);
glm::dvec3 deg = galacticCartesianToIcrs(x, y, z);
std::pair<std::string, std::string> raDecPair = decimalDegreesToIcrs(deg.x, deg.y);
glm::dvec3 degrees = galacticCartesianToIcrs(x, y, z);
std::pair<std::string, std::string> raDecPair
= decimalDegreesToIcrs(degrees.x, degrees.y);
ghoul::lua::push(L, raDecPair.first); // Ra
ghoul::lua::push(L, raDecPair.second); // Dec
ghoul::lua::push(L, degrees.z); // Distance
ghoul_assert(lua_gettop(L) == 3, "Incorrect number of items left on stack");
// Ra, Dec, Distance
ghoul::lua::push(L, raDecPair.first, raDecPair.second, deg.z);
return 3;
}
+1 -1
View File
@@ -52,4 +52,4 @@ private:
} // namespace openspace
#endif __OPENSPACE_MODULE_STATEMACHINE___STATE___H__
#endif // __OPENSPACE_MODULE_STATEMACHINE___STATE___H__
+9 -2
View File
@@ -43,11 +43,18 @@ public:
void transitionTo(const std::string& newState);
bool canTransitionTo(const std::string& state) const;
/*
/**
* Return the identifiers of all possible transitions from the current state
*/
std::vector<std::string> possibleTransitions() const;
/**
* Saves the state machine to a .dot file, as a directed graph.
* filename is the full name of the file, including the directory,
* but without the extension.
*/
void saveToDotFile(const std::string& filename) const;
static documentation::Documentation Documentation();
private:
@@ -61,4 +68,4 @@ private:
} // namespace openspace
#endif __OPENSPACE_MODULE_STATEMACHINE___STATEMACHINE___H__
#endif // __OPENSPACE_MODULE_STATEMACHINE___STATEMACHINE___H__
+1 -1
View File
@@ -51,4 +51,4 @@ private:
} // namespace openspace
#endif __OPENSPACE_MODULE_STATEMACHINE___TRANSITION___H__
#endif // __OPENSPACE_MODULE_STATEMACHINE___TRANSITION___H__
+24
View File
@@ -26,6 +26,7 @@
#include <openspace/documentation/documentation.h>
#include <ghoul/logging/logmanager.h>
#include <fstream>
#include <optional>
namespace {
@@ -195,4 +196,27 @@ std::vector<std::string> StateMachine::possibleTransitions() const {
return res;
}
void StateMachine::saveToDotFile(const std::string& filename) const {
const std::string outputFile = filename + ".dot";
std::ofstream file(outputFile);
if (!file.good()) {
LERROR(fmt::format(
"Error opening file {} for saving state machine dot file", outputFile
));
return;
}
file << "digraph statemachine {" << std::endl;
for (const State& s : _states) {
file << "\t" << s.name() << ";" << std::endl;
}
for (const Transition& t : _transitions) {
file << "\t" << t.from() << " -> " << t.to() << ";" << std::endl;
}
file << "}" << std::endl;
LINFO(fmt::format("Saved state machine to file: {}", outputFile));
}
} // namespace openspace
+33 -5
View File
@@ -29,7 +29,9 @@
#include <modules/statemachine/include/transition.h>
#include <openspace/documentation/documentation.h>
#include <openspace/scripting/lualibrary.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/logging/logmanager.h>
#include <string>
#include "statemachinemodule_lua.inl"
@@ -73,7 +75,7 @@ bool StateMachineModule::hasStateMachine() const {
void StateMachineModule::setInitialState(const std::string initialState) {
if (!_machine) {
LWARNING("Attempting to use uninitialized state machine");
LERROR("Attempting to use uninitialized state machine");
return;
}
@@ -82,7 +84,7 @@ void StateMachineModule::setInitialState(const std::string initialState) {
std::string StateMachineModule::currentState() const {
if (!_machine || !_machine->currentState()) {
LWARNING("Attempting to use uninitialized state machine");
LERROR("Attempting to use uninitialized state machine");
return "";
}
@@ -91,7 +93,7 @@ std::string StateMachineModule::currentState() const {
std::vector<std::string> StateMachineModule::possibleTransitions() const {
if (!_machine) {
LWARNING("Attempting to use uninitialized state machine");
LERROR("Attempting to use uninitialized state machine");
return std::vector<std::string>();
}
@@ -100,7 +102,7 @@ std::vector<std::string> StateMachineModule::possibleTransitions() const {
void StateMachineModule::transitionTo(const std::string& newState) {
if (!_machine) {
LWARNING("Attempting to use uninitialized state machine");
LERROR("Attempting to use uninitialized state machine");
return;
}
@@ -109,13 +111,29 @@ void StateMachineModule::transitionTo(const std::string& newState) {
bool StateMachineModule::canGoToState(const std::string& state) const {
if (!_machine) {
LWARNING("Attempting to use uninitialized state machine");
LERROR("Attempting to use uninitialized state machine");
return false;
}
return _machine->canTransitionTo(state);
}
void StateMachineModule::saveToFile(const std::string& filename,
std::string directory) const
{
if (!_machine) {
LERROR("Attempting to use uninitialized state machine");
return;
}
if (directory.back() != '/') {
directory += '/';
}
const std::string outputFile = absPath(directory + filename).string();
_machine->saveToDotFile(outputFile);
}
scripting::LuaLibrary StateMachineModule::luaLibrary() const {
scripting::LuaLibrary res;
res.name = "statemachine";
@@ -177,6 +195,16 @@ scripting::LuaLibrary StateMachineModule::luaLibrary() const {
{},
"",
"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."
}
};
return res;
+8 -1
View File
@@ -53,6 +53,13 @@ public:
void transitionTo(const std::string& newState);
bool canGoToState(const std::string& state) const;
/**
* Save the state machine to a file given by the name and optional directory.
* If no directory is given, the TEMP folder is used
*/
void saveToFile(const std::string& fileName,
std::string directory = "${TEMPORARY}/") const;
scripting::LuaLibrary luaLibrary() const override;
std::vector<documentation::Documentation> documentations() const override;
@@ -63,4 +70,4 @@ private:
} // namespace openspace
#endif __OPENSPACE_MODULE_STATEMACHINE___STATEMACHINEMODULE___H__
#endif // __OPENSPACE_MODULE_STATEMACHINE___STATEMACHINEMODULE___H__
+29 -91
View File
@@ -33,95 +33,37 @@
namespace openspace::luascriptfunctions {
int createStateMachine(lua_State* L) {
const int nArguments = ghoul::lua::checkArgumentsAndThrow(
L,
{ 2, 3 },
"lua::createStateMachine"
);
// If three arguments, a start state was included
std::optional<std::string> startState = std::nullopt;
if (nArguments > 2) {
startState = ghoul::lua::value<std::string>(L, 3, ghoul::lua::PopValue::Yes);
}
// Last dictionary is on top of the stack
ghoul::Dictionary transitions;
try {
ghoul::lua::luaDictionaryFromState(L, transitions);
}
catch (const ghoul::lua::LuaFormatException& e) {
LERRORC("createStateMachine", e.what());
return 0;
}
// Pop, so that first dictionary is on top and can be read
lua_pop(L, 1);
ghoul::Dictionary states;
try {
ghoul::lua::luaDictionaryFromState(L, states);
}
catch (const ghoul::lua::LuaFormatException& e) {
LERRORC("createStateMachine", e.what());
return 0;
}
ghoul::lua::checkArgumentsAndThrow(L, { 2, 3 }, "lua::createStateMachine");
auto [states, transitions, startState] = ghoul::lua::values<
ghoul::Dictionary, ghoul::Dictionary, std::optional<std::string>
>(L);
StateMachineModule* module = global::moduleEngine->module<StateMachineModule>();
module->initializeStateMachine(states, transitions, startState);
lua_settop(L, 0);
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
module->initializeStateMachine(
std::move(states),
std::move(transitions),
std::move(startState)
);
return 0;
}
int goToState(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::goToState");
const bool isString = (lua_isstring(L, 1) != 0);
std::string newState = ghoul::lua::value<std::string>(L);
if (!isString) {
lua_settop(L, 0);
const char* msg = lua_pushfstring(
L,
"%s expected, got %s",
lua_typename(L, LUA_TSTRING),
luaL_typename(L, 0)
);
return luaL_error(L, "bad argument #%d (%s)", 1, msg);
}
const std::string newState = lua_tostring(L, 1);
StateMachineModule* module = global::moduleEngine->module<StateMachineModule>();
module->transitionTo(newState);
LINFOC("StateMachine", "Transitioning to " + newState);
lua_settop(L, 0);
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
int setInitialState(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::setStartState");
const bool isString = (lua_isstring(L, 1) != 0);
std::string startState = ghoul::lua::value<std::string>(L);
if (!isString) {
lua_settop(L, 0);
const char* msg = lua_pushfstring(
L,
"%s expected, got %s",
lua_typename(L, LUA_TSTRING),
luaL_typename(L, 0)
);
return luaL_error(L, "bad argument #%d (%s)", 1, msg);
}
const std::string startState = lua_tostring(L, 1);
StateMachineModule* module = global::moduleEngine->module<StateMachineModule>();
module->setInitialState(startState);
LINFOC("StateMachine", "Initial state set to: " + startState);
lua_settop(L, 0);
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
@@ -130,9 +72,7 @@ int currentState(lua_State* L) {
StateMachineModule* module = global::moduleEngine->module<StateMachineModule>();
std::string currentState = module->currentState();
lua_pushstring(L, currentState.c_str());
ghoul_assert(lua_gettop(L) == 1, "Incorrect number of items left on stack");
ghoul::lua::push(L, std::move(currentState));
return 1;
}
@@ -141,32 +81,16 @@ int possibleTransitions(lua_State* L) {
StateMachineModule* module = global::moduleEngine->module<StateMachineModule>();
std::vector<std::string> transitions = module->possibleTransitions();
ghoul::lua::push(L, transitions);
ghoul_assert(lua_gettop(L) == 1, "Incorrect number of items left on stack");
return 1;
}
int canGoToState(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::canGoToState");
const bool isString = (lua_isstring(L, 1) != 0);
std::string state = ghoul::lua::value<std::string>(L);
if (!isString) {
lua_settop(L, 0);
const char* msg = lua_pushfstring(
L,
"%s expected, got %s",
lua_typename(L, LUA_TSTRING),
luaL_typename(L, 0)
);
return luaL_error(L, "bad argument #%d (%s)", 1, msg);
}
const std::string state = lua_tostring(L, 1);
StateMachineModule* module = global::moduleEngine->module<StateMachineModule>();
ghoul::lua::push(L, module->canGoToState(state));
ghoul_assert(lua_gettop(L) == 1, "Incorrect number of items left on stack");
return 1;
}
@@ -174,7 +98,6 @@ int printCurrentStateInfo(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::printCurrentStateInfo");
StateMachineModule* module = global::moduleEngine->module<StateMachineModule>();
if (module->hasStateMachine()) {
std::string currentState = module->currentState();
std::vector<std::string> transitions = module->possibleTransitions();
@@ -188,8 +111,23 @@ int printCurrentStateInfo(lua_State* L) {
LINFOC("StateMachine", "No state machine has been created");
}
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
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);
StateMachineModule* module = global::moduleEngine->module<StateMachineModule>();
if (directory.has_value()) {
module->saveToFile(filename, *directory);
}
else {
module->saveToFile(filename);
}
return 0;
}
} //namespace openspace::luascriptfunctions
+1
View File
@@ -34,6 +34,7 @@ source_group("Header Files" FILES ${HEADER_FILES})
set(SOURCE_FILES
syncmodule.cpp
syncmodule_lua.inl
syncs/httpsynchronization.cpp
syncs/urlsynchronization.cpp
tasks/syncassettask.cpp
+32
View File
@@ -31,6 +31,7 @@
#include <openspace/engine/globalscallbacks.h>
#include <openspace/rendering/renderable.h>
#include <openspace/rendering/screenspacerenderable.h>
#include <openspace/scripting/lualibrary.h>
#include <openspace/util/factorymanager.h>
#include <openspace/util/resourcesynchronization.h>
#include <ghoul/filesystem/filesystem.h>
@@ -40,6 +41,8 @@
#include <ghoul/misc/memorypool.h>
#include <ghoul/misc/templatefactory.h>
#include "syncmodule_lua.inl"
namespace {
constexpr const char* KeyHttpSynchronizationRepositories =
"HttpSynchronizationRepositories";
@@ -140,4 +143,33 @@ std::vector<documentation::Documentation> SyncModule::documentations() const {
};
}
scripting::LuaLibrary SyncModule::luaLibrary() const {
scripting::LuaLibrary res;
res.name = "sync";
res.functions = {
{
"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."
}
};
return res;
}
} // namespace openspace
+2
View File
@@ -42,6 +42,8 @@ public:
std::vector<documentation::Documentation> documentations() const override;
scripting::LuaLibrary luaLibrary() const override;
protected:
void internalInitialize(const ghoul::Dictionary& configuration) override;
+80
View File
@@ -0,0 +1,80 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <openspace/engine/globals.h>
#include <openspace/engine/moduleengine.h>
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);
ghoul::Dictionary dict;
dict.setValue("Identifier", identifier);
dict.setValue("Version", version);
const SyncModule* module = global::moduleEngine->module<SyncModule>();
HttpSynchronization sync(
dict,
module->synchronizationRoot(),
module->httpSynchronizationRepositories()
);
sync.start();
while (sync.isSyncing()) {
std::this_thread::sleep_for(std::chrono::milliseconds(20));
}
ghoul::lua::push(L, sync.isResolved());
return 1;
}
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);
const SyncModule* module = global::moduleEngine->module<SyncModule>();
std::filesystem::path sync = absPath(module->synchronizationRoot());
std::filesystem::path base = sync / "http" / identifier;
if (!version.has_value()) {
// If no version was provided, we remove all of the files
std::filesystem::remove_all(base);
}
else {
const int v = *version;
std::filesystem::path folder = base / std::to_string(v);
std::string syncFile = std::to_string(v) + ".ossync";
std::filesystem::remove_all(folder);
std::filesystem::remove(base / syncFile);
}
return 0;
}
} // namespace openspace::luascriptfunctions
+1 -1
View File
@@ -276,7 +276,7 @@ void create() {
actionManager = new (currentPos) interaction::ActionManager;
ghoul_assert(actionManager, "No action manager");
currentPos += sizeof(interaction::ActionManager);
#else ^^^ WIN32 / !WIN32 vvv
#else // ^^^ WIN32 / !WIN32 vvv
actionManager = new interaction::ActionManager;
#endif // WIN32
+5 -20
View File
@@ -34,30 +34,15 @@ namespace openspace::luascriptfunctions {
*/
int isLoaded(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::isLoaded");
const int type = lua_type(L, 1);
if (type != LUA_TSTRING) {
return ghoul::lua::luaError(L, "Expected argument of type 'string'");
}
const std::string& moduleName = ghoul::lua::value<std::string>(
L,
1,
ghoul::lua::PopValue::Yes
);
const std::string name = ghoul::lua::value<std::string>(L);
const std::vector<OpenSpaceModule*>& modules = global::moduleEngine->modules();
auto it = std::find_if(
modules.begin(),
modules.end(),
[moduleName](OpenSpaceModule* module) {
return module->identifier() == moduleName;
}
const auto it = std::find_if(
modules.cbegin(), modules.cend(),
[name](OpenSpaceModule* module) { return module->identifier() == name; }
);
ghoul::lua::push(L, it != modules.end());
ghoul_assert(lua_gettop(L) == 1, "Incorrect number of items left on stack");
ghoul::lua::push(L, it != modules.cend());
return 1;
}
+39 -92
View File
@@ -43,25 +43,19 @@ namespace openspace::luascriptfunctions {
*/
int toggleShutdown(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::toggleShutdown");
global::openSpaceEngine->toggleShutdownMode();
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
/**
* \ingroup LuaScripts
* writeDocumentation():
* Writes out documentation files
*/
* \ingroup LuaScripts
* writeDocumentation():
* Writes out documentation files
*/
int writeDocumentation(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::writeDocumentation");
global::openSpaceEngine->writeStaticDocumentation();
global::openSpaceEngine->writeSceneDocumentation();
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
@@ -72,15 +66,12 @@ int writeDocumentation(lua_State* L) {
*/
int addVirtualProperty(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, { 5, 7 }, "lua::addVirtualProperty");
const std::string& type = ghoul::lua::value<std::string>(L, 1);
const std::string& name = ghoul::lua::value<std::string>(L, 2);
const std::string& identifier = ghoul::lua::value<std::string>(L, 3);
const std::string& description = ghoul::lua::value<std::string>(L, 4);
auto [type, name, identifier, description] =
ghoul::lua::values<std::string, std::string, std::string, std::string>(L);
std::unique_ptr<properties::Property> prop;
if (type == "BoolProperty") {
const bool v = ghoul::lua::value<bool>(L, 5);
const bool v = ghoul::lua::value<bool>(L);
prop = std::make_unique<properties::BoolProperty>(
properties::Property::PropertyInfo {
identifier.c_str(),
@@ -91,10 +82,7 @@ int addVirtualProperty(lua_State* L) {
);
}
else if (type == "IntProperty") {
const int v = ghoul::lua::value<int>(L, 5);
const int min = ghoul::lua::value<int>(L, 6);
const int max = ghoul::lua::value<int>(L, 7);
auto [v, min, max] = ghoul::lua::values<int, int, int>(L);
prop = std::make_unique<properties::IntProperty>(
properties::Property::PropertyInfo {
identifier.c_str(),
@@ -107,10 +95,7 @@ int addVirtualProperty(lua_State* L) {
);
}
else if (type == "FloatProperty") {
const float v = ghoul::lua::value<float>(L, 5);
const float min = ghoul::lua::value<float>(L, 6);
const float max = ghoul::lua::value<float>(L, 7);
auto [v, min, max] = ghoul::lua::values<float, float, float>(L);
prop = std::make_unique<properties::FloatProperty>(
properties::Property::PropertyInfo {
identifier.c_str(),
@@ -132,26 +117,22 @@ int addVirtualProperty(lua_State* L) {
);
}
else {
lua_settop(L, 0);
return ghoul::lua::luaError(L, fmt::format("Unknown property type '{}'", type));
}
lua_settop(L, 0);
global::virtualPropertyManager->addProperty(std::move(prop));
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
/**
* \ingroup LuaScripts
* removeVirtualProperty():
* Removes a previously added virtual property
*/
* \ingroup LuaScripts
* removeVirtualProperty():
* Removes a previously added virtual property
*/
int removeVirtualProperty(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::removeVirtualProperty");
const std::string name = ghoul::lua::value<std::string>(L);
const std::string& name = ghoul::lua::value<std::string>(L, 1);
properties::Property* p = global::virtualPropertyManager->property(name);
if (p) {
global::virtualPropertyManager->removeProperty(p);
@@ -159,39 +140,30 @@ int removeVirtualProperty(lua_State* L) {
else {
LWARNINGC(
"removeVirtualProperty",
fmt::format("Virtual Property with name '{}'' did not exist", name)
fmt::format("Virtual Property with name '{}' did not exist", name)
);
}
lua_settop(L, 0);
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
/**
* \ingroup LuaScripts
* removeAllVirtualProperties():
* Remove all registered virtual properties
*/
* \ingroup LuaScripts
* removeAllVirtualProperties():
* Remove all registered virtual properties
*/
int removeAllVirtualProperties(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::removeAllVirtualProperties");
const std::vector<properties::Property*>& ps =
global::virtualPropertyManager->properties();
for (properties::Property* p : ps) {
for (properties::Property* p : global::virtualPropertyManager->properties()) {
global::virtualPropertyManager->removeProperty(p);
delete p;
}
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
int setScreenshotFolder(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::setScreenshotFolder");
std::string arg = ghoul::lua::value<std::string>(L);
lua_pop(L, 0);
const std::string arg = ghoul::lua::value<std::string>(L);
std::filesystem::path folder = absPath(arg);
if (!std::filesystem::exists(folder)) {
@@ -215,22 +187,14 @@ int setScreenshotFolder(lua_State* L) {
*/
int addTag(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::addTag");
const std::string& uri = ghoul::lua::value<std::string>(L, 1);
std::string tag = ghoul::lua::value<std::string>(L, 2);
lua_settop(L, 0);
auto [uri, tag] = ghoul::lua::values<std::string, std::string>(L);
SceneGraphNode* node = global::renderEngine->scene()->sceneGraphNode(uri);
if (!node) {
return ghoul::lua::luaError(
L,
fmt::format("Unknown scene graph node type '{}'", uri)
);
return ghoul::lua::luaError(L, fmt::format("Unknown scene graph node '{}'", uri));
}
node->addTag(std::move(tag));
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
@@ -240,41 +204,28 @@ int addTag(lua_State* L) {
* Removes a tag from a SceneGraphNode
*/
int removeTag(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::addTag");
const std::string& uri = ghoul::lua::value<std::string>(L, 1);
const std::string& tag = ghoul::lua::value<std::string>(L, 2);
lua_settop(L, 0);
ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::removeTag");
auto [uri, tag] = ghoul::lua::values<std::string, std::string>(L);
SceneGraphNode* node = global::renderEngine->scene()->sceneGraphNode(uri);
if (!node) {
return ghoul::lua::luaError(
L,
fmt::format("Unknown scene graph node type '{}'", uri)
);
return ghoul::lua::luaError(L, fmt::format("Unknown scene graph node '{}'", uri));
}
node->removeTag(tag);
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
/**
* \ingroup LuaScripts
* downloadFile():
* Downloads a file from Lua interpreter
*/
* \ingroup LuaScripts
* downloadFile():
* Downloads a file from Lua interpreter
*/
int downloadFile(lua_State* L) {
int n = ghoul::lua::checkArgumentsAndThrow(L, {2, 3}, "lua::addTag");
const std::string& uri = ghoul::lua::value<std::string>(L, 1);
const std::string& savePath = ghoul::lua::value<std::string>(L, 2);
bool waitForComplete = false;
if (n == 3) {
waitForComplete = ghoul::lua::value<bool>(L, 3);
}
lua_settop(L, 0);
ghoul::lua::checkArgumentsAndThrow(L, { 2, 3 }, "lua::downloadFile");
auto [uri, savePath, waitForComplete] =
ghoul::lua::values<std::string, std::string, std::optional<bool>>(L);
waitForComplete = waitForComplete.value_or(false);
LINFOC("OpenSpaceEngine", fmt::format("Downloading file from {}", uri));
std::shared_ptr<DownloadManager::FileFuture> future =
@@ -300,21 +251,17 @@ int downloadFile(lua_State* L) {
);
}
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
/**
* \ingroup LuaScripts
* createSingleColorImage():
* Creates a one pixel image with a given color and returns the path to the cached file
*/
* \ingroup LuaScripts
* createSingleColorImage():
* Creates a one pixel image with a given color and returns the path to the cached file
*/
int createSingleColorImage(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::createSingleColorImage");
const std::string& name = ghoul::lua::value<std::string>(L, 1);
const ghoul::Dictionary& d = ghoul::lua::value<ghoul::Dictionary>(L, 2);
lua_settop(L, 0);
auto [name, d] = ghoul::lua::values<std::string, ghoul::Dictionary>(L);
// @TODO (emmbr 2020-12-18) Verify that the input dictionary is a vec3
// Would like to clean this up with a more direct use of the Verifier in the future
+11 -21
View File
@@ -33,8 +33,8 @@ namespace openspace::luascriptfunctions {
*/
int hasAction(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::hasAction");
const std::string identifier = ghoul::lua::value<std::string>(L);
const std::string& identifier = ghoul::lua::value<std::string>(L, 1);
if (identifier.empty()) {
return ghoul::lua::luaError(L, "Identifier must not be empty");
}
@@ -51,8 +51,8 @@ int hasAction(lua_State* L) {
*/
int removeAction(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::removeAction");
const std::string identifier = ghoul::lua::value<std::string>(L);
const std::string& identifier = ghoul::lua::value<std::string>(L, 1);
if (identifier.empty()) {
return ghoul::lua::luaError(L, "Identifier must not be empty");
}
@@ -63,7 +63,6 @@ int removeAction(lua_State* L) {
);
}
global::actionManager->removeAction(identifier);
return 0;
}
@@ -81,8 +80,7 @@ int removeAction(lua_State* L) {
*/
int registerAction(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::registerAction");
ghoul::Dictionary d = ghoul::lua::value<ghoul::Dictionary>(L, 1);
const ghoul::Dictionary d = ghoul::lua::value<ghoul::Dictionary>(L);
if (!d.hasValue<std::string>("Identifier")) {
return ghoul::lua::luaError(L, "Identifier must to provided to register action");
@@ -138,8 +136,8 @@ int registerAction(lua_State* L) {
*/
int action(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::action");
const std::string identifier = ghoul::lua::value<std::string>(L);
const std::string& identifier = ghoul::lua::value<std::string>(L, 1);
if (identifier.empty()) {
return ghoul::lua::luaError(L, "Identifier must not be empty");
}
@@ -168,7 +166,6 @@ int action(lua_State* L) {
action.synchronization == interaction::Action::IsSynchronized::Yes
);
lua_settable(L, -3);
return 1;
}
@@ -216,25 +213,18 @@ int actions(lua_State* L) {
* Triggers the action given by the specified identifier.
*/
int triggerAction(lua_State* L) {
int n = ghoul::lua::checkArgumentsAndThrow(L, { 1, 2 }, "lua::triggerAction");
ghoul::lua::checkArgumentsAndThrow(L, { 1, 2 }, "lua::triggerAction");
auto [id, arg] = ghoul::lua::values<std::string, std::optional<ghoul::Dictionary>>(L);
arg = arg.value_or(ghoul::Dictionary());
const std::string& identifier = ghoul::lua::value<std::string>(L, 1);
if (identifier.empty()) {
if (id.empty()) {
return ghoul::lua::luaError(L, "Identifier must not be empty");
}
if (!global::actionManager->hasAction(identifier)) {
return ghoul::lua::luaError(
L,
fmt::format("Identifier '{}' for action not found", identifier)
);
if (!global::actionManager->hasAction(id)) {
return ghoul::lua::luaError(L, fmt::format("Action '{}' not found", id));
}
ghoul::Dictionary arguments;
if (n == 2) {
ghoul::lua::luaDictionaryFromState(L, arguments, 2);
}
global::actionManager->triggerAction(identifier, arguments);
global::actionManager->triggerAction(id, *arg);
return 0;
}
+7 -35
View File
@@ -34,35 +34,24 @@ namespace openspace::luascriptfunctions {
* node is hosting a parallel connection.
*/
int bindKey(lua_State* L) {
using ghoul::lua::luaTypeToString;
ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::bindKey");
std::string key = ghoul::lua::value<std::string>(L, 1);
std::string action = ghoul::lua::value<std::string>(L, 2);
auto [key, action] = ghoul::lua::values<std::string, std::string>(L);
if (action.empty()) {
lua_settop(L, 0);
return ghoul::lua::luaError(L, "Action must not be empty");
}
if (!global::actionManager->hasAction(action)) {
lua_settop(L, 0);
return ghoul::lua::luaError(L, fmt::format("Action '{}' does not exist", action));
}
openspace::KeyWithModifier iKey = openspace::stringToKey(key);
if (iKey.key == openspace::Key::Unknown) {
std::string error = fmt::format("Could not find key '{}'", key);
LERRORC("lua.bindKey", error);
lua_settop(L, 0);
return ghoul::lua::luaError(L, error);
}
global::keybindingManager->bindKey(iKey.key, iKey.modifier, std::move(action));
lua_settop(L, 0);
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
@@ -74,16 +63,10 @@ int bindKey(lua_State* L) {
*/
int getKeyBindings(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::getKeyBindings");
const std::string& key = ghoul::lua::value<std::string>(
L,
1,
ghoul::lua::PopValue::Yes
);
const std::string& key = ghoul::lua::value<std::string>(L);
using K = KeyWithModifier;
using V = std::string;
const std::vector<std::pair<K, V>>& info = global::keybindingManager->keyBinding(
stringToKey(key)
);
@@ -97,7 +80,6 @@ int getKeyBindings(lua_State* L) {
++i;
}
ghoul_assert(lua_gettop(L) == 1, "Incorrect number of items left on stack");
return 1;
}
@@ -109,25 +91,18 @@ int getKeyBindings(lua_State* L) {
int clearKey(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::clearKey");
const int t = lua_type(L, 1);
if (t == LUA_TSTRING) {
// The user provided a single key
const std::string& key = ghoul::lua::value<std::string>(L, 1);
global::keybindingManager->removeKeyBinding(stringToKey(key));
std::variant key = ghoul::lua::value<std::variant<std::string, ghoul::Dictionary>>(L);
if (std::holds_alternative<std::string>(key)) {
KeyWithModifier k = stringToKey(std::get<std::string>(key));
global::keybindingManager->removeKeyBinding(k);
}
else {
// The user provided a list of keys
ghoul::Dictionary d;
ghoul::lua::luaDictionaryFromState(L, d);
ghoul::Dictionary d = std::get<ghoul::Dictionary>(key);
for (size_t i = 1; i <= d.size(); ++i) {
const std::string& k = d.value<std::string>(std::to_string(i));
global::keybindingManager->removeKeyBinding(stringToKey(k));
}
lua_pop(L, 1);
}
lua_settop(L, 0);
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
@@ -138,10 +113,7 @@ int clearKey(lua_State* L) {
*/
int clearKeys(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::clearKeys");
global::keybindingManager->resetKeyBindings();
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
+32 -136
View File
@@ -24,17 +24,9 @@
namespace openspace::luascriptfunctions {
int startRecording(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::startRecording");
using ghoul::lua::luaTypeToString;
const std::string recordFilePath = ghoul::lua::value<std::string>(
L,
1,
ghoul::lua::PopValue::Yes
);
const std::string recordFilePath = ghoul::lua::value<std::string>(L);
if (recordFilePath.empty()) {
return luaL_error(L, "filepath string is empty");
@@ -43,21 +35,12 @@ int startRecording(lua_State* L) {
interaction::SessionRecording::DataMode::Binary
);
global::sessionRecording->startRecording(recordFilePath);
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
int startRecordingAscii(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::startRecordingAscii");
using ghoul::lua::luaTypeToString;
const std::string recordFilePath = ghoul::lua::value<std::string>(
L,
1,
ghoul::lua::PopValue::Yes
);
const std::string recordFilePath = ghoul::lua::value<std::string>(L);
if (recordFilePath.empty()) {
return luaL_error(L, "filepath string is empty");
@@ -66,196 +49,109 @@ int startRecordingAscii(lua_State* L) {
interaction::SessionRecording::DataMode::Ascii
);
global::sessionRecording->startRecording(recordFilePath);
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
int stopRecording(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::stopRecording");
global::sessionRecording->stopRecording();
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
int startPlayback(lua_State* L, interaction::KeyframeTimeRef timeMode,
bool forceSimTimeAtStart)
{
using ghoul::lua::luaTypeToString;
const int nArguments = lua_gettop(L);
bool loop = false;
ghoul::lua::checkArgumentsAndThrow(L, { 1, 2 }, "lua::startPlayback");
auto [file, loop] = ghoul::lua::values<std::string, std::optional<bool>>(L);
loop = loop.value_or(false);
if (nArguments == 2) {
loop = lua_toboolean(L, 2) == 1;
if (file.empty()) {
return ghoul::lua::luaError(L, "Filepath string is empty");
}
else if (nArguments != 1) {
lua_settop(L, 0);
return luaL_error(
L,
"bad number of arguments, expected 1 or 2, got %i",
nArguments
);
}
const std::string playbackFilePath = ghoul::lua::value<std::string>(
L,
1,
ghoul::lua::PopValue::Yes
);
if (playbackFilePath.empty()) {
return luaL_error(L, "filepath string is empty");
}
global::sessionRecording->startPlayback(
const_cast<std::string&>(playbackFilePath),
timeMode,
forceSimTimeAtStart,
loop
);
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
global::sessionRecording->startPlayback(file, timeMode, forceSimTimeAtStart, *loop);
return 0;
}
int startPlaybackDefault(lua_State* L) {
using interaction::KeyframeNavigator;
ghoul::lua::checkArgumentsAndThrow(L, {1, 2}, "lua::startPlaybackDefault");
return startPlayback(L,
interaction::KeyframeTimeRef::Relative_recordedStart, true);
ghoul::lua::checkArgumentsAndThrow(L, { 1, 2 }, "lua::startPlaybackDefault");
return startPlayback(L, interaction::KeyframeTimeRef::Relative_recordedStart, true);
}
int startPlaybackApplicationTime(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::startPlaybackApplicationTime");
return startPlayback(L,
interaction::KeyframeTimeRef::Relative_applicationStart, false);
return startPlayback(
L,
interaction::KeyframeTimeRef::Relative_applicationStart,
false
);
}
int startPlaybackRecordedTime(lua_State* L) {
using interaction::KeyframeNavigator;
ghoul::lua::checkArgumentsAndThrow(L, {1, 2}, "lua::startPlaybackRecordedTime");
return startPlayback(L,
interaction::KeyframeTimeRef::Relative_recordedStart, false);
ghoul::lua::checkArgumentsAndThrow(L, { 1, 2 }, "lua::startPlaybackRecordedTime");
return startPlayback(L, interaction::KeyframeTimeRef::Relative_recordedStart, false);
}
int startPlaybackSimulationTime(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::startPlaybackSimulationTime");
using interaction::KeyframeNavigator;
return startPlayback(L,
interaction::KeyframeTimeRef::Absolute_simTimeJ2000, false);
return startPlayback(L, interaction::KeyframeTimeRef::Absolute_simTimeJ2000, false);
}
int stopPlayback(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::stopPlayback");
global::sessionRecording->stopPlayback();
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
int enableTakeScreenShotDuringPlayback(lua_State* L) {
const int nArguments = ghoul::lua::checkArgumentsAndThrow(
ghoul::lua::checkArgumentsAndThrow(
L,
{ 0, 1 },
"lua::enableTakeScreenShotDuringPlayback"
);
std::optional<int> fps = ghoul::lua::value<std::optional<int>>(L);
fps = fps.value_or(60);
const int fps = nArguments == 0 ? 60 : ghoul::lua::value<int>(L, 1);
global::sessionRecording->enableTakeScreenShotDuringPlayback(fps);
lua_settop(L, 0);
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
global::sessionRecording->enableTakeScreenShotDuringPlayback(*fps);
return 0;
}
int disableTakeScreenShotDuringPlayback(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::disableTakeScreenShotDuringPlayback");
global::sessionRecording->disableTakeScreenShotDuringPlayback();
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
int fileFormatConversion(lua_State* L) {
using ghoul::lua::luaTypeToString;
const std::string convertFilePath = ghoul::lua::value<std::string>(
L,
1,
ghoul::lua::PopValue::Yes
);
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::fileFormatConversion");
const std::string convertFilePath = ghoul::lua::value<std::string>(L);
if (convertFilePath.empty()) {
return luaL_error(L, "filepath string is empty");
return luaL_error(L, "Filepath string must not be empty");
}
global::sessionRecording->convertFile(convertFilePath);
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
int setPlaybackPause(lua_State* L) {
const int nArguments = lua_gettop(L);
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::setPlaybackPause");
const bool pause = ghoul::lua::value<bool>(L);
if (nArguments == 1) {
const bool pause = lua_toboolean(L, 1) == 1;
global::sessionRecording->setPlaybackPause(pause);
}
else {
lua_settop(L, 0);
return luaL_error(
L,
"bad number of arguments, expected 1, got %i",
nArguments
);
}
lua_settop(L, 0);
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
global::sessionRecording->setPlaybackPause(pause);
return 0;
}
int togglePlaybackPause(lua_State* L) {
const int nArguments = lua_gettop(L);
if (nArguments == 0) {
bool isPlaybackPaused = global::sessionRecording->isPlaybackPaused();
global::sessionRecording->setPlaybackPause(!isPlaybackPaused);
}
else {
lua_settop(L, 0);
return luaL_error(
L,
"bad number of arguments, expected 0, got %i",
nArguments
);
}
lua_settop(L, 0);
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::togglePlaybackPause");
bool isPlaybackPaused = global::sessionRecording->isPlaybackPaused();
global::sessionRecording->setPlaybackPause(!isPlaybackPaused);
return 0;
}
int isPlayingBack(lua_State* L) {
const int nArguments = lua_gettop(L);
if (nArguments != 0) {
lua_settop(L, 0);
return luaL_error(
L,
"bad number of arguments, expected 0, got %i",
nArguments
);
}
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::isPlayingBack");
ghoul::lua::push(L, global::sessionRecording->isPlayingBack());
ghoul_assert(lua_gettop(L) == 1, "Incorrect number of items left on stack");
return 1;
}
@@ -105,21 +105,19 @@ void ConvertRecFormatTask::convert() {
expectedFileExtension_out = SessionRecording::FileExtensionBinary;
}
if (std::filesystem::path(_inFilePath).extension() != expectedFileExtension_in) {
if (_inFilePath.extension() != expectedFileExtension_in) {
LWARNING(fmt::format(
"Input filename doesn't have expected {} format file extension", currentFormat
));
}
if (std::filesystem::path(_outFilePath).extension() == expectedFileExtension_in) {
if (_outFilePath.extension() == expectedFileExtension_in) {
LERROR(fmt::format(
"Output filename has {} file extension, but is conversion from {}",
currentFormat, currentFormat
));
return;
}
else if (std::filesystem::path(_outFilePath).extension() !=
expectedFileExtension_out)
{
else if (_outFilePath.extension() != expectedFileExtension_out) {
_outFilePath += expectedFileExtension_out;
}
+5 -33
View File
@@ -28,33 +28,21 @@ namespace openspace::luascriptfunctions {
int loadMission(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::loadMission");
const std::string& missionFileName = ghoul::lua::value<std::string>(L);
const std::string& missionFileName = ghoul::lua::value<std::string>(
L,
1,
ghoul::lua::PopValue::Yes
);
if (missionFileName.empty()) {
return ghoul::lua::luaError(L, "Filepath is empty");
}
std::string name = global::missionManager->loadMission(
absPath(missionFileName).string()
);
const std::string name = global::missionManager->loadMission(missionFileName);
ghoul::lua::push(L, name);
ghoul_assert(lua_gettop(L) == 1, "Incorrect number of items left on stack");
return 1;
}
int unloadMission(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::unloadMission");
const std::string missionName = ghoul::lua::value<std::string>(L);
const std::string& missionName = ghoul::lua::value<std::string>(
L,
1,
ghoul::lua::PopValue::Yes
);
if (missionName.empty()) {
return ghoul::lua::luaError(L, "Mission name is empty");
}
@@ -64,46 +52,30 @@ int unloadMission(lua_State* L) {
}
global::missionManager->unloadMission(missionName);
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
int hasMission(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::hasMission");
const std::string missionName = ghoul::lua::value<std::string>(L);
const std::string& missionName = ghoul::lua::value<std::string>(
L,
1,
ghoul::lua::PopValue::Yes
);
if (missionName.empty()) {
return ghoul::lua::luaError(L, "Missing name is empty");
}
const bool hasMission = global::missionManager->hasMission(missionName);
ghoul::lua::push(L, hasMission);
ghoul_assert(lua_gettop(L) == 1, "Incorrect number of items left on stack");
return 1;
}
int setCurrentMission(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::setCurrentMission");
const std::string missionName = ghoul::lua::value<std::string>(L);
const std::string& missionName = ghoul::lua::value<std::string>(
L,
1,
ghoul::lua::PopValue::Yes
);
if (missionName.empty()) {
return ghoul::lua::luaError(L, "Mission name is empty");
}
global::missionManager->setCurrentMission(missionName);
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
+61 -160
View File
@@ -30,41 +30,28 @@ namespace openspace::luascriptfunctions {
int loadNavigationState(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::loadNavigationState");
const std::string& cameraStateFilePath = ghoul::lua::value<std::string>(
L,
1,
ghoul::lua::PopValue::Yes
);
const std::string cameraStateFilePath = ghoul::lua::value<std::string>(L);
if (cameraStateFilePath.empty()) {
return ghoul::lua::luaError(L, "filepath string is empty");
}
global::navigationHandler->loadNavigationState(cameraStateFilePath);
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
int getNavigationState(lua_State* L) {
const int n = ghoul::lua::checkArgumentsAndThrow(
L,
{ 0, 1 },
"lua::getNavigationState"
);
ghoul::lua::checkArgumentsAndThrow(L, { 0, 1 }, "lua::getNavigationState");
std::optional<std::string> frame = ghoul::lua::value<std::optional<std::string>>(L);
interaction::NavigationState state;
if (n == 1) {
const std::string referenceFrameIdentifier = ghoul::lua::value<std::string>(L, 1);
const SceneGraphNode* referenceFrame = sceneGraphNode(referenceFrameIdentifier);
if (frame.has_value()) {
const SceneGraphNode* referenceFrame = sceneGraphNode(*frame);
if (!referenceFrame) {
LERROR(fmt::format(
"Could not find node '{}' to use as reference frame",
referenceFrameIdentifier
));
lua_settop(L, 0);
return 0;
return ghoul::lua::luaError(
L,
fmt::format("Could not find node '{}' as reference frame", *frame)
);
}
state = global::navigationHandler->navigationState(*referenceFrame);
}
@@ -72,7 +59,6 @@ int getNavigationState(lua_State* L) {
state = global::navigationHandler->navigationState();
}
lua_settop(L, 0);
const auto pushVector = [](lua_State* s, const glm::dvec3& v) {
lua_newtable(s);
@@ -114,15 +100,12 @@ int getNavigationState(lua_State* L) {
lua_rawset(L, -3);
}
ghoul_assert(lua_gettop(L) == 1, "Incorrect number of items left on stack");
return 1;
}
int setNavigationState(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::setNavigationState");
ghoul::Dictionary navigationStateDictionary;
ghoul::lua::luaDictionaryFromState(L, navigationStateDictionary);
ghoul::Dictionary navigationStateDictionary = ghoul::lua::value<ghoul::Dictionary>(L);
openspace::documentation::TestResult r = openspace::documentation::testSpecification(
interaction::NavigationState::Documentation(),
@@ -130,278 +113,196 @@ int setNavigationState(lua_State* L) {
);
if (!r.success) {
lua_settop(L, 0);
return ghoul::lua::luaError(
L, fmt::format("Could not set camera state: {}", ghoul::to_string(r))
L,
fmt::format("Could not set camera state: {}", ghoul::to_string(r))
);
}
global::navigationHandler->setNavigationStateNextFrame(
interaction::NavigationState(navigationStateDictionary)
);
// @CLEANUP: When luaDictionaryFromState doesn't leak space anymore, remove the next
// line ---abock(2018-02-15)
lua_settop(L, 0);
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
int saveNavigationState(lua_State* L) {
const int n = ghoul::lua::checkArgumentsAndThrow(
L,
{ 1, 2 },
"lua::saveNavigationState"
);
ghoul::lua::checkArgumentsAndThrow(L, { 1, 2 }, "lua::saveNavigationState");
auto [path, frame] = ghoul::lua::values<std::string, std::optional<std::string>>(L);
frame = frame.value_or("");
const std::string& cameraStateFilePath = ghoul::lua::value<std::string>(L, 1);
std::string referenceFrame = "";
if (n > 1) {
referenceFrame = ghoul::lua::value<std::string>(L, 2);
if (path.empty()) {
return ghoul::lua::luaError(L, "Filepath string is empty");
}
if (cameraStateFilePath.empty()) {
return ghoul::lua::luaError(L, "filepath string is empty");
}
global::navigationHandler->saveNavigationState(cameraStateFilePath, referenceFrame);
lua_settop(L, 0);
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
global::navigationHandler->saveNavigationState(path, *frame);
return 0;
}
int retargetAnchor(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::retargetAnchor");
global::navigationHandler->orbitalNavigator().startRetargetAnchor();
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
int retargetAim(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::retargetAim");
global::navigationHandler->orbitalNavigator().startRetargetAim();
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
int bindJoystickAxis(lua_State* L) {
const int n = ghoul::lua::checkArgumentsAndThrow(
L,
{ 2, 6 },
"lua::bindJoystickAxis"
);
const int axis = ghoul::lua::value<int>(L, 1);
const std::string& axisType = ghoul::lua::value<std::string>(L, 2);
const bool shouldInvert = n > 2 ? ghoul::lua::value<bool>(L, 3) : false;
const bool shouldNormalize = n > 3 ? ghoul::lua::value<bool>(L, 4) : false;
const bool isSticky = n > 4 ? ghoul::lua::value<bool>(L, 5) : false;
const double sensitivity = n > 5 ? ghoul::lua::value<double>(L, 6) : 0.0;
ghoul::lua::checkArgumentsAndThrow(L, { 2, 6 }, "lua::bindJoystickAxis");
auto [axis, axisType, shouldInvert, shouldNormalize, isSticky, sensitivity] =
ghoul::lua::values<
int, std::string, std::optional<bool>, std::optional<bool>,
std::optional<bool>, std::optional<double>
>(L);
shouldInvert = shouldInvert.value_or(false);
shouldNormalize = shouldNormalize.value_or(false);
isSticky = isSticky.value_or(false);
sensitivity = sensitivity.value_or(0.0);
global::navigationHandler->setJoystickAxisMapping(
axis,
ghoul::from_string<interaction::JoystickCameraStates::AxisType>(axisType),
interaction::JoystickCameraStates::AxisInvert(shouldInvert),
interaction::JoystickCameraStates::AxisNormalize(shouldNormalize),
isSticky,
sensitivity
interaction::JoystickCameraStates::AxisInvert(*shouldInvert),
interaction::JoystickCameraStates::AxisNormalize(*shouldNormalize),
*isSticky,
*sensitivity
);
lua_settop(L, 0);
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
int joystickAxis(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::joystickAxis");
const int axis = ghoul::lua::value<int>(L, 1);
const int axis = ghoul::lua::value<int>(L);
using AI = interaction::JoystickCameraStates::AxisInformation;
AI info = global::navigationHandler->joystickAxisMapping(axis);
lua_settop(L, 0);
const bool invert = info.invert;
const bool normalize = info.normalize;
const bool isSticky = info.isSticky;
const double sensitivity = info.sensitivity;
ghoul::lua::push(
L,
ghoul::to_string(info.type),
invert,
normalize,
isSticky,
sensitivity
static_cast<bool>(info.invert),
static_cast<bool>(info.normalize),
info.isSticky,
info.sensitivity
);
ghoul_assert(lua_gettop(L) == 5, "Incorrect number of items left on stack");
return 5;
}
int setJoystickAxisDeadzone(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::setJoystickAxisDeadzone");
const int axis = ghoul::lua::value<int>(L, 1);
const float deadzone = ghoul::lua::value<float>(L, 2);
lua_settop(L, 0);
auto [axis, deadzone] = ghoul::lua::values<int, float>(L);
global::navigationHandler->setJoystickAxisDeadzone(axis, deadzone);
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
int joystickAxisDeadzone(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::setJoystickAxisDeadzone");
const int axis = ghoul::lua::value<int>(L, 1, ghoul::lua::PopValue::Yes);
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::joystickAxisDeadzone");
const int axis = ghoul::lua::value<int>(L);
const float deadzone = global::navigationHandler->joystickAxisDeadzone(axis);
ghoul::lua::push(L, deadzone);
ghoul_assert(lua_gettop(L) == 1, "Incorrect number of items left on stack");
return 1;
}
int bindJoystickButton(lua_State* L) {
const int n = ghoul::lua::checkArgumentsAndThrow(
L,
{ 3, 5 },
"lua::bindJoystickButton"
);
ghoul::lua::checkArgumentsAndThrow(L, { 3, 5 }, "lua::bindJoystickButton");
auto [button, command, documentation, actionStr, isRemote] =
ghoul::lua::values<
int, std::string, std::string, std::optional<std::string>, std::optional<bool>
>(L);
actionStr = actionStr.value_or("Press");
isRemote = isRemote.value_or(true);
const int button = ghoul::lua::value<int>(L, 1);
std::string command = ghoul::lua::value<std::string>(L, 2);
std::string documentation = ghoul::lua::value<std::string>(L, 3);
interaction::JoystickAction action = interaction::JoystickAction::Press;
if (n >= 4) {
const std::string& actionStr = ghoul::lua::value<std::string>(L, 4);
action = ghoul::from_string<interaction::JoystickAction>(actionStr);
}
const bool isRemote = n == 5 ? ghoul::lua::value<bool>(L, 5) : true;
lua_settop(L, 0);
interaction::JoystickAction action =
ghoul::from_string<interaction::JoystickAction>(*actionStr);
global::navigationHandler->bindJoystickButtonCommand(
button,
command,
action,
interaction::JoystickCameraStates::ButtonCommandRemote(isRemote),
interaction::JoystickCameraStates::ButtonCommandRemote(*isRemote),
documentation
);
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
int clearJoystickButton(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::bindJoystickButton");
const int button = ghoul::lua::value<int>(L, 1, ghoul::lua::PopValue::Yes);
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::clearJoystickButton");
const int button = ghoul::lua::value<int>(L);
global::navigationHandler->clearJoystickButtonCommand(button);
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
int joystickButton(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::bindJoystickButton");
const int button = ghoul::lua::value<int>(L, 1, ghoul::lua::PopValue::Yes);
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::joystickButton");
const int button = ghoul::lua::value<int>(L);
const std::vector<std::string>& cmds =
global::navigationHandler->joystickButtonCommand(button);
std::string cmd = std::accumulate(
cmds.begin(),
cmds.end(),
cmds.cbegin(),
cmds.cend(),
std::string(),
[](const std::string& lhs, const std::string& rhs) {
return lhs + ";" + rhs;
}
);
ghoul::lua::push(L, cmd);
ghoul_assert(lua_gettop(L) == 1, "Incorrect number of items left on stack");
return 1;
}
int addGlobalRotation(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::addGlobalRotation");
const double v1 = ghoul::lua::value<double>(L, 1, ghoul::lua::PopValue::No);
const double v2 = ghoul::lua::value<double>(L, 2, ghoul::lua::PopValue::No);
auto [v1, v2] = ghoul::lua::values<double, double>(L);
global::navigationHandler->orbitalNavigator().scriptStates().addGlobalRotation(
glm::dvec2(v1, v2)
);
lua_settop(L, 0);
return 0;
}
int addLocalRotation(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::addLocalRotation");
const double v1 = ghoul::lua::value<double>(L, 1, ghoul::lua::PopValue::No);
const double v2 = ghoul::lua::value<double>(L, 2, ghoul::lua::PopValue::No);
auto [v1, v2] = ghoul::lua::values<double, double>(L);
global::navigationHandler->orbitalNavigator().scriptStates().addLocalRotation(
glm::dvec2(v1, v2)
);
lua_settop(L, 0);
return 0;
}
int addTruckMovement(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::addTruckMovement");
const double v1 = ghoul::lua::value<double>(L, 1, ghoul::lua::PopValue::No);
const double v2 = ghoul::lua::value<double>(L, 2, ghoul::lua::PopValue::No);
auto [v1, v2] = ghoul::lua::values<double, double>(L);
global::navigationHandler->orbitalNavigator().scriptStates().addTruckMovement(
glm::dvec2(v1, v2)
);
lua_settop(L, 0);
return 0;
}
int addLocalRoll(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::addLocalRoll");
const double v1 = ghoul::lua::value<double>(L, 1, ghoul::lua::PopValue::No);
const double v2 = ghoul::lua::value<double>(L, 2, ghoul::lua::PopValue::No);
auto [v1, v2] = ghoul::lua::values<double, double>(L);
global::navigationHandler->orbitalNavigator().scriptStates().addLocalRoll(
glm::dvec2(v1, v2)
);
lua_settop(L, 0);
return 0;
}
int addGlobalRoll(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::addGlobalRoll");
const double v1 = ghoul::lua::value<double>(L, 1, ghoul::lua::PopValue::No);
const double v2 = ghoul::lua::value<double>(L, 2, ghoul::lua::PopValue::No);
auto [v1, v2] = ghoul::lua::values<double, double>(L);
global::navigationHandler->orbitalNavigator().scriptStates().addGlobalRoll(
glm::dvec2(v1, v2)
);
lua_settop(L, 0);
return 0;
}
+1 -2
View File
@@ -121,8 +121,7 @@ CameraPose NavigationState::cameraPose() const {
const glm::dvec3 anchorWorldPosition = anchorNode->worldPosition();
const glm::dmat3 referenceFrameTransform = referenceFrameNode->worldRotationMatrix();
resultingPose.position = anchorWorldPosition +
glm::dvec3(referenceFrameTransform * glm::dvec4(position, 1.0));
resultingPose.position = anchorWorldPosition + referenceFrameTransform * position;
glm::dvec3 upVector = up.has_value() ?
glm::normalize(referenceFrameTransform * up.value()) :
+24 -16
View File
@@ -310,7 +310,8 @@ OrbitalNavigator::IdleBehavior::IdleBehavior()
addProperty(apply);
chosenBehavior.addOptions({
{ IdleBehavior::Behavior::Orbit, "Orbit" },
{ IdleBehavior::Behavior::OrbitAtConstantLat, "OrbitAtConstantLatitude" }
{ IdleBehavior::Behavior::OrbitAtConstantLat, "OrbitAtConstantLatitude" },
{ IdleBehavior::Behavior::OrbitAroundUp, "OrbitAroundUp" }
});
chosenBehavior = IdleBehavior::Behavior::Orbit;
addProperty(chosenBehavior);
@@ -572,7 +573,7 @@ void OrbitalNavigator::updateCameraStateFromStates(double deltaTime) {
// Calculate a position handle based on the camera position in world space
glm::dvec3 camPosToAnchorPosDiff = prevCameraPosition - anchorPos;
// Use the interaction sphere to get an approximate distance to the node surface
double nodeRadius = static_cast<double>(_anchorNode->interactionSphere());
double nodeRadius = _anchorNode->interactionSphere();
double distFromCameraToFocus =
glm::distance(prevCameraPosition, anchorPos) - nodeRadius;
@@ -1614,9 +1615,21 @@ void OrbitalNavigator::applyIdleBehavior(double deltaTime, glm::dvec3& position,
case IdleBehavior::Behavior::Orbit:
orbitAnchor(deltaTime, position, globalRotation, speedScale);
break;
case IdleBehavior::Behavior::OrbitAtConstantLat:
orbitAtConstantLatitude(deltaTime, position, globalRotation, speedScale);
case IdleBehavior::Behavior::OrbitAtConstantLat: {
// Assume that "north" coincides with the local z-direction
// @TODO (2021-07-09, emmbr) Make each scene graph node aware of its own
// north/up, so that we can query this information rather than assuming it.
// The we could also combine this idle behavior with the next
const glm::dvec3 north = glm::dvec3(0.0, 0.0, 1.0);
orbitAroundAxis(north, deltaTime, position, globalRotation, speedScale);
break;
}
case IdleBehavior::Behavior::OrbitAroundUp: {
// Assume that "up" coincides with the local y-direction
const glm::dvec3 up = glm::dvec3(0.0, 1.0, 0.0);
orbitAroundAxis(up, deltaTime, position, globalRotation, speedScale);
break;
}
default:
throw ghoul::MissingCaseException();
}
@@ -1645,24 +1658,19 @@ void OrbitalNavigator::orbitAnchor(double deltaTime, glm::dvec3& position,
position += rotationDiffVec3;
}
void OrbitalNavigator::orbitAtConstantLatitude(double deltaTime, glm::dvec3& position,
glm::dquat& globalRotation,
double speedScale)
void OrbitalNavigator::orbitAroundAxis(const glm::dvec3 axis, double deltaTime,
glm::dvec3& position, glm::dquat& globalRotation,
double speedScale)
{
ghoul_assert(_anchorNode != nullptr, "Node to orbit must be set!");
const glm::dmat4 modelTransform = _anchorNode->modelTransform();
const glm::dvec3 axisInWorldCoords =
glm::dmat3(modelTransform) * glm::normalize(axis);
// Assume north coincides with the local z-direction
// @TODO (2021-07-09, emmbr) Make each scene graph node aware of its own north/up, so
// that we can query this information rather than assuming it
const glm::dvec3 northInWorldCoords =
glm::dmat3(modelTransform) * glm::dvec3(0.0, 0.0, 1.0);
// Compute rotation around the north axis to be applied
// Compute rotation to be applied around the axis
double angle = deltaTime * speedScale;
const glm::dquat spinRotation =
glm::angleAxis(angle, glm::normalize(northInWorldCoords));
const glm::dquat spinRotation = glm::angleAxis(angle, axisInWorldCoords);
// Rotate the position vector from the center to camera and update position
const glm::dvec3 anchorCenterToCamera = position - _anchorNode->worldPosition();
+15 -15
View File
@@ -107,19 +107,19 @@ Path::Path(Waypoint start, Waypoint end, Type type,
throw ghoul::MissingCaseException();
}
_duration = duration.value_or(std::log(pathLength()));
// Compute speed factor to match any given duration, by traversing the path and
// computing how much faster/slower it should be
_speedFactorFromDuration = 1.0;
if (duration.has_value()) {
constexpr const double dt = 0.05; // 20 fps
while (!hasReachedEnd()) {
traversePath(dt);
}
// Compute speed factor to match the generated path length and duration, by
// traversing the path and computing how much faster/slower it should be
const int nSteps = 500;
const double dt = (_duration / nSteps) > 0.01 ? (_duration / nSteps) : 0.01;
while (!hasReachedEnd()) {
traversePath(dt);
// We now know how long it took to traverse the path. Use that
_speedFactorFromDuration = _progressedTime / *duration;
}
_speedFactorFromDuration = _progressedTime / _duration;
// Reset playback variables
_traveledDistance = 0.0;
_progressedTime = 0.0;
@@ -129,8 +129,6 @@ Waypoint Path::startPoint() const { return _start; }
Waypoint Path::endPoint() const { return _end; }
double Path::duration() const { return _duration; }
double Path::pathLength() const { return _curve->length(); }
std::vector<glm::dvec3> Path::controlPoints() const {
@@ -219,11 +217,13 @@ glm::dquat Path::lookAtTargetsRotation(double t) const {
}
// Handle up vector separately
// @TODO (2021-09-06 emmbr) This actually does not interpolate the up vector of the
// camera, but just the "hint" up vector for the lookAt. This leads to fast rolling
// when the up vector gets close to the camera's forward vector. Should be improved
// so any rolling is spread out over the entire motion instead
double tUp = ghoul::sineEaseInOut(t);
glm::dvec3 startUp = _start.rotation() * glm::dvec3(0.0, 1.0, 0.0);
glm::dvec3 endUp = _end.rotation() * glm::dvec3(0.0, 1.0, 0.0);
double tUp = helpers::shiftAndScale(t, t1, t2);
tUp = ghoul::sineEaseInOut(tUp);
glm::dvec3 up = ghoul::interpolateLinear(tUp, startUp, endUp);
return ghoul::lookAtQuaternion(_curve->positionAt(t), lookAtPos, up);
+58 -88
View File
@@ -44,94 +44,44 @@ namespace openspace::luascriptfunctions {
int isFlying(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::isFlying");
bool hasFinished = global::navigationHandler->pathNavigator().hasFinished();
ghoul::lua::push(L, !hasFinished);
ghoul_assert(lua_gettop(L) == 1, "Incorrect number of items left on stack");
return 1;
}
int continuePath(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::continuePath");
global::navigationHandler->pathNavigator().continuePath();
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
int pausePath(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::pausePath");
global::navigationHandler->pathNavigator().pausePath();
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
int stopPath(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::stopPath");
global::navigationHandler->pathNavigator().abortPath();
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
// All the goTo function has the same two optional input parameters at the end. The
// purpose of this function is to handle these input parameters and add the result
// to the dictionary specifying the instruction for a camera path.
int handleOptionalGoToParameters(lua_State* L, const int startLocation,
const int nArguments,
ghoul::Dictionary& resultInstruction)
{
const bool firstIsNumber = (lua_isnumber(L, startLocation) != 0);
const bool firstIsBool = (lua_isboolean(L, startLocation) != 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 #{} ({})", startLocation, msg)
);
}
int location = startLocation;
if (firstIsBool) {
const bool useUpFromTarget = (lua_toboolean(L, location) == 1);
resultInstruction.setValue("UseTargetUpDirection", useUpFromTarget);
if (nArguments > startLocation) {
location++;
}
}
if (firstIsNumber || nArguments > startLocation) {
double duration = ghoul::lua::value<double>(L, location);
if (duration <= Epsilon) {
lua_settop(L, 0);
return ghoul::lua::luaError(L, "Duration must be larger than zero.");
}
resultInstruction.setValue("Duration", duration);
}
return 0;
}
int goTo(lua_State* L) {
int nArguments = ghoul::lua::checkArgumentsAndThrow(L, { 1, 3 }, "lua::goTo");
ghoul::lua::checkArgumentsAndThrow(L, { 1, 3 }, "lua::goTo");
auto [nodeIdentifier, useUpFromTargetOrDuration, duration] = ghoul::lua::values<
std::string, std::optional<std::variant<bool, double>>, std::optional<double>
>(L);
if (useUpFromTargetOrDuration.has_value() &&
std::holds_alternative<double>(*useUpFromTargetOrDuration)
&& duration.has_value())
{
return ghoul::lua::luaError(L, "Duration cannot be specified twice");
}
const std::string& nodeIdentifier = ghoul::lua::value<std::string>(L, 1);
if (!sceneGraphNode(nodeIdentifier)) {
lua_settop(L, 0);
return ghoul::lua::luaError(L, "Unknown node name: " + nodeIdentifier);
}
@@ -139,12 +89,27 @@ int goTo(lua_State* L) {
ghoul::Dictionary insDict;
insDict.setValue("TargetType", "Node"s);
insDict.setValue("Target", nodeIdentifier);
if (nArguments > 1) {
int result = handleOptionalGoToParameters(L, 2, nArguments, insDict);
if (result != 0) {
return result; // An error occurred
if (useUpFromTargetOrDuration.has_value()) {
if (std::holds_alternative<bool>(*useUpFromTargetOrDuration)) {
insDict.setValue(
"UseTargetUpDirection",
std::get<bool>(*useUpFromTargetOrDuration)
);
}
else {
double d = std::get<double>(*useUpFromTargetOrDuration);
if (d <= Epsilon) {
return ghoul::lua::luaError(L, "Duration must be larger than zero");
}
insDict.setValue("Duration", d);
}
}
if (duration.has_value()) {
double d = *duration;
if (d <= Epsilon) {
return ghoul::lua::luaError(L, "Duration must be larger than zero");
}
insDict.setValue("Duration", d);
}
global::navigationHandler->pathNavigator().createPath(insDict);
@@ -152,35 +117,48 @@ int goTo(lua_State* L) {
if (global::navigationHandler->pathNavigator().hasCurrentPath()) {
global::navigationHandler->pathNavigator().startPath();
}
lua_settop(L, 0);
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
int goToHeight(lua_State* L) {
int nArguments = ghoul::lua::checkArgumentsAndThrow(L, { 2, 4 }, "lua::goToHeight");
ghoul::lua::checkArgumentsAndThrow(L, { 2, 4 }, "lua::goToHeight");
auto [nodeIdentifier, height, useUpFromTargetOrDuration, duration] =
ghoul::lua::values<
std::string, double, std::optional<std::variant<bool, double>>,
std::optional<double>
>(L);
const std::string& nodeIdentifier = ghoul::lua::value<std::string>(L, 1);
if (!sceneGraphNode(nodeIdentifier)) {
lua_settop(L, 0);
return ghoul::lua::luaError(L, "Unknown node name: " + nodeIdentifier);
}
double height = ghoul::lua::value<double>(L, 2);
using namespace std::string_literals;
ghoul::Dictionary insDict;
insDict.setValue("TargetType", "Node"s);
insDict.setValue("Target", nodeIdentifier);
insDict.setValue("Height", height);
if (nArguments > 2) {
int result = handleOptionalGoToParameters(L, 3, nArguments, insDict);
if (result != 0) {
return result; // An error occurred
if (useUpFromTargetOrDuration.has_value()) {
if (std::holds_alternative<bool>(*useUpFromTargetOrDuration)) {
insDict.setValue(
"UseTargetUpDirection",
std::get<bool>(*useUpFromTargetOrDuration)
);
}
else {
double d = std::get<double>(*useUpFromTargetOrDuration);
if (d <= Epsilon) {
return ghoul::lua::luaError(L, "Duration must be larger than zero");
}
insDict.setValue("Duration", d);
}
}
if (duration.has_value()) {
double d = *duration;
if (d <= Epsilon) {
return ghoul::lua::luaError(L, "Duration must be larger than zero");
}
insDict.setValue("Duration", d);
}
global::navigationHandler->pathNavigator().createPath(insDict);
@@ -189,25 +167,17 @@ int goToHeight(lua_State* L) {
global::navigationHandler->pathNavigator().startPath();
}
lua_settop(L, 0);
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
int generatePath(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::generatePath");
ghoul::Dictionary dictionary;
ghoul::lua::luaDictionaryFromState(L, dictionary);
ghoul::Dictionary dictionary = ghoul::lua::value<ghoul::Dictionary>(L);
global::navigationHandler->pathNavigator().createPath(dictionary);
if (global::navigationHandler->pathNavigator().hasCurrentPath()) {
global::navigationHandler->pathNavigator().startPath();
}
lua_settop(L, 0);
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
+1 -1
View File
@@ -61,7 +61,7 @@ ParallelConnection::ParallelConnection(std::unique_ptr<ghoul::io::TcpSocket> soc
{}
bool ParallelConnection::isConnectedOrConnecting() const {
return _socket->isConnected() || _socket->isConnecting();
return _socket != nullptr && (_socket->isConnected() || _socket->isConnecting());
}
void ParallelConnection::sendDataMessage(const DataMessage& dataMessage) {
-12
View File
@@ -26,45 +26,33 @@ namespace openspace::luascriptfunctions {
int connect(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::connect");
if (global::windowDelegate->isMaster()) {
global::parallelPeer->connect();
}
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
int disconnect(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::disconnect");
if (global::windowDelegate->isMaster()) {
global::parallelPeer->connect();
}
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
int requestHostship(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::requestHostship");
if (global::windowDelegate->isMaster()) {
global::parallelPeer->requestHostship();
}
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
int resignHostship(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::resignHostship");
if (global::windowDelegate->isMaster()) {
global::parallelPeer->resignHostship();
}
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
+25 -50
View File
@@ -28,70 +28,45 @@
namespace openspace::luascriptfunctions {
/**
* \ingroup LuaScripts
* addDashboardItem(table):
*/
* \ingroup LuaScripts
* addDashboardItem(table):
*/
int addDashboardItem(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::addDashboardItem");
ghoul::Dictionary d = ghoul::lua::value<ghoul::Dictionary>(L);
const int type = lua_type(L, -1);
if (type == LUA_TTABLE) {
ghoul::Dictionary d;
try {
ghoul::lua::luaDictionaryFromState(L, d);
}
catch (const ghoul::lua::LuaFormatException& e) {
LERRORC("addDashboardItem", e.what());
lua_settop(L, 0);
return 0;
}
lua_settop(L, 0);
try {
global::dashboard->addDashboardItem(DashboardItem::createFromDictionary(d));
}
catch (const ghoul::RuntimeError& e) {
LERRORC("addDashboardItem", e.what());
return ghoul::lua::luaError(L, "Error adding dashboard item");
}
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
try {
global::dashboard->addDashboardItem(
DashboardItem::createFromDictionary(std::move(d))
);
}
else {
return ghoul::lua::luaError(L, "Expected argument of type 'table'");
catch (const ghoul::RuntimeError& e) {
LERRORC("addDashboardItem", e.what());
return ghoul::lua::luaError(L, "Error adding dashboard item");
}
}
/**
* \ingroup LuaScripts
* removeDashboardItem(string):
*/
int removeDashboardItem(lua_State* L) {
using ghoul::lua::errorLocation;
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::removeDashbordItem");
std::string identifier = luaL_checkstring(L, -1);
global::dashboard->removeDashboardItem(identifier);
lua_settop(L, 0);
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
/**
* \ingroup LuaScripts
* removeDashboardItem(string):
*/
int removeDashboardItem(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::removeDashbordItem");
const std::string identifier = ghoul::lua::value<std::string>(L);
global::dashboard->removeDashboardItem(identifier);
return 0;
}
/**
* \ingroup LuaScripts
* removeDashboardItems():
*/
* \ingroup LuaScripts
* removeDashboardItems():
*/
int clearDashboardItems(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::clearDashboardItems");
global::dashboard->clearDashboardItems();
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
+22 -2
View File
@@ -252,6 +252,18 @@ namespace {
"Enable FXAA",
"Enable FXAA"
};
constexpr openspace::properties::Property::PropertyInfo EnabledFontColorInfo = {
"EnabledFontColor",
"Enabled Font Color",
"The font color used for enabled options."
};
constexpr openspace::properties::Property::PropertyInfo DisabledFontColorInfo = {
"DisabledFontColor",
"Disabled Font Color",
"The font color used for disabled options."
};
} // namespace
namespace openspace {
@@ -295,6 +307,8 @@ RenderEngine::RenderEngine()
glm::vec3(-glm::pi<float>()),
glm::vec3(glm::pi<float>())
)
, _enabledFontColor(EnabledFontColorInfo, glm::vec4(0.2f, 0.75f, 0.2f, 1.f))
, _disabledFontColor(DisabledFontColorInfo, glm::vec4(0.55f, 0.2f, 0.2f, 1.f))
{
addProperty(_showOverlayOnSlaves);
addProperty(_showLog);
@@ -380,6 +394,12 @@ RenderEngine::RenderEngine()
addProperty(_screenSpaceRotation);
addProperty(_masterRotation);
addProperty(_disableMasterRendering);
_enabledFontColor.setViewOption(openspace::properties::Property::ViewOptions::Color);
addProperty(_enabledFontColor);
_disabledFontColor.setViewOption(openspace::properties::Property::ViewOptions::Color);
addProperty(_disabledFontColor);
}
RenderEngine::~RenderEngine() {} // NOLINT
@@ -1148,8 +1168,8 @@ void RenderEngine::renderCameraInformation() {
return;
}
const glm::vec4 EnabledColor = glm::vec4(0.2f, 0.75f, 0.2f, 1.f);
const glm::vec4 DisabledColor = glm::vec4(0.55f, 0.2f, 0.2f, 1.f);
const glm::vec4 EnabledColor = _enabledFontColor.value();
const glm::vec4 DisabledColor = _disabledFontColor.value();
const glm::vec2 rotationBox = _fontCameraInfo->boundingBox("Rotation");
+4 -26
View File
@@ -28,50 +28,28 @@ namespace openspace::luascriptfunctions {
int addScreenSpaceRenderable(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::addScreenSpaceRenderable");
using ghoul::lua::errorLocation;
ghoul::Dictionary d;
try {
ghoul::lua::luaDictionaryFromState(L, d);
lua_settop(L, 0);
}
catch (const ghoul::lua::LuaFormatException& e) {
LERRORC("addScreenSpaceRenderable", e.what());
lua_settop(L, 0);
return 0;
}
const ghoul::Dictionary d = ghoul::lua::value<ghoul::Dictionary>(L);
std::unique_ptr<ScreenSpaceRenderable> s =
ScreenSpaceRenderable::createFromDictionary(d);
ScreenSpaceRenderable::createFromDictionary(d);
global::renderEngine->addScreenSpaceRenderable(std::move(s));
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
int removeScreenSpaceRenderable(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::removeScreenSpaceRenderable");
const std::string name = ghoul::lua::value<std::string>(L);
const std::string& name = ghoul::lua::value<std::string>(
L,
1,
ghoul::lua::PopValue::Yes
);
global::renderEngine->removeScreenSpaceRenderable(name);
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
int takeScreenshot(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::takeScreenshot");
global::renderEngine->takeScreenshot();
const unsigned int screenshotNumber = global::renderEngine->latestScreenshotNumber();
lua_pushinteger(L, screenshotNumber);
ghoul::lua::push(L, screenshotNumber);
return 1;
}
+26 -34
View File
@@ -28,8 +28,8 @@ namespace openspace::assetloader {
* Adds a Lua function to be called upon asset initialization
* Usage: void asset.onInitialize(function<void()> initFun)
*/
int onInitialize(lua_State* state) {
Asset* asset = reinterpret_cast<Asset*>(lua_touserdata(state, lua_upvalueindex(1)));
int onInitialize(lua_State* L) {
Asset* asset = reinterpret_cast<Asset*>(lua_touserdata(L, lua_upvalueindex(1)));
return asset->loader()->onInitializeLua(asset);
}
@@ -37,36 +37,28 @@ int onInitialize(lua_State* state) {
* Adds a Lua function to be called upon asset deinitialization
* Usage: void asset.onDeinitialize(function<void()> initFun)
*/
int onDeinitialize(lua_State* state) {
Asset* asset = reinterpret_cast<Asset*>(lua_touserdata(state, lua_upvalueindex(1)));
int onDeinitialize(lua_State* L) {
Asset* asset = reinterpret_cast<Asset*>(lua_touserdata(L, lua_upvalueindex(1)));
return asset->loader()->onDeinitializeLua(asset);
}
/**
* Adds a Lua function to be called when a dependency link is initialized
* Usage: void asset.onInitialize(function<void()> initFun)
*/
int onInitializeDependency(lua_State* state) {
Asset* dependant = reinterpret_cast<Asset*>(
lua_touserdata(state, lua_upvalueindex(1))
);
Asset* dependency = reinterpret_cast<Asset*>(
lua_touserdata(state, lua_upvalueindex(2))
);
* Adds a Lua function to be called when a dependency link is initialized
* Usage: void asset.onInitialize(function<void()> initFun)
*/
int onInitializeDependency(lua_State* L) {
Asset* dependant = reinterpret_cast<Asset*>(lua_touserdata(L, lua_upvalueindex(1)));
Asset* dependency = reinterpret_cast<Asset*>(lua_touserdata(L, lua_upvalueindex(2)));
return dependant->loader()->onInitializeDependencyLua(dependant, dependency);
}
/**
* Adds a Lua function to be called upon asset deinitialization
* Usage: void asset.onDeinitialize(function<void()> initFun)
*/
int onDeinitializeDependency(lua_State* state) {
Asset* dependant = reinterpret_cast<Asset*>(
lua_touserdata(state, lua_upvalueindex(1))
);
Asset* dependency = reinterpret_cast<Asset*>(
lua_touserdata(state, lua_upvalueindex(2))
);
* Adds a Lua function to be called upon asset deinitialization
* Usage: void asset.onDeinitialize(function<void()> initFun)
*/
int onDeinitializeDependency(lua_State* L) {
Asset* dependant = reinterpret_cast<Asset*>(lua_touserdata(L, lua_upvalueindex(1)));
Asset* dependency = reinterpret_cast<Asset*>(lua_touserdata(L, lua_upvalueindex(2)));
return dependant->loader()->onDeinitializeDependencyLua(dependant, dependency);
}
@@ -77,28 +69,28 @@ int onDeinitializeDependency(lua_State* state) {
* Dependency: ...
* Usage: {AssetTable, Dependency} = asset.import(string assetIdentifier)
*/
int require(lua_State* state) {
Asset* asset = reinterpret_cast<Asset*>(lua_touserdata(state, lua_upvalueindex(1)));
int require(lua_State* L) {
Asset* asset = reinterpret_cast<Asset*>(lua_touserdata(L, lua_upvalueindex(1)));
return asset->loader()->requireLua(asset);
}
int exists(lua_State* state) {
Asset* asset = reinterpret_cast<Asset*>(lua_touserdata(state, lua_upvalueindex(1)));
int exists(lua_State* L) {
Asset* asset = reinterpret_cast<Asset*>(lua_touserdata(L, lua_upvalueindex(1)));
return asset->loader()->existsLua(asset);
}
int localResource(lua_State* state) {
Asset* asset = reinterpret_cast<Asset*>(lua_touserdata(state, lua_upvalueindex(1)));
int localResource(lua_State* L) {
Asset* asset = reinterpret_cast<Asset*>(lua_touserdata(L, lua_upvalueindex(1)));
return asset->loader()->localResourceLua(asset);
}
int syncedResource(lua_State* state) {
Asset* asset = reinterpret_cast<Asset*>(lua_touserdata(state, lua_upvalueindex(1)));
int syncedResource(lua_State* L) {
Asset* asset = reinterpret_cast<Asset*>(lua_touserdata(L, lua_upvalueindex(1)));
return asset->loader()->syncedResourceLua(asset);
}
int exportAsset(lua_State* state) {
Asset* asset = reinterpret_cast<Asset*>(lua_touserdata(state, lua_upvalueindex(1)));
int exportAsset(lua_State* L) {
Asset* asset = reinterpret_cast<Asset*>(lua_touserdata(L, lua_upvalueindex(1)));
return asset->loader()->exportAssetLua(asset);
}
+12 -25
View File
@@ -28,17 +28,13 @@
namespace openspace::luascriptfunctions::asset {
int add(lua_State* state) {
ghoul::lua::checkArgumentsAndThrow(state, 1, "lua::add");
int add(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::add");
AssetManager* assetManager =
reinterpret_cast<AssetManager*>(lua_touserdata(state, lua_upvalueindex(1)));
const std::string& assetName = ghoul::lua::value<std::string>(
state,
1,
ghoul::lua::PopValue::Yes
AssetManager* assetManager = reinterpret_cast<AssetManager*>(
lua_touserdata(L, lua_upvalueindex(1))
);
const std::string assetName = ghoul::lua::value<std::string>(L);
if (global::renderEngine->scene()) {
assetManager->add(assetName);
@@ -49,36 +45,27 @@ int add(lua_State* state) {
global::openSpaceEngine->scheduleLoadSingleAsset(assetName);
}
ghoul_assert(lua_gettop(state) == 0, "Incorrect number of items left on stack");
return 0;
}
int remove(lua_State* state) {
ghoul::lua::checkArgumentsAndThrow(state, 1, "lua::remove");
int remove(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::remove");
AssetManager* assetManager =
reinterpret_cast<AssetManager*>(lua_touserdata(state, lua_upvalueindex(1)));
reinterpret_cast<AssetManager*>(lua_touserdata(L, lua_upvalueindex(1)));
const std::string assetName = ghoul::lua::value<std::string>(L);
const std::string& assetName = ghoul::lua::value<std::string>(
state,
1,
ghoul::lua::PopValue::Yes
);
assetManager->remove(assetName);
ghoul_assert(lua_gettop(state) == 0, "Incorrect number of items left on stack");
return 0;
}
int removeAll(lua_State* state) {
ghoul::lua::checkArgumentsAndThrow(state, 0, "lua::removeAll");
int removeAll(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::removeAll");
AssetManager* assetManager =
reinterpret_cast<AssetManager*>(lua_touserdata(state, lua_upvalueindex(1)));
reinterpret_cast<AssetManager*>(lua_touserdata(L, lua_upvalueindex(1)));
assetManager->removeAll();
return 0;
}
+4 -8
View File
@@ -499,12 +499,8 @@ void convertVersion10to11(nlohmann::json& profile) {
return;
}
// This needs to be changed if there is another version for any of these types later
using Action = Profile::Action;
using Keybinding = Profile::Keybinding;
std::vector<Action> actions;
std::vector<Keybinding> keybindings;
std::vector<Profile::Action> actions;
std::vector<Profile::Keybinding> keybindings;
std::vector<version10::Keybinding> kbs =
profile.at("keybindings").get<std::vector<version10::Keybinding>>();
@@ -512,7 +508,7 @@ void convertVersion10to11(nlohmann::json& profile) {
version10::Keybinding& kb = kbs[i];
std::string identifier = fmt::format("profile.keybind.{}", i);
Action action;
Profile::Action action;
action.identifier = identifier;
action.documentation = std::move(kb.documentation);
action.name = std::move(kb.name);
@@ -521,7 +517,7 @@ void convertVersion10to11(nlohmann::json& profile) {
action.script = std::move(kb.script);
actions.push_back(std::move(action));
Keybinding keybinding;
Profile::Keybinding keybinding;
keybinding.key = kb.key;
keybinding.action = identifier;
keybindings.push_back(keybinding);
+40 -40
View File
@@ -37,21 +37,19 @@ namespace openspace::luascriptfunctions {
int saveSettingsToProfile(lua_State* L) {
if (!global::configuration->usingProfile) {
return luaL_error(
return ghoul::lua::luaError(
L,
"Program was not started with a profile, so cannot use this "
"save-current-settings feature"
);
}
const int n = ghoul::lua::checkArgumentsAndThrow(
L,
{ 0, 2 },
"lua::saveSettingsToProfile"
);
ghoul::lua::checkArgumentsAndThrow(L, { 0, 2 }, "lua::saveSettingsToProfile");
auto [saveFilePath, overwrite] =
ghoul::lua::values<std::optional<std::string>, std::optional<bool>>(L);
overwrite = overwrite.value_or(true);
std::string saveFilePath;
if (n == 0) {
if (!saveFilePath.has_value()) {
std::time_t t = std::time(nullptr);
std::tm* utcTime = std::gmtime(&t);
ghoul_assert(utcTime, "Conversion to UTC failed");
@@ -68,22 +66,27 @@ int saveSettingsToProfile(lua_State* L) {
std::filesystem::path path = global::configuration->profile;
path.replace_extension();
std::string newFile = fmt::format("{}_{}", path.string(), time);
std::string sourcePath = fmt::format("{}/{}.profile",
absPath("${USER_PROFILES}").string(), global::configuration->profile);
std::string destPath = fmt::format("{}/{}.profile",
absPath("${PROFILES}").string(), global::configuration->profile);
std::string sourcePath = fmt::format(
"{}/{}.profile",
absPath("${USER_PROFILES}").string(), global::configuration->profile
);
std::string destPath = fmt::format(
"{}/{}.profile",
absPath("${PROFILES}").string(), global::configuration->profile
);
if (!std::filesystem::is_regular_file(sourcePath)) {
sourcePath = absPath("${USER_PROFILES}").string()
+ '/' + global::configuration->profile + ".profile";
sourcePath = fmt::format(
"{}/{}.profile",
absPath("${USER_PROFILES}").string(), global::configuration->profile
);
}
LINFOC("Profile", fmt::format("Saving a copy of the old profile as {}", newFile));
std::filesystem::copy(sourcePath, destPath);
saveFilePath = global::configuration->profile;
}
else {
saveFilePath = ghoul::lua::value<std::string>(L, 1);
if (saveFilePath.empty()) {
return luaL_error(L, "save filepath string is empty");
if (saveFilePath->empty()) {
return ghoul::lua::luaError(L, "Save filepath string is empty");
}
}
@@ -91,32 +94,35 @@ int saveSettingsToProfile(lua_State* L) {
std::string currentTime = std::string(global::timeManager->time().ISO8601());
interaction::NavigationState navState = global::navigationHandler->navigationState();
global::profile->saveCurrentSettingsToProfile(root, currentTime, navState);
global::configuration->profile = saveFilePath;
global::configuration->profile = *saveFilePath;
if (saveFilePath.find('/') != std::string::npos) {
return luaL_error(L, "Profile filename must not contain path (/) elements");
if (saveFilePath->find('/') != std::string::npos) {
return ghoul::lua::luaError(L, "Profile filename must not contain (/) elements");
}
else if (saveFilePath.find(':') != std::string::npos) {
return luaL_error(L, "Profile filename must not contain path (:) elements");
else if (saveFilePath->find(':') != std::string::npos) {
return ghoul::lua::luaError(L, "Profile filename must not contain (:) elements");
}
else if (saveFilePath.find('.') != std::string::npos) {
return luaL_error(L, "Only provide the filename to save without file extension");
else if (saveFilePath->find('.') != std::string::npos) {
return ghoul::lua::luaError(
L,
"Only provide the filename to save without file extension"
);
}
std::string absFilename = fmt::format("{}/{}.profile",
absPath("${PROFILES}").string(), saveFilePath);
std::string absFilename = fmt::format(
"{}/{}.profile", absPath("${PROFILES}").string(), *saveFilePath
);
if (!std::filesystem::is_regular_file(absFilename)) {
absFilename = absPath("${USER_PROFILES}/" + saveFilePath + ".profile").string();
absFilename = absPath("${USER_PROFILES}/" + *saveFilePath + ".profile").string();
}
const bool overwrite = (n == 2) ? ghoul::lua::value<bool>(L, 2) : true;
if (std::filesystem::is_regular_file(absFilename) && !overwrite) {
return luaL_error(
return ghoul::lua::luaError(
L,
fmt::format(
"Unable to save profile '{}'. File of same name already exists",
absFilename
).c_str()
)
);
}
@@ -126,11 +132,11 @@ int saveSettingsToProfile(lua_State* L) {
outFile.open(absFilename, std::ofstream::out);
}
catch (const std::ofstream::failure& e) {
return luaL_error(
return ghoul::lua::luaError(
L,
fmt::format(
"Exception opening profile file for write: {} ({})", absFilename, e.what()
).c_str()
)
);
}
@@ -138,17 +144,11 @@ int saveSettingsToProfile(lua_State* L) {
outFile << global::profile->serialize();
}
catch (const std::ofstream::failure& e) {
return luaL_error(
return ghoul::lua::luaError(
L,
fmt::format(
"Data write error to file: {} ({})", absFilename, e.what()
).c_str()
fmt::format("Data write error to file: {} ({})", absFilename, e.what())
);
}
outFile.close();
lua_settop(L, 0);
return 0;
}
+74 -150
View File
@@ -38,7 +38,7 @@ namespace {
template <class T>
properties::PropertyOwner* findPropertyOwnerWithMatchingGroupTag(T* prop,
const std::string& tagToMatch)
const std::string& tagToMatch)
{
properties::PropertyOwner* tagMatchOwner = nullptr;
properties::PropertyOwner* owner = prop->owner();
@@ -62,10 +62,9 @@ properties::PropertyOwner* findPropertyOwnerWithMatchingGroupTag(T* prop,
}
void applyRegularExpression(lua_State* L, const std::string& regex,
const std::vector<properties::Property*>& properties,
double interpolationDuration,
const std::string& groupName,
ghoul::EasingFunction easingFunction)
const std::vector<properties::Property*>& properties,
double interpolationDuration, const std::string& groupName,
ghoul::EasingFunction easingFunction)
{
using ghoul::lua::errorLocation;
using ghoul::lua::luaTypeToString;
@@ -76,8 +75,8 @@ void applyRegularExpression(lua_State* L, const std::string& regex,
const int type = lua_type(L, -1);
// Extract the property and node name to be searched for from regex
std::string propertyName = "";
std::string nodeName = "";
std::string propertyName;
std::string nodeName;
size_t wildPos = regex.find_first_of("*");
if (wildPos != std::string::npos) {
nodeName = regex.substr(0, wildPos);
@@ -88,8 +87,8 @@ void applyRegularExpression(lua_State* L, const std::string& regex,
LERRORC(
"applyRegularExpression",
fmt::format(
"Malformed regular expression: '{}': "
"Empty both before and after '*'", regex
"Malformed regular expression: '{}': Empty both before and after '*'",
regex
)
);
return;
@@ -100,8 +99,8 @@ void applyRegularExpression(lua_State* L, const std::string& regex,
LERRORC(
"applyRegularExpression",
fmt::format(
"Malformed regular expression: '{}': "
"Currently only one '*' is supported", regex
"Malformed regular expression: '{}': Currently only one '*' is "
"supported", regex
)
);
return;
@@ -120,7 +119,7 @@ void applyRegularExpression(lua_State* L, const std::string& regex,
bool foundMatching = false;
for (properties::Property* prop : properties) {
// Check the regular expression for all properties
const std::string& id = prop->fullyQualifiedIdentifier();
const std::string id = prop->fullyQualifiedIdentifier();
if (isLiteral && id != propertyName) {
continue;
@@ -141,10 +140,7 @@ void applyRegularExpression(lua_State* L, const std::string& regex,
// Check tag
if (isGroupMode) {
properties::PropertyOwner* matchingTaggedOwner =
findPropertyOwnerWithMatchingGroupTag(
prop,
groupName
);
findPropertyOwnerWithMatchingGroupTag(prop, groupName);
if (!matchingTaggedOwner) {
continue;
}
@@ -157,14 +153,10 @@ void applyRegularExpression(lua_State* L, const std::string& regex,
else if (!nodeName.empty()) {
size_t nodePos = id.find(nodeName);
if (nodePos != std::string::npos) {
// Check tag
if (isGroupMode) {
properties::PropertyOwner* matchingTaggedOwner =
findPropertyOwnerWithMatchingGroupTag(
prop,
groupName
);
findPropertyOwnerWithMatchingGroupTag(prop, groupName);
if (!matchingTaggedOwner) {
continue;
}
@@ -184,12 +176,10 @@ void applyRegularExpression(lua_State* L, const std::string& regex,
LERRORC(
"property_setValue",
fmt::format(
"{}: Property '{}' does not accept input of type '{}'. "
"Requested type: '{}'",
errorLocation(L),
prop->fullyQualifiedIdentifier(),
luaTypeToString(type),
luaTypeToString(prop->typeLua())
"{}: Property '{}' does not accept input of type '{}'. Requested "
"type: '{}'",
errorLocation(L), prop->fullyQualifiedIdentifier(),
luaTypeToString(type), luaTypeToString(prop->typeLua())
)
);
}
@@ -220,9 +210,7 @@ void applyRegularExpression(lua_State* L, const std::string& regex,
LERRORC(
"property_setValue",
fmt::format(
"{}: No property matched the requested URI '{}'",
errorLocation(L),
regex
"{}: No property matched the requested URI '{}'", errorLocation(L), regex
)
);
}
@@ -231,7 +219,7 @@ void applyRegularExpression(lua_State* L, const std::string& regex,
// Checks to see if URI contains a group tag (with { } around the first term). If so,
// returns true and sets groupName with the tag
bool doesUriContainGroupTag(const std::string& command, std::string& groupName) {
std::string name = command.substr(0, command.find_first_of("."));
const std::string name = command.substr(0, command.find_first_of("."));
if (name.front() == '{' && name.back() == '}') {
groupName = name.substr(1, name.length() - 2);
return true;
@@ -251,8 +239,8 @@ std::string removeGroupNameFromUri(const std::string& uri) {
namespace openspace::luascriptfunctions {
int setPropertyCall_single(properties::Property& prop, const std::string& uri,
lua_State* L, double duration,
ghoul::EasingFunction easingFunction)
lua_State* L, double duration,
ghoul::EasingFunction easingFunction)
{
using ghoul::lua::errorLocation;
using ghoul::lua::luaTypeToString;
@@ -264,9 +252,7 @@ int setPropertyCall_single(properties::Property& prop, const std::string& uri,
fmt::format(
"{}: Property '{}' does not accept input of type '{}'. "
"Requested type: '{}'",
errorLocation(L),
uri,
luaTypeToString(type),
errorLocation(L), uri, luaTypeToString(type),
luaTypeToString(prop.typeLua())
)
);
@@ -304,37 +290,39 @@ int setPropertyCall_single(properties::Property& prop, const std::string& uri,
*/
int property_setValue(lua_State* L) {
using ghoul::lua::errorLocation;
using ghoul::lua::luaTypeToString;
ghoul::lua::checkArgumentsAndThrow(L, { 2, 5 }, "lua::property_setValue");
defer { lua_settop(L, 0); };
std::string uriOrRegex = ghoul::lua::value<std::string>(L, 1);
std::string uriOrRegex =
ghoul::lua::value<std::string>(L, 1, ghoul::lua::PopValue::No);
std::string optimization;
double interpolationDuration = 0.0;
std::string easingMethodName;
ghoul::EasingFunction easingMethod = ghoul::EasingFunction::Linear;
if (lua_gettop(L) >= 3) {
if (lua_type(L, 3) == LUA_TNUMBER) {
interpolationDuration = ghoul::lua::value<double>(L, 3);
if (ghoul::lua::hasValue<double>(L, 3)) {
interpolationDuration =
ghoul::lua::value<double>(L, 3, ghoul::lua::PopValue::No);
}
else {
optimization = ghoul::lua::value<std::string>(L, 3);
optimization =
ghoul::lua::value<std::string>(L, 3, ghoul::lua::PopValue::No);
}
if (lua_gettop(L) >= 4) {
if (lua_type(L, 4) == LUA_TNUMBER) {
interpolationDuration = ghoul::lua::value<double>(L, 4);
if (ghoul::lua::hasValue<double>(L, 4)) {
interpolationDuration =
ghoul::lua::value<double>(L, 4, ghoul::lua::PopValue::No);
}
else {
easingMethodName = ghoul::lua::value<std::string>(L, 4);
easingMethodName =
ghoul::lua::value<std::string>(L, 4, ghoul::lua::PopValue::No);
}
}
if (lua_gettop(L) == 5) {
optimization = ghoul::lua::value<std::string>(L, 5);
optimization = ghoul::lua::value<std::string>(L, 5, ghoul::lua::PopValue::No);
}
// Later functions expect the value to be at the last position on the stack
@@ -349,7 +337,7 @@ int property_setValue(lua_State* L) {
}
if (!easingMethodName.empty()) {
bool correctName = ghoul::isValidEasingFunctionName(easingMethodName.c_str());
bool correctName = ghoul::isValidEasingFunctionName(easingMethodName);
if (!correctName) {
LWARNINGC(
"property_setValue",
@@ -357,7 +345,7 @@ int property_setValue(lua_State* L) {
);
}
else {
easingMethod = ghoul::easingFunctionFromName(easingMethodName.c_str());
easingMethod = ghoul::easingFunctionFromName(easingMethodName);
}
}
@@ -395,8 +383,7 @@ int property_setValue(lua_State* L) {
"property_setValue",
fmt::format(
"{}: Property with URI '{}' was not found",
errorLocation(L),
uriOrRegex
ghoul::lua::errorLocation(L), uriOrRegex
)
);
return 0;
@@ -414,8 +401,7 @@ int property_setValue(lua_State* L) {
"lua::property_setGroup",
fmt::format(
"{}: Unexpected optimization '{}'",
errorLocation(L),
optimization
ghoul::lua::errorLocation(L), optimization
)
);
}
@@ -442,14 +428,9 @@ int property_setValueSingle(lua_State* L) {
*/
int property_hasProperty(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::property_hasProperty");
const std::string uri = ghoul::lua::value<std::string>(L);
std::string uri = ghoul::lua::value<std::string>(
L,
1,
ghoul::lua::PopValue::Yes
);
openspace::properties::Property* prop = property(uri);
properties::Property* prop = property(uri);
ghoul::lua::push(L, prop != nullptr);
return 1;
}
@@ -462,44 +443,33 @@ int property_hasProperty(lua_State* L) {
*/
int property_getValue(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::property_getValue");
const std::string uri = ghoul::lua::value<std::string>(L);
std::string uri = ghoul::lua::value<std::string>(
L,
1,
ghoul::lua::PopValue::Yes
);
openspace::properties::Property* prop = property(uri);
properties::Property* prop = property(uri);
if (!prop) {
LERRORC(
"property_getValue",
fmt::format(
"{}: Property with URI '{}' was not found",
ghoul::lua::errorLocation(L),
uri
ghoul::lua::errorLocation(L), uri
)
);
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
else {
prop->getLuaValue(L);
}
ghoul_assert(lua_gettop(L) == 1, "Incorrect number of items left on stack");
return 1;
}
/**
* \ingroup LuaScripts
* getProperty
* Returns a list of property identifiers that match the passed regular expression
*/
* \ingroup LuaScripts
* getProperty
* Returns a list of property identifiers that match the passed regular expression
*/
int property_getProperty(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::property_getProperty");
std::string regex = ghoul::lua::value<std::string>(L, 1);
lua_pop(L, 1);
std::string regex = ghoul::lua::value<std::string>(L);
std::string groupName;
if (doesUriContainGroupTag(regex, groupName)) {
@@ -509,8 +479,8 @@ int property_getProperty(lua_State* L) {
// Extract the property and node name to be searched for from regex
bool isLiteral = false;
std::string propertyName = "";
std::string nodeName = "";
std::string propertyName;
std::string nodeName;
size_t wildPos = regex.find_first_of("*");
if (wildPos != std::string::npos) {
nodeName = regex.substr(0, wildPos);
@@ -521,8 +491,8 @@ int property_getProperty(lua_State* L) {
LERRORC(
"property_getProperty",
fmt::format(
"Malformed regular expression: '{}': "
"Empty both before and after '*'", regex
"Malformed regular expression: '{}': Empty both before and after '*'",
regex
)
);
return 0;
@@ -574,10 +544,7 @@ int property_getProperty(lua_State* L) {
// Check tag
if (!groupName.empty()) {
properties::PropertyOwner* matchingTaggedOwner =
findPropertyOwnerWithMatchingGroupTag(
prop,
groupName
);
findPropertyOwnerWithMatchingGroupTag(prop, groupName);
if (!matchingTaggedOwner) {
continue;
}
@@ -594,10 +561,7 @@ int property_getProperty(lua_State* L) {
// Check tag
if (!groupName.empty()) {
properties::PropertyOwner* matchingTaggedOwner =
findPropertyOwnerWithMatchingGroupTag(
prop,
groupName
);
findPropertyOwnerWithMatchingGroupTag(prop, groupName);
if (!matchingTaggedOwner) {
continue;
}
@@ -618,35 +582,24 @@ int property_getProperty(lua_State* L) {
lua_newtable(L);
int number = 1;
for (const std::string& s : res) {
lua_pushstring(L, s.c_str());
ghoul::lua::push(L, s);
lua_rawseti(L, -2, number);
++number;
}
return 1;
}
int loadScene(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::loadScene");
std::string sceneFile = ghoul::lua::value<std::string>(L);
const std::string& sceneFile = ghoul::lua::value<std::string>(L, 1);
global::openSpaceEngine->scheduleLoadSingleAsset(sceneFile);
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
global::openSpaceEngine->scheduleLoadSingleAsset(std::move(sceneFile));
return 0;
}
int addSceneGraphNode(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::addSceneGraphNode");
ghoul::Dictionary d;
try {
ghoul::lua::luaDictionaryFromState(L, d);
}
catch (const ghoul::lua::LuaFormatException& e) {
LERRORC("addSceneGraphNode", e.what());
return ghoul::lua::luaError(L, "Error loading dictionary from lua state");
}
const ghoul::Dictionary d = ghoul::lua::value<ghoul::Dictionary>(L);
try {
SceneGraphNode* node = global::renderEngine->scene()->loadNode(d);
@@ -658,7 +611,7 @@ int addSceneGraphNode(lua_State* L) {
global::renderEngine->scene()->initializeNode(node);
}
catch (const documentation::SpecificationError& e) {
std::string cat =
std::string cat =
d.hasValue<std::string>("Identifier") ?
d.value<std::string>("Identifier") :
"Scene";
@@ -675,16 +628,12 @@ int addSceneGraphNode(lua_State* L) {
fmt::format("Error loading scene graph node: {}", e.what())
);
}
lua_settop(L, 0);
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
int removeSceneGraphNode(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::removeSceneGraphNode");
std::string name = ghoul::lua::value<std::string>(L, 1, ghoul::lua::PopValue::Yes);
const std::string name = ghoul::lua::value<std::string>(L);
SceneGraphNode* foundNode = sceneGraphNode(name);
if (!foundNode) {
@@ -733,23 +682,20 @@ int removeSceneGraphNode(lua_State* L) {
};
removeNode(foundNode);
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
int removeSceneGraphNodesFromRegex(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::removeSceneGraphNodesFromRegex");
std::string name = ghoul::lua::value<std::string>(L, 1, ghoul::lua::PopValue::Yes);
const std::string name = ghoul::lua::value<std::string>(L);
const std::vector<SceneGraphNode*>& nodes =
global::renderEngine->scene()->allSceneGraphNodes();
// Extract the property and node name to be searched for from name
bool isLiteral = false;
std::string propertyName = "";
std::string nodeName = "";
std::string propertyName;
std::string nodeName;
size_t wildPos = name.find_first_of("*");
if (wildPos != std::string::npos) {
nodeName = name.substr(0, wildPos);
@@ -760,8 +706,8 @@ int removeSceneGraphNodesFromRegex(lua_State* L) {
LERRORC(
"removeSceneGraphNodesFromRegex",
fmt::format(
"Malformed regular expression: '{}': "
"Empty both before and after '*'", name
"Malformed regular expression: '{}': Empty both before and after '*'",
name
)
);
return 0;
@@ -827,8 +773,7 @@ int removeSceneGraphNodesFromRegex(lua_State* L) {
SceneGraphNode* parent = node->parent();
if (!parent) {
LERRORC(
"removeSceneGraphNodesFromRegex",
fmt::format("Cannot remove root node")
"removeSceneGraphNodesFromRegex", fmt::format("Cannot remove root node")
);
}
else {
@@ -848,8 +793,7 @@ int removeSceneGraphNodesFromRegex(lua_State* L) {
std::function<void(SceneGraphNode*, std::vector<SceneGraphNode*>&)> markNode =
[&markNode](SceneGraphNode* node, std::vector<SceneGraphNode*>& marked)
{
std::vector<SceneGraphNode*> children = node->children();
for (SceneGraphNode* child : children) {
for (SceneGraphNode* child : node->children()) {
markNode(child, marked);
}
@@ -899,48 +843,33 @@ int removeSceneGraphNodesFromRegex(lua_State* L) {
removeNode(markedList[0]);
}
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
int hasSceneGraphNode(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::hasSceneGraphNode");
const std::string nodeName = ghoul::lua::value<std::string>(L);
std::string nodeName = ghoul::lua::value<std::string>(
L,
1,
ghoul::lua::PopValue::Yes
);
SceneGraphNode* node = global::renderEngine->scene()->sceneGraphNode(nodeName);
ghoul::lua::push(L, node != nullptr);
ghoul_assert(lua_gettop(L) == 1, "Incorrect number of items left on stack");
return 1;
}
int addInterestingTime(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::addInterestingTime");
std::string name = ghoul::lua::value<std::string>(L, 1, ghoul::lua::PopValue::No);
std::string time = ghoul::lua::value<std::string>(L, 2, ghoul::lua::PopValue::No);
lua_pop(L, 2);
auto [name, time] = ghoul::lua::values<std::string, std::string>(L);
global::renderEngine->scene()->addInterestingTime(
{ std::move(name), std::move(time) }
);
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
int worldPosition(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::worldPosition");
const std::string identifier = ghoul::lua::value<std::string>(L);
std::string identifier = ghoul::lua::value<std::string>(L, 1, ghoul::lua::PopValue::Yes);
SceneGraphNode* node = sceneGraphNode(identifier);
if (!node) {
return ghoul::lua::luaError(
L,
@@ -949,18 +878,15 @@ int worldPosition(lua_State* L) {
}
glm::dvec3 pos = node->worldPosition();
ghoul::lua::push(L, pos);
ghoul_assert(lua_gettop(L) == 1, "Incorrect number of items left on stack");
ghoul::lua::push(L, std::move(pos));
return 1;
}
int worldRotation(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::worldRotation");
std::string identifier = ghoul::lua::value<std::string>(L);
std::string identifier = ghoul::lua::value<std::string>(L, 1, ghoul::lua::PopValue::Yes);
SceneGraphNode* node = sceneGraphNode(identifier);
if (!node) {
return ghoul::lua::luaError(
L,
@@ -969,9 +895,7 @@ int worldRotation(lua_State* L) {
}
glm::dmat3 rot = node->worldRotationMatrix();
ghoul::lua::push(L, rot);
ghoul_assert(lua_gettop(L) == 1, "Incorrect number of items left on stack");
ghoul::lua::push(L, std::move(rot));
return 1;
}
+35 -86
View File
@@ -35,8 +35,6 @@ int printInternal(ghoul::logging::LogLevel level, lua_State* L) {
log(level, "print", ghoul::lua::luaValueToString(L, i));
}
lua_pop(L, nArguments);
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
@@ -114,16 +112,9 @@ int printFatal(lua_State* L) {
*/
int absolutePath(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::absolutePath");
const std::string& path = ghoul::lua::value<std::string>(
L,
1,
ghoul::lua::PopValue::Yes
);
const std::string path = ghoul::lua::value<std::string>(L);
ghoul::lua::push(L, absPath(path).string());
ghoul_assert(lua_gettop(L) == 1, "Incorrect number of items left on stack");
return 1;
}
@@ -135,18 +126,13 @@ int absolutePath(lua_State* L) {
*/
int setPathToken(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::setPathToken");
std::string pathToken = ghoul::lua::value<std::string>(L, 1);
std::string path = ghoul::lua::value<std::string>(L, 2);
auto [pathToken, path] = ghoul::lua::values<std::string, std::string>(L);
FileSys.registerPathToken(
std::move(pathToken),
std::move(path),
ghoul::filesystem::FileSystem::Override::Yes
);
lua_pop(L, 2);
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
@@ -157,17 +143,10 @@ int setPathToken(lua_State* L) {
*/
int fileExists(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::fileExists");
std::string file = ghoul::lua::value<std::string>(L);
const std::string& file = ghoul::lua::value<std::string>(
L,
1,
ghoul::lua::PopValue::Yes
);
const bool e = std::filesystem::is_regular_file(absPath(file));
const bool e = std::filesystem::is_regular_file(absPath(std::move(file)));
ghoul::lua::push(L, e);
ghoul_assert(lua_gettop(L) == 1, "Incorrect number of items left on stack");
return 1;
}
@@ -178,15 +157,11 @@ int fileExists(lua_State* L) {
*/
int readFile(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::readFile");
const std::string file = ghoul::lua::value<std::string>(L);
const std::string& file = ghoul::lua::value<std::string>(
L,
1,
ghoul::lua::PopValue::Yes
);
std::filesystem::path p = absPath(file);
if (!std::filesystem::is_regular_file(p)) {
return ghoul::lua::luaError(L, fmt::format("Could not open file {}", file));
return ghoul::lua::luaError(L, fmt::format("Could not open file '{}'", file));
}
std::ifstream f(p);
@@ -204,26 +179,19 @@ int readFile(lua_State* L) {
*/
int directoryExists(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::directoryExists");
std::string file = ghoul::lua::value<std::string>(L);
const std::string& file = ghoul::lua::value<std::string>(
L,
1,
ghoul::lua::PopValue::Yes
);
const bool e = std::filesystem::is_directory(absPath(file));
const bool e = std::filesystem::is_directory(absPath(std::move(file)));
ghoul::lua::push(L, e);
ghoul_assert(lua_gettop(L) == 1, "Incorrect number of items left on stack");
return 1;
}
int walkCommon(lua_State* L, std::function<bool(const std::filesystem::path&)> filter) {
int nArguments = ghoul::lua::checkArgumentsAndThrow(L, { 1, 3 }, "lua::walkCommon");
const std::string path = ghoul::lua::value<std::string>(L, 1);
const bool recursive = nArguments >= 2 ? ghoul::lua::value<bool>(L, 2) : false;
const bool sorted = nArguments == 3 ? ghoul::lua::value<bool>(L, 3) : false;
ghoul::lua::checkArgumentsAndThrow(L, { 1, 3 }, "lua::walkCommon");
auto [path, recursive, sorted] =
ghoul::lua::values<std::string, std::optional<bool>, std::optional<bool>>(L);
recursive = recursive.value_or(false);
sorted = sorted.value_or(false);
namespace fs = std::filesystem;
std::vector<fs::directory_entry> result;
@@ -242,16 +210,14 @@ int walkCommon(lua_State* L, std::function<bool(const std::filesystem::path&)> f
}
}
}
if (sorted) {
std::sort(result.begin(), result.end());
}
}
if (sorted) {
std::sort(result.begin(), result.end());
}
lua_newtable(L);
for (int i = 0; i < static_cast<int>(result.size()); ++i) {
lua_pushstring(L, result[i].path().string().c_str());
ghoul::lua::push(L, result[i].path().string());
lua_rawseti(L, -2, i + 1);
}
return 1;
@@ -289,14 +255,14 @@ int walkDirectoryFiles(lua_State* L) {
}
/**
* \ingroup LuaScripts
* walkDirectory(string, bool, bool):
* Walks a directory and returns the subfolders of the directory as absolute paths. The
* first argument is the path of the directory that should be walked, the second argument
* determines if the walk is recursive and will continue in contained directories. The
* default value for this parameter is "false". The third argument determines whether the
* table that is returned is sorted. The default value for this parameter is "false".
*/
* \ingroup LuaScripts
* walkDirectory(string, bool, bool):
* Walks a directory and returns the subfolders of the directory as absolute paths. The
* first argument is the path of the directory that should be walked, the second argument
* determines if the walk is recursive and will continue in contained directories. The
* default value for this parameter is "false". The third argument determines whether the
* table that is returned is sorted. The default value for this parameter is "false".
*/
int walkDirectoryFolder(lua_State* L) {
namespace fs = std::filesystem;
return walkCommon(L, [](const fs::path& p) { return fs::is_directory(p); });
@@ -311,13 +277,10 @@ int walkDirectoryFolder(lua_State* L) {
*/
int directoryForPath(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::directoryForPath");
std::string file = ghoul::lua::value<std::string>(L);
std::string file = ghoul::lua::value<std::string>(L, 1, ghoul::lua::PopValue::Yes);
std::string path = std::filesystem::path(std::move(file)).parent_path().string();
ghoul::lua::push(L, path);
ghoul_assert(lua_gettop(L) == 1, "Incorrect number of items left on stack");
ghoul::lua::push(L, std::move(path));
return 1;
}
@@ -330,33 +293,19 @@ int directoryForPath(lua_State* L) {
* is finished.
*/
int unzipFile(lua_State* L) {
const int nArguments = ghoul::lua::checkArgumentsAndThrow(
L,
{ 2, 3 },
"lua::unzipFile"
);
ghoul::lua::checkArgumentsAndThrow(L, { 2, 3 }, "lua::unzipFile");
auto [source, dest, deleteSource] =
ghoul::lua::values<std::string, std::string, std::optional<bool>>(L);
source = absPath(source).string();
dest = absPath(dest).string();
deleteSource = deleteSource.value_or(false);
std::filesystem::path source = absPath(
ghoul::lua::value<std::string>(L, 1, ghoul::lua::PopValue::No)
);
std::filesystem::path dest = absPath(
ghoul::lua::value<std::string>(L, 2, ghoul::lua::PopValue::No)
);
bool deleteSource = false;
if (nArguments == 3) {
deleteSource = ghoul::lua::value<bool>(L, 3, ghoul::lua::PopValue::No);
}
auto onExtractEntry = [](const char*, void*) { return 0; };
int arg = 2;
zip_extract(source.string().c_str(), dest.string().c_str(), onExtractEntry, &arg);
zip_extract(source.c_str(), dest.c_str(), [](const char*, void*) { return 0; }, &arg);
if (deleteSource && std::filesystem::is_regular_file(source)) {
std::filesystem::remove(source);
}
lua_settop(L, 0);
return 0;
}
@@ -372,7 +321,7 @@ int saveLastChangeToProfile(lua_State* L) {
std::string actualLastLine;
std::string lastLine;
std::string line;
//add check for log file
// add check for log file
if (!logfile.good()) {
ghoul::lua::push(L, fmt::format("Could not open scriptlog {}", logFilePath));
printInternal(ghoul::logging::LogLevel::Error, L);
+7 -41
View File
@@ -28,12 +28,8 @@ namespace openspace::luascriptfunctions {
int loadFile(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::loadFile");
const std::string& fileName = ghoul::lua::value<std::string>(L);
const std::string& fileName = ghoul::lua::value<std::string>(
L,
1,
ghoul::lua::PopValue::Yes
);
if (fileName.empty()) {
return ghoul::lua::luaError(L, "filepath string is empty");
}
@@ -56,78 +52,48 @@ int loadFile(lua_State* L) {
}
global::scriptScheduler->loadScripts(scripts);
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
int loadScheduledScript(lua_State* L) {
int nArguments = ghoul::lua::checkArgumentsAndThrow(
L,
{ 2, 4 },
"lua::loadScheduledScript"
);
ghoul::lua::checkArgumentsAndThrow(L, { 2, 4 }, "lua::loadScheduledScript");
auto [time, forwardScript, backwardScript, universalScript] = ghoul::lua::values<
std::string, std::string, std::optional<std::string>, std::optional<std::string>
>(L);
scripting::ScriptScheduler::ScheduledScript script;
std::string time = ghoul::lua::value<std::string>(L, 1);
script.time = Time::convertTime(time);
std::string forwardScript = ghoul::lua::value<std::string>(L, 2);
script.forwardScript = std::move(forwardScript);
script.backwardScript = backwardScript.value_or(script.backwardScript);
script.universalScript = universalScript.value_or(script.universalScript);
if (nArguments == 3) {
std::string backwardScript = ghoul::lua::value<std::string>(L, 3);
script.backwardScript = std::move(backwardScript);
}
else if (nArguments == 4) {
std::string backwardScript = ghoul::lua::value<std::string>(L, 3);
script.backwardScript = std::move(backwardScript);
std::string universalScript = ghoul::lua::value<std::string>(L, 4);
script.universalScript = std::move(universalScript);
}
std::vector<scripting::ScriptScheduler::ScheduledScript> scripts;
scripts.push_back(std::move(script));
global::scriptScheduler->loadScripts(scripts);
lua_settop(L, 0);
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
int setModeApplicationTime(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::setModeApplicationTime");
global::scriptScheduler->setModeApplicationTime();
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
int setModeRecordedTime(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::setModeRecordedTime");
global::scriptScheduler->setModeRecordedTime();
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
int setModeSimulationTime(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::setModeSimulationTime");
global::scriptScheduler->setModeSimulationTime();
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
int clear(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::clear");
global::scriptScheduler->clearSchedule();
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
+1 -3
View File
@@ -50,9 +50,7 @@ bool lineSphereIntersection(glm::dvec3 p1, glm::dvec3 p2, glm::dvec3 center,
// Intersection
else {
// Only care about the first intersection point if we have two
const double t = static_cast<double>(
(-b - std::sqrt(intersectionTest)) / (2.0 * a)
);
const double t = (-b - std::sqrt(intersectionTest)) / (2.0 * a);
// Check if utside of line segment between p1 and p2
if (t <= 0 || t >= 1.0) {
+3 -5
View File
@@ -406,21 +406,19 @@ bool HttpFileDownload::initDownload() {
char buffer[255];
LERROR(fmt::format(
"Cannot open file '{}': {}",
std::string(_destination),
_destination,
std::string(strerror_r(errno, buffer, sizeof(buffer)))
));
return false;
#else
LERROR(fmt::format(
"Cannot open file '{}': {}",
std::string(_destination),
std::string(strerror(errno))
"Cannot open file '{}': {}", _destination, std::string(strerror(errno))
));
return false;
#endif
}
LERROR(fmt::format("Cannot open file {}", std::string(_destination)));
LERROR(fmt::format("Cannot open file {}", _destination));
return false;
#endif
}
+4 -4
View File
@@ -231,7 +231,7 @@ SpiceManager::KernelHandle SpiceManager::loadKernel(std::string filePath) {
// kernels
std::filesystem::path currentDirectory = std::filesystem::current_path();
std::filesystem::path p = std::filesystem::path(path).parent_path();
std::filesystem::path p = path.parent_path();
std::filesystem::current_path(p);
LINFO(fmt::format("Loading SPICE kernel {}", path));
@@ -245,7 +245,7 @@ SpiceManager::KernelHandle SpiceManager::loadKernel(std::string filePath) {
throwSpiceError("Kernel loading");
}
std::filesystem::path fileExtension = std::filesystem::path(path).extension();
std::filesystem::path fileExtension = path.extension();
if (fileExtension == ".bc" || fileExtension == ".BC") {
findCkCoverage(path.string()); // binary ck kernel
}
@@ -1362,14 +1362,14 @@ scripting::LuaLibrary SpiceManager::luaLibrary() {
"getSpkCoverage",
&luascriptfunctions::spkCoverage,
{},
"{string [, printValues]}",
"string",
"Returns a list of SPK coverage intervals for the target."
},
{
"getCkCoverage",
&luascriptfunctions::ckCoverage,
{},
"{string [, printValues]}",
"string",
"Returns a list of CK coverage intervals for the target."
},
{
+38 -159
View File
@@ -38,20 +38,8 @@ namespace openspace::luascriptfunctions {
int loadKernel(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::loadKernel");
std::string argument = ghoul::lua::value<std::string>(L);
bool isString = (lua_isstring(L, 1) == 1);
if (!isString) {
LERROR(fmt::format(
"{}: Expected argument of type 'string'", ghoul::lua::errorLocation(L)
));
return 0;
}
std::string argument = ghoul::lua::value<std::string>(
L,
1,
ghoul::lua::PopValue::Yes
);
if (!std::filesystem::is_regular_file(argument)) {
return ghoul::lua::luaError(
L,
@@ -59,10 +47,7 @@ int loadKernel(lua_State* L) {
);
}
unsigned int result = SpiceManager::ref().loadKernel(argument);
lua_pushnumber(L, result);
ghoul_assert(lua_gettop(L) == 1, "Incorrect number of items left on stack");
ghoul::lua::push(L, result);
return 1;
}
@@ -72,37 +57,16 @@ int loadKernel(lua_State* L) {
* automatically resolved.
*/
int unloadKernel(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::loadKernel");
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::unloadKernel");
std::variant<std::string, unsigned int> argument =
ghoul::lua::value<std::variant<std::string, unsigned int>>(L);
bool isString = (lua_isstring(L, 1) == 1);
bool isNumber = (lua_isnumber(L, 1) == 1);
if (!isString && !isNumber) {
LERRORC(
"loadKernel",
fmt::format(
"{}: Expected argument of type 'string' or 'number'",
ghoul::lua::errorLocation(L)
)
);
lua_settop(L, 0);
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
if (std::holds_alternative<std::string>(argument)) {
SpiceManager::ref().unloadKernel(std::get<std::string>(argument));
}
if (isString) {
std::string argument = ghoul::lua::value<std::string>(L, 1);
SpiceManager::ref().unloadKernel(argument);
else {
SpiceManager::ref().unloadKernel(std::get<unsigned int>(argument));
}
if (isNumber) {
unsigned int argument = ghoul::lua::value<unsigned int>(L, 1);
SpiceManager::ref().unloadKernel(argument);
}
lua_settop(L, 0);
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
@@ -111,13 +75,9 @@ int unloadKernel(lua_State* L) {
* Returns the list of bodies loaded into the spicemanager
*/
int spiceBodies(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, { 1,2 }, "lua::getSpiceBodies");
bool isBool = (lua_isboolean(L, 1) == 1);
const bool buildInBodies = isBool ? ghoul::lua::value<bool>(L, 1) : false;
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::spiceBodies");
const bool buildInBodies = ghoul::lua::value<bool>(L);
isBool = (lua_isboolean(L, 2) == 1);
bool printValues = isBool ? ghoul::lua::value<bool>(L, 2) : false;
lua_settop(L, 0);
std::vector<std::pair<int, std::string>> bodies = SpiceManager::ref().spiceBodies(
buildInBodies
);
@@ -132,35 +92,20 @@ int spiceBodies(lua_State* L) {
lua_rawset(L, -3);
lua_rawseti(L, -2, number);
++number;
if (printValues) {
LINFO(fmt::format("Body id '{}' and name: {}", body.first, body.second));
}
}
return 1;
}
//internal function for getSpk and getCk coverages
// internal function for getSpk and getCk coverages
void buildLuaCoverageStack(lua_State* L,
const std::vector<std::pair<double, double>>& coverage,
bool printValues)
const std::vector<std::pair<double, double>>& coverage)
{
lua_settop(L, 0);
lua_newtable(L);
int number = 1;
for (const std::pair<double, double>& window : coverage) {
std::string start = SpiceManager::ref().dateFromEphemerisTime(window.first);
std::string end = SpiceManager::ref().dateFromEphemerisTime(window.second);
if (printValues) {
LINFO(fmt::format(
"Coverage start {} and end: {}",
SpiceManager::ref().dateFromEphemerisTime(window.first),
SpiceManager::ref().dateFromEphemerisTime(window.second)
));
}
lua_newtable(L);
ghoul::lua::push(L, 1, start);
lua_rawset(L, -3);
@@ -172,97 +117,45 @@ void buildLuaCoverageStack(lua_State* L,
}
/**
* getSpkCoverage({string, bool(optional)}):
* spkCoverage(string):
* Returns the spk coverage for given body
*/
int spkCoverage(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, { 1, 2 }, "lua::getSpkCoverage");
const bool isString = (lua_isstring(L, 1) == 1);
const bool isBool = (lua_isboolean(L, 2) == 1);
if (!isString) {
LERRORC(
"getSpkCoverage",
fmt::format(
"{}: Expected argument of type 'string'",
ghoul::lua::errorLocation(L)
)
);
lua_settop(L, 0);
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
std::string argument = ghoul::lua::value<std::string>(L, 1);
bool printValues = isBool ? ghoul::lua::value<bool>(L, 2) : false;
buildLuaCoverageStack(L, SpiceManager::ref().spkCoverage(argument), printValues);
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::spkCoverage");
std::string argument = ghoul::lua::value<std::string>(L);
buildLuaCoverageStack(L, SpiceManager::ref().spkCoverage(argument));
return 1;
}
/**
* getCkCoverage({string, bool(optional)}):
* ckCoverage(string):
* Returns the spk coverage for given body
*/
int ckCoverage(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, { 1, 2 }, "lua::getCkCoverage");
const bool isString = (lua_isstring(L, 1) == 1);
const bool isBool = (lua_isboolean(L, 2) == 1);
if (!isString) {
LERRORC(
"getCkCoverage",
fmt::format(
"{}: Expected argument of type 'string'",
ghoul::lua::errorLocation(L)
)
);
lua_settop(L, 0);
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
std::string argument = ghoul::lua::value<std::string>(L, 1);
bool printValues = isBool ? ghoul::lua::value<bool>(L, 2) : false;
buildLuaCoverageStack(L, SpiceManager::ref().ckCoverage(argument), printValues);
ghoul::lua::checkArgumentsAndThrow(L, { 1, 2 }, "lua::ckCoverage");
std::string argument = ghoul::lua::value<std::string>(L);
buildLuaCoverageStack(L, SpiceManager::ref().ckCoverage(argument));
return 1;
}
/**
* rotationMatrix({string, string, string}):
* Returns the rotationMatrix for a given body in a frame of reference
* at a specific time.
* Returns the rotationMatrix for a given body in a frame of reference at a specific time
*/
int rotationMatrix(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 3, "lua::rotationMatrix");
auto [body, frame, date] =
ghoul::lua::values<std::string, std::string, std::string>(L);
const bool isString = (lua_isstring(L, 1) == 1) &&
(lua_isstring(L, 2) == 1) && (lua_isstring(L, 3) == 1);
if (!isString) {
LERRORC(
"rotationMatrix",
fmt::format(
"{}: Expected argument of type 'string' for all three agruments",
ghoul::lua::errorLocation(L)
)
);
lua_settop(L, 0);
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
std::string body = ghoul::lua::value<std::string>(L, 1);
std::string frame = ghoul::lua::value<std::string>(L, 2);
std::string date = ghoul::lua::value<std::string>(L, 3);
const double ephemerisTime = SpiceManager::ref().ephemerisTimeFromDate(date);
glm::dmat3 rotationMatrix = SpiceManager::ref().frameTransformationMatrix
(body, frame, ephemerisTime);
glm::dmat3 rotationMatrix = SpiceManager::ref().frameTransformationMatrix(
body,
frame,
ephemerisTime
);
ghoul::lua::push(L, 1, rotationMatrix);
return 1;
}
@@ -273,31 +166,17 @@ int rotationMatrix(lua_State* L) {
*/
int position(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 4, "lua::position");
auto [target, observer, frame, date] =
ghoul::lua::values<std::string, std::string, std::string, std::string>(L);
const bool isString = (lua_isstring(L, 1) == 1) &&
(lua_isstring(L, 2) == 1) &&
(lua_isstring(L, 3) == 1) &&
(lua_isstring(L, 4) == 1);
if (!isString) {
LERRORC(
"position",
fmt::format(
"{}: Expected argument of type 'string' for all four agruments",
ghoul::lua::errorLocation(L)
)
);
lua_settop(L, 0);
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
std::string target = ghoul::lua::value<std::string>(L, 1);
std::string observer = ghoul::lua::value<std::string>(L, 2);
std::string frame = ghoul::lua::value<std::string>(L, 3);
std::string date = ghoul::lua::value<std::string>(L, 4);
const double ephemerisTime = SpiceManager::ref().ephemerisTimeFromDate(date);
glm::dvec3 postion = SpiceManager::ref().targetPosition(target, observer, frame, {}, ephemerisTime);
glm::dvec3 postion = SpiceManager::ref().targetPosition(
target,
observer,
frame,
{},
ephemerisTime
);
ghoul::lua::push(L, 1, postion);
return 1;

Some files were not shown because too many files have changed in this diff Show More