mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-02-27 15:29:26 -06:00
Merge branch 'master' into feature/skybrowser
This commit is contained in:
Submodule apps/OpenSpace/ext/sgct updated: 489c8f1820...5cd9a45cd1
@@ -25,7 +25,11 @@ local object = {
|
||||
ScaleFactor = 540.9,
|
||||
FadeInDistances = { 1000.0, 10000.0 }, -- Fade in value in the same unit as "Unit"
|
||||
BillboardMinMaxSize = { 0.0, 11.1 },
|
||||
EnablePixelSizeControl = true
|
||||
EnablePixelSizeControl = true,
|
||||
ColorMap = speck .. "viridis.cmap",
|
||||
ColorOption = { "redshift", "Tlookback", "distMpc" },
|
||||
ColorRange = { { 0.102, 7.085 }, { 1.4, 13.0 }, { 440.5, 8852.099609 } },
|
||||
UseColorMap = false
|
||||
},
|
||||
GUI = {
|
||||
Name = "Quasars",
|
||||
|
||||
@@ -3,7 +3,7 @@ local propertyHelper = asset.require("./property_helper")
|
||||
local toggle_native_ui = {
|
||||
Identifier = "os_default.toggle_native_ui",
|
||||
Name = "Show Native GUI",
|
||||
Command = propertyHelper.invert("Modules.ImGUI.Main.Enabled"),
|
||||
Command = propertyHelper.invert("Modules.ImGUI.Enabled"),
|
||||
Documentation = "Shows or hides the native UI",
|
||||
GuiPath = "/Native GUI",
|
||||
IsLocal = true,
|
||||
|
||||
@@ -114,7 +114,7 @@ protected:
|
||||
void setRenderBinFromOpacity();
|
||||
void registerUpdateRenderBinFromOpacity();
|
||||
|
||||
/// Returns the full opacity constructed from the _opactiy and _fade property values
|
||||
/// Returns the full opacity constructed from the _opacity and _fade property values
|
||||
float opacity() const;
|
||||
|
||||
double _boundingSphere = 0.0;
|
||||
|
||||
@@ -59,12 +59,12 @@ namespace {
|
||||
constexpr const char* ProgramObjectName = "RenderableBillboardsCloud";
|
||||
constexpr const char* RenderToPolygonProgram = "RenderableBillboardsCloud_Polygon";
|
||||
|
||||
constexpr const std::array<const char*, 20> UniformNames = {
|
||||
constexpr const std::array<const char*, 21> UniformNames = {
|
||||
"cameraViewProjectionMatrix", "modelMatrix", "cameraPosition", "cameraLookUp",
|
||||
"renderOption", "minBillboardSize", "maxBillboardSize",
|
||||
"correctionSizeEndDistance", "correctionSizeFactor", "color", "alphaValue",
|
||||
"scaleFactor", "up", "right", "fadeInValue", "screenSize", "spriteTexture",
|
||||
"hasColorMap", "enabledRectSizeControl", "hasDvarScaling"
|
||||
"hasColorMap", "useColorMap", "enabledRectSizeControl", "hasDvarScaling"
|
||||
};
|
||||
|
||||
enum RenderOption {
|
||||
@@ -85,6 +85,14 @@ namespace {
|
||||
"size of each point."
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo UseColorMapInfo = {
|
||||
"UseColorMap",
|
||||
"Use Color Map",
|
||||
"If this value is set to 'true', the provided color map is used (if one was "
|
||||
"provided in the configuration). If no color map was provided, changing this "
|
||||
"setting does not do anything."
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo ColorInfo = {
|
||||
"Color",
|
||||
"Color",
|
||||
@@ -253,6 +261,9 @@ namespace {
|
||||
// [[codegen::verbatim(ScaleFactorInfo.description)]]
|
||||
std::optional<float> scaleFactor;
|
||||
|
||||
// [[codegen::verbatim(UseColorMapInfo.description)]]
|
||||
std::optional<bool> useColorMap;
|
||||
|
||||
// [[codegen::verbatim(ColorMapInfo.description)]]
|
||||
std::optional<std::string> colorMap;
|
||||
|
||||
@@ -328,6 +339,7 @@ documentation::Documentation RenderableBillboardsCloud::Documentation() {
|
||||
RenderableBillboardsCloud::RenderableBillboardsCloud(const ghoul::Dictionary& dictionary)
|
||||
: Renderable(dictionary)
|
||||
, _scaleFactor(ScaleFactorInfo, 1.f, 0.f, 600.f)
|
||||
, _useColorMap(UseColorMapInfo, true)
|
||||
, _pointColor(ColorInfo, glm::vec3(1.f), glm::vec3(0.f), glm::vec3(1.f))
|
||||
, _spriteTexturePath(SpriteTextureInfo)
|
||||
, _textColor(TextColorInfo, glm::vec3(1.f), glm::vec3(0.f), glm::vec3(1.f))
|
||||
@@ -374,6 +386,8 @@ RenderableBillboardsCloud::RenderableBillboardsCloud(const ghoul::Dictionary& di
|
||||
}
|
||||
_hasSpeckFile = p.file.has_value();
|
||||
|
||||
_useColorMap = p.useColorMap.value_or(_useColorMap);
|
||||
|
||||
_drawElements = p.drawElements.value_or(_drawElements);
|
||||
_drawElements.onChange([&]() { _hasSpeckFile = !_hasSpeckFile; });
|
||||
addProperty(_drawElements);
|
||||
@@ -440,11 +454,10 @@ RenderableBillboardsCloud::RenderableBillboardsCloud(const ghoul::Dictionary& di
|
||||
|
||||
_isColorMapExact = p.exactColorMap.value_or(_isColorMapExact);
|
||||
}
|
||||
else {
|
||||
_pointColor = p.color;
|
||||
_pointColor.setViewOption(properties::Property::ViewOptions::Color);
|
||||
addProperty(_pointColor);
|
||||
}
|
||||
|
||||
_pointColor = p.color;
|
||||
_pointColor.setViewOption(properties::Property::ViewOptions::Color);
|
||||
addProperty(_pointColor);
|
||||
|
||||
addProperty(_opacity);
|
||||
|
||||
@@ -538,6 +551,9 @@ RenderableBillboardsCloud::RenderableBillboardsCloud(const ghoul::Dictionary& di
|
||||
});
|
||||
addProperty(_setRangeFromData);
|
||||
|
||||
_useColorMap.onChange([this]() { _dataIsDirty = true; });
|
||||
addProperty(_useColorMap);
|
||||
|
||||
_useLinearFiltering = p.useLinearFiltering.value_or(_useLinearFiltering);
|
||||
_useLinearFiltering.onChange([&]() { _dataIsDirty = true; });
|
||||
addProperty(_useLinearFiltering);
|
||||
@@ -713,6 +729,7 @@ void RenderableBillboardsCloud::renderBillboards(const RenderData& data,
|
||||
}
|
||||
_program->setUniform(_uniformCache.spriteTexture, textureUnit);
|
||||
_program->setUniform(_uniformCache.hasColormap, _hasColorMapFile);
|
||||
_program->setUniform(_uniformCache.useColormap, _useColorMap);
|
||||
|
||||
glBindVertexArray(_vao);
|
||||
glDrawArrays(GL_POINTS, 0, static_cast<GLsizei>(_dataset.entries.size()));
|
||||
@@ -972,7 +989,8 @@ std::vector<float> RenderableBillboardsCloud::createDataSlice() {
|
||||
}
|
||||
|
||||
// what datavar in use for the index color
|
||||
int colorMapInUse = _hasColorMapFile ? _dataset.index(_colorOptionString) : 0;
|
||||
int colorMapInUse =
|
||||
_hasColorMapFile ? _dataset.index(_colorOptionString) : 0;
|
||||
|
||||
// what datavar in use for the size scaling (if present)
|
||||
int sizeScalingInUse =
|
||||
@@ -1035,7 +1053,7 @@ std::vector<float> RenderableBillboardsCloud::createDataSlice() {
|
||||
const double r = glm::length(p);
|
||||
maxRadius = std::max(maxRadius, r);
|
||||
|
||||
if (_hasColorMapFile) {
|
||||
if (_hasColorMapFile && _useColorMap && !_colorMap.entries.empty()) {
|
||||
for (int j = 0; j < 4; ++j) {
|
||||
result.push_back(position[j]);
|
||||
}
|
||||
|
||||
@@ -98,6 +98,7 @@ private:
|
||||
GLuint _pTexture = 0;
|
||||
|
||||
properties::FloatProperty _scaleFactor;
|
||||
properties::BoolProperty _useColorMap;
|
||||
properties::Vec3Property _pointColor;
|
||||
properties::StringProperty _spriteTexturePath;
|
||||
properties::Vec3Property _textColor;
|
||||
@@ -128,7 +129,8 @@ private:
|
||||
cameraViewProjectionMatrix, modelMatrix, cameraPos, cameraLookup, renderOption,
|
||||
minBillboardSize, maxBillboardSize, correctionSizeEndDistance,
|
||||
correctionSizeFactor, color, alphaValue, scaleFactor, up, right, fadeInValue,
|
||||
screenSize, spriteTexture, hasColormap, enabledRectSizeControl, hasDvarScaling
|
||||
screenSize, spriteTexture, hasColormap, useColormap, enabledRectSizeControl,
|
||||
hasDvarScaling
|
||||
) _uniformCache;
|
||||
|
||||
std::shared_ptr<ghoul::fontrendering::Font> _font;
|
||||
|
||||
@@ -33,6 +33,7 @@ uniform float alphaValue;
|
||||
uniform vec3 color;
|
||||
uniform sampler2D spriteTexture;
|
||||
uniform bool hasColorMap;
|
||||
uniform bool useColorMap;
|
||||
uniform float fadeInValue;
|
||||
|
||||
Fragment getFragment() {
|
||||
@@ -47,7 +48,7 @@ Fragment getFragment() {
|
||||
|
||||
vec4 fullColor = textureColor;
|
||||
|
||||
if (hasColorMap) {
|
||||
if (hasColorMap && useColorMap) {
|
||||
fullColor *= gs_colorMap;
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
include(${OPENSPACE_CMAKE_EXT_DIR}/module_definition.cmake)
|
||||
|
||||
set(HEADER_FILES
|
||||
include/gui.h
|
||||
include/guiactioncomponent.h
|
||||
include/guicomponent.h
|
||||
include/guifilepathcomponent.h
|
||||
@@ -37,15 +36,14 @@ set(HEADER_FILES
|
||||
include/guimissioncomponent.h
|
||||
include/guiparallelcomponent.h
|
||||
include/guipropertycomponent.h
|
||||
include/guiscenecomponent.h
|
||||
include/guispacetimecomponent.h
|
||||
include/guiiswacomponent.h
|
||||
include/imgui_include.h
|
||||
include/renderproperties.h
|
||||
)
|
||||
source_group("Header Files" FILES ${HEADER_FILES})
|
||||
|
||||
set(SOURCE_FILES
|
||||
src/gui.cpp
|
||||
src/guiactioncomponent.cpp
|
||||
src/guicomponent.cpp
|
||||
src/guifilepathcomponent.cpp
|
||||
@@ -57,8 +55,8 @@ set(SOURCE_FILES
|
||||
src/guimissioncomponent.cpp
|
||||
src/guiparallelcomponent.cpp
|
||||
src/guipropertycomponent.cpp
|
||||
src/guiscenecomponent.cpp
|
||||
src/guispacetimecomponent.cpp
|
||||
src/guiiswacomponent.cpp
|
||||
src/renderproperties.cpp
|
||||
)
|
||||
source_group("Source Files" FILES ${SOURCE_FILES})
|
||||
|
||||
@@ -24,10 +24,11 @@
|
||||
|
||||
#include <modules/imgui/imguimodule.h>
|
||||
|
||||
#include <modules/imgui/include/imgui_include.h>
|
||||
#include <openspace/engine/globals.h>
|
||||
#include <openspace/engine/globalscallbacks.h>
|
||||
#include <openspace/engine/windowdelegate.h>
|
||||
#include <openspace/engine/moduleengine.h>
|
||||
#include <openspace/engine/windowdelegate.h>
|
||||
#include <openspace/interaction/sessionrecording.h>
|
||||
#include <openspace/navigation/navigationhandler.h>
|
||||
#include <openspace/network/parallelpeer.h>
|
||||
@@ -35,136 +36,183 @@
|
||||
#include <openspace/rendering/luaconsole.h>
|
||||
#include <openspace/rendering/renderengine.h>
|
||||
#include <openspace/scene/scene.h>
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <ghoul/misc/profiling.h>
|
||||
#include <openspace/scripting/scriptengine.h>
|
||||
#include <ghoul/filesystem/cachemanager.h>
|
||||
#include <ghoul/filesystem/filesystem.h>
|
||||
#include <ghoul/opengl/textureunit.h>
|
||||
|
||||
// #define SHOW_IMGUI_HELPERS
|
||||
|
||||
namespace {
|
||||
constexpr const char* _loggerCat = "GUI";
|
||||
constexpr const char* GuiFont = "${FONTS}/arimo/Arimo-Regular.ttf";
|
||||
constexpr const float FontSize = 14.f;
|
||||
|
||||
ImFont* captionFont = nullptr;
|
||||
|
||||
constexpr const std::array<const char*, 2> UniformNames = { "tex", "ortho" };
|
||||
|
||||
void addScreenSpaceRenderableLocal(std::string identifier, std::string texturePath) {
|
||||
if (!std::filesystem::is_regular_file(absPath(texturePath))) {
|
||||
LWARNING(fmt::format("Could not find image '{}'", texturePath));
|
||||
return;
|
||||
}
|
||||
|
||||
std::string script;
|
||||
if (identifier.empty()) {
|
||||
script = fmt::format(
|
||||
"openspace.addScreenSpaceRenderable({{\
|
||||
Type = 'ScreenSpaceImageLocal',\
|
||||
TexturePath = openspace.absPath('{}')\
|
||||
}});",
|
||||
texturePath
|
||||
);
|
||||
}
|
||||
else {
|
||||
script = fmt::format(
|
||||
"openspace.addScreenSpaceRenderable({{\
|
||||
Type = 'ScreenSpaceImageLocal',\
|
||||
TexturePath = openspace.absPath('{0}'),\
|
||||
Identifier = '{1}',\
|
||||
Name = '{1}'\
|
||||
}});",
|
||||
texturePath, identifier
|
||||
);
|
||||
}
|
||||
|
||||
openspace::global::scriptEngine->queueScript(
|
||||
script,
|
||||
openspace::scripting::ScriptEngine::RemoteScripting::Yes
|
||||
);
|
||||
}
|
||||
|
||||
void addScreenSpaceRenderableOnline(std::string identifier, std::string texturePath) {
|
||||
std::string script;
|
||||
if (identifier.empty()) {
|
||||
script = fmt::format(
|
||||
"openspace.addScreenSpaceRenderable({{\
|
||||
Type = 'ScreenSpaceImageOnline',\
|
||||
URL = '{}'\
|
||||
}});",
|
||||
texturePath
|
||||
);
|
||||
}
|
||||
else {
|
||||
script = fmt::format(
|
||||
"openspace.addScreenSpaceRenderable({{\
|
||||
Type = 'ScreenSpaceImageOnline',\
|
||||
URL = '{0}',\
|
||||
Identifier = '{1}',\
|
||||
Name = '{1}'\
|
||||
}});",
|
||||
texturePath,
|
||||
identifier
|
||||
);
|
||||
}
|
||||
|
||||
openspace::global::scriptEngine->queueScript(
|
||||
script,
|
||||
openspace::scripting::ScriptEngine::RemoteScripting::Yes
|
||||
);
|
||||
}
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo EnabledInfo = {
|
||||
"Enabled",
|
||||
"Is Enabled",
|
||||
"This setting determines whether this object will be visible or not."
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo CollapsedInfo = {
|
||||
"Collapsed",
|
||||
"Is Collapsed",
|
||||
"This setting determines whether this window is collapsed or not."
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo ShowHelpInfo = {
|
||||
"ShowHelpText",
|
||||
"Show tooltip help",
|
||||
"If this value is enabled these kinds of tooltips are shown for most properties "
|
||||
"explaining what impact they have on the visuals."
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo HelpTextDelayInfo = {
|
||||
"HelpTextDelay",
|
||||
"Tooltip Delay (in s)",
|
||||
"This value determines the delay in seconds after which the tooltip is shown."
|
||||
};
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
ImGUIModule::ImGUIModule() : OpenSpaceModule(Name) {
|
||||
addPropertySubOwner(gui);
|
||||
void CaptionText(const char* text) {
|
||||
ImGui::PushFont(captionFont);
|
||||
ImGui::Text("%s", text);
|
||||
ImGui::PopFont();
|
||||
}
|
||||
|
||||
global::callback::initialize->emplace_back([&]() {
|
||||
LDEBUGC("ImGUIModule", "Initializing GUI");
|
||||
gui.initialize();
|
||||
ImGUIModule::ImGUIModule()
|
||||
: OpenSpaceModule(Name)
|
||||
, _isEnabled(EnabledInfo, false)
|
||||
, _isCollapsed(CollapsedInfo, false)
|
||||
, _sceneProperty("Scene", "Scene", gui::GuiPropertyComponent::UseTreeLayout::Yes)
|
||||
, _property("Settings", "Settings")
|
||||
, _showHelpText(ShowHelpInfo, true)
|
||||
, _helpTextDelay(HelpTextDelayInfo, 1.f, 0.f, 10.f)
|
||||
{
|
||||
addProperty(_isEnabled);
|
||||
addProperty(_isCollapsed);
|
||||
|
||||
gui._globalProperty.setSource(
|
||||
[]() {
|
||||
std::vector<properties::PropertyOwner*> res = {
|
||||
global::navigationHandler,
|
||||
global::sessionRecording,
|
||||
global::timeManager,
|
||||
global::renderEngine,
|
||||
global::parallelPeer,
|
||||
global::luaConsole,
|
||||
global::dashboard
|
||||
};
|
||||
return res;
|
||||
}
|
||||
);
|
||||
for (gui::GuiComponent* comp : _components) {
|
||||
addPropertySubOwner(comp);
|
||||
}
|
||||
_spaceTime.setEnabled(true);
|
||||
|
||||
gui._screenSpaceProperty.setSource(
|
||||
[]() {
|
||||
return global::screenSpaceRootPropertyOwner->propertySubOwners();
|
||||
{
|
||||
auto showHelpTextFunc = [this]() {
|
||||
for (gui::GuiComponent* comp : _components) {
|
||||
comp->setShowHelpTooltip(_showHelpText);
|
||||
}
|
||||
);
|
||||
};
|
||||
showHelpTextFunc();
|
||||
_showHelpText.onChange(std::move(showHelpTextFunc));
|
||||
addProperty(_showHelpText);
|
||||
}
|
||||
|
||||
gui._moduleProperty.setSource(
|
||||
[]() {
|
||||
std::vector<properties::PropertyOwner*> v;
|
||||
v.push_back(global::moduleEngine);
|
||||
return v;
|
||||
{
|
||||
auto helpTextDelayFunc = [this]() {
|
||||
for (gui::GuiComponent* comp : _components) {
|
||||
comp->setShowHelpTooltipDelay(_helpTextDelay);
|
||||
}
|
||||
);
|
||||
|
||||
gui._sceneProperty.setSource(
|
||||
[]() {
|
||||
const Scene* scene = global::renderEngine->scene();
|
||||
const std::vector<SceneGraphNode*>& nodes = scene ?
|
||||
scene->allSceneGraphNodes() :
|
||||
std::vector<SceneGraphNode*>();
|
||||
|
||||
return std::vector<properties::PropertyOwner*>(
|
||||
nodes.begin(),
|
||||
nodes.end()
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
gui._featuredProperties.setSource(
|
||||
[]() {
|
||||
std::vector<SceneGraphNode*> nodes =
|
||||
global::renderEngine->scene()->allSceneGraphNodes();
|
||||
|
||||
nodes.erase(
|
||||
std::remove_if(
|
||||
nodes.begin(),
|
||||
nodes.end(),
|
||||
[](SceneGraphNode* n) {
|
||||
const std::vector<std::string>& tags = n->tags();
|
||||
const auto it = std::find(
|
||||
tags.begin(),
|
||||
tags.end(),
|
||||
"GUI.Interesting"
|
||||
);
|
||||
return it == tags.end();
|
||||
}
|
||||
),
|
||||
nodes.end()
|
||||
);
|
||||
return std::vector<properties::PropertyOwner*>(
|
||||
nodes.begin(),
|
||||
nodes.end()
|
||||
);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
global::callback::deinitialize->emplace_back([&]() {
|
||||
ZoneScopedN("ImGUI")
|
||||
|
||||
LDEBUGC("ImGui", "Deinitialize GUI");
|
||||
gui.deinitialize();
|
||||
});
|
||||
|
||||
global::callback::initializeGL->emplace_back([&]() {
|
||||
ZoneScopedN("ImGUI")
|
||||
|
||||
LDEBUGC("ImGui", "Initializing GUI OpenGL");
|
||||
gui.initializeGL();
|
||||
});
|
||||
|
||||
global::callback::deinitializeGL->emplace_back([&]() {
|
||||
ZoneScopedN("ImGUI")
|
||||
|
||||
LDEBUGC("ImGui", "Deinitialize GUI OpenGL");
|
||||
gui.deinitializeGL();
|
||||
});
|
||||
};
|
||||
helpTextDelayFunc();
|
||||
_helpTextDelay.onChange(std::move(helpTextDelayFunc));
|
||||
addProperty(_helpTextDelay);
|
||||
}
|
||||
|
||||
global::callback::draw2D->emplace_back([&]() {
|
||||
ZoneScopedN("ImGUI")
|
||||
|
||||
if (!_isEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
WindowDelegate& delegate = *global::windowDelegate;
|
||||
const bool showGui = delegate.hasGuiWindow() ? delegate.isGuiWindow() : true;
|
||||
if (delegate.isMaster() && showGui) {
|
||||
const glm::ivec2 windowSize = delegate.currentSubwindowSize();
|
||||
const glm::ivec2 resolution = delegate.currentDrawBufferResolution();
|
||||
|
||||
if (windowSize.x <= 0 || windowSize.y <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const glm::ivec2 resolution = delegate.currentDrawBufferResolution();
|
||||
const double dt = std::max(delegate.averageDeltaTime(), 0.0);
|
||||
// We don't do any collection of immediate mode user interface, so it
|
||||
// is fine to open and close a frame immediately
|
||||
gui.startFrame(
|
||||
renderFrame(
|
||||
static_cast<float>(dt),
|
||||
glm::vec2(windowSize),
|
||||
resolution / windowSize,
|
||||
_mousePosition,
|
||||
_mouseButtons
|
||||
);
|
||||
|
||||
gui.endFrame();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -172,13 +220,7 @@ ImGUIModule::ImGUIModule() : OpenSpaceModule(Name) {
|
||||
[&](Key key, KeyModifier mod, KeyAction action) -> bool {
|
||||
ZoneScopedN("ImGUI")
|
||||
|
||||
// A list of all the windows that can show up by themselves
|
||||
if (gui.isEnabled() ||gui._sceneProperty.isEnabled()) {
|
||||
return gui.keyCallback(key, mod, action);
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
return _isEnabled ? keyCallback(key, mod, action) : false;
|
||||
}
|
||||
);
|
||||
|
||||
@@ -186,13 +228,7 @@ ImGUIModule::ImGUIModule() : OpenSpaceModule(Name) {
|
||||
[&](unsigned int codepoint, KeyModifier modifier) -> bool {
|
||||
ZoneScopedN("ImGUI")
|
||||
|
||||
// A list of all the windows that can show up by themselves
|
||||
if (gui.isEnabled() || gui._sceneProperty.isEnabled()) {
|
||||
return gui.charCallback(codepoint, modifier);
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
return _isEnabled ? charCallback(codepoint, modifier) : false;
|
||||
}
|
||||
);
|
||||
|
||||
@@ -213,13 +249,7 @@ ImGUIModule::ImGUIModule() : OpenSpaceModule(Name) {
|
||||
_mouseButtons &= ~(1 << static_cast<int>(button));
|
||||
}
|
||||
|
||||
// A list of all the windows that can show up by themselves
|
||||
if (gui.isEnabled() || gui._sceneProperty.isEnabled()) {
|
||||
return gui.mouseButtonCallback(button, action);
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
return _isEnabled ? mouseButtonCallback(button, action) : false;
|
||||
}
|
||||
);
|
||||
|
||||
@@ -227,33 +257,575 @@ ImGUIModule::ImGUIModule() : OpenSpaceModule(Name) {
|
||||
[&](double, double posY) -> bool {
|
||||
ZoneScopedN("ImGUI")
|
||||
|
||||
// A list of all the windows that can show up by themselves
|
||||
if (gui.isEnabled() || gui._sceneProperty.isEnabled()) {
|
||||
return gui.mouseWheelCallback(posY);
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
return _isEnabled ? mouseWheelCallback(posY) : false;
|
||||
}
|
||||
);
|
||||
|
||||
global::callback::touchDetected->emplace_back(
|
||||
[&](TouchInput input) -> bool {
|
||||
return gui.touchDetectedCallback(input);
|
||||
return touchDetectedCallback(input);
|
||||
}
|
||||
);
|
||||
|
||||
global::callback::touchUpdated->emplace_back(
|
||||
[&](TouchInput input) -> bool {
|
||||
return gui.touchUpdatedCallback(input);
|
||||
return touchUpdatedCallback(input);
|
||||
}
|
||||
);
|
||||
|
||||
global::callback::touchExit->emplace_back(
|
||||
[&](TouchInput input) {
|
||||
gui.touchExitCallback(input);
|
||||
touchExitCallback(input);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
void ImGUIModule::internalInitialize(const ghoul::Dictionary&) {
|
||||
LDEBUGC("ImGUIModule", "Initializing GUI");
|
||||
|
||||
_sceneProperty.setPropertyOwnerFunction(
|
||||
[]() {
|
||||
const Scene* scene = global::renderEngine->scene();
|
||||
const std::vector<SceneGraphNode*>& nodes = scene ?
|
||||
scene->allSceneGraphNodes() :
|
||||
std::vector<SceneGraphNode*>();
|
||||
|
||||
return std::vector<properties::PropertyOwner*>(nodes.begin(), nodes.end());
|
||||
}
|
||||
);
|
||||
|
||||
_property.setPropertyOwners({
|
||||
global::screenSpaceRootPropertyOwner,
|
||||
global::moduleEngine,
|
||||
global::navigationHandler,
|
||||
global::sessionRecording,
|
||||
global::timeManager,
|
||||
global::renderEngine,
|
||||
global::parallelPeer,
|
||||
global::luaConsole,
|
||||
global::dashboard
|
||||
});
|
||||
}
|
||||
|
||||
void ImGUIModule::internalDeinitialize() {
|
||||
for (ImGuiContext* ctx : _contexts) {
|
||||
ImGui::DestroyContext(ctx);
|
||||
}
|
||||
|
||||
for (gui::GuiComponent* comp : _components) {
|
||||
comp->deinitialize();
|
||||
}
|
||||
}
|
||||
|
||||
void ImGUIModule::internalInitializeGL() {
|
||||
std::filesystem::path file = FileSys.cacheManager()->cachedFilename("imgui.ini", "");
|
||||
LDEBUG(fmt::format("Using {} as ImGUI cache location", file));
|
||||
|
||||
_iniFileBuffer.resize(file.string().size() + 1);
|
||||
|
||||
#ifdef WIN32
|
||||
strcpy_s(_iniFileBuffer.data(), file.string().size() + 1, file.string().c_str());
|
||||
#else
|
||||
strcpy(_iniFileBuffer.data(), file.c_str());
|
||||
#endif
|
||||
|
||||
int nWindows = global::windowDelegate->nWindows();
|
||||
_contexts.resize(nWindows);
|
||||
|
||||
for (int i = 0; i < nWindows; ++i) {
|
||||
_contexts[i] = ImGui::CreateContext();
|
||||
ImGui::SetCurrentContext(_contexts[i]);
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.IniFilename = _iniFileBuffer.data();
|
||||
io.DeltaTime = 1.f / 60.f;
|
||||
io.KeyMap[ImGuiKey_Tab] = static_cast<int>(Key::Tab);
|
||||
io.KeyMap[ImGuiKey_LeftArrow] = static_cast<int>(Key::Left);
|
||||
io.KeyMap[ImGuiKey_RightArrow] = static_cast<int>(Key::Right);
|
||||
io.KeyMap[ImGuiKey_UpArrow] = static_cast<int>(Key::Up);
|
||||
io.KeyMap[ImGuiKey_DownArrow] = static_cast<int>(Key::Down);
|
||||
io.KeyMap[ImGuiKey_Home] = static_cast<int>(Key::Home);
|
||||
io.KeyMap[ImGuiKey_End] = static_cast<int>(Key::End);
|
||||
io.KeyMap[ImGuiKey_Delete] = static_cast<int>(Key::Delete);
|
||||
io.KeyMap[ImGuiKey_Backspace] = static_cast<int>(Key::BackSpace);
|
||||
io.KeyMap[ImGuiKey_Enter] = static_cast<int>(Key::Enter);
|
||||
io.KeyMap[ImGuiKey_Escape] = static_cast<int>(Key::Escape);
|
||||
io.KeyMap[ImGuiKey_A] = static_cast<int>(Key::A);
|
||||
io.KeyMap[ImGuiKey_C] = static_cast<int>(Key::C);
|
||||
io.KeyMap[ImGuiKey_V] = static_cast<int>(Key::V);
|
||||
io.KeyMap[ImGuiKey_X] = static_cast<int>(Key::X);
|
||||
io.KeyMap[ImGuiKey_Y] = static_cast<int>(Key::Y);
|
||||
io.KeyMap[ImGuiKey_Z] = static_cast<int>(Key::Z);
|
||||
|
||||
io.Fonts->AddFontFromFileTTF(absPath(GuiFont).string().c_str(), FontSize);
|
||||
captionFont = io.Fonts->AddFontFromFileTTF(
|
||||
absPath(GuiFont).string().c_str(),
|
||||
FontSize * 1.5f
|
||||
);
|
||||
|
||||
ImGuiStyle& style = ImGui::GetStyle();
|
||||
style.WindowPadding = { 4.f, 4.f };
|
||||
style.WindowRounding = 0.f;
|
||||
style.FramePadding = { 3.f, 3.f };
|
||||
style.FrameRounding = 0.f;
|
||||
style.ItemSpacing = { 3.f, 2.f };
|
||||
style.ItemInnerSpacing = { 3.f, 2.f };
|
||||
style.TouchExtraPadding = { 1.f, 1.f };
|
||||
style.IndentSpacing = 15.f;
|
||||
style.ScrollbarSize = 10.f;
|
||||
style.ScrollbarRounding = 0.f;
|
||||
style.GrabMinSize = 10.f;
|
||||
style.GrabRounding = 16.f;
|
||||
|
||||
style.Colors[ImGuiCol_Text] = ImVec4(0.90f, 0.90f, 0.90f, 1.00f);
|
||||
style.Colors[ImGuiCol_TextDisabled] = ImVec4(0.60f, 0.60f, 0.60f, 1.00f);
|
||||
style.Colors[ImGuiCol_WindowBg] = ImVec4(0.13f, 0.13f, 0.13f, 0.96f);
|
||||
style.Colors[ImGuiCol_ChildBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
|
||||
style.Colors[ImGuiCol_PopupBg] = ImVec4(0.05f, 0.05f, 0.10f, 0.90f);
|
||||
style.Colors[ImGuiCol_Border] = ImVec4(0.65f, 0.65f, 0.65f, 0.59f);
|
||||
style.Colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
|
||||
style.Colors[ImGuiCol_FrameBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.30f);
|
||||
style.Colors[ImGuiCol_FrameBgHovered] = ImVec4(0.91f, 0.94f, 0.99f, 0.40f);
|
||||
style.Colors[ImGuiCol_FrameBgActive] = ImVec4(0.90f, 0.90f, 0.90f, 0.45f);
|
||||
style.Colors[ImGuiCol_TitleBg] = ImVec4(0.71f, 0.81f, 1.00f, 0.45f);
|
||||
style.Colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.71f, 0.81f, 1.00f, 0.45f);
|
||||
style.Colors[ImGuiCol_TitleBgActive] = ImVec4(0.51f, 0.69f, 1.00f, 0.63f);
|
||||
style.Colors[ImGuiCol_MenuBarBg] = ImVec4(0.26f, 0.27f, 0.33f, 0.80f);
|
||||
style.Colors[ImGuiCol_ScrollbarBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
|
||||
style.Colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.40f, 0.75f, 0.80f, 0.43f);
|
||||
style.Colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.40f, 0.75f, 0.80f, 0.65f);
|
||||
style.Colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.40f, 0.75f, 0.80f, 0.65f);
|
||||
style.Colors[ImGuiCol_CheckMark] = ImVec4(1.00f, 1.00f, 1.00f, 0.50f);
|
||||
style.Colors[ImGuiCol_SliderGrab] = ImVec4(1.00f, 1.00f, 1.00f, 0.30f);
|
||||
style.Colors[ImGuiCol_SliderGrabActive] = ImVec4(0.50f, 0.80f, 0.76f, 1.00f);
|
||||
style.Colors[ImGuiCol_Button] = ImVec4(0.36f, 0.54f, 0.68f, 0.62f);
|
||||
style.Colors[ImGuiCol_ButtonHovered] = ImVec4(0.36f, 0.54f, 0.68f, 1.00f);
|
||||
style.Colors[ImGuiCol_ButtonActive] = ImVec4(0.36f, 0.61f, 0.81f, 1.00f);
|
||||
style.Colors[ImGuiCol_Header] = ImVec4(0.69f, 0.69f, 0.69f, 0.45f);
|
||||
style.Colors[ImGuiCol_HeaderHovered] = ImVec4(0.36f, 0.54f, 0.68f, 0.62f);
|
||||
style.Colors[ImGuiCol_HeaderActive] = ImVec4(0.53f, 0.63f, 0.87f, 0.80f);
|
||||
style.Colors[ImGuiCol_Separator] = ImVec4(0.50f, 0.50f, 0.50f, 1.00f);
|
||||
style.Colors[ImGuiCol_SeparatorHovered] = ImVec4(0.70f, 0.60f, 0.60f, 1.00f);
|
||||
style.Colors[ImGuiCol_SeparatorActive] = ImVec4(0.90f, 0.70f, 0.70f, 1.00f);
|
||||
style.Colors[ImGuiCol_ResizeGrip] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
|
||||
style.Colors[ImGuiCol_ResizeGripHovered] = ImVec4(1.00f, 1.00f, 1.00f, 0.60f);
|
||||
style.Colors[ImGuiCol_ResizeGripActive] = ImVec4(1.00f, 1.00f, 1.00f, 0.90f);
|
||||
style.Colors[ImGuiCol_PlotLines] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
|
||||
style.Colors[ImGuiCol_PlotLinesHovered] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
|
||||
style.Colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
|
||||
style.Colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f);
|
||||
style.Colors[ImGuiCol_TextSelectedBg] = ImVec4(0.44f, 0.63f, 1.00f, 0.35f);
|
||||
style.Colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.20f, 0.20f, 0.20f, 0.35f);
|
||||
}
|
||||
|
||||
for (gui::GuiComponent* comp : _components) {
|
||||
comp->initialize();
|
||||
}
|
||||
|
||||
_program = ghoul::opengl::ProgramObject::Build(
|
||||
"GUI",
|
||||
absPath("${MODULE_IMGUI}/shaders/gui_vs.glsl"),
|
||||
absPath("${MODULE_IMGUI}/shaders/gui_fs.glsl")
|
||||
);
|
||||
|
||||
ghoul::opengl::updateUniformLocations(*_program, _uniformCache, UniformNames);
|
||||
|
||||
{
|
||||
unsigned char* texData;
|
||||
glm::ivec2 texSize = glm::ivec2(0, 0);
|
||||
for (int i = 0; i < nWindows; ++i) {
|
||||
ImGui::SetCurrentContext(_contexts[i]);
|
||||
|
||||
ImGui::GetIO().Fonts->GetTexDataAsRGBA32(&texData, &texSize.x, &texSize.y);
|
||||
}
|
||||
_fontTexture = std::make_unique<ghoul::opengl::Texture>(
|
||||
texData,
|
||||
glm::uvec3(texSize.x, texSize.y, 1),
|
||||
GL_TEXTURE_2D
|
||||
);
|
||||
_fontTexture->setName("Gui Text");
|
||||
_fontTexture->setDataOwnership(ghoul::opengl::Texture::TakeOwnership::No);
|
||||
_fontTexture->uploadTexture();
|
||||
}
|
||||
for (int i = 0; i < nWindows; ++i) {
|
||||
uintptr_t texture = static_cast<GLuint>(*_fontTexture);
|
||||
ImGui::SetCurrentContext(_contexts[i]);
|
||||
ImGui::GetIO().Fonts->TexID = reinterpret_cast<void*>(texture);
|
||||
}
|
||||
|
||||
glGenBuffers(1, &vbo);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, 0, nullptr, GL_DYNAMIC_DRAW);
|
||||
|
||||
glGenBuffers(1, &vboElements);
|
||||
|
||||
glGenVertexArrays(1, &vao);
|
||||
glBindVertexArray(vao);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
||||
|
||||
GLuint positionAttrib = _program->attributeLocation("in_position");
|
||||
GLuint uvAttrib = _program->attributeLocation("in_uv");
|
||||
GLuint colorAttrib = _program->attributeLocation("in_color");
|
||||
|
||||
glEnableVertexAttribArray(positionAttrib);
|
||||
glVertexAttribPointer(
|
||||
positionAttrib,
|
||||
2,
|
||||
GL_FLOAT,
|
||||
GL_FALSE,
|
||||
sizeof(ImDrawVert),
|
||||
nullptr
|
||||
);
|
||||
|
||||
glEnableVertexAttribArray(uvAttrib);
|
||||
glVertexAttribPointer(
|
||||
uvAttrib,
|
||||
2,
|
||||
GL_FLOAT,
|
||||
GL_FALSE,
|
||||
sizeof(ImDrawVert),
|
||||
reinterpret_cast<GLvoid*>(offsetof(ImDrawVert, uv))
|
||||
);
|
||||
|
||||
glEnableVertexAttribArray(colorAttrib);
|
||||
glVertexAttribPointer(
|
||||
colorAttrib,
|
||||
4,
|
||||
GL_UNSIGNED_BYTE,
|
||||
GL_TRUE,
|
||||
sizeof(ImDrawVert),
|
||||
reinterpret_cast<GLvoid*>(offsetof(ImDrawVert, col))
|
||||
);
|
||||
glBindVertexArray(0);
|
||||
|
||||
for (gui::GuiComponent* comp : _components) {
|
||||
comp->initializeGL();
|
||||
}
|
||||
}
|
||||
|
||||
void ImGUIModule::internalDeinitializeGL() {
|
||||
_program = nullptr;
|
||||
_fontTexture = nullptr;
|
||||
|
||||
glDeleteVertexArrays(1, &vao);
|
||||
glDeleteBuffers(1, &vbo);
|
||||
glDeleteBuffers(1, &vboElements);
|
||||
|
||||
for (gui::GuiComponent* comp : _components) {
|
||||
comp->deinitializeGL();
|
||||
}
|
||||
}
|
||||
|
||||
void ImGUIModule::renderFrame(float deltaTime, const glm::vec2& windowSize,
|
||||
const glm::vec2& dpiScaling, const glm::vec2& mousePos,
|
||||
uint32_t mouseButtonsPressed)
|
||||
{
|
||||
const int iWindow = global::windowDelegate->currentWindowId();
|
||||
ImGui::SetCurrentContext(_contexts[iWindow]);
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.DisplaySize = ImVec2(windowSize.x, windowSize.y);
|
||||
io.DisplayFramebufferScale = ImVec2(dpiScaling.x, dpiScaling.y);
|
||||
io.DeltaTime = deltaTime;
|
||||
|
||||
io.MousePos = ImVec2(mousePos.x, mousePos.y);
|
||||
|
||||
io.MouseDown[0] = mouseButtonsPressed & (1 << 0);
|
||||
io.MouseDown[1] = mouseButtonsPressed & (1 << 1);
|
||||
|
||||
ImGui::NewFrame();
|
||||
|
||||
if (_program->isDirty()) {
|
||||
_program->rebuildFromFile();
|
||||
ghoul::opengl::updateUniformLocations(*_program, _uniformCache, UniformNames);
|
||||
}
|
||||
|
||||
//
|
||||
// Render
|
||||
ImGui::SetNextWindowCollapsed(_isCollapsed);
|
||||
|
||||
ImGui::Begin("OpenSpace GUI", nullptr);
|
||||
|
||||
_isCollapsed = ImGui::IsWindowCollapsed();
|
||||
|
||||
for (gui::GuiComponent* comp : _components) {
|
||||
bool enabled = comp->isEnabled();
|
||||
ImGui::Checkbox(comp->guiName().c_str(), &enabled);
|
||||
comp->setEnabled(enabled);
|
||||
}
|
||||
|
||||
// Render and Update property visibility
|
||||
// Fragile! Keep this in sync with properties::Property::Visibility
|
||||
using V = properties::Property::Visibility;
|
||||
int t = static_cast<std::underlying_type_t<V>>(_currentVisibility);
|
||||
|
||||
// Array is sorted by importance
|
||||
std::array<const char*, 4> items = { "User", "Developer", "Hidden", "All" };
|
||||
ImGui::Combo("PropertyVisibility", &t, items.data(), static_cast<int>(items.size()));
|
||||
|
||||
_currentVisibility = static_cast<V>(t);
|
||||
_property.setVisibility(_currentVisibility);
|
||||
|
||||
#ifdef SHOW_IMGUI_HELPERS
|
||||
ImGui::Checkbox("ImGUI Internals", &_showInternals);
|
||||
if (_showInternals) {
|
||||
ImGui::Begin("Style Editor");
|
||||
ImGui::ShowStyleEditor();
|
||||
ImGui::End();
|
||||
|
||||
ImGui::Begin("Test Window");
|
||||
ImGui::ShowDemoWindow();
|
||||
ImGui::End();
|
||||
|
||||
ImGui::Begin("Metrics Window");
|
||||
ImGui::ShowMetricsWindow();
|
||||
ImGui::End();
|
||||
}
|
||||
#endif
|
||||
|
||||
ImGui::End();
|
||||
|
||||
|
||||
for (gui::GuiComponent* comp : _components) {
|
||||
if (comp->isEnabled()) {
|
||||
comp->render();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::Render();
|
||||
|
||||
// Drawing
|
||||
ImDrawData* drawData = ImGui::GetDrawData();
|
||||
|
||||
// Avoid rendering when minimized, scale coordinates for retina displays
|
||||
// (screen coordinates != framebuffer coordinates)
|
||||
GLsizei fbWidth = static_cast<GLsizei>(
|
||||
io.DisplaySize.x * io.DisplayFramebufferScale.x
|
||||
);
|
||||
GLsizei fbHeight = static_cast<GLsizei>(
|
||||
io.DisplaySize.y * io.DisplayFramebufferScale.y
|
||||
);
|
||||
if (fbWidth == 0 || fbHeight == 0) {
|
||||
return;
|
||||
}
|
||||
drawData->ScaleClipRects(io.DisplayFramebufferScale);
|
||||
|
||||
// Setup render state:
|
||||
// alpha-blending enabled, no face culling, no depth testing, scissor enabled
|
||||
glEnable(GL_BLEND);
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glDisable(GL_CULL_FACE);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
|
||||
ghoul::opengl::TextureUnit unit;
|
||||
unit.activate();
|
||||
_fontTexture->bind();
|
||||
|
||||
// Setup orthographic projection matrix
|
||||
const float width = ImGui::GetIO().DisplaySize.x;
|
||||
const float height = ImGui::GetIO().DisplaySize.y;
|
||||
glViewport(0, 0, fbWidth, fbHeight);
|
||||
const glm::mat4 ortho(
|
||||
2.f / width, 0.f, 0.f, 0.f,
|
||||
0.f, 2.f / -height, 0.f, 0.f,
|
||||
0.f, 0.f, -1.f, 0.f,
|
||||
-1.f, 1.f, 0.f, 1.f
|
||||
);
|
||||
_program->activate();
|
||||
|
||||
_program->setUniform(_uniformCache.tex, unit);
|
||||
_program->setUniform(_uniformCache.ortho, ortho);
|
||||
|
||||
glBindVertexArray(vao);
|
||||
|
||||
for (int i = 0; i < drawData->CmdListsCount; ++i) {
|
||||
const ImDrawList* cmdList = drawData->CmdLists[i];
|
||||
const ImDrawIdx* indexBufferOffset = nullptr;
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
||||
glBufferData(
|
||||
GL_ARRAY_BUFFER,
|
||||
cmdList->VtxBuffer.size() * sizeof(ImDrawVert),
|
||||
reinterpret_cast<const GLvoid*>(&cmdList->VtxBuffer.front()),
|
||||
GL_STREAM_DRAW
|
||||
);
|
||||
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboElements);
|
||||
glBufferData(
|
||||
GL_ELEMENT_ARRAY_BUFFER,
|
||||
cmdList->IdxBuffer.size() * sizeof(ImDrawIdx),
|
||||
reinterpret_cast<const GLvoid*>(&cmdList->IdxBuffer.front()),
|
||||
GL_STREAM_DRAW
|
||||
);
|
||||
|
||||
for (const ImDrawCmd* pcmd = cmdList->CmdBuffer.begin();
|
||||
pcmd != cmdList->CmdBuffer.end();
|
||||
pcmd++)
|
||||
{
|
||||
if (pcmd->UserCallback) {
|
||||
pcmd->UserCallback(cmdList, pcmd);
|
||||
}
|
||||
else {
|
||||
glBindTexture(
|
||||
GL_TEXTURE_2D,
|
||||
static_cast<GLuint>(reinterpret_cast<intptr_t>(pcmd->TextureId))
|
||||
);
|
||||
glScissor(
|
||||
static_cast<int>(pcmd->ClipRect.x),
|
||||
static_cast<int>(fbHeight - pcmd->ClipRect.w),
|
||||
static_cast<int>(pcmd->ClipRect.z - pcmd->ClipRect.x),
|
||||
static_cast<int>(pcmd->ClipRect.w - pcmd->ClipRect.y)
|
||||
);
|
||||
glDrawElements(
|
||||
GL_TRIANGLES,
|
||||
static_cast<GLsizei>(pcmd->ElemCount),
|
||||
sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
|
||||
indexBufferOffset
|
||||
);
|
||||
}
|
||||
indexBufferOffset += pcmd->ElemCount;
|
||||
}
|
||||
}
|
||||
|
||||
glBindVertexArray(0);
|
||||
_program->deactivate();
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
}
|
||||
|
||||
bool ImGUIModule::mouseButtonCallback(MouseButton, MouseAction) {
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
bool consumeEvent = io.WantCaptureMouse;
|
||||
return consumeEvent;
|
||||
}
|
||||
|
||||
bool ImGUIModule::mouseWheelCallback(double position) {
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
bool consumeEvent = io.WantCaptureMouse;
|
||||
if (consumeEvent) {
|
||||
io.MouseWheel = static_cast<float>(position);
|
||||
}
|
||||
return consumeEvent;
|
||||
}
|
||||
|
||||
bool ImGUIModule::keyCallback(Key key, KeyModifier modifier, KeyAction action) {
|
||||
const int keyIndex = static_cast<int>(key);
|
||||
if (keyIndex < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const bool hasShift = hasKeyModifier(modifier, KeyModifier::Shift);
|
||||
const bool hasCtrl = hasKeyModifier(modifier, KeyModifier::Control);
|
||||
const bool hasAlt = hasKeyModifier(modifier, KeyModifier::Alt);
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
const bool consumeEvent = io.WantCaptureKeyboard;
|
||||
if (consumeEvent) {
|
||||
if (action == KeyAction::Press) {
|
||||
io.KeysDown[keyIndex] = true;
|
||||
}
|
||||
io.KeyShift = hasShift;
|
||||
io.KeyCtrl = hasCtrl;
|
||||
io.KeyAlt = hasAlt;
|
||||
}
|
||||
|
||||
// Even if the event is not consumed,
|
||||
// set keys and modifiers to false when they are released.
|
||||
if (action == KeyAction::Release) {
|
||||
io.KeysDown[keyIndex] = false;
|
||||
}
|
||||
if (!hasShift) {
|
||||
io.KeyShift = false;
|
||||
}
|
||||
if (!hasCtrl) {
|
||||
io.KeyCtrl = false;
|
||||
}
|
||||
if (!hasAlt) {
|
||||
io.KeyAlt = false;
|
||||
}
|
||||
|
||||
return consumeEvent;
|
||||
}
|
||||
|
||||
bool ImGUIModule::charCallback(unsigned int character, KeyModifier) {
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
bool consumeEvent = io.WantCaptureKeyboard;
|
||||
if (consumeEvent) {
|
||||
io.AddInputCharacter(static_cast<unsigned short>(character));
|
||||
}
|
||||
return consumeEvent;
|
||||
}
|
||||
|
||||
bool ImGUIModule::touchDetectedCallback(TouchInput input) {
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
const glm::vec2 windowPos = input.currentWindowCoordinates();
|
||||
const bool consumeEvent = io.WantCaptureMouse;
|
||||
|
||||
if (!consumeEvent) {
|
||||
return false;
|
||||
}
|
||||
if (_validTouchStates.empty()) {
|
||||
io.MousePos = { windowPos.x, windowPos.y };
|
||||
io.MouseClicked[0] = true;
|
||||
}
|
||||
_validTouchStates.push_back(input);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ImGUIModule::touchUpdatedCallback(TouchInput input) {
|
||||
if (_validTouchStates.empty()) {
|
||||
return false;
|
||||
}
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
auto it = std::find_if(
|
||||
_validTouchStates.cbegin(),
|
||||
_validTouchStates.cend(),
|
||||
[&](const TouchInput& state) {
|
||||
return state.fingerId == input.fingerId &&
|
||||
state.touchDeviceId == input.touchDeviceId;
|
||||
}
|
||||
);
|
||||
|
||||
if (it == _validTouchStates.cbegin()) {
|
||||
glm::vec2 windowPos = input.currentWindowCoordinates();
|
||||
io.MousePos = ImVec2(windowPos.x, windowPos.y);
|
||||
io.MouseClicked[0] = true;
|
||||
return true;
|
||||
}
|
||||
else if (it != _validTouchStates.cend()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ImGUIModule::touchExitCallback(TouchInput input) {
|
||||
if (_validTouchStates.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto found = std::find_if(
|
||||
_validTouchStates.cbegin(),
|
||||
_validTouchStates.cend(),
|
||||
[&](const TouchInput& state) {
|
||||
return state.fingerId == input.fingerId &&
|
||||
state.touchDeviceId == input.touchDeviceId;
|
||||
}
|
||||
);
|
||||
|
||||
if (found == _validTouchStates.cend()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
_validTouchStates.erase(found);
|
||||
if (_validTouchStates.empty()) {
|
||||
glm::vec2 windowPos = input.currentWindowCoordinates();
|
||||
io.MousePos = ImVec2(windowPos.x, windowPos.y);
|
||||
io.MouseClicked[0] = false;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -27,7 +27,30 @@
|
||||
|
||||
#include <openspace/util/openspacemodule.h>
|
||||
|
||||
#include <modules/imgui/include/gui.h>
|
||||
#include <modules/imgui/include/guiactioncomponent.h>
|
||||
#include <modules/imgui/include/guifilepathcomponent.h>
|
||||
#include <modules/imgui/include/guigibscomponent.h>
|
||||
#include <modules/imgui/include/guiglobebrowsingcomponent.h>
|
||||
#include <modules/imgui/include/guihelpcomponent.h>
|
||||
#include <modules/imgui/include/guijoystickcomponent.h>
|
||||
#include <modules/imgui/include/guimemorycomponent.h>
|
||||
#include <modules/imgui/include/guimissioncomponent.h>
|
||||
#include <modules/imgui/include/guiparallelcomponent.h>
|
||||
#include <modules/imgui/include/guipropertycomponent.h>
|
||||
#include <modules/imgui/include/guiscenecomponent.h>
|
||||
#include <modules/imgui/include/guispacetimecomponent.h>
|
||||
#include <openspace/properties/scalar/boolproperty.h>
|
||||
#include <openspace/properties/scalar/floatproperty.h>
|
||||
#include <openspace/util/keys.h>
|
||||
#include <openspace/util/mouse.h>
|
||||
#include <openspace/util/touch.h>
|
||||
#include <ghoul/glm.h>
|
||||
#include <ghoul/opengl/ghoul_gl.h>
|
||||
#include <ghoul/opengl/uniformcache.h>
|
||||
#include <ghoul/opengl/texture.h>
|
||||
#include <array>
|
||||
|
||||
struct ImGuiContext;
|
||||
|
||||
namespace openspace {
|
||||
|
||||
@@ -37,13 +60,85 @@ public:
|
||||
|
||||
ImGUIModule();
|
||||
|
||||
gui::GUI gui;
|
||||
void internalInitialize(const ghoul::Dictionary& configuration) override;
|
||||
void internalDeinitialize() override;
|
||||
void internalInitializeGL() override;
|
||||
void internalDeinitializeGL() override;
|
||||
|
||||
private:
|
||||
bool mouseButtonCallback(MouseButton button, MouseAction action);
|
||||
bool mouseWheelCallback(double position);
|
||||
bool keyCallback(Key key, KeyModifier modifier, KeyAction action);
|
||||
bool charCallback(unsigned int character, KeyModifier modifier);
|
||||
|
||||
bool touchDetectedCallback(TouchInput input);
|
||||
bool touchUpdatedCallback(TouchInput input);
|
||||
void touchExitCallback(TouchInput input);
|
||||
|
||||
void renderFrame(float deltaTime, const glm::vec2& windowSize,
|
||||
const glm::vec2& dpiScaling, const glm::vec2& mousePos,
|
||||
uint32_t mouseButtonsPressed);
|
||||
|
||||
properties::BoolProperty _isEnabled;
|
||||
properties::BoolProperty _isCollapsed;
|
||||
|
||||
gui::GuiPropertyComponent _sceneProperty;
|
||||
gui::GuiPropertyComponent _property;
|
||||
gui::GuiSpaceTimeComponent _spaceTime;
|
||||
gui::GuiJoystickComponent _joystick;
|
||||
gui::GuiActionComponent _actions;
|
||||
gui::GuiParallelComponent _parallel;
|
||||
gui::GuiGlobeBrowsingComponent _globeBrowsing;
|
||||
gui::GuiGIBSComponent _gibs;
|
||||
gui::GuiMissionComponent _mission;
|
||||
gui::GuiMemoryComponent _memoryComponent;
|
||||
gui::GuiSceneComponent _sceneView;
|
||||
gui::GuiFilePathComponent _filePath;
|
||||
gui::GuiHelpComponent _help;
|
||||
|
||||
properties::BoolProperty _showHelpText;
|
||||
properties::FloatProperty _helpTextDelay;
|
||||
|
||||
// The ordering of this array determines the order of components in the in-game menu
|
||||
static constexpr int nComponents = 13;
|
||||
std::array<gui::GuiComponent*, nComponents> _components = {
|
||||
&_sceneProperty,
|
||||
&_property,
|
||||
&_spaceTime,
|
||||
&_joystick,
|
||||
&_actions,
|
||||
&_parallel,
|
||||
&_globeBrowsing,
|
||||
&_gibs,
|
||||
&_mission,
|
||||
&_memoryComponent,
|
||||
&_sceneView,
|
||||
&_filePath,
|
||||
&_help
|
||||
};
|
||||
|
||||
GLuint vao = 0;
|
||||
GLuint vbo = 0;
|
||||
GLuint vboElements = 0;
|
||||
std::unique_ptr<ghoul::opengl::ProgramObject> _program;
|
||||
UniformCache(tex, ortho) _uniformCache;
|
||||
std::unique_ptr<ghoul::opengl::Texture> _fontTexture;
|
||||
|
||||
properties::Property::Visibility _currentVisibility =
|
||||
properties::Property::Visibility::Developer;
|
||||
|
||||
std::vector<ImGuiContext*> _contexts;
|
||||
|
||||
std::vector<TouchInput> _validTouchStates;
|
||||
|
||||
std::vector<char> _iniFileBuffer;
|
||||
|
||||
glm::vec2 _mousePosition = glm::vec2(0.f);
|
||||
uint32_t _mouseButtons = 0;
|
||||
};
|
||||
|
||||
void CaptionText(const char* text);
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
#endif // __OPENSPACE_MODULE_IMGUI___IMGUIMODULE___H__
|
||||
|
||||
@@ -1,178 +0,0 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2022 *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
|
||||
* software and associated documentation files (the "Software"), to deal in the Software *
|
||||
* without restriction, including without limitation the rights to use, copy, modify, *
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
|
||||
* permit persons to whom the Software is furnished to do so, subject to the following *
|
||||
* conditions: *
|
||||
* *
|
||||
* The above copyright notice and this permission notice shall be included in all copies *
|
||||
* or substantial portions of the Software. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#ifndef __OPENSPACE_MODULE_IMGUI___GUI___H__
|
||||
#define __OPENSPACE_MODULE_IMGUI___GUI___H__
|
||||
|
||||
#include <modules/imgui/include/guicomponent.h>
|
||||
|
||||
#include <modules/imgui/include/guiactioncomponent.h>
|
||||
#include <modules/imgui/include/guifilepathcomponent.h>
|
||||
#include <modules/imgui/include/guigibscomponent.h>
|
||||
#include <modules/imgui/include/guiglobebrowsingcomponent.h>
|
||||
#include <modules/imgui/include/guihelpcomponent.h>
|
||||
#include <modules/imgui/include/guiiswacomponent.h>
|
||||
#include <modules/imgui/include/guijoystickcomponent.h>
|
||||
#include <modules/imgui/include/guimemorycomponent.h>
|
||||
#include <modules/imgui/include/guimissioncomponent.h>
|
||||
#include <modules/imgui/include/guiparallelcomponent.h>
|
||||
#include <modules/imgui/include/guipropertycomponent.h>
|
||||
#include <modules/imgui/include/guispacetimecomponent.h>
|
||||
#include <openspace/properties/property.h>
|
||||
#include <openspace/properties/scalar/boolproperty.h>
|
||||
#include <openspace/properties/scalar/floatproperty.h>
|
||||
#include <openspace/util/keys.h>
|
||||
#include <openspace/util/mouse.h>
|
||||
#include <openspace/util/touch.h>
|
||||
#include <ghoul/glm.h>
|
||||
#include <ghoul/opengl/ghoul_gl.h>
|
||||
#include <ghoul/opengl/uniformcache.h>
|
||||
#include <array>
|
||||
|
||||
//#define SHOW_IMGUI_HELPERS
|
||||
|
||||
struct ImGuiContext;
|
||||
|
||||
namespace ghoul::opengl {
|
||||
class ProgramObject;
|
||||
class Texture;
|
||||
} // namespace ghoul::opengl
|
||||
|
||||
namespace openspace::gui {
|
||||
|
||||
namespace detail {
|
||||
constexpr int nComponents() {
|
||||
const int nRegularComponents = 15;
|
||||
int totalComponents = nRegularComponents;
|
||||
|
||||
#ifdef OPENSPACE_MODULE_ISWA_ENABLED
|
||||
++totalComponents;
|
||||
#endif
|
||||
|
||||
return totalComponents;
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
class GUI : public GuiComponent {
|
||||
public:
|
||||
GUI();
|
||||
~GUI();
|
||||
|
||||
void initialize() override;
|
||||
void deinitialize() override;
|
||||
|
||||
void initializeGL() override;
|
||||
void deinitializeGL() override;
|
||||
|
||||
bool mouseButtonCallback(MouseButton button, MouseAction action);
|
||||
bool mouseWheelCallback(double position);
|
||||
bool keyCallback(Key key, KeyModifier modifier, KeyAction action);
|
||||
bool charCallback(unsigned int character, KeyModifier modifier);
|
||||
|
||||
bool touchDetectedCallback(TouchInput input);
|
||||
bool touchUpdatedCallback(TouchInput input);
|
||||
void touchExitCallback(TouchInput input);
|
||||
|
||||
void startFrame(float deltaTime, const glm::vec2& windowSize,
|
||||
const glm::vec2& dpiScaling, const glm::vec2& mousePos,
|
||||
uint32_t mouseButtonsPressed);
|
||||
void endFrame();
|
||||
|
||||
void render() override;
|
||||
|
||||
//protected:
|
||||
GuiHelpComponent _help;
|
||||
GuiFilePathComponent _filePath;
|
||||
GuiGIBSComponent _gibs;
|
||||
GuiGlobeBrowsingComponent _globeBrowsing;
|
||||
|
||||
GuiPropertyComponent _globalProperty;
|
||||
GuiPropertyComponent _sceneProperty;
|
||||
GuiPropertyComponent _screenSpaceProperty;
|
||||
GuiPropertyComponent _moduleProperty;
|
||||
GuiMemoryComponent _memoryComponent;
|
||||
|
||||
GuiSpaceTimeComponent _spaceTime;
|
||||
GuiMissionComponent _mission;
|
||||
#ifdef OPENSPACE_MODULE_ISWA_ENABLED
|
||||
GuiIswaComponent _iswa;
|
||||
#endif // OPENSPACE_MODULE_ISWA_ENABLED
|
||||
GuiActionComponent _actions;
|
||||
GuiJoystickComponent _joystick;
|
||||
GuiParallelComponent _parallel;
|
||||
GuiPropertyComponent _featuredProperties;
|
||||
|
||||
|
||||
properties::BoolProperty _showHelpText;
|
||||
properties::FloatProperty _helpTextDelay;
|
||||
|
||||
private:
|
||||
void renderAndUpdatePropertyVisibility();
|
||||
|
||||
// The ordering of this array determines the order of components in the in-game menu
|
||||
std::array<GuiComponent*, detail::nComponents()> _components = {
|
||||
&_sceneProperty,
|
||||
&_screenSpaceProperty,
|
||||
&_featuredProperties,
|
||||
&_globalProperty,
|
||||
&_moduleProperty,
|
||||
&_memoryComponent,
|
||||
&_spaceTime,
|
||||
&_mission,
|
||||
&_parallel,
|
||||
&_gibs,
|
||||
&_globeBrowsing,
|
||||
#ifdef OPENSPACE_MODULE_ISWA_ENABLED
|
||||
&_iswa,
|
||||
#endif
|
||||
&_actions,
|
||||
&_joystick,
|
||||
&_filePath,
|
||||
&_help
|
||||
};
|
||||
|
||||
GLuint vao = 0;
|
||||
GLuint vbo = 0;
|
||||
GLuint vboElements = 0;
|
||||
std::unique_ptr<ghoul::opengl::ProgramObject> _program;
|
||||
UniformCache(tex, ortho) _uniformCache;
|
||||
std::unique_ptr<ghoul::opengl::Texture> _fontTexture;
|
||||
|
||||
#ifdef SHOW_IMGUI_HELPERS
|
||||
bool _showInternals = false;
|
||||
#endif // SHOW_IMGUI_HELPERS
|
||||
|
||||
properties::Property::Visibility _currentVisibility =
|
||||
properties::Property::Visibility::Developer;
|
||||
|
||||
std::vector<ImGuiContext*> _contexts;
|
||||
|
||||
std::vector<TouchInput> _validTouchStates;
|
||||
};
|
||||
|
||||
void CaptionText(const char* text);
|
||||
|
||||
} // namespace openspace::gui
|
||||
|
||||
#endif // __OPENSPACE_MODULE_IMGUI___GUI___H__
|
||||
@@ -43,16 +43,14 @@ namespace openspace::gui {
|
||||
|
||||
class GuiPropertyComponent : public GuiComponent {
|
||||
public:
|
||||
using SourceFunction = std::function<std::vector<properties::PropertyOwner*>()>;
|
||||
|
||||
BooleanType(UseTreeLayout);
|
||||
|
||||
GuiPropertyComponent(std::string identifier, std::string guiName = "",
|
||||
GuiPropertyComponent(std::string identifier, std::string guiName,
|
||||
UseTreeLayout useTree = UseTreeLayout::No);
|
||||
|
||||
// This is the function that evaluates to the list of Propertyowners that this
|
||||
// component should render
|
||||
void setSource(SourceFunction function);
|
||||
void setPropertyOwners(std::vector<properties::PropertyOwner*> propertyOwners);
|
||||
void setPropertyOwnerFunction(
|
||||
std::function<std::vector<properties::PropertyOwner*>()> func);
|
||||
|
||||
void setVisibility(properties::Property::Visibility visibility);
|
||||
|
||||
@@ -64,7 +62,8 @@ protected:
|
||||
|
||||
properties::Property::Visibility _visibility = properties::Property::Visibility::User;
|
||||
|
||||
SourceFunction _function;
|
||||
std::vector<properties::PropertyOwner*> _propertyOwners;
|
||||
std::function<std::vector<properties::PropertyOwner*>()> _propertyOwnerFunction;
|
||||
|
||||
properties::BoolProperty _useTreeLayout;
|
||||
properties::StringListProperty _treeOrdering;
|
||||
|
||||
@@ -22,34 +22,22 @@
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#ifndef __OPENSPACE_MODULE_IMGUI___GUIISWACOMPONENT___H__
|
||||
#define __OPENSPACE_MODULE_IMGUI___GUIISWACOMPONENT___H__
|
||||
#ifndef __OPENSPACE_MODULE_IMGUI___GUISCENECOMPONENT___H__
|
||||
#define __OPENSPACE_MODULE_IMGUI___GUISCENECOMPONENT___H__
|
||||
|
||||
#ifdef OPENSPACE_MODULE_ISWA_ENABLED
|
||||
#include <modules/imgui/include/guicomponent.h>
|
||||
|
||||
#include <modules/imgui/include/guipropertycomponent.h>
|
||||
|
||||
#include <map>
|
||||
namespace openspace { class SceneGraphNode; }
|
||||
|
||||
namespace openspace::gui {
|
||||
|
||||
class GuiIswaComponent : public GuiPropertyComponent {
|
||||
class GuiSceneComponent : public GuiComponent {
|
||||
public:
|
||||
GuiIswaComponent();
|
||||
GuiSceneComponent();
|
||||
|
||||
void render() override;
|
||||
|
||||
private:
|
||||
bool _gmData = false;
|
||||
bool _gmImage = false;
|
||||
bool _ionData = false;
|
||||
std::vector<int> _cdfOptions;
|
||||
std::map<std::string, int> _cdfOptionsMap;
|
||||
};
|
||||
|
||||
} // namespace openspace::gui
|
||||
|
||||
#endif // OPENSPACE_MODULE_ISWA_ENABLED
|
||||
|
||||
|
||||
#endif // __OPENSPACE_MODULE_IMGUI___GUIISWACOMPONENT___H__
|
||||
#endif // __OPENSPACE_MODULE_IMGUI___GUISCENECOMPONENT___H__
|
||||
@@ -1,796 +0,0 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2022 *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
|
||||
* software and associated documentation files (the "Software"), to deal in the Software *
|
||||
* without restriction, including without limitation the rights to use, copy, modify, *
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
|
||||
* permit persons to whom the Software is furnished to do so, subject to the following *
|
||||
* conditions: *
|
||||
* *
|
||||
* The above copyright notice and this permission notice shall be included in all copies *
|
||||
* or substantial portions of the Software. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#include <modules/imgui/include/gui.h>
|
||||
|
||||
#include <modules/imgui/imguimodule.h>
|
||||
#include <modules/imgui/include/imgui_include.h>
|
||||
#include <openspace/engine/globals.h>
|
||||
#include <openspace/engine/windowdelegate.h>
|
||||
#include <openspace/mission/missionmanager.h>
|
||||
#include <openspace/scripting/scriptengine.h>
|
||||
#include <ghoul/fmt.h>
|
||||
#include <ghoul/filesystem/cachemanager.h>
|
||||
#include <ghoul/filesystem/filesystem.h>
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <ghoul/opengl/ghoul_gl.h>
|
||||
#include <ghoul/opengl/programobject.h>
|
||||
#include <ghoul/opengl/texture.h>
|
||||
#include <ghoul/opengl/textureunit.h>
|
||||
#include <filesystem>
|
||||
|
||||
namespace {
|
||||
constexpr const char* _loggerCat = "GUI";
|
||||
constexpr const char* configurationFile = "imgui.ini";
|
||||
constexpr const char* GuiFont = "${FONTS}/arimo/Arimo-Regular.ttf";
|
||||
constexpr const float FontSize = 14.f;
|
||||
|
||||
char* iniFileBuffer = nullptr;
|
||||
|
||||
ImFont* captionFont = nullptr;
|
||||
|
||||
constexpr const std::array<const char*, 2> UniformNames = { "tex", "ortho" };
|
||||
|
||||
void addScreenSpaceRenderableLocal(std::string identifier, std::string texturePath) {
|
||||
if (!std::filesystem::is_regular_file(absPath(texturePath))) {
|
||||
LWARNING(fmt::format("Could not find image '{}'", texturePath));
|
||||
return;
|
||||
}
|
||||
|
||||
std::string script;
|
||||
if (identifier.empty()) {
|
||||
script = fmt::format(
|
||||
"openspace.addScreenSpaceRenderable({{\
|
||||
Type = 'ScreenSpaceImageLocal',\
|
||||
TexturePath = openspace.absPath('{}')\
|
||||
}});",
|
||||
texturePath
|
||||
);
|
||||
}
|
||||
else {
|
||||
script = fmt::format(
|
||||
"openspace.addScreenSpaceRenderable({{\
|
||||
Type = 'ScreenSpaceImageLocal',\
|
||||
TexturePath = openspace.absPath('{}'),\
|
||||
Identifier = '{}',\
|
||||
Name = '{}'\
|
||||
}});",
|
||||
texturePath,
|
||||
identifier,
|
||||
identifier
|
||||
);
|
||||
}
|
||||
|
||||
openspace::global::scriptEngine->queueScript(
|
||||
script,
|
||||
openspace::scripting::ScriptEngine::RemoteScripting::Yes
|
||||
);
|
||||
}
|
||||
|
||||
void addScreenSpaceRenderableOnline(std::string identifier, std::string texturePath) {
|
||||
std::string script;
|
||||
if (identifier.empty()) {
|
||||
script = fmt::format(
|
||||
"openspace.addScreenSpaceRenderable({{\
|
||||
Type = 'ScreenSpaceImageOnline',\
|
||||
URL = '{}'\
|
||||
}});",
|
||||
texturePath
|
||||
);
|
||||
}
|
||||
else {
|
||||
script = fmt::format(
|
||||
"openspace.addScreenSpaceRenderable({{\
|
||||
Type = 'ScreenSpaceImageOnline',\
|
||||
URL = '{}',\
|
||||
Identifier = '{}',\
|
||||
Name = '{}'\
|
||||
}});",
|
||||
texturePath,
|
||||
identifier,
|
||||
identifier
|
||||
);
|
||||
}
|
||||
|
||||
openspace::global::scriptEngine->queueScript(
|
||||
script,
|
||||
openspace::scripting::ScriptEngine::RemoteScripting::Yes
|
||||
);
|
||||
}
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo ShowHelpInfo = {
|
||||
"ShowHelpText",
|
||||
"Show tooltip help",
|
||||
"If this value is enabled these kinds of tooltips are shown for most properties "
|
||||
"explaining what impact they have on the visuals."
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo HelpTextDelayInfo = {
|
||||
"HelpTextDelay",
|
||||
"Tooltip Delay (in s)",
|
||||
"This value determines the delay in seconds after which the tooltip is shown."
|
||||
};
|
||||
} // namespace
|
||||
|
||||
namespace openspace::gui {
|
||||
|
||||
void CaptionText(const char* text) {
|
||||
ImGui::PushFont(captionFont);
|
||||
ImGui::Text("%s", text);
|
||||
ImGui::PopFont();
|
||||
}
|
||||
|
||||
GUI::GUI()
|
||||
: GuiComponent("Main")
|
||||
, _globalProperty("Global", "Global Properties")
|
||||
, _sceneProperty(
|
||||
"SceneProperties", "Scene Properties",
|
||||
GuiPropertyComponent::UseTreeLayout::Yes
|
||||
)
|
||||
, _screenSpaceProperty("ScreenSpaceProperties", "ScreenSpace Properties")
|
||||
, _moduleProperty("ModuleProperties", "Module Properties")
|
||||
, _featuredProperties(
|
||||
"FeaturedProperties",
|
||||
"Featured Properties",
|
||||
GuiPropertyComponent::UseTreeLayout::No
|
||||
)
|
||||
, _showHelpText(ShowHelpInfo, true)
|
||||
, _helpTextDelay(HelpTextDelayInfo, 1.0, 0.0, 10.0)
|
||||
{
|
||||
for (GuiComponent* comp : _components) {
|
||||
addPropertySubOwner(comp);
|
||||
}
|
||||
_spaceTime.setEnabled(true);
|
||||
|
||||
{
|
||||
auto showHelpTextFunc = [this]() {
|
||||
for (GuiComponent* comp : _components) {
|
||||
comp->setShowHelpTooltip(_showHelpText);
|
||||
}
|
||||
};
|
||||
showHelpTextFunc();
|
||||
_showHelpText.onChange(std::move(showHelpTextFunc));
|
||||
addProperty(_showHelpText);
|
||||
}
|
||||
|
||||
{
|
||||
auto helpTextDelayFunc = [this](){
|
||||
for (GuiComponent* comp : _components) {
|
||||
comp->setShowHelpTooltipDelay(_helpTextDelay);
|
||||
}
|
||||
};
|
||||
helpTextDelayFunc();
|
||||
_helpTextDelay.onChange(std::move(helpTextDelayFunc));
|
||||
addProperty(_helpTextDelay);
|
||||
}
|
||||
}
|
||||
|
||||
GUI::~GUI() {} // NOLINT
|
||||
|
||||
void GUI::initialize() {}
|
||||
|
||||
void GUI::deinitialize() {
|
||||
for (ImGuiContext* ctx : _contexts) {
|
||||
ImGui::DestroyContext(ctx);
|
||||
}
|
||||
|
||||
for (GuiComponent* comp : _components) {
|
||||
comp->deinitialize();
|
||||
}
|
||||
|
||||
delete iniFileBuffer;
|
||||
}
|
||||
|
||||
void GUI::initializeGL() {
|
||||
std::filesystem::path cachedFile = FileSys.cacheManager()->cachedFilename(
|
||||
configurationFile,
|
||||
""
|
||||
);
|
||||
|
||||
LDEBUG(fmt::format("Using {} as ImGUI cache location", cachedFile));
|
||||
|
||||
iniFileBuffer = new char[cachedFile.string().size() + 1];
|
||||
|
||||
#ifdef WIN32
|
||||
strcpy_s(iniFileBuffer, cachedFile.string().size() + 1, cachedFile.string().c_str());
|
||||
#else
|
||||
strcpy(iniFileBuffer, cachedFile.c_str());
|
||||
#endif
|
||||
|
||||
int nWindows = global::windowDelegate->nWindows();
|
||||
_contexts.resize(nWindows);
|
||||
|
||||
for (int i = 0; i < nWindows; ++i) {
|
||||
_contexts[i] = ImGui::CreateContext();
|
||||
ImGui::SetCurrentContext(_contexts[i]);
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.IniFilename = iniFileBuffer;
|
||||
io.DeltaTime = 1.f / 60.f;
|
||||
io.KeyMap[ImGuiKey_Tab] = static_cast<int>(Key::Tab);
|
||||
io.KeyMap[ImGuiKey_LeftArrow] = static_cast<int>(Key::Left);
|
||||
io.KeyMap[ImGuiKey_RightArrow] = static_cast<int>(Key::Right);
|
||||
io.KeyMap[ImGuiKey_UpArrow] = static_cast<int>(Key::Up);
|
||||
io.KeyMap[ImGuiKey_DownArrow] = static_cast<int>(Key::Down);
|
||||
io.KeyMap[ImGuiKey_Home] = static_cast<int>(Key::Home);
|
||||
io.KeyMap[ImGuiKey_End] = static_cast<int>(Key::End);
|
||||
io.KeyMap[ImGuiKey_Delete] = static_cast<int>(Key::Delete);
|
||||
io.KeyMap[ImGuiKey_Backspace] = static_cast<int>(Key::BackSpace);
|
||||
io.KeyMap[ImGuiKey_Enter] = static_cast<int>(Key::Enter);
|
||||
io.KeyMap[ImGuiKey_Escape] = static_cast<int>(Key::Escape);
|
||||
io.KeyMap[ImGuiKey_A] = static_cast<int>(Key::A);
|
||||
io.KeyMap[ImGuiKey_C] = static_cast<int>(Key::C);
|
||||
io.KeyMap[ImGuiKey_V] = static_cast<int>(Key::V);
|
||||
io.KeyMap[ImGuiKey_X] = static_cast<int>(Key::X);
|
||||
io.KeyMap[ImGuiKey_Y] = static_cast<int>(Key::Y);
|
||||
io.KeyMap[ImGuiKey_Z] = static_cast<int>(Key::Z);
|
||||
|
||||
io.Fonts->AddFontFromFileTTF(absPath(GuiFont).string().c_str(), FontSize);
|
||||
captionFont = io.Fonts->AddFontFromFileTTF(
|
||||
absPath(GuiFont).string().c_str(),
|
||||
FontSize * 1.5f
|
||||
);
|
||||
|
||||
ImGuiStyle& style = ImGui::GetStyle();
|
||||
style.WindowPadding = { 4.f, 4.f };
|
||||
style.WindowRounding = 0.f;
|
||||
style.FramePadding = { 3.f, 3.f };
|
||||
style.FrameRounding = 0.f;
|
||||
style.ItemSpacing = { 3.f, 2.f };
|
||||
style.ItemInnerSpacing = { 3.f, 2.f };
|
||||
style.TouchExtraPadding = { 1.f, 1.f };
|
||||
style.IndentSpacing = 15.f;
|
||||
style.ScrollbarSize = 10.f;
|
||||
style.ScrollbarRounding = 0.f;
|
||||
style.GrabMinSize = 10.f;
|
||||
style.GrabRounding = 16.f;
|
||||
|
||||
style.Colors[ImGuiCol_Text] = ImVec4(0.90f, 0.90f, 0.90f, 1.00f);
|
||||
style.Colors[ImGuiCol_TextDisabled] = ImVec4(0.60f, 0.60f, 0.60f, 1.00f);
|
||||
style.Colors[ImGuiCol_WindowBg] = ImVec4(0.13f, 0.13f, 0.13f, 0.96f);
|
||||
style.Colors[ImGuiCol_ChildBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
|
||||
style.Colors[ImGuiCol_PopupBg] = ImVec4(0.05f, 0.05f, 0.10f, 0.90f);
|
||||
style.Colors[ImGuiCol_Border] = ImVec4(0.65f, 0.65f, 0.65f, 0.59f);
|
||||
style.Colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
|
||||
style.Colors[ImGuiCol_FrameBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.30f);
|
||||
style.Colors[ImGuiCol_FrameBgHovered] = ImVec4(0.91f, 0.94f, 0.99f, 0.40f);
|
||||
style.Colors[ImGuiCol_FrameBgActive] = ImVec4(0.90f, 0.90f, 0.90f, 0.45f);
|
||||
style.Colors[ImGuiCol_TitleBg] = ImVec4(0.71f, 0.81f, 1.00f, 0.45f);
|
||||
style.Colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.71f, 0.81f, 1.00f, 0.45f);
|
||||
style.Colors[ImGuiCol_TitleBgActive] = ImVec4(0.51f, 0.69f, 1.00f, 0.63f);
|
||||
style.Colors[ImGuiCol_MenuBarBg] = ImVec4(0.26f, 0.27f, 0.33f, 0.80f);
|
||||
style.Colors[ImGuiCol_ScrollbarBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
|
||||
style.Colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.40f, 0.75f, 0.80f, 0.43f);
|
||||
style.Colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.40f, 0.75f, 0.80f, 0.65f);
|
||||
style.Colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.40f, 0.75f, 0.80f, 0.65f);
|
||||
style.Colors[ImGuiCol_CheckMark] = ImVec4(1.00f, 1.00f, 1.00f, 0.50f);
|
||||
style.Colors[ImGuiCol_SliderGrab] = ImVec4(1.00f, 1.00f, 1.00f, 0.30f);
|
||||
style.Colors[ImGuiCol_SliderGrabActive] = ImVec4(0.50f, 0.80f, 0.76f, 1.00f);
|
||||
style.Colors[ImGuiCol_Button] = ImVec4(0.36f, 0.54f, 0.68f, 0.62f);
|
||||
style.Colors[ImGuiCol_ButtonHovered] = ImVec4(0.36f, 0.54f, 0.68f, 1.00f);
|
||||
style.Colors[ImGuiCol_ButtonActive] = ImVec4(0.36f, 0.61f, 0.81f, 1.00f);
|
||||
style.Colors[ImGuiCol_Header] = ImVec4(0.69f, 0.69f, 0.69f, 0.45f);
|
||||
style.Colors[ImGuiCol_HeaderHovered] = ImVec4(0.36f, 0.54f, 0.68f, 0.62f);
|
||||
style.Colors[ImGuiCol_HeaderActive] = ImVec4(0.53f, 0.63f, 0.87f, 0.80f);
|
||||
style.Colors[ImGuiCol_Separator] = ImVec4(0.50f, 0.50f, 0.50f, 1.00f);
|
||||
style.Colors[ImGuiCol_SeparatorHovered] = ImVec4(0.70f, 0.60f, 0.60f, 1.00f);
|
||||
style.Colors[ImGuiCol_SeparatorActive] = ImVec4(0.90f, 0.70f, 0.70f, 1.00f);
|
||||
style.Colors[ImGuiCol_ResizeGrip] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
|
||||
style.Colors[ImGuiCol_ResizeGripHovered] = ImVec4(1.00f, 1.00f, 1.00f, 0.60f);
|
||||
style.Colors[ImGuiCol_ResizeGripActive] = ImVec4(1.00f, 1.00f, 1.00f, 0.90f);
|
||||
style.Colors[ImGuiCol_PlotLines] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
|
||||
style.Colors[ImGuiCol_PlotLinesHovered] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
|
||||
style.Colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
|
||||
style.Colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f);
|
||||
style.Colors[ImGuiCol_TextSelectedBg] = ImVec4(0.44f, 0.63f, 1.00f, 0.35f);
|
||||
style.Colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.20f, 0.20f, 0.20f, 0.35f);
|
||||
}
|
||||
|
||||
for (GuiComponent* comp : _components) {
|
||||
comp->initialize();
|
||||
}
|
||||
|
||||
_program = ghoul::opengl::ProgramObject::Build(
|
||||
"GUI",
|
||||
absPath("${MODULE_IMGUI}/shaders/gui_vs.glsl"),
|
||||
absPath("${MODULE_IMGUI}/shaders/gui_fs.glsl")
|
||||
);
|
||||
|
||||
ghoul::opengl::updateUniformLocations(*_program, _uniformCache, UniformNames);
|
||||
|
||||
{
|
||||
unsigned char* texData;
|
||||
glm::ivec2 texSize = glm::ivec2(0);
|
||||
for (int i = 0; i < nWindows; ++i) {
|
||||
//_contexts[i] = ImGui::CreateContext();
|
||||
ImGui::SetCurrentContext(_contexts[i]);
|
||||
|
||||
ImGui::GetIO().Fonts->GetTexDataAsRGBA32(&texData, &texSize.x, &texSize.y);
|
||||
}
|
||||
_fontTexture = std::make_unique<ghoul::opengl::Texture>(
|
||||
texData,
|
||||
glm::uvec3(texSize.x, texSize.y, 1),
|
||||
GL_TEXTURE_2D
|
||||
);
|
||||
_fontTexture->setName("Gui Text");
|
||||
_fontTexture->setDataOwnership(ghoul::opengl::Texture::TakeOwnership::No);
|
||||
_fontTexture->uploadTexture();
|
||||
}
|
||||
for (int i = 0; i < nWindows; ++i) {
|
||||
uintptr_t texture = static_cast<GLuint>(*_fontTexture);
|
||||
ImGui::SetCurrentContext(_contexts[i]);
|
||||
ImGui::GetIO().Fonts->TexID = reinterpret_cast<void*>(texture);
|
||||
}
|
||||
|
||||
glGenBuffers(1, &vbo);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, 0, nullptr, GL_DYNAMIC_DRAW);
|
||||
|
||||
glGenBuffers(1, &vboElements);
|
||||
|
||||
glGenVertexArrays(1, &vao);
|
||||
glBindVertexArray(vao);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
||||
|
||||
GLuint positionAttrib = _program->attributeLocation("in_position");
|
||||
GLuint uvAttrib = _program->attributeLocation("in_uv");
|
||||
GLuint colorAttrib = _program->attributeLocation("in_color");
|
||||
|
||||
glEnableVertexAttribArray(positionAttrib);
|
||||
glVertexAttribPointer(
|
||||
positionAttrib,
|
||||
2,
|
||||
GL_FLOAT,
|
||||
GL_FALSE,
|
||||
sizeof(ImDrawVert),
|
||||
nullptr
|
||||
);
|
||||
glEnableVertexAttribArray(uvAttrib);
|
||||
glVertexAttribPointer(
|
||||
uvAttrib,
|
||||
2,
|
||||
GL_FLOAT,
|
||||
GL_FALSE,
|
||||
sizeof(ImDrawVert),
|
||||
reinterpret_cast<GLvoid*>(offsetof(ImDrawVert, uv)) // NOLINT
|
||||
);
|
||||
glEnableVertexAttribArray(colorAttrib);
|
||||
glVertexAttribPointer(
|
||||
colorAttrib,
|
||||
4,
|
||||
GL_UNSIGNED_BYTE,
|
||||
GL_TRUE,
|
||||
sizeof(ImDrawVert),
|
||||
reinterpret_cast<GLvoid*>(offsetof(ImDrawVert, col)) // NOLINT
|
||||
);
|
||||
glBindVertexArray(0);
|
||||
|
||||
for (GuiComponent* comp : _components) {
|
||||
comp->initializeGL();
|
||||
}
|
||||
}
|
||||
|
||||
void GUI::deinitializeGL() {
|
||||
_program = nullptr;
|
||||
_fontTexture = nullptr;
|
||||
|
||||
glDeleteVertexArrays(1, &vao);
|
||||
glDeleteBuffers(1, &vbo);
|
||||
glDeleteBuffers(1, &vboElements);
|
||||
|
||||
for (GuiComponent* comp : _components) {
|
||||
comp->deinitializeGL();
|
||||
}
|
||||
}
|
||||
|
||||
void GUI::startFrame(float deltaTime, const glm::vec2& windowSize,
|
||||
const glm::vec2& dpiScaling, const glm::vec2& mousePos,
|
||||
uint32_t mouseButtonsPressed)
|
||||
{
|
||||
const int iWindow = global::windowDelegate->currentWindowId();
|
||||
ImGui::SetCurrentContext(_contexts[iWindow]);
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.DisplaySize = ImVec2(windowSize.x, windowSize.y);
|
||||
io.DisplayFramebufferScale = ImVec2(dpiScaling.x, dpiScaling.y);
|
||||
io.DeltaTime = deltaTime;
|
||||
|
||||
io.MousePos = ImVec2(mousePos.x, mousePos.y);
|
||||
|
||||
io.MouseDown[0] = mouseButtonsPressed & (1 << 0);
|
||||
io.MouseDown[1] = mouseButtonsPressed & (1 << 1);
|
||||
|
||||
ImGui::NewFrame();
|
||||
}
|
||||
|
||||
void GUI::endFrame() {
|
||||
if (_program->isDirty()) {
|
||||
_program->rebuildFromFile();
|
||||
ghoul::opengl::updateUniformLocations(*_program, _uniformCache, UniformNames);
|
||||
}
|
||||
|
||||
if (_isEnabled) {
|
||||
render();
|
||||
|
||||
for (GuiComponent* comp : _components) {
|
||||
if (comp->isEnabled()) {
|
||||
comp->render();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::Render();
|
||||
|
||||
if (!_isEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Drawing
|
||||
ImDrawData* drawData = ImGui::GetDrawData();
|
||||
|
||||
// Avoid rendering when minimized, scale coordinates for retina displays
|
||||
// (screen coordinates != framebuffer coordinates)
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
GLsizei fb_width = static_cast<GLsizei>(
|
||||
io.DisplaySize.x * io.DisplayFramebufferScale.x
|
||||
);
|
||||
GLsizei fb_height = static_cast<GLsizei>(
|
||||
io.DisplaySize.y * io.DisplayFramebufferScale.y
|
||||
);
|
||||
if (fb_width == 0 || fb_height == 0) {
|
||||
return;
|
||||
}
|
||||
drawData->ScaleClipRects(io.DisplayFramebufferScale);
|
||||
|
||||
// Setup render state:
|
||||
// alpha-blending enabled, no face culling, no depth testing, scissor enabled
|
||||
glEnable(GL_BLEND);
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glDisable(GL_CULL_FACE);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
|
||||
ghoul::opengl::TextureUnit unit;
|
||||
unit.activate();
|
||||
_fontTexture->bind();
|
||||
|
||||
// Setup orthographic projection matrix
|
||||
const float width = ImGui::GetIO().DisplaySize.x;
|
||||
const float height = ImGui::GetIO().DisplaySize.y;
|
||||
glViewport(0, 0, fb_width, fb_height);
|
||||
const glm::mat4 ortho(
|
||||
2.f / width, 0.0f, 0.0f, 0.f,
|
||||
0.0f, 2.0f / -height, 0.0f, 0.f,
|
||||
0.0f, 0.0f, -1.0f, 0.0f,
|
||||
-1.0f, 1.0f, 0.0f, 1.0f
|
||||
);
|
||||
_program->activate();
|
||||
|
||||
_program->setUniform(_uniformCache.tex, unit);
|
||||
_program->setUniform(_uniformCache.ortho, ortho);
|
||||
|
||||
glBindVertexArray(vao);
|
||||
|
||||
for (int i = 0; i < drawData->CmdListsCount; ++i) {
|
||||
const ImDrawList* cmdList = drawData->CmdLists[i];
|
||||
const ImDrawIdx* indexBufferOffset = nullptr;
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
||||
glBufferData(
|
||||
GL_ARRAY_BUFFER,
|
||||
cmdList->VtxBuffer.size() * sizeof(ImDrawVert),
|
||||
reinterpret_cast<const GLvoid*>(&cmdList->VtxBuffer.front()),
|
||||
GL_STREAM_DRAW
|
||||
);
|
||||
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboElements);
|
||||
glBufferData(
|
||||
GL_ELEMENT_ARRAY_BUFFER,
|
||||
cmdList->IdxBuffer.size() * sizeof(ImDrawIdx),
|
||||
reinterpret_cast<const GLvoid*>(&cmdList->IdxBuffer.front()),
|
||||
GL_STREAM_DRAW
|
||||
);
|
||||
|
||||
for (const ImDrawCmd* pcmd = cmdList->CmdBuffer.begin();
|
||||
pcmd != cmdList->CmdBuffer.end();
|
||||
pcmd++)
|
||||
{
|
||||
if (pcmd->UserCallback) {
|
||||
pcmd->UserCallback(cmdList, pcmd);
|
||||
}
|
||||
else {
|
||||
glBindTexture(
|
||||
GL_TEXTURE_2D,
|
||||
static_cast<GLuint>(reinterpret_cast<intptr_t>(pcmd->TextureId))
|
||||
);
|
||||
glScissor(
|
||||
static_cast<int>(pcmd->ClipRect.x),
|
||||
static_cast<int>(fb_height - pcmd->ClipRect.w),
|
||||
static_cast<int>(pcmd->ClipRect.z - pcmd->ClipRect.x),
|
||||
static_cast<int>(pcmd->ClipRect.w - pcmd->ClipRect.y)
|
||||
);
|
||||
glDrawElements(
|
||||
GL_TRIANGLES,
|
||||
static_cast<GLsizei>(pcmd->ElemCount),
|
||||
sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
|
||||
indexBufferOffset
|
||||
);
|
||||
}
|
||||
indexBufferOffset += pcmd->ElemCount;
|
||||
}
|
||||
}
|
||||
|
||||
glBindVertexArray(0);
|
||||
_program->deactivate();
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
}
|
||||
|
||||
bool GUI::mouseButtonCallback(MouseButton, MouseAction) {
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
bool consumeEvent = io.WantCaptureMouse;
|
||||
return consumeEvent;
|
||||
}
|
||||
|
||||
bool GUI::mouseWheelCallback(double position) {
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
bool consumeEvent = io.WantCaptureMouse;
|
||||
if (consumeEvent) {
|
||||
io.MouseWheel = static_cast<float>(position);
|
||||
}
|
||||
|
||||
return consumeEvent;
|
||||
}
|
||||
|
||||
bool GUI::keyCallback(Key key, KeyModifier modifier, KeyAction action) {
|
||||
const int keyIndex = static_cast<int>(key);
|
||||
if (keyIndex < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const bool hasShift = hasKeyModifier(modifier, KeyModifier::Shift);
|
||||
const bool hasCtrl = hasKeyModifier(modifier, KeyModifier::Control);
|
||||
const bool hasAlt = hasKeyModifier(modifier, KeyModifier::Alt);
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
const bool consumeEvent = io.WantCaptureKeyboard;
|
||||
if (consumeEvent) {
|
||||
if (action == KeyAction::Press) {
|
||||
io.KeysDown[keyIndex] = true;
|
||||
}
|
||||
io.KeyShift = hasShift;
|
||||
io.KeyCtrl = hasCtrl;
|
||||
io.KeyAlt = hasAlt;
|
||||
}
|
||||
|
||||
// Even if the event is not consumed,
|
||||
// set keys and modifiers to false when they are released.
|
||||
if (action == KeyAction::Release) {
|
||||
io.KeysDown[keyIndex] = false;
|
||||
}
|
||||
if (!hasShift) {
|
||||
io.KeyShift = false;
|
||||
}
|
||||
if (!hasCtrl) {
|
||||
io.KeyCtrl = false;
|
||||
}
|
||||
if (!hasAlt) {
|
||||
io.KeyAlt = false;
|
||||
}
|
||||
|
||||
return consumeEvent;
|
||||
}
|
||||
|
||||
bool GUI::charCallback(unsigned int character, KeyModifier) {
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
bool consumeEvent = io.WantCaptureKeyboard;
|
||||
|
||||
if (consumeEvent) {
|
||||
io.AddInputCharacter(static_cast<unsigned short>(character));
|
||||
}
|
||||
|
||||
return consumeEvent;
|
||||
}
|
||||
|
||||
bool GUI::touchDetectedCallback(TouchInput input) {
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
const glm::vec2 windowPos = input.currentWindowCoordinates();
|
||||
const bool consumeEvent = io.WantCaptureMouse;
|
||||
|
||||
if (!consumeEvent) {
|
||||
return false;
|
||||
}
|
||||
if (_validTouchStates.empty()) {
|
||||
io.MousePos = {windowPos.x, windowPos.y};
|
||||
io.MouseClicked[0] = true;
|
||||
}
|
||||
_validTouchStates.push_back(input);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GUI::touchUpdatedCallback(TouchInput input) {
|
||||
if (_validTouchStates.empty()) {
|
||||
return false;
|
||||
}
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
auto it = std::find_if(
|
||||
_validTouchStates.cbegin(),
|
||||
_validTouchStates.cend(),
|
||||
[&](const TouchInput& state){
|
||||
return state.fingerId == input.fingerId &&
|
||||
state.touchDeviceId == input.touchDeviceId;
|
||||
}
|
||||
);
|
||||
|
||||
if (it == _validTouchStates.cbegin()) {
|
||||
glm::vec2 windowPos = input.currentWindowCoordinates();
|
||||
io.MousePos = {windowPos.x, windowPos.y};
|
||||
io.MouseClicked[0] = true;
|
||||
return true;
|
||||
}
|
||||
else if (it != _validTouchStates.cend()){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void GUI::touchExitCallback(TouchInput input) {
|
||||
if (_validTouchStates.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto found = std::find_if(
|
||||
_validTouchStates.cbegin(),
|
||||
_validTouchStates.cend(),
|
||||
[&](const TouchInput& state){
|
||||
return state.fingerId == input.fingerId &&
|
||||
state.touchDeviceId == input.touchDeviceId;
|
||||
}
|
||||
);
|
||||
|
||||
if (found == _validTouchStates.cend()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
_validTouchStates.erase(found);
|
||||
if (_validTouchStates.empty()) {
|
||||
glm::vec2 windowPos = input.currentWindowCoordinates();
|
||||
io.MousePos = {windowPos.x, windowPos.y};
|
||||
io.MouseClicked[0] = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GUI::render() {
|
||||
ImGui::SetNextWindowCollapsed(_isCollapsed);
|
||||
|
||||
ImGui::Begin("OpenSpace GUI", nullptr);
|
||||
|
||||
_isCollapsed = ImGui::IsWindowCollapsed();
|
||||
|
||||
for (GuiComponent* comp : _components) {
|
||||
bool enabled = comp->isEnabled();
|
||||
ImGui::Checkbox(comp->guiName().c_str(), &enabled);
|
||||
comp->setEnabled(enabled);
|
||||
}
|
||||
|
||||
renderAndUpdatePropertyVisibility();
|
||||
|
||||
static const int addImageBufferSize = 256;
|
||||
static char identifierBuffer[addImageBufferSize];
|
||||
static char addImageLocalBuffer[addImageBufferSize];
|
||||
static char addImageOnlineBuffer[addImageBufferSize];
|
||||
|
||||
ImGui::InputText(
|
||||
"Identifier for Local/Online Images",
|
||||
identifierBuffer,
|
||||
addImageBufferSize
|
||||
);
|
||||
|
||||
bool addImageLocal = ImGui::InputText(
|
||||
"Add Local Image",
|
||||
addImageLocalBuffer,
|
||||
addImageBufferSize,
|
||||
ImGuiInputTextFlags_EnterReturnsTrue
|
||||
);
|
||||
if (addImageLocal) {
|
||||
addScreenSpaceRenderableLocal(
|
||||
std::string(identifierBuffer),
|
||||
std::string(addImageLocalBuffer)
|
||||
);
|
||||
}
|
||||
|
||||
bool addImageOnline = ImGui::InputText(
|
||||
"Add Online Image",
|
||||
addImageOnlineBuffer,
|
||||
addImageBufferSize,
|
||||
ImGuiInputTextFlags_EnterReturnsTrue
|
||||
);
|
||||
|
||||
if (addImageOnline) {
|
||||
addScreenSpaceRenderableOnline(
|
||||
std::string(identifierBuffer),
|
||||
std::string(addImageOnlineBuffer)
|
||||
);
|
||||
}
|
||||
|
||||
bool addDashboard = ImGui::Button("Add New Dashboard");
|
||||
if (addDashboard) {
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.addScreenSpaceRenderable({ Type = 'ScreenSpaceDashboard' });",
|
||||
openspace::scripting::ScriptEngine::RemoteScripting::Yes
|
||||
);
|
||||
}
|
||||
|
||||
bool addDashboardCopy = ImGui::Button("Add Copy of Main Dashboard");
|
||||
if (addDashboardCopy) {
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.addScreenSpaceRenderable({ "
|
||||
"Type = 'ScreenSpaceDashboard', UseMainDashboard = true "
|
||||
"});",
|
||||
openspace::scripting::ScriptEngine::RemoteScripting::Yes
|
||||
);
|
||||
}
|
||||
|
||||
#ifdef SHOW_IMGUI_HELPERS
|
||||
ImGui::Checkbox("ImGUI Internals", &_showInternals);
|
||||
if (_showInternals) {
|
||||
ImGui::Begin("Style Editor");
|
||||
ImGui::ShowStyleEditor();
|
||||
ImGui::End();
|
||||
|
||||
ImGui::Begin("Test Window");
|
||||
ImGui::ShowDemoWindow();
|
||||
ImGui::End();
|
||||
|
||||
ImGui::Begin("Metrics Window");
|
||||
ImGui::ShowMetricsWindow();
|
||||
ImGui::End();
|
||||
}
|
||||
#endif
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
void GUI::renderAndUpdatePropertyVisibility() {
|
||||
// Fragile! Keep this in sync with properties::Property::Visibility
|
||||
using V = properties::Property::Visibility;
|
||||
int t = static_cast<std::underlying_type_t<V>>(_currentVisibility);
|
||||
|
||||
// Array is sorted by importance
|
||||
std::array<const char*, 4> items = { "User", "Developer", "Hidden", "All"};
|
||||
ImGui::Combo("PropertyVisibility", &t, items.data(), static_cast<int>(items.size()));
|
||||
|
||||
_currentVisibility = static_cast<V>(t);
|
||||
_globalProperty.setVisibility(_currentVisibility);
|
||||
_moduleProperty.setVisibility(_currentVisibility);
|
||||
_sceneProperty.setVisibility(_currentVisibility);
|
||||
_screenSpaceProperty.setVisibility(_currentVisibility);
|
||||
_featuredProperties.setVisibility(_currentVisibility);
|
||||
}
|
||||
|
||||
} // namespace openspace::gui
|
||||
@@ -24,19 +24,18 @@
|
||||
|
||||
#include <modules/imgui/include/guiactioncomponent.h>
|
||||
|
||||
#include <modules/imgui/include/gui.h>
|
||||
#include <modules/imgui/imguimodule.h>
|
||||
#include <modules/imgui/include/imgui_include.h>
|
||||
#include <openspace/engine/globals.h>
|
||||
#include <openspace/interaction/actionmanager.h>
|
||||
#include <openspace/interaction/keybindingmanager.h>
|
||||
#include <openspace/scripting/scriptengine.h>
|
||||
#include <openspace/util/keys.h>
|
||||
|
||||
#include <modules/imgui/include/imgui_include.h>
|
||||
#include <set>
|
||||
|
||||
namespace openspace::gui {
|
||||
|
||||
GuiActionComponent::GuiActionComponent()
|
||||
: GuiComponent("Shortcuts", "Shortcuts")
|
||||
: GuiComponent("Actions", "Actions")
|
||||
{}
|
||||
|
||||
void GuiActionComponent::render() {
|
||||
@@ -92,6 +91,7 @@ void GuiActionComponent::render() {
|
||||
ImGui::Text("(%s)", "local");
|
||||
}
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
} // namespace openspace::gui
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
namespace openspace::gui {
|
||||
|
||||
GuiFilePathComponent::GuiFilePathComponent() : GuiComponent("FilePath", "File Path") {}
|
||||
GuiFilePathComponent::GuiFilePathComponent() : GuiComponent("FilePaths", "File Paths") {}
|
||||
|
||||
void GuiFilePathComponent::render() {
|
||||
ImGui::SetNextWindowCollapsed(_isCollapsed);
|
||||
|
||||
@@ -1,225 +0,0 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2022 *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
|
||||
* software and associated documentation files (the "Software"), to deal in the Software *
|
||||
* without restriction, including without limitation the rights to use, copy, modify, *
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
|
||||
* permit persons to whom the Software is furnished to do so, subject to the following *
|
||||
* conditions: *
|
||||
* *
|
||||
* The above copyright notice and this permission notice shall be included in all copies *
|
||||
* or substantial portions of the Software. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#ifdef OPENSPACE_MODULE_ISWA_ENABLED
|
||||
|
||||
#include <modules/imgui/include/guiiswacomponent.h>
|
||||
|
||||
#include <modules/imgui/include/imgui_include.h>
|
||||
#include <modules/iswa/util/iswamanager.h>
|
||||
#include <openspace/json.h>
|
||||
#include <ghoul/filesystem/filesystem.h>
|
||||
|
||||
#include <openspace/engine/globals.h>
|
||||
#include <openspace/scripting/scriptengine.h>
|
||||
|
||||
namespace {
|
||||
using json = nlohmann::json;
|
||||
const ImVec2 WindowSize = ImVec2(350, 500);
|
||||
} // namespace
|
||||
|
||||
namespace openspace::gui {
|
||||
|
||||
GuiIswaComponent::GuiIswaComponent() : GuiPropertyComponent("iSWA") {}
|
||||
|
||||
void GuiIswaComponent::render() {
|
||||
#ifdef OPENSPACE_MODULE_ISWA_ENABLED
|
||||
const bool oldGmDataValue = _gmData;
|
||||
const bool oldGmImageValue = _gmImage;
|
||||
const bool oldIonDataValue = _ionData;
|
||||
|
||||
ImGui::SetNextWindowCollapsed(_isCollapsed);
|
||||
|
||||
bool e = _isEnabled;
|
||||
ImGui::Begin("ISWA", &e, WindowSize, 0.5f);
|
||||
_isEnabled = e;
|
||||
_isCollapsed = ImGui::IsWindowCollapsed();
|
||||
|
||||
ImGui::Text("Global Magnetosphere");
|
||||
ImGui::Checkbox("Gm From Data", &_gmData);
|
||||
ImGui::SameLine();
|
||||
ImGui::Checkbox("Gm From Images", &_gmImage);
|
||||
|
||||
ImGui::Text("Ionosphere");
|
||||
ImGui::Checkbox("Ion From Data", &_ionData);
|
||||
|
||||
ImGui::Spacing();
|
||||
constexpr const int AddCygnetBufferSize = 256;
|
||||
static char addCygnetBuffer[AddCygnetBufferSize];
|
||||
ImGui::InputText("addCynget", addCygnetBuffer, AddCygnetBufferSize);
|
||||
|
||||
if (ImGui::SmallButton("Add Cygnet")) {
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.iswa.addCygnet(" + std::string(addCygnetBuffer) + ");",
|
||||
scripting::ScriptEngine::RemoteScripting::Yes
|
||||
);
|
||||
}
|
||||
|
||||
if (_gmData != oldGmDataValue) {
|
||||
if (_gmData) {
|
||||
constexpr const char* script = R"(
|
||||
openspace.iswa.addCygnet(-4, 'Data', 'GMData');
|
||||
openspace.iswa.addCygnet(-5, 'Data', 'GMData');
|
||||
openspace.iswa.addCygnet(-6, 'Data', 'GMData');
|
||||
)";
|
||||
global::scriptEngine->queueScript(
|
||||
script,
|
||||
scripting::ScriptEngine::RemoteScripting::Yes
|
||||
);
|
||||
}
|
||||
else {
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.iswa.removeGroup('GMData');",
|
||||
scripting::ScriptEngine::RemoteScripting::Yes
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (_gmImage != oldGmImageValue) {
|
||||
if (_gmImage) {
|
||||
constexpr const char* script = R"(
|
||||
openspace.iswa.addCygnet(-4, 'Texture', 'GMImage');
|
||||
openspace.iswa.addCygnet(-5, 'Texture', 'GMImage');
|
||||
openspace.iswa.addCygnet(-6, 'Texture', 'GMImage');
|
||||
)";
|
||||
global::scriptEngine->queueScript(
|
||||
script,
|
||||
scripting::ScriptEngine::RemoteScripting::Yes
|
||||
);
|
||||
}
|
||||
else {
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.iswa.removeGroup('GMImage');",
|
||||
scripting::ScriptEngine::RemoteScripting::Yes
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (_ionData != oldIonDataValue) {
|
||||
if (_ionData) {
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.iswa.addCygnet(-10, 'Data', 'Ionosphere');",
|
||||
scripting::ScriptEngine::RemoteScripting::Yes
|
||||
);
|
||||
}
|
||||
else {
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.iswa.removeGroup('Ionosphere');",
|
||||
scripting::ScriptEngine::RemoteScripting::Yes
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui::CollapsingHeader("Cdf Files")) {
|
||||
const std::map<std::string, std::vector<CdfInfo>>& cdfInfo =
|
||||
IswaManager::ref().cdfInformation();
|
||||
|
||||
using K = std::string;
|
||||
using V = std::vector<CdfInfo>;
|
||||
for (const std::pair<const K, V>& group : cdfInfo) {
|
||||
const std::string& groupName = group.first;
|
||||
if (_cdfOptionsMap.find(groupName) == _cdfOptionsMap.end()) {
|
||||
_cdfOptionsMap[groupName] = -1;
|
||||
}
|
||||
|
||||
if (ImGui::CollapsingHeader(groupName.c_str())) {
|
||||
int cdfOptionValue = _cdfOptionsMap[groupName];
|
||||
const std::vector<CdfInfo>& cdfs = group.second;
|
||||
|
||||
for (size_t i = 0; i < cdfs.size(); ++i) {
|
||||
ImGui::RadioButton(
|
||||
cdfs[i].name.c_str(),
|
||||
&_cdfOptionsMap[groupName],
|
||||
static_cast<int>(i)
|
||||
);
|
||||
}
|
||||
|
||||
const int cdfOption = _cdfOptionsMap[groupName];
|
||||
if (cdfOptionValue != cdfOption) {
|
||||
const std::string& date = cdfs[cdfOption].date;
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.iswa.addKameleonPlanes('" +
|
||||
cdfs[cdfOption].group +
|
||||
"'," +
|
||||
std::to_string(cdfOption) +
|
||||
");",
|
||||
scripting::ScriptEngine::RemoteScripting::Yes
|
||||
);
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.time.setTime('" + date + "');",
|
||||
scripting::ScriptEngine::RemoteScripting::Yes
|
||||
);
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.time.setDeltaTime(0);",
|
||||
scripting::ScriptEngine::RemoteScripting::Yes
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GuiPropertyComponent::render();
|
||||
|
||||
if (ImGui::CollapsingHeader("iSWA screen space cygntes")) {
|
||||
const std::map<int, std::shared_ptr<CygnetInfo>>& map =
|
||||
IswaManager::ref().cygnetInformation();
|
||||
|
||||
for (const std::pair<const int, std::shared_ptr<CygnetInfo>>& cygnetInfo : map) {
|
||||
int id = cygnetInfo.first;
|
||||
CygnetInfo& info = *cygnetInfo.second;
|
||||
|
||||
bool selected = info.selected;
|
||||
ImGui::Checkbox(info.name.c_str(), &info.selected);
|
||||
ImGui::SameLine();
|
||||
|
||||
if (ImGui::CollapsingHeader(("Description" + std::to_string(id)).c_str())) {
|
||||
ImGui::TextWrapped("%s", info.description.c_str());
|
||||
ImGui::Spacing();
|
||||
}
|
||||
|
||||
if (selected != info.selected) {
|
||||
const std::string idStr = std::to_string(id);
|
||||
if (info.selected) {
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.iswa.addScreenSpaceCygnet({CygnetId=" + idStr + "});",
|
||||
scripting::ScriptEngine::RemoteScripting::Yes
|
||||
);
|
||||
}
|
||||
else {
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.iswa.removeScreenSpaceCygnet(" + idStr + ");",
|
||||
scripting::ScriptEngine::RemoteScripting::Yes
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace openspace::gui
|
||||
|
||||
#endif // OPENSPACE_MODULE_ISWA_ENABLED
|
||||
@@ -24,13 +24,11 @@
|
||||
|
||||
#include <modules/imgui/include/guimissioncomponent.h>
|
||||
|
||||
#include <modules/imgui/include/gui.h>
|
||||
#include <modules/imgui/imguimodule.h>
|
||||
#include <modules/imgui/include/imgui_include.h>
|
||||
#include <openspace/engine/globals.h>
|
||||
#include <openspace/mission/mission.h>
|
||||
#include <openspace/mission/missionmanager.h>
|
||||
#include <openspace/util/timerange.h>
|
||||
#include <openspace/util/time.h>
|
||||
#include <openspace/util/timemanager.h>
|
||||
|
||||
namespace {
|
||||
@@ -61,7 +59,7 @@ namespace {
|
||||
openspace::Time startTime = openspace::Time(range.start);
|
||||
openspace::Time endTime = openspace::Time(range.end);
|
||||
|
||||
openspace::gui::CaptionText("Mission Progress");
|
||||
openspace::CaptionText("Mission Progress");
|
||||
|
||||
ImGui::Text("%s", std::string(startTime.UTC()).c_str());
|
||||
ImGui::SameLine();
|
||||
@@ -79,7 +77,7 @@ namespace {
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("%s", std::string(endTime.UTC()).c_str());
|
||||
|
||||
openspace::gui::CaptionText("Phases");
|
||||
openspace::CaptionText("Phases");
|
||||
|
||||
for (const openspace::Mission& m : mission.phases()) {
|
||||
renderMission(m);
|
||||
@@ -98,9 +96,7 @@ GuiMissionComponent::GuiMissionComponent()
|
||||
{}
|
||||
|
||||
void GuiMissionComponent::render() {
|
||||
if (!global::missionManager->hasCurrentMission()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
ImGui::SetNextWindowCollapsed(_isCollapsed);
|
||||
bool v = _isEnabled;
|
||||
@@ -111,8 +107,13 @@ void GuiMissionComponent::render() {
|
||||
|
||||
_isCollapsed = ImGui::IsWindowCollapsed();
|
||||
|
||||
const Mission& currentMission = global::missionManager->currentMission();
|
||||
renderMission(currentMission);
|
||||
if (global::missionManager->hasCurrentMission()) {
|
||||
const Mission& currentMission = global::missionManager->currentMission();
|
||||
renderMission(currentMission);
|
||||
}
|
||||
else {
|
||||
ImGui::Text("%s", "No mission loaded");
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
@@ -159,7 +159,6 @@ void GuiParallelComponent::renderHost() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GuiParallelComponent::render() {
|
||||
ImGui::SetNextWindowCollapsed(_isCollapsed);
|
||||
bool v = _isEnabled;
|
||||
|
||||
@@ -194,8 +194,16 @@ GuiPropertyComponent::GuiPropertyComponent(std::string identifier, std::string g
|
||||
addProperty(_ignoreHiddenHint);
|
||||
}
|
||||
|
||||
void GuiPropertyComponent::setSource(SourceFunction function) {
|
||||
_function = std::move(function);
|
||||
void GuiPropertyComponent::setPropertyOwners(
|
||||
std::vector<properties::PropertyOwner*> propertyOwners)
|
||||
{
|
||||
_propertyOwners = std::move(propertyOwners);
|
||||
}
|
||||
|
||||
void GuiPropertyComponent::setPropertyOwnerFunction(
|
||||
std::function<std::vector<properties::PropertyOwner*>()> func)
|
||||
{
|
||||
_propertyOwnerFunction = std::move(func);
|
||||
}
|
||||
|
||||
void GuiPropertyComponent::setVisibility(properties::Property::Visibility visibility) {
|
||||
@@ -282,182 +290,167 @@ void GuiPropertyComponent::render() {
|
||||
_isCollapsed = ImGui::IsWindowCollapsed();
|
||||
using namespace properties;
|
||||
|
||||
if (_function) {
|
||||
std::vector<properties::PropertyOwner*> owners = _function();
|
||||
std::vector<properties::PropertyOwner*> owners =
|
||||
_propertyOwnerFunction ? _propertyOwnerFunction() : _propertyOwners;
|
||||
|
||||
std::sort(
|
||||
std::sort(
|
||||
owners.begin(),
|
||||
owners.end(),
|
||||
[](properties::PropertyOwner* lhs, properties::PropertyOwner* rhs) {
|
||||
return lhs->guiName() < rhs->guiName();
|
||||
}
|
||||
);
|
||||
|
||||
if (_useTreeLayout) {
|
||||
for (properties::PropertyOwner* owner : owners) {
|
||||
ghoul_assert(
|
||||
dynamic_cast<SceneGraphNode*>(owner),
|
||||
"When using the tree layout, all owners must be SceneGraphNodes"
|
||||
);
|
||||
(void)owner; // using [[maybe_unused]] in the for loop gives an error
|
||||
}
|
||||
|
||||
// Sort:
|
||||
// if guigrouping, sort by name and shortest first, but respect the user specified
|
||||
// ordering then all w/o guigroup
|
||||
const std::vector<std::string>& ordering = _treeOrdering;
|
||||
std::stable_sort(
|
||||
owners.begin(),
|
||||
owners.end(),
|
||||
[](properties::PropertyOwner* lhs, properties::PropertyOwner* rhs) {
|
||||
return lhs->guiName() < rhs->guiName();
|
||||
}
|
||||
);
|
||||
[&ordering](PropertyOwner* lhs, PropertyOwner* rhs) {
|
||||
std::string lhsGroup = dynamic_cast<SceneGraphNode*>(lhs)->guiPath();
|
||||
std::string rhsGroup = dynamic_cast<SceneGraphNode*>(rhs)->guiPath();
|
||||
|
||||
if (_useTreeLayout) {
|
||||
for (properties::PropertyOwner* owner : owners) {
|
||||
ghoul_assert(
|
||||
dynamic_cast<SceneGraphNode*>(owner),
|
||||
"When using the tree layout, all owners must be SceneGraphNodes"
|
||||
);
|
||||
(void)owner; // using [[maybe_unused]] in the for loop gives an error
|
||||
}
|
||||
if (lhsGroup.empty()) {
|
||||
return false;
|
||||
}
|
||||
if (rhsGroup.empty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Sort:
|
||||
// if guigrouping, sort by name and shortest first, but respect the user
|
||||
// specified ordering
|
||||
// then all w/o guigroup
|
||||
const std::vector<std::string>& ordering = _treeOrdering;
|
||||
std::stable_sort(
|
||||
owners.begin(),
|
||||
owners.end(),
|
||||
[&ordering](PropertyOwner* lhs, PropertyOwner* rhs) {
|
||||
std::string lhsGroup = dynamic_cast<SceneGraphNode*>(lhs)->guiPath();
|
||||
std::string rhsGroup = dynamic_cast<SceneGraphNode*>(rhs)->guiPath();
|
||||
if (ordering.empty()) {
|
||||
return lhsGroup < rhsGroup;
|
||||
}
|
||||
|
||||
if (lhsGroup.empty()) {
|
||||
return false;
|
||||
}
|
||||
if (rhsGroup.empty()) {
|
||||
return true;
|
||||
}
|
||||
std::vector<std::string> lhsToken = ghoul::tokenizeString(lhsGroup, '/');
|
||||
// The first token is always empty
|
||||
auto lhsIt = std::find(ordering.begin(), ordering.end(), lhsToken[1]);
|
||||
|
||||
if (ordering.empty()) {
|
||||
return lhsGroup < rhsGroup;
|
||||
}
|
||||
std::vector<std::string> rhsToken = ghoul::tokenizeString(rhsGroup, '/');
|
||||
// The first token is always empty
|
||||
auto rhsIt = std::find(ordering.begin(), ordering.end(), rhsToken[1]);
|
||||
|
||||
std::vector<std::string> lhsToken = ghoul::tokenizeString(
|
||||
lhsGroup,
|
||||
'/'
|
||||
);
|
||||
// The first token is always empty
|
||||
auto lhsIt = std::find(ordering.begin(), ordering.end(), lhsToken[1]);
|
||||
|
||||
std::vector<std::string> rhsToken = ghoul::tokenizeString(
|
||||
rhsGroup,
|
||||
'/'
|
||||
);
|
||||
// The first token is always empty
|
||||
auto rhsIt = std::find(ordering.begin(), ordering.end(), rhsToken[1]);
|
||||
|
||||
if (lhsIt != ordering.end() && rhsIt != ordering.end()) {
|
||||
if (lhsToken[1] != rhsToken[1]) {
|
||||
// If both top-level groups are in the ordering list, the
|
||||
// order of the iterators gives us the order of the groups
|
||||
return lhsIt < rhsIt;
|
||||
}
|
||||
else {
|
||||
return lhsGroup < rhsGroup;
|
||||
}
|
||||
}
|
||||
else if (lhsIt != ordering.end() && rhsIt == ordering.end()) {
|
||||
// If only one of them is in the list, we have a sorting
|
||||
return true;
|
||||
}
|
||||
else if (lhsIt == ordering.end() && rhsIt != ordering.end()) {
|
||||
return false;
|
||||
if (lhsIt != ordering.end() && rhsIt != ordering.end()) {
|
||||
if (lhsToken[1] != rhsToken[1]) {
|
||||
// If both top-level groups are in the ordering list, the
|
||||
// order of the iterators gives us the order of the groups
|
||||
return lhsIt < rhsIt;
|
||||
}
|
||||
else {
|
||||
return lhsGroup < rhsGroup;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// If the owners list is empty, we wnat to do the normal thing (-> nothing)
|
||||
// Otherwise, check if the first owner has a GUI group
|
||||
// This makes the assumption that the tree layout is only used if the owners are
|
||||
// SceenGraphNodes (checked above)
|
||||
const bool noGuiGroups = owners.empty() ||
|
||||
(dynamic_cast<SceneGraphNode*>(*owners.begin()) &&
|
||||
dynamic_cast<SceneGraphNode*>(*owners.begin())->guiPath().empty());
|
||||
|
||||
auto renderProp = [&](properties::PropertyOwner* pOwner) {
|
||||
const int count = nVisibleProperties(
|
||||
pOwner->propertiesRecursive(),
|
||||
_visibility
|
||||
);
|
||||
|
||||
if (count == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto header = [&]() -> bool {
|
||||
if (owners.size() > 1) {
|
||||
// Create a header in case we have multiple owners
|
||||
return ImGui::CollapsingHeader(pOwner->guiName().c_str());
|
||||
}
|
||||
else if (!pOwner->identifier().empty()) {
|
||||
// If the owner has a name, print it first
|
||||
ImGui::Text("%s", pOwner->guiName().c_str());
|
||||
ImGui::Spacing();
|
||||
else if (lhsIt != ordering.end() && rhsIt == ordering.end()) {
|
||||
// If only one of them is in the list, we have a sorting
|
||||
return true;
|
||||
}
|
||||
else if (lhsIt == ordering.end() && rhsIt != ordering.end()) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
// Otherwise, do nothing
|
||||
return true;
|
||||
return lhsGroup < rhsGroup;
|
||||
}
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
if (header()) {
|
||||
renderPropertyOwner(pOwner);
|
||||
// If the owners list is empty, we wnat to do the normal thing (-> nothing)
|
||||
// Otherwise, check if the first owner has a GUI group
|
||||
// This makes the assumption that the tree layout is only used if the owners are
|
||||
// SceenGraphNodes (checked above)
|
||||
const bool noGuiGroups = owners.empty() ||
|
||||
(dynamic_cast<SceneGraphNode*>(*owners.begin()) &&
|
||||
dynamic_cast<SceneGraphNode*>(*owners.begin())->guiPath().empty());
|
||||
|
||||
auto renderProp = [&](properties::PropertyOwner* pOwner) {
|
||||
const int count = nVisibleProperties(pOwner->propertiesRecursive(), _visibility);
|
||||
|
||||
if (count == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto header = [&]() -> bool {
|
||||
if (owners.size() > 1) {
|
||||
// Create a header in case we have multiple owners
|
||||
return ImGui::CollapsingHeader(pOwner->guiName().c_str());
|
||||
}
|
||||
else if (!pOwner->identifier().empty()) {
|
||||
// If the owner has a name, print it first
|
||||
ImGui::Text("%s", pOwner->guiName().c_str());
|
||||
ImGui::Spacing();
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
// Otherwise, do nothing
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
if (!_useTreeLayout || noGuiGroups) {
|
||||
if (!_ignoreHiddenHint) {
|
||||
// Remove all of the nodes that we want hidden first
|
||||
owners.erase(
|
||||
std::remove_if(
|
||||
owners.begin(),
|
||||
owners.end(),
|
||||
[](properties::PropertyOwner* p) {
|
||||
SceneGraphNode* s = dynamic_cast<SceneGraphNode*>(p);
|
||||
return s && s->hasGuiHintHidden();
|
||||
}
|
||||
),
|
||||
owners.end()
|
||||
);
|
||||
}
|
||||
std::for_each(owners.begin(), owners.end(), renderProp);
|
||||
if (header()) {
|
||||
renderPropertyOwner(pOwner);
|
||||
}
|
||||
else { // _useTreeLayout && gui groups exist
|
||||
TreeNode root("");
|
||||
};
|
||||
|
||||
for (properties::PropertyOwner* pOwner : owners) {
|
||||
// We checked above that pOwner is a SceneGraphNode
|
||||
SceneGraphNode* nOwner = static_cast<SceneGraphNode*>(pOwner);
|
||||
if (!_ignoreHiddenHint && nOwner->hasGuiHintHidden()) {
|
||||
continue;
|
||||
}
|
||||
const std::string guiPath = nOwner->guiPath();
|
||||
if (guiPath.empty()) {
|
||||
// We know that we are done now since we stable_sort:ed them above
|
||||
break;
|
||||
}
|
||||
std::vector<std::string> paths = ghoul::tokenizeString(
|
||||
guiPath.substr(1),
|
||||
'/'
|
||||
);
|
||||
if (!_useTreeLayout || noGuiGroups) {
|
||||
if (!_ignoreHiddenHint) {
|
||||
// Remove all of the nodes that we want hidden first
|
||||
owners.erase(
|
||||
std::remove_if(
|
||||
owners.begin(),
|
||||
owners.end(),
|
||||
[](properties::PropertyOwner* p) {
|
||||
SceneGraphNode* s = dynamic_cast<SceneGraphNode*>(p);
|
||||
return s && s->hasGuiHintHidden();
|
||||
}
|
||||
),
|
||||
owners.end()
|
||||
);
|
||||
}
|
||||
std::for_each(owners.begin(), owners.end(), renderProp);
|
||||
}
|
||||
else { // _useTreeLayout && gui groups exist
|
||||
TreeNode root("");
|
||||
|
||||
addPathToTree(root, paths, nOwner);
|
||||
for (properties::PropertyOwner* pOwner : owners) {
|
||||
// We checked above that pOwner is a SceneGraphNode
|
||||
SceneGraphNode* nOwner = static_cast<SceneGraphNode*>(pOwner);
|
||||
if (!_ignoreHiddenHint && nOwner->hasGuiHintHidden()) {
|
||||
continue;
|
||||
}
|
||||
const std::string gui = nOwner->guiPath();
|
||||
if (gui.empty()) {
|
||||
// We know that we are done now since we stable_sort:ed them above
|
||||
break;
|
||||
}
|
||||
std::vector<std::string> paths = ghoul::tokenizeString(gui.substr(1), '/');
|
||||
addPathToTree(root, paths, nOwner);
|
||||
}
|
||||
|
||||
simplifyTree(root);
|
||||
|
||||
renderTree(root, renderProp);
|
||||
|
||||
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 20.f);
|
||||
|
||||
for (properties::PropertyOwner* pOwner : owners) {
|
||||
// We checked above that pOwner is a SceneGraphNode
|
||||
SceneGraphNode* nOwner = static_cast<SceneGraphNode*>(pOwner);
|
||||
|
||||
if (!nOwner->guiPath().empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
simplifyTree(root);
|
||||
|
||||
renderTree(root, renderProp);
|
||||
|
||||
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 20.f);
|
||||
|
||||
for (properties::PropertyOwner* pOwner : owners) {
|
||||
// We checked above that pOwner is a SceneGraphNode
|
||||
SceneGraphNode* nOwner = static_cast<SceneGraphNode*>(pOwner);
|
||||
|
||||
if (!nOwner->guiPath().empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
renderProp(pOwner);
|
||||
}
|
||||
renderProp(pOwner);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
113
modules/imgui/src/guiscenecomponent.cpp
Normal file
113
modules/imgui/src/guiscenecomponent.cpp
Normal file
@@ -0,0 +1,113 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2022 *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
|
||||
* software and associated documentation files (the "Software"), to deal in the Software *
|
||||
* without restriction, including without limitation the rights to use, copy, modify, *
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
|
||||
* permit persons to whom the Software is furnished to do so, subject to the following *
|
||||
* conditions: *
|
||||
* *
|
||||
* The above copyright notice and this permission notice shall be included in all copies *
|
||||
* or substantial portions of the Software. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#include <modules/imgui/include/guiscenecomponent.h>
|
||||
|
||||
#include <modules/imgui/imguimodule.h>
|
||||
#include <modules/imgui/include/imgui_include.h>
|
||||
#include <openspace/engine/globals.h>
|
||||
#include <openspace/rendering/renderable.h>
|
||||
#include <openspace/rendering/renderengine.h>
|
||||
#include <openspace/scene/scenegraphnode.h>
|
||||
#include <openspace/scene/scene.h>
|
||||
#include <openspace/util/timemanager.h>
|
||||
#include <ghoul/misc/misc.h>
|
||||
#include <algorithm>
|
||||
|
||||
namespace {
|
||||
const ImVec2 Size = ImVec2(350, 500);
|
||||
|
||||
void renderSceneGraphNode(const openspace::SceneGraphNode& node,
|
||||
const openspace::Time& time)
|
||||
{
|
||||
using namespace openspace;
|
||||
|
||||
if (ImGui::TreeNode(node.identifier().c_str())) {
|
||||
std::vector<SceneGraphNode*> children = node.children();
|
||||
for (SceneGraphNode* c : children) {
|
||||
renderSceneGraphNode(*c, time);
|
||||
}
|
||||
|
||||
bool timeRangeActive = node.isTimeFrameActive(time);
|
||||
ImGui::Checkbox("Time Range Active", &timeRangeActive);
|
||||
|
||||
const Renderable* renderable = node.renderable();
|
||||
if (renderable) {
|
||||
CaptionText("Renderable");
|
||||
bool enabled = renderable->isEnabled();
|
||||
ImGui::Checkbox("Enabled", &enabled);
|
||||
|
||||
bool isVisible = renderable->isVisible();
|
||||
ImGui::Checkbox("Is Visible", &isVisible);
|
||||
|
||||
bool shouldUpdateIfDisabled = renderable->shouldUpdateIfDisabled();
|
||||
ImGui::Checkbox("Should update if disabled", &shouldUpdateIfDisabled);
|
||||
|
||||
bool isReady = renderable->isReady();
|
||||
ImGui::Checkbox("Is Ready", &isReady);
|
||||
|
||||
Renderable::RenderBin bin = renderable->renderBin();
|
||||
std::string binStr = [](Renderable::RenderBin bin) {
|
||||
switch (bin) {
|
||||
case Renderable::RenderBin::Background:
|
||||
return "Background";
|
||||
case Renderable::RenderBin::Opaque:
|
||||
return "Opaque";
|
||||
case Renderable::RenderBin::PreDeferredTransparent:
|
||||
return "PreDeferredTransparent";
|
||||
case Renderable::RenderBin::PostDeferredTransparent:
|
||||
return "PostDeferredTransparent";
|
||||
case Renderable::RenderBin::Overlay:
|
||||
return "Overlay";
|
||||
default:
|
||||
throw ghoul::MissingCaseException();
|
||||
}
|
||||
}(bin);
|
||||
ImGui::Text("RenderBin: %s", binStr.c_str());
|
||||
}
|
||||
ImGui::TreePop();
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace openspace::gui {
|
||||
|
||||
GuiSceneComponent::GuiSceneComponent() : GuiComponent("SceneView", "Scene View") {}
|
||||
|
||||
void GuiSceneComponent::render() {
|
||||
ImGui::SetNextWindowCollapsed(_isCollapsed);
|
||||
|
||||
bool v = _isEnabled;
|
||||
ImGui::Begin("File Path", &v);
|
||||
_isEnabled = v;
|
||||
_isCollapsed = ImGui::IsWindowCollapsed();
|
||||
|
||||
SceneGraphNode* root = global::renderEngine->scene()->root();
|
||||
const Time& now = global::timeManager->time();
|
||||
renderSceneGraphNode(*root, now);
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
} // namespace openspace::gui
|
||||
@@ -24,22 +24,17 @@
|
||||
|
||||
#include <modules/imgui/include/guispacetimecomponent.h>
|
||||
|
||||
#include <modules/imgui/include/gui.h>
|
||||
#include <modules/imgui/imguimodule.h>
|
||||
#include <modules/imgui/include/imgui_include.h>
|
||||
#include <openspace/engine/globals.h>
|
||||
#include <openspace/engine/windowdelegate.h>
|
||||
#include <openspace/navigation/navigationhandler.h>
|
||||
#include <openspace/navigation/orbitalnavigator.h>
|
||||
#include <openspace/rendering/renderengine.h>
|
||||
#include <openspace/scene/scenegraphnode.h>
|
||||
#include <openspace/scene/scene.h>
|
||||
#include <openspace/util/time.h>
|
||||
#include <openspace/util/timeconversion.h>
|
||||
#include <openspace/util/timemanager.h>
|
||||
#include <openspace/scripting/scriptengine.h>
|
||||
|
||||
#include <numeric>
|
||||
|
||||
namespace {
|
||||
const ImVec2 Size = ImVec2(350, 500);
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ void renderTooltip(Property* prop, double delay) {
|
||||
|
||||
void executeSetPropertyScript(const std::string& id, const std::string& value) {
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.setPropertyValueSingle('" + id + "', " + value + ");",
|
||||
fmt::format("openspace.setPropertyValueSingle('{}', {});", id, value),
|
||||
scripting::ScriptEngine::RemoteScripting::Yes
|
||||
);
|
||||
}
|
||||
@@ -115,46 +115,47 @@ void renderOptionProperty(Property* prop, const std::string& ownerName,
|
||||
int value = *p;
|
||||
const std::vector<OptionProperty::Option>& options = p->options();
|
||||
switch (p->displayType()) {
|
||||
case OptionProperty::DisplayType::Radio: {
|
||||
ImGui::Text("%s", name.c_str());
|
||||
ImGui::Separator();
|
||||
for (const OptionProperty::Option& o : options) {
|
||||
ImGui::RadioButton(o.description.c_str(), &value, o.value);
|
||||
case OptionProperty::DisplayType::Radio: {
|
||||
ImGui::Text("%s", name.c_str());
|
||||
ImGui::Separator();
|
||||
for (const OptionProperty::Option& o : options) {
|
||||
ImGui::RadioButton(o.description.c_str(), &value, o.value);
|
||||
if (showTooltip) {
|
||||
renderTooltip(prop, tooltipDelay);
|
||||
}
|
||||
}
|
||||
ImGui::Separator();
|
||||
break;
|
||||
}
|
||||
case OptionProperty::DisplayType::Dropdown: {
|
||||
// The order of the options does not have to correspond with the value of the
|
||||
// option
|
||||
std::string nodeNames;
|
||||
for (const OptionProperty::Option& o : options) {
|
||||
nodeNames += o.description + '\0';
|
||||
}
|
||||
nodeNames += '\0';
|
||||
|
||||
int idx = static_cast<int>(std::distance(
|
||||
options.begin(),
|
||||
std::find_if(
|
||||
options.begin(),
|
||||
options.end(),
|
||||
[value](const OptionProperty::Option& o) { return o.value == value; }
|
||||
)
|
||||
));
|
||||
|
||||
const bool hasChanged = ImGui::Combo(name.c_str(), &idx, nodeNames.c_str());
|
||||
if (showTooltip) {
|
||||
renderTooltip(prop, tooltipDelay);
|
||||
}
|
||||
}
|
||||
ImGui::Separator();
|
||||
break;
|
||||
}
|
||||
case OptionProperty::DisplayType::Dropdown: {
|
||||
// The order of the options does not have to correspond with the value of the
|
||||
// option
|
||||
std::string nodeNames;
|
||||
for (const OptionProperty::Option& o : options) {
|
||||
nodeNames += o.description + '\0';
|
||||
}
|
||||
nodeNames += '\0';
|
||||
|
||||
int idx = static_cast<int>(std::distance(
|
||||
options.begin(),
|
||||
std::find_if(
|
||||
options.begin(),
|
||||
options.end(),
|
||||
[value](const OptionProperty::Option& o) { return o.value == value; }
|
||||
)));
|
||||
if (hasChanged) {
|
||||
value = options[idx].value;
|
||||
}
|
||||
|
||||
const bool hasChanged = ImGui::Combo(name.c_str(), &idx, nodeNames.c_str());
|
||||
if (showTooltip) {
|
||||
renderTooltip(prop, tooltipDelay);
|
||||
break;
|
||||
}
|
||||
|
||||
if (hasChanged) {
|
||||
value = options[idx].value;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (value != p->value() && !isReadOnly) {
|
||||
executeSetPropertyScript(p->fullyQualifiedIdentifier(), std::to_string(value));
|
||||
@@ -224,12 +225,7 @@ void renderStringProperty(Property* prop, const std::string& ownerName,
|
||||
#else
|
||||
strcpy(buffer, value.c_str());
|
||||
#endif
|
||||
bool hasNewValue = ImGui::InputText(
|
||||
name.c_str(),
|
||||
buffer,
|
||||
bufferSize,
|
||||
ImGuiInputTextFlags_EnterReturnsTrue
|
||||
);
|
||||
bool hasNewValue = ImGui::InputText(name.c_str(), buffer, bufferSize);
|
||||
if (showTooltip) {
|
||||
renderTooltip(prop, tooltipDelay);
|
||||
}
|
||||
@@ -262,13 +258,8 @@ void renderListProperty(const std::string& name, const std::string& fullIdentifi
|
||||
#else
|
||||
strcpy(buffer, value.c_str());
|
||||
#endif
|
||||
bool hasNewValue = ImGui::InputText(
|
||||
name.c_str(),
|
||||
buffer,
|
||||
bufferSize,
|
||||
ImGuiInputTextFlags_EnterReturnsTrue
|
||||
);
|
||||
|
||||
|
||||
bool hasNewValue = ImGui::InputText(name.c_str(), buffer, bufferSize);
|
||||
if (hasNewValue) {
|
||||
std::vector<std::string> tokens = ghoul::tokenizeString(std::string(buffer), ',');
|
||||
std::string script = "{";
|
||||
@@ -415,21 +406,13 @@ void renderIVec2Property(Property* prop, const std::string& ownerName,
|
||||
IVec2Property::ValueType value = *p;
|
||||
int min = glm::compMin(p->minValue());
|
||||
int max = glm::compMax(p->maxValue());
|
||||
bool changed = ImGui::SliderInt2(
|
||||
name.c_str(),
|
||||
&value.x,
|
||||
min,
|
||||
max
|
||||
);
|
||||
bool changed = ImGui::SliderInt2(name.c_str(), &value.x, min, max);
|
||||
if (showTooltip) {
|
||||
renderTooltip(prop, tooltipDelay);
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
executeSetPropertyScript(
|
||||
p->fullyQualifiedIdentifier(),
|
||||
ghoul::to_string(value)
|
||||
);
|
||||
executeSetPropertyScript(p->fullyQualifiedIdentifier(), ghoul::to_string(value));
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
@@ -447,21 +430,13 @@ void renderIVec3Property(Property* prop, const std::string& ownerName,
|
||||
int min = glm::compMin(p->minValue());
|
||||
int max = glm::compMax(p->maxValue());
|
||||
|
||||
bool changed = ImGui::SliderInt3(
|
||||
name.c_str(),
|
||||
&value.x,
|
||||
min,
|
||||
max
|
||||
);
|
||||
bool changed = ImGui::SliderInt3(name.c_str(), &value.x, min, max);
|
||||
if (showTooltip) {
|
||||
renderTooltip(prop, tooltipDelay);
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
executeSetPropertyScript(
|
||||
p->fullyQualifiedIdentifier(),
|
||||
ghoul::to_string(value)
|
||||
);
|
||||
executeSetPropertyScript(p->fullyQualifiedIdentifier(), ghoul::to_string(value));
|
||||
}
|
||||
ImGui::PopID();
|
||||
}
|
||||
@@ -478,21 +453,13 @@ void renderIVec4Property(Property* prop, const std::string& ownerName,
|
||||
int min = glm::compMin(p->minValue());
|
||||
int max = glm::compMax(p->maxValue());
|
||||
|
||||
bool changed = ImGui::SliderInt4(
|
||||
name.c_str(),
|
||||
&value.x,
|
||||
min,
|
||||
max
|
||||
);
|
||||
bool changed = ImGui::SliderInt4(name.c_str(), &value.x, min, max);
|
||||
if (showTooltip) {
|
||||
renderTooltip(prop, tooltipDelay);
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
executeSetPropertyScript(
|
||||
p->fullyQualifiedIdentifier(),
|
||||
ghoul::to_string(value)
|
||||
);
|
||||
executeSetPropertyScript(p->fullyQualifiedIdentifier(), ghoul::to_string(value));
|
||||
}
|
||||
ImGui::PopID();
|
||||
}
|
||||
@@ -552,10 +519,7 @@ void renderVec2Property(Property* prop, const std::string& ownerName,
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
executeSetPropertyScript(
|
||||
p->fullyQualifiedIdentifier(),
|
||||
ghoul::to_string(value)
|
||||
);
|
||||
executeSetPropertyScript(p->fullyQualifiedIdentifier(), ghoul::to_string(value));
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
@@ -575,10 +539,7 @@ void renderVec3Property(Property* prop, const std::string& ownerName,
|
||||
|
||||
bool changed = false;
|
||||
if (prop->viewOption(Property::ViewOptions::Color)) {
|
||||
changed = ImGui::ColorEdit3(
|
||||
name.c_str(),
|
||||
glm::value_ptr(value)
|
||||
);
|
||||
changed = ImGui::ColorEdit3(name.c_str(), glm::value_ptr(value));
|
||||
}
|
||||
else {
|
||||
changed = ImGui::SliderFloat3(
|
||||
@@ -595,10 +556,7 @@ void renderVec3Property(Property* prop, const std::string& ownerName,
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
executeSetPropertyScript(
|
||||
p->fullyQualifiedIdentifier(),
|
||||
ghoul::to_string(value)
|
||||
);
|
||||
executeSetPropertyScript(p->fullyQualifiedIdentifier(), ghoul::to_string(value));
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
@@ -618,10 +576,7 @@ void renderVec4Property(Property* prop, const std::string& ownerName,
|
||||
|
||||
bool changed = false;
|
||||
if (prop->viewOption(Property::ViewOptions::Color)) {
|
||||
changed = ImGui::ColorEdit4(
|
||||
name.c_str(),
|
||||
glm::value_ptr(value)
|
||||
);
|
||||
changed = ImGui::ColorEdit4(name.c_str(), glm::value_ptr(value));
|
||||
}
|
||||
else {
|
||||
changed = ImGui::SliderFloat4(
|
||||
@@ -638,10 +593,7 @@ void renderVec4Property(Property* prop, const std::string& ownerName,
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
executeSetPropertyScript(
|
||||
p->fullyQualifiedIdentifier(),
|
||||
ghoul::to_string(value)
|
||||
);
|
||||
executeSetPropertyScript(p->fullyQualifiedIdentifier(), ghoul::to_string(value));
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
@@ -671,10 +623,7 @@ void renderDVec2Property(Property* prop, const std::string& ownerName,
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
executeSetPropertyScript(
|
||||
p->fullyQualifiedIdentifier(),
|
||||
ghoul::to_string(value)
|
||||
);
|
||||
executeSetPropertyScript(p->fullyQualifiedIdentifier(), ghoul::to_string(value));
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
@@ -705,10 +654,7 @@ void renderDVec3Property(Property* prop, const std::string& ownerName,
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
executeSetPropertyScript(
|
||||
p->fullyQualifiedIdentifier(),
|
||||
ghoul::to_string(value)
|
||||
);
|
||||
executeSetPropertyScript(p->fullyQualifiedIdentifier(), ghoul::to_string(value));
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
@@ -739,10 +685,7 @@ void renderDVec4Property(Property* prop, const std::string& ownerName,
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
executeSetPropertyScript(
|
||||
p->fullyQualifiedIdentifier(),
|
||||
ghoul::to_string(value)
|
||||
);
|
||||
executeSetPropertyScript(p->fullyQualifiedIdentifier(), ghoul::to_string(value));
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
@@ -794,10 +737,7 @@ void renderDMat2Property(Property* prop, const std::string& ownerName,
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
executeSetPropertyScript(
|
||||
p->fullyQualifiedIdentifier(),
|
||||
ghoul::to_string(value)
|
||||
);
|
||||
executeSetPropertyScript(p->fullyQualifiedIdentifier(), ghoul::to_string(value));
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
@@ -859,10 +799,7 @@ void renderDMat3Property(Property* prop, const std::string& ownerName,
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
executeSetPropertyScript(
|
||||
p->fullyQualifiedIdentifier(),
|
||||
ghoul::to_string(value)
|
||||
);
|
||||
executeSetPropertyScript(p->fullyQualifiedIdentifier(), ghoul::to_string(value));
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
@@ -934,10 +871,7 @@ void renderDMat4Property(Property* prop, const std::string& ownerName,
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
executeSetPropertyScript(
|
||||
p->fullyQualifiedIdentifier(),
|
||||
ghoul::to_string(value)
|
||||
);
|
||||
executeSetPropertyScript(p->fullyQualifiedIdentifier(), ghoul::to_string(value));
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
|
||||
@@ -68,7 +68,7 @@ end
|
||||
|
||||
openspace.setDefaultGuiSorting = function()
|
||||
openspace.setPropertyValueSingle(
|
||||
'Modules.ImGUI.Main.SceneProperties.Ordering',
|
||||
'Modules.ImGUI.Scene.Ordering',
|
||||
{
|
||||
"Solar System", "Milky Way", "Universe", "Other"
|
||||
}
|
||||
|
||||
@@ -94,19 +94,19 @@ void ModuleEngine::deinitialize() {
|
||||
ZoneScoped
|
||||
|
||||
LDEBUG("Deinitializing modules");
|
||||
for (std::unique_ptr<OpenSpaceModule>& m : _modules) {
|
||||
LDEBUG(fmt::format("Deinitializing module '{}'", m->identifier()));
|
||||
m->deinitialize();
|
||||
}
|
||||
|
||||
for (auto mIt = _modules.rbegin(); mIt != _modules.rend(); ++mIt) {
|
||||
LDEBUG(fmt::format("Deinitializing module '{}'", (*mIt)->identifier()));
|
||||
(*mIt)->deinitialize();
|
||||
}
|
||||
LDEBUG("Finished deinitializing modules");
|
||||
|
||||
for (std::unique_ptr<OpenSpaceModule>& m : _modules) {
|
||||
LDEBUG(fmt::format("Destroying module '{}'", m->identifier()));
|
||||
m = nullptr;
|
||||
for (auto mIt = _modules.rbegin(); mIt != _modules.rend(); ++mIt) {
|
||||
LDEBUG(fmt::format("Destroying module '{}'", (*mIt)->identifier()));
|
||||
(*mIt) = nullptr;
|
||||
}
|
||||
|
||||
LDEBUG("Finished destroying modules");
|
||||
|
||||
_modules.clear();
|
||||
}
|
||||
|
||||
@@ -114,9 +114,9 @@ void ModuleEngine::deinitializeGL() {
|
||||
ZoneScoped
|
||||
|
||||
LDEBUG("Deinitializing OpenGL of modules");
|
||||
for (std::unique_ptr<OpenSpaceModule>& m : _modules) {
|
||||
LDEBUG(fmt::format("Deinitializing OpenGL of module '{}'", m->identifier()));
|
||||
m->deinitializeGL();
|
||||
for (auto mIt = _modules.rbegin(); mIt != _modules.rend(); ++mIt) {
|
||||
LDEBUG(fmt::format("Deinitializing OpenGL of module '{}'", (*mIt)->identifier()));
|
||||
(*mIt)->deinitializeGL();
|
||||
|
||||
}
|
||||
LDEBUG("Finished deinitializing OpenGL of modules");
|
||||
|
||||
@@ -617,7 +617,8 @@ scripting::LuaLibrary NavigationHandler::luaLibrary() {
|
||||
codegen::lua::AddLocalRoll,
|
||||
codegen::lua::AddGlobalRoll,
|
||||
codegen::lua::TriggerIdleBehavior,
|
||||
codegen::lua::ListAllJoysticks
|
||||
codegen::lua::ListAllJoysticks,
|
||||
codegen::lua::TargetNextInterestingAnchor
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -128,6 +128,36 @@ namespace {
|
||||
openspace::global::navigationHandler->orbitalNavigator().startRetargetAim();
|
||||
}
|
||||
|
||||
// Picks the next node from the interesting nodes out of the profile and selects that. If
|
||||
// the current anchor is not an interesting node, the first will be selected
|
||||
[[codegen::luawrap]] void targetNextInterestingAnchor() {
|
||||
using namespace openspace;
|
||||
if (global::profile->markNodes.empty()) {
|
||||
LWARNINGC(
|
||||
"targetNextInterestingAnchor",
|
||||
"Profile does not define any interesting nodes"
|
||||
);
|
||||
return;
|
||||
}
|
||||
const std::vector<std::string>& markNodes = global::profile->markNodes;
|
||||
|
||||
std::string currAnchor =
|
||||
global::navigationHandler->orbitalNavigator().anchorNode()->identifier();
|
||||
|
||||
auto it = std::find(markNodes.begin(), markNodes.end(), currAnchor);
|
||||
if (it == markNodes.end() || ((it + 1) == markNodes.end())) {
|
||||
// We want to use the first node either if
|
||||
// 1. The current node is not an interesting node
|
||||
// 2. The current node is the last interesting node
|
||||
global::navigationHandler->orbitalNavigator().setFocusNode(markNodes.front());
|
||||
}
|
||||
else {
|
||||
// Otherwise we can just select the next one
|
||||
global::navigationHandler->orbitalNavigator().setFocusNode(*(it + 1));
|
||||
}
|
||||
global::navigationHandler->orbitalNavigator().startRetargetAnchor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the input joystick with the given 'name' and binds the axis identified by the
|
||||
* second argument to be used as the type identified by the third argument. If
|
||||
|
||||
Reference in New Issue
Block a user