DYT/Tool/OpenSceneGraph-3.6.5/include/osgEarthImGui/ImGuiPanel
2024-12-25 07:49:36 +08:00

447 lines
14 KiB
C++

/* -*-c++-*- */
/* osgEarth - Geospatial SDK for OpenSceneGraph
* Copyright 2018 Pelican Mapping
* http://osgearth.org
*
* osgEarth is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#pragma once
#include <osgEarthImGui/Common>
#include <osgEarth/BuildConfig>
#include <osgEarth/Config>
#include <osgEarth/GLUtils>
#include <osgEarth/MapNode>
#include <osgEarth/Terrain>
#include <osgEarth/GeoData>
#include <osgEarth/NodeUtils>
#include <osgDB/ReadFile>
#include <osg/observer_ptr>
#include <osg/StateSet>
#include <osg/RenderInfo>
#include <osgViewer/View>
#include <memory>
namespace osgEarth
{
// base class for GUI elements that allows you to toggle visibility
// no export. header only.
class ImGuiPanel // no export
{
public:
void setVisible(bool value) {
_visible = value;
dirtySettings();
}
//! whether it's current shown
bool isVisible() const {
return _visible;
}
//! name of the GUI panel
const char* name() const {
return _name.c_str();
}
//! render this GUI
virtual void draw(osg::RenderInfo& ri) { }
//! override to set custom values in the .ini file
virtual void load(const osgEarth::Config&) { }
//! override to get custom values from the .ini file
virtual void save(osgEarth::Config&) { }
protected:
ImGuiPanel(const char* name) :
_name(name), _visible(false), _last_visible(false)
{
//nop
}
//! convenience function for finding nodes
template<typename T>
T* findNode(osg::RenderInfo& ri) const {
return osgEarth::findTopMostNodeOfType<T>(ri.getCurrentCamera());
}
//! convenience function for getting the current view
inline osgViewer::View* view(osg::RenderInfo& ri) const {
return dynamic_cast<osgViewer::View*>(ri.getView());
}
//! convenience function for getting the current camera
inline osg::Camera* camera(osg::RenderInfo& ri) const {
return ri.getCurrentCamera();
}
//! convenience function for getting the topmost stateset
inline osg::StateSet* stateset(osg::RenderInfo& ri) const {
return ri.getCurrentCamera()->getOrCreateStateSet();
}
//! convenience function for finding nodes
template<typename T>
bool findNode(osg::observer_ptr<T>& node, osg::RenderInfo& ri) const {
if (!node.valid())
node = osgEarth::findTopMostNodeOfType<T>(ri.getCurrentCamera());
return node.valid();
}
//! convenience function for finding nodes
template<typename T>
bool findNodeOrHide(osg::observer_ptr<T>& node, osg::RenderInfo& ri) {
if (!node.valid())
node = osgEarth::findTopMostNodeOfType<T>(ri.getCurrentCamera());
if (!node.valid())
setVisible(false);
return node.valid();
}
template<typename T>
bool findLayer(osg::observer_ptr<T>& layer, osg::RenderInfo& ri) {
if (!layer.valid()) {
MapNode* mapNode = osgEarth::findTopMostNodeOfType<MapNode>(ri.getCurrentCamera());
if (mapNode)
layer = mapNode->getMap()->getLayer<T>();
}
return layer.valid();
}
template<typename T>
bool findLayerOrHide(osg::observer_ptr<T>& layer, osg::RenderInfo& ri) {
if (!layer.valid()) {
MapNode* mapNode = osgEarth::findTopMostNodeOfType<MapNode>(ri.getCurrentCamera());
if (mapNode)
layer = mapNode->getMap()->getLayer<T>();
}
if (!layer.valid())
setVisible(false);
return layer.valid();
}
//! sets a value and dirties the .ini store
template<typename A, typename B>
void set_and_dirty(A& var, const B& value)
{
if (var != value) {
var = value;
dirtySettings();
}
}
//! Map point under the mouse cursor
GeoPoint getPointAtMouse(MapNode* mapNode, osg::View* v, float x, float y)
{
GeoPoint point;
osg::Vec3d world;
if (mapNode->getTerrain()->getWorldCoordsUnderMouse(v, x, y, world))
point.fromWorld(mapNode->getMapSRS(), world);
return point;
}
private:
std::string _name;
bool _visible;
bool _last_visible;
bool* _dirtySettings = nullptr;
friend class ImGuiAppEngine;
public:
bool* visible() {
return &_visible;
}
//! override to set custom values in the .ini file
void load_base(const osgEarth::Config& conf)
{
conf.get("Visible", _visible);
load(conf);
}
//! override to set custom values in the .ini file
void save_base(osgEarth::Config& conf)
{
conf.set("Visible", _visible);
save(conf);
}
//! whether the visibility changed (and resets the flag)
bool visibilityChanged() {
bool whether = _visible != _last_visible;
_last_visible = _visible;
return whether;
}
void dirtySettings()
{
if (_dirtySettings)
*_dirtySettings = true;
}
};
}
// various additions to ImGui.
namespace ImGuiLTable
{
static bool Begin(const char* name, int flags = 0)
{
bool ok = ImGui::BeginTable(name, 2, ImGuiTableFlags_SizingFixedFit | flags);
if (ok) {
ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_NoHide);
ImGui::TableSetupColumn("Value", ImGuiTableColumnFlags_NoHide | ImGuiTableColumnFlags_WidthStretch);
}
return ok;
}
static bool SliderFloat(const char* label, float* v, float v_min, float v_max)
{
ImGui::TableNextColumn();
ImGui::Text(label);
ImGui::TableNextColumn();
ImGui::SetNextItemWidth(-1);
std::string s("##" + std::string(label));
return ImGui::SliderFloat(s.c_str(), v, v_min, v_max);
}
static bool SliderFloat(const char* label, float* v, float v_min, float v_max, const char* format, ImGuiSliderFlags flags)
{
ImGui::TableNextColumn();
ImGui::Text(label);
ImGui::TableNextColumn();
ImGui::SetNextItemWidth(-1);
std::string s("##" + std::string(label));
return ImGui::SliderFloat(s.c_str(), v, v_min, v_max, format, flags);
}
static bool SliderDouble(const char* label, double* v, double v_min, double v_max, const char* format = nullptr)
{
ImGui::TableNextColumn();
ImGui::Text(label);
ImGui::TableNextColumn();
ImGui::SetNextItemWidth(-1);
std::string s("##" + std::string(label));
float temp = *v;
bool ok = ImGui::SliderFloat(s.c_str(), &temp, (float)v_min, (float)v_max, format);
if (ok) *v = (double)temp;
return ok;
}
static bool SliderDouble(const char* label, double* v, double v_min, double v_max, const char* format, ImGuiSliderFlags flags)
{
ImGui::TableNextColumn();
ImGui::Text(label);
ImGui::TableNextColumn();
ImGui::SetNextItemWidth(-1);
std::string s("##" + std::string(label));
float temp = *v;
bool ok = ImGui::SliderFloat(s.c_str(), &temp, (float)v_min, (float)v_max, format, flags);
if (ok) *v = (double)temp;
return ok;
}
static bool SliderInt(const char* label, int* v, int v_min, int v_max)
{
ImGui::TableNextColumn();
ImGui::Text(label);
ImGui::TableNextColumn();
ImGui::SetNextItemWidth(-1);
std::string s("##" + std::string(label));
return ImGui::SliderInt(s.c_str(), v, v_min, v_max);
}
static bool SliderInt(const char* label, int* v, int v_min, int v_max, const char* format, ImGuiSliderFlags flags)
{
ImGui::TableNextColumn();
ImGui::Text(label);
ImGui::TableNextColumn();
ImGui::SetNextItemWidth(-1);
std::string s("##" + std::string(label));
return ImGui::SliderInt(s.c_str(), v, v_min, v_max, format, flags);
}
static bool Checkbox(const char* label, bool* v)
{
ImGui::TableNextColumn();
ImGui::Text(label);
ImGui::TableNextColumn();
ImGui::SetNextItemWidth(-1);
std::string s("##" + std::string(label));
return ImGui::Checkbox(s.c_str(), v);
}
static bool BeginCombo(const char* label, const char* defaultItem)
{
ImGui::TableNextColumn();
ImGui::Text(label);
ImGui::TableNextColumn();
ImGui::SetNextItemWidth(-1);
std::string s("##" + std::string(label));
return ImGui::BeginCombo(s.c_str(), defaultItem);
}
static void EndCombo()
{
return ImGui::EndCombo();
}
static bool InputFloat(const char* label, float* v)
{
ImGui::TableNextColumn();
ImGui::Text(label);
ImGui::TableNextColumn();
ImGui::SetNextItemWidth(-1);
std::string s("##" + std::string(label));
return ImGui::InputFloat(s.c_str(), v);
}
template<typename...Args>
static void Text(const char* label, const char* format, Args...args)
{
ImGui::TableNextColumn();
ImGui::Text(label);
ImGui::TableNextColumn();
ImGui::SetNextItemWidth(-1);
ImGui::Text(format, args...);
}
static void Section(const char* label)
{
ImGui::TableNextColumn();
ImGui::TextColored(ImVec4(1, 1, 0, 1), label);
ImGui::TableNextColumn();
}
static bool InputScalar(const char* label, ImGuiDataType data_type, void* p_data, const void* p_step, const void* p_step_fast, const char* format, ImGuiInputTextFlags flags = 0)
{
ImGui::TableNextColumn();
ImGui::Text(label);
ImGui::TableNextColumn();
ImGui::SetNextItemWidth(-1);
std::string s("##" + std::string(label));
return ImGui::InputScalar(s.c_str(), data_type, p_data, p_step, p_step_fast, format, flags);
}
static bool ColorEdit3(const char* label, float col[3], ImGuiColorEditFlags flags = 0)
{
ImGui::TableNextColumn();
ImGui::Text(label);
ImGui::TableNextColumn();
ImGui::SetNextItemWidth(-1);
return ImGui::ColorEdit3(label, col, flags);
}
static bool ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flags = 0)
{
ImGui::TableNextColumn();
ImGui::Text(label);
ImGui::TableNextColumn();
ImGui::SetNextItemWidth(-1);
return ImGui::ColorEdit4(label, col, flags);
}
static void PlotLines(const char* label, float(*getter)(void*, int), void* data, int values_count, int values_offset, const char* overlay = nullptr,
float scale_min = FLT_MAX, float scale_max = FLT_MAX)
{
ImGui::TableNextColumn();
ImGui::Text(label);
ImGui::TableNextColumn();
ImGui::SetNextItemWidth(-1);
ImGui::PlotLines("", getter, data, values_count, values_offset, overlay, scale_min, scale_max);
}
static void End()
{
ImGui::EndTable();
}
}
// Added functions to the top level ImGui namespace
namespace ImGuiEx
{
template<typename... Args>
static void TextCentered(const char* format, Args&&... args)
{
char buf[1024];
sprintf(buf, format, args...);
ImGui::SetCursorPosX((ImGui::GetWindowSize().x - ImGui::CalcTextSize(buf).x) * 0.5f);
ImGui::Text(buf);
}
static void OSGTexture(osg::Texture2D* texture, osg::RenderInfo& renderInfo, unsigned int width = 0, unsigned int height = 0)
{
// Get the context id
const unsigned int contextID = osgEarth::GLUtils::getSharedContextID(*renderInfo.getState());
// Apply the texture
texture->apply(*renderInfo.getState());
// Default to the textures size
unsigned int w = texture->getTextureWidth();
unsigned int h = texture->getTextureHeight();
// Get the aspect ratio
double ar = (double)w / (double)h;
// If both width and height are specified use that.
if (width != 0 && height != 0)
{
w = width;
h = height;
}
// If just the width is specified compute the height using the ar
else if (width != 0)
{
w = width;
h = (1.0 / ar) * w;
}
// If just the height is specified compute the width using the ar
else if (height != 0)
{
h = height;
w = ar * height;
}
// Get the TextureObject.
osg::Texture::TextureObject* textureObject = texture->getTextureObject(contextID);
if (textureObject)
{
bool flip = (texture->getImage() && texture->getImage()->getOrigin() == osg::Image::TOP_LEFT);
ImGui::Image((void*)(intptr_t)textureObject->_id, ImVec2(w, h), ImVec2(0, flip ? 0 : 1), ImVec2(1, flip ? 1 : 0), ImVec4(1, 1, 1, 1), ImVec4(1, 1, 0, 1));
}
}
static int InputTextCallback(ImGuiInputTextCallbackData* data)
{
std::string* str = (std::string*)data->UserData;
if (data->EventFlag == ImGuiInputTextFlags_CallbackResize)
{
// Resize string callback
IM_ASSERT(data->Buf == str->c_str());
str->resize(data->BufTextLen);
data->Buf = (char*)str->c_str();
}
return 0;
}
static bool InputTextMultiline(const char* label, std::string* str, const ImVec2& size)
{
ImGuiInputTextFlags flags = ImGuiInputTextFlags_CallbackResize;
return ImGui::InputTextMultiline(label, (char*)str->c_str(), str->capacity() + 1, size, flags, InputTextCallback, (void*)str);
}
}