Skip to content
Snippets Groups Projects
Commit 653c52ea authored by Sebastian Hahta's avatar Sebastian Hahta
Browse files

WIP: new gui

parent b8c93fb7
No related branches found
No related tags found
1 merge request!316Resolves #343 GUI and Frame Refactor
Showing
with 904 additions and 0 deletions
...@@ -480,6 +480,7 @@ endif() ...@@ -480,6 +480,7 @@ endif()
if (HAVE_NANOGUI) if (HAVE_NANOGUI)
add_subdirectory(applications/gui) add_subdirectory(applications/gui)
add_subdirectory(applications/gui2)
endif() endif()
### Generate Build Configuration Files ========================================= ### Generate Build Configuration Files =========================================
......
# Need to include staged files and libs
#include_directories(${PROJECT_SOURCE_DIR}/reconstruct/include)
#include_directories(${PROJECT_BINARY_DIR})
set(GUI2SRC
src/main.cpp
src/inputoutput.cpp
src/screen.cpp
src/view.cpp
src/gltexture.cpp
src/modules/home.cpp
)
if (HAVE_OPENVR)
list(APPEND GUI2SRC "src/vr/vr.cpp")
endif()
# Various preprocessor definitions have been generated by NanoGUI
add_definitions(${NANOGUI_EXTRA_DEFS})
# On top of adding the path to nanogui/include, you may need extras
include_directories(${NANOGUI_EXTRA_INCS})
add_executable(ftl-gui2 ${GUI2SRC})
target_include_directories(ftl-gui PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/ext/nanogui/include>
$<INSTALL_INTERFACE:include>
PRIVATE src)
#if (CUDA_FOUND)
#set_property(TARGET ftl-gui2 PROPERTY CUDA_SEPARABLE_COMPILATION ON)
#endif()
#target_include_directories(cv-node PUBLIC ${PROJECT_SOURCE_DIR}/include)
target_link_libraries(ftl-gui2 ftlcommon ftlctrl ftlrgbd ftlstreams ftlrender Threads::Threads ${OpenCV_LIBS} openvr ftlnet nanogui ${NANOGUI_EXTRA_LIBS})
#include "gltexture.hpp"
#include <nanogui/opengl.h>
#include <loguru.hpp>
#include <ftl/cuda_common.hpp>
#include <cuda_gl_interop.h>
#include <ftl/exception.hpp>
using ftl::gui2::GLTexture;
GLTexture::GLTexture(GLTexture::Type type) {
glid_ = std::numeric_limits<unsigned int>::max();
glbuf_ = std::numeric_limits<unsigned int>::max();
cuda_res_ = nullptr;
width_ = 0;
height_ = 0;
changed_ = true;
type_ = type;
}
GLTexture::~GLTexture() {
//glDeleteTextures(1, &glid_);
}
void GLTexture::update(cv::Mat &m) {
LOG(INFO) << "DEPRECATED";
if (m.rows == 0) return;
if (glid_ == std::numeric_limits<unsigned int>::max()) {
glGenTextures(1, &glid_);
glBindTexture(GL_TEXTURE_2D, glid_);
//cv::Mat m(cv::Size(100,100), CV_8UC3);
if (type_ == Type::BGRA) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, m.cols, m.rows, 0, GL_BGRA, GL_UNSIGNED_BYTE, m.data);
} else if (type_ == Type::Float) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, m.cols, m.rows, 0, GL_RED, GL_FLOAT, m.data);
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
} else {
//glBindTexture(GL_TEXTURE_2D, glid_);
// TODO Allow for other formats
//glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, m.cols, m.rows, 0, GL_BGRA, GL_UNSIGNED_BYTE, m.data);
}
auto err = glGetError();
if (err != 0) LOG(ERROR) << "OpenGL Texture error: " << err;
}
void GLTexture::make(int width, int height) {
if (width != width_ || height != height_) {
free();
}
static constexpr int ALIGNMENT = 128;
width_ = width;
height_ = height;
stride_ = ((width*4) % ALIGNMENT != 0) ? ((width*4) + (ALIGNMENT - ((width*4) % ALIGNMENT))) / 4 : width;
if (width == 0 || height == 0) {
throw FTL_Error("Invalid texture size");
}
if (glid_ == std::numeric_limits<unsigned int>::max()) {
glGenTextures(1, &glid_);
glBindTexture(GL_TEXTURE_2D, glid_);
glPixelStorei(GL_UNPACK_ROW_LENGTH, stride_);
//cv::Mat m(cv::Size(100,100), CV_8UC3);
//glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, nullptr);
if (type_ == Type::BGRA) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, nullptr);
} else if (type_ == Type::Float) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, width, height, 0, GL_RED, GL_FLOAT, nullptr);
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
auto err = glGetError();
if (err != 0) LOG(ERROR) << "OpenGL Texture error: " << err;
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glGenBuffers(1, &glbuf_);
// Make this the current UNPACK buffer (OpenGL is state-based)
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, glbuf_);
// Allocate data for the buffer. 4-channel 8-bit image
glBufferData(GL_PIXEL_UNPACK_BUFFER, stride_ * height * 4, NULL, GL_DYNAMIC_COPY);
cudaSafeCall(cudaGraphicsGLRegisterBuffer(&cuda_res_, glbuf_, cudaGraphicsRegisterFlagsWriteDiscard));
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
}
}
void GLTexture::free() {
if (glid_ != std::numeric_limits<unsigned int>::max()) {
glDeleteTextures(1, &glid_);
glid_ = std::numeric_limits<unsigned int>::max();
}
if (glbuf_ != std::numeric_limits<unsigned int>::max()) {
cudaSafeCall(cudaGraphicsUnregisterResource( cuda_res_ ));
cuda_res_ = nullptr;
glDeleteBuffers(1, &glbuf_);
glbuf_ = std::numeric_limits<unsigned int>::max();
}
}
cv::cuda::GpuMat GLTexture::map(cudaStream_t stream) {
void *devptr;
size_t size;
cudaSafeCall(cudaGraphicsMapResources(1, &cuda_res_, stream));
cudaSafeCall(cudaGraphicsResourceGetMappedPointer(&devptr, &size, cuda_res_));
return cv::cuda::GpuMat(height_, width_, (type_ == Type::BGRA) ? CV_8UC4 : CV_32F, devptr, stride_*4);
}
void GLTexture::unmap(cudaStream_t stream) {
cudaSafeCall(cudaGraphicsUnmapResources(1, &cuda_res_, stream));
changed_ = true;
//glActiveTexture(GL_TEXTURE0);
glBindBuffer( GL_PIXEL_UNPACK_BUFFER, glbuf_);
// Select the appropriate texture
glBindTexture( GL_TEXTURE_2D, glid_);
glPixelStorei(GL_UNPACK_ROW_LENGTH, stride_);
// Make a texture from the buffer
if (type_ == Type::BGRA) {
glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, width_, height_, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
} else {
glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, width_, height_, GL_RED, GL_FLOAT, NULL);
}
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glBindBuffer( GL_PIXEL_UNPACK_BUFFER, 0);
}
unsigned int GLTexture::texture() const {
if (glbuf_ < std::numeric_limits<unsigned int>::max()) {
/*//glActiveTexture(GL_TEXTURE0);
glBindBuffer( GL_PIXEL_UNPACK_BUFFER, glbuf_);
// Select the appropriate texture
glBindTexture( GL_TEXTURE_2D, glid_);
// Make a texture from the buffer
glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, width_, height_, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
glBindBuffer( GL_PIXEL_UNPACK_BUFFER, 0);*/
return glid_;
} else {
return glid_;
}
}
#ifndef _FTL_GUI_GLTEXTURE_HPP_
#define _FTL_GUI_GLTEXTURE_HPP_
#include <opencv2/core/mat.hpp>
#include <cuda_runtime.h>
struct cudaGraphicsResource;
namespace ftl {
namespace gui2 {
class GLTexture {
public:
enum class Type {
RGBA,
BGRA,
Float
};
explicit GLTexture(Type);
~GLTexture();
void update(cv::Mat &m);
void make(int width, int height);
unsigned int texture() const;
bool isValid() const { return glid_ != std::numeric_limits<unsigned int>::max(); }
cv::cuda::GpuMat map(cudaStream_t stream);
void unmap(cudaStream_t stream);
void free();
int width() const { return width_; }
int height() const { return height_; }
private:
unsigned int glid_;
unsigned int glbuf_;
int width_;
int height_;
int stride_;
bool changed_;
Type type_;
cudaGraphicsResource *cuda_res_;
};
}
}
#endif // _FTL_GUI_GLTEXTURE_HPP_
#include <loguru.hpp>
#include <nlohmann/json.hpp>
#include <ftl/codecs/shapes.hpp>
#include "inputoutput.hpp"
using ftl::gui2::InputOutput;
using ftl::codecs::Channel;
InputOutput::InputOutput(ftl::Configurable *root, ftl::net::Universe *net) : net_(net) {
UNIQUE_LOCK(mtx_, lk);
controller_ = std::unique_ptr<ftl::ctrl::Master>(new ftl::ctrl::Master(root, net));
controller_->onLog([](const ftl::ctrl::LogEvent &e){
const int v = e.verbosity;
switch (v) {
case -2: LOG(ERROR) << "Remote log: " << e.message; break;
case -1: LOG(WARNING) << "Remote log: " << e.message; break;
case 0: LOG(INFO) << "Remote log: " << e.message; break;
}
});
net_->onConnect([this](ftl::net::Peer *p) {
ftl::pool.push([this](int id) {
// FIXME: Find better option that waiting here.
// Wait to make sure streams have started properly.
std::this_thread::sleep_for(std::chrono::milliseconds(100));
//_updateCameras(screen_->net()->findAll<string>("list_streams"));
});
});
stream_ = std::unique_ptr<ftl::stream::Muxer>(ftl::create<ftl::stream::Muxer>(root, "muxer"));
interceptor_ = std::unique_ptr<ftl::stream::Intercept>(ftl::create<ftl::stream::Intercept>(root, "intercept"));
interceptor_->setStream(stream_.get());
receiver_ = std::unique_ptr<ftl::stream::Receiver>(ftl::create<ftl::stream::Receiver>(root, "receiver"));
receiver_->setStream(interceptor_.get());
// Create a recorder
recorder_ = std::unique_ptr<ftl::stream::File>(ftl::create<ftl::stream::File>(root, "recorder"));
recorder_->setMode(ftl::stream::File::Mode::Write);
interceptor_->onIntercept([this] (const ftl::codecs::StreamPacket &spkt, const ftl::codecs::Packet &pkt) {
if (recorder_->active() && pkt.data.size() > 0) {
if (spkt.channel == Channel::Shapes3D && spkt.frame_number == 255) {
// Decode the shapes channel to insert the virtual camera...
std::vector<ftl::codecs::Shape3D> shapes;
auto unpacked = msgpack::unpack((const char*)pkt.data.data(), pkt.data.size());
unpacked.get().convert(shapes);
/*
auto *cam = screen_->activeCamera();
if (cam) {
// Modify shapes
auto &s = shapes.emplace_back();
s.id = shapes.size();
s.label = std::string("virtual-")+std::to_string(shapes.size());
s.type = ftl::codecs::Shape3DType::CAMERA;
s.pose = cam->getPose().cast<float>();
//LOG(INFO) << "Inject virtual : " << shapes.size();
}
auto npkt = pkt;
npkt.data.resize(0);
ftl::util::FTLVectorBuffer buf(npkt.data);
msgpack::pack(buf, shapes);
recorder_->post(spkt, npkt);
*/
}
else {
recorder_->post(spkt, pkt);
}
}
});
receiver_->onFrameSet([this](ftl::rgbd::FrameSet &fs){ return process_callbacks_video(fs); });
speaker_ = std::unique_ptr<ftl::audio::Speaker>(ftl::create<ftl::audio::Speaker>(root, "speaker_test"));
receiver_->onAudio([this](ftl::audio::FrameSet &fs) {
/*
if (framesets_.size() == 0) return true;
auto *c = screen_->activeCamera();
int64_t renddelay = (c) ? c->getFrameTimeMS() : 0;
speaker_->setDelay(fs.timestamp - framesets_[0]->timestamp + renddelay); // Add Xms for local render time
speaker_->queue(fs.timestamp, fs.frames[0]);
//LOG(INFO) << "Audio delay = " << (fs.timestamp - framesets_[0]->timestamp + renddelay);
*/return true;
});
/*ftl::timer::add(ftl::timer::kTimerMain, [this](int64_t ts) {
auto *c = screen_->activeCamera();
// Only offer full framerate render on active camera.
if (c) {
c->draw(framesets_);
}
return true;
});* //
// Add network sources
_updateCameras(screen_->control()->getNet()->findAll<string>("list_streams"));
*/
// Also check for a file on command line.
// Check paths for FTL files to load.
auto paths = (*root->get<nlohmann::json>("paths"));
for (auto &x : paths.items()) {
std::string path = x.value().get<std::string>();
auto eix = path.find_last_of('.');
auto ext = path.substr(eix+1);
// Command line path is ftl file
if (ext == "ftl") {
const int fsid = frameset_counter_++;
LOG(INFO) << "Found FTL file: " << path << ", fsid: " << fsid;
// who cleans this up (delete fstream)?
auto *fstream = ftl::create<ftl::stream::File>(root, std::string("ftlfile-")+std::to_string(fsid));
fstream->set("filename", path);
stream_->add(fstream, fsid);
}
else if (path.rfind("device:", 0) == 0) {
ftl::URI uri(path);
uri.to_json(root->getConfig()["sources"].emplace_back());
}
else {
ftl::URI uri(path);
if (uri.getScheme() == ftl::URI::SCHEME_TCP || uri.getScheme() == ftl::URI::SCHEME_WS) {
net_->connect(path);
}
}
}
// Finally, check for any device sources configured
/*
std::vector<Source*> devices;
// Create a vector of all input RGB-Depth sources
if (screen->root()->getConfig()["sources"].size() > 0) {
devices = ftl::createArray<Source>(screen->root(), "sources", screen->control()->getNet());
auto *gen = createSourceGenerator(screen->root(), devices);
int fsid = ftl::gui::mapToFrameset(screen->root()->getID());
gen->onFrameSet([this, fsid](ftl::rgbd::FrameSet &fs) {
fs.id = fsid; // Set a frameset id to something unique.
return _processFrameset(fs, false);
});
}*/
stream_->begin();
}
bool InputOutput::process_callbacks_video(ftl::rgbd::FrameSet &fs) {
UNIQUE_LOCK(mtx_, lk);
for (auto &f : cb_video_) {
f(fs);
}
return true;
}
bool InputOutput::process_callbacks_audio(ftl::audio::FrameSet &fs) {
UNIQUE_LOCK(mtx_, lk);
for (auto &f : cb_audio_) {
f(fs);
}
return true;
}
void InputOutput::subscribe(const std::function<bool(ftl::rgbd::FrameSet&)> &f) {
UNIQUE_LOCK(mtx_, lk);
cb_video_.push_back(f);
}
void InputOutput::subscribe(const std::function<bool(ftl::audio::FrameSet&)> &f) {
UNIQUE_LOCK(mtx_, lk);
cb_audio_.push_back(f);
}
#pragma once
#include <memory>
#include <mutex>
#include <ftl/configuration.hpp>
#include <ftl/net/universe.hpp>
#include <ftl/master.hpp>
#include <ftl/streams/stream.hpp>
#include <ftl/streams/receiver.hpp>
#include <ftl/streams/filestream.hpp>
#include <ftl/audio/speaker.hpp>
namespace ftl {
namespace gui2 {
class InputOutput {
public:
InputOutput(ftl::Configurable *config, ftl::net::Universe *net);
InputOutput(const InputOutput&) = delete;
void operator=(const InputOutput&) = delete;
void subscribe(const std::function<bool(ftl::rgbd::FrameSet&)>&);
void subscribe(const std::function<bool(ftl::audio::FrameSet&)>&);
void unsubscribe();
void unsubscribe_audio();
void unsubscribe_video();
ftl::net::Universe* net() const;
private:
bool process_callbacks_video(ftl::rgbd::FrameSet &fs);
bool process_callbacks_audio(ftl::audio::FrameSet &fs);
std::mutex mtx_;
ftl::net::Universe* net_;
std::unique_ptr<ftl::ctrl::Master> controller_;
std::unique_ptr<ftl::stream::Muxer> stream_;
std::unique_ptr<ftl::stream::Intercept> interceptor_;
std::unique_ptr<ftl::stream::File> recorder_;
std::unique_ptr<ftl::stream::Receiver> receiver_;
std::unique_ptr<ftl::audio::Speaker> speaker_;
//std::unordered_map<std::string, ftl::stream::Stream*> available_;
std::vector<uintptr_t> cb_video_id_;
std::vector<uintptr_t> cb_audio_id_;
std::vector<std::function<bool(ftl::rgbd::FrameSet&)>> cb_video_;
std::vector<std::function<bool(ftl::audio::FrameSet&)>> cb_audio_;
int frameset_counter_ = 0;
};
}
}
#include <memory>
#include <loguru.hpp>
#include <ftl/configuration.hpp>
#include <ftl/net/universe.hpp>
#include <ftl/net_configurable.hpp>
#include <ftl/rgbd.hpp>
#include <nanogui/nanogui.h>
#include <cuda_gl_interop.h>
#include "inputoutput.hpp"
#include "modules.hpp"
#include "screen.hpp"
using std::unique_ptr;
int main(int argc, char **argv) {
int cuda_device;
cudaSafeCall(cudaGetDevice(&cuda_device));
//cudaSafeCall(cudaGLSetGLDevice(cuda_device));
auto root = unique_ptr<ftl::Configurable>(ftl::configure(argc, argv, "gui_default"));
auto net = unique_ptr<ftl::net::Universe>(ftl::create<ftl::net::Universe>(root.get(), "net"));
auto io = ftl::gui2::InputOutput(root.get(), net.get());
net->start();
net->waitConnections();
ftl::timer::start();
try {
nanogui::init();
{
nanogui::ref<ftl::gui2::Screen> gui =
new ftl::gui2::Screen();
nanogui::ref<ftl::gui2::HomeView> home =
new ftl::gui2::HomeView(root.get(), &io);
gui->setView(home);
gui->drawAll();
gui->setVisible(true);
float last_draw_time = 0.0f;
while (ftl::running) {
if (!gui->visible()) {
ftl::running = false;
}
else if (glfwWindowShouldClose(gui->glfwWindow())) {
gui->setVisible(false);
ftl::running = false;
}
else {
float now = float(glfwGetTime());
float delta = now - last_draw_time;
// Generate poses and render and virtual frame here
// at full FPS (25 without VR and 90 with VR currently)
//gui->drawFast();
// Only draw the GUI at 25fps
if (delta >= 0.04f) {
last_draw_time = now;
gui->drawAll();
}
}
// Wait for mouse/keyboard or empty refresh events
glfwPollEvents();
}
// Process events once more
glfwPollEvents();
LOG(INFO) << "Stopping...";
ftl::timer::stop(false);
ftl::pool.stop(true);
LOG(INFO) << "All threads stopped.";
}
nanogui::shutdown();
}
catch (const ftl::exception &e) {
LOG(ERROR) << "Fatal error: " << e.what();
LOG(ERROR) << e.trace();
}
catch (const std::runtime_error &e) {
std::string error_msg = std::string("Caught a fatal error: ") + std::string(e.what());
#ifdef _WIN32
MessageBoxA(nullptr, error_msg.c_str(), NULL, MB_ICONERROR | MB_OK);
#else
LOG(ERROR) << error_msg;
#endif
return -1;
}
net->shutdown();
return 0;
}
#pragma once
#include "modules/home.hpp"
#include "home.hpp"
using ftl::gui2::HomeView;
namespace {
constexpr char const *const defaultImageViewVertexShader =
R"(#version 330
uniform vec2 scaleFactor;
uniform vec2 position;
in vec2 vertex;
out vec2 uv;
void main() {
uv = vec2(vertex.x, vertex.y);
vec2 scaledVertex = (vertex * scaleFactor) + position;
gl_Position = vec4(2.0*scaledVertex.x - 1.0,
2.0*scaledVertex.y - 1.0,
0.0, 1.0);
})";
constexpr char const *const defaultImageViewFragmentShader =
R"(#version 330
uniform sampler2D image1;
uniform sampler2D image2;
uniform sampler2D depthImage;
uniform float blendAmount;
out vec4 color;
in vec2 uv;
void main() {
color = blendAmount * texture(image1, uv) + (1.0 - blendAmount) * texture(image2, uv);
color.w = 1.0f;
gl_FragDepth = texture(depthImage, uv).r;
})";
}
HomeView::HomeView(ftl::Configurable *cfg, ftl::gui2::InputOutput *io) :
ftl::gui2::View(cfg, io), texture_(ftl::gui2::GLTexture::Type::RGBA) {
io_->subscribe([this](ftl::rgbd::FrameSet &fs) { return process_FrameSet(fs); });
mShader.init("RGBDShader", defaultImageViewVertexShader, defaultImageViewFragmentShader);
nanogui::MatrixXu indices(3, 2);
indices.col(0) << 0, 1, 2;
indices.col(1) << 2, 3, 1;
nanogui::MatrixXf vertices(2, 4);
vertices.col(0) << 0, 0;
vertices.col(1) << 1, 0;
vertices.col(2) << 0, 1;
vertices.col(3) << 1, 1;
mShader.bind();
mShader.uploadIndices(indices);
mShader.uploadAttrib("vertex", vertices);
}
HomeView::~HomeView() {
mShader.free();
}
bool HomeView::process_FrameSet(ftl::rgbd::FrameSet &fs) {
auto im = fs.frames[0].fastDownload(ftl::codecs::Channel::Left, cv::cuda::Stream::Null());
texture_.make(im.cols, im.rows);
return true;
}
#pragma once
#include <nanogui/glutil.h>
#include "../view.hpp"
#include "../gltexture.hpp"
namespace ftl {
namespace gui2 {
class HomeView : public View {
public:
HomeView(ftl::Configurable *config, InputOutput *io);
~HomeView();
private:
bool process_FrameSet(ftl::rgbd::FrameSet&);
nanogui::GLShader mShader;
GLTexture texture_;
};
}
}
#include <nanogui/opengl.h>
#include <nanogui/glutil.h>
#include <nanogui/screen.h>
#include <nanogui/window.h>
#include <nanogui/layout.h>
#include <nanogui/imageview.h>
#include <nanogui/label.h>
#include <nanogui/toolbutton.h>
#include <nanogui/popupbutton.h>
#include <Eigen/Eigen>
#include "window.hpp"
#include "screen.hpp"
#include "modules.hpp"
#include <loguru.hpp>
using std::min;
using std::max;
using Eigen::Vector2i;
using ftl::gui2::Screen;
Screen::Screen() :
nanogui::Screen(Eigen::Vector2i(1024, 768), "FT-Lab Remote Presence"),
mediatheme(nullptr),
toolbuttheme(nullptr),
windowtheme(nullptr),
toolbar(nullptr),
view(nullptr) {
using namespace nanogui;
setSize(Vector2i(1280,720));
// themes
toolbuttheme = new Theme(*theme());
toolbuttheme->mBorderDark = nanogui::Color(0,0);
toolbuttheme->mBorderLight = nanogui::Color(0,0);
toolbuttheme->mButtonGradientBotFocused = nanogui::Color(60,255);
toolbuttheme->mButtonGradientBotUnfocused = nanogui::Color(0,0);
toolbuttheme->mButtonGradientTopFocused = nanogui::Color(60,255);
toolbuttheme->mButtonGradientTopUnfocused = nanogui::Color(0,0);
toolbuttheme->mButtonGradientTopPushed = nanogui::Color(60,180);
toolbuttheme->mButtonGradientBotPushed = nanogui::Color(60,180);
toolbuttheme->mTextColor = nanogui::Color(0.9f,0.9f,0.9f,0.9f);
mediatheme = new Theme(*theme());
mediatheme->mIconScale = 1.2f;
mediatheme->mWindowDropShadowSize = 0;
mediatheme->mWindowFillFocused = nanogui::Color(45, 150);
mediatheme->mWindowFillUnfocused = nanogui::Color(45, 80);
mediatheme->mButtonGradientTopUnfocused = nanogui::Color(0,0);
mediatheme->mButtonGradientBotUnfocused = nanogui::Color(0,0);
mediatheme->mButtonGradientTopFocused = nanogui::Color(80,230);
mediatheme->mButtonGradientBotFocused = nanogui::Color(80,230);
mediatheme->mIconColor = nanogui::Color(255,255);
mediatheme->mTextColor = nanogui::Color(1.0f,1.0f,1.0f,1.0f);
mediatheme->mBorderDark = nanogui::Color(0,0);
mediatheme->mBorderMedium = nanogui::Color(0,0);
mediatheme->mBorderLight = nanogui::Color(0,0);
mediatheme->mDropShadow = nanogui::Color(0,0);
mediatheme->mButtonFontSize = 30;
mediatheme->mStandardFontSize = 20;
windowtheme = new Theme(*theme());
windowtheme->mWindowFillFocused = nanogui::Color(220, 200);
windowtheme->mWindowFillUnfocused = nanogui::Color(220, 200);
windowtheme->mWindowHeaderGradientBot = nanogui::Color(60,230);
windowtheme->mWindowHeaderGradientTop = nanogui::Color(60,230);
windowtheme->mTextColor = nanogui::Color(20,255);
windowtheme->mWindowCornerRadius = 0;
windowtheme->mButtonGradientBotFocused = nanogui::Color(210,255);
windowtheme->mButtonGradientBotUnfocused = nanogui::Color(190,255);
windowtheme->mButtonGradientTopFocused = nanogui::Color(230,255);
windowtheme->mButtonGradientTopUnfocused = nanogui::Color(230,255);
windowtheme->mButtonGradientTopPushed = nanogui::Color(170,255);
windowtheme->mButtonGradientBotPushed = nanogui::Color(210,255);
windowtheme->mBorderDark = nanogui::Color(150,255);
windowtheme->mBorderMedium = nanogui::Color(165,255);
windowtheme->mBorderLight = nanogui::Color(230,255);
windowtheme->mButtonFontSize = 16;
windowtheme->mTextColorShadow = nanogui::Color(0,0);
windowtheme->mWindowTitleUnfocused = windowtheme->mWindowTitleFocused;
windowtheme->mWindowTitleFocused = nanogui::Color(240,255);
windowtheme->mWindowDropShadowSize = 0;
windowtheme->mDropShadow = nanogui::Color(0,0);
windowtheme->mIconScale = 0.85f;
toolbar = new StationaryWindow(this, "");
toolbar->setPosition(Vector2i(0,0));
toolbar->setFixedWidth(50);
toolbar->setFixedHeight(height());
setResizeCallback([this](Vector2i s) {
toolbar->setFixedSize({toolbar->width(), s[1]});
toolbar->setPosition({0, 0});
if (view) {
view->setFixedSize({max(s[0] - toolbar->width(), 0), s[1]});
view->setPosition({toolbar->width(), 0});
}
this->performLayout();
});
auto tools = new Widget(toolbar);
tools->setLayout(new BoxLayout( Orientation::Vertical,
Alignment::Middle, 0, 10));
tools->setPosition(Vector2i(5,10));
auto button = new ToolButton(tools, ENTYPO_ICON_HOME);
button->setIconExtraScale(1.5f);
button->setTheme(toolbuttheme);
button->setTooltip("Home");
button->setFixedSize(Vector2i(40,40));
button->setCallback([this]() {
});
setVisible(true);
performLayout();
}
Screen::~Screen() {}
void Screen::setView(ftl::gui2::View *window) {
if (view) {
view->setVisible(false);
this->removeChild(view);
}
view = window;
view->setTheme(windowtheme);
this->addChild(view);
view->setFixedSize(Vector2i(width() - toolbar->width(), height()));
view->setVisible(true);
}
#pragma once
#include <nanogui/screen.h>
#include <nanogui/glutil.h>
#include <memory>
#ifdef HAVE_OPENVR
#include <openvr/openvr.h>
#endif
#include "view.hpp"
namespace ftl {
namespace gui2 {
class Screen : public nanogui::Screen {
public:
explicit Screen();
~Screen();
void render();
void setView(ftl::gui2::View *view);
private:
nanogui::Theme* mediatheme;
nanogui::Theme* toolbuttheme;
nanogui::Theme* windowtheme;
nanogui::Widget *toolbar;
ftl::gui2::View *view;
};
}
}
#include "view.hpp"
using ftl::gui2::View;
View::View(ftl::Configurable *config, ftl::gui2::InputOutput *io,
const std::string &title) :
StationaryWindow(nullptr, title), config_(config), io_(io) {
}
#pragma once
#include "window.hpp"
#include "inputoutput.hpp"
namespace ftl {
namespace gui2 {
class View : public nanogui::StationaryWindow {
public:
View(ftl::Configurable *config, ftl::gui2::InputOutput *io, const std::string &title = "");
virtual ~View() {}
virtual void render() {}
protected:
ftl::Configurable *config_;
ftl::gui2::InputOutput *io_;
};
};
};
#pragma once
#include <nanogui/window.h>
namespace nanogui {
/**
* Non-movable Window widget
*/
class StationaryWindow : public nanogui::Window {
using Window::Window;
virtual bool mouseDragEvent(const Vector2i&, const Vector2i &, int, int) override { return false; }
};
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment