add experimental menu

This commit is contained in:
2019-03-18 20:26:18 +01:00
parent 4bb1eb28a3
commit e635ad00a8
5 changed files with 217 additions and 105 deletions

View File

@@ -1447,6 +1447,29 @@ Here's a list of what's available in this release.
</popup-menu>
</layout>
<!-- MENU EXPERIMENTAL -->
<layout id="experimental-menu">
<popup-menu positioning="absolute" position="100 100" width="150" thickness="1" border-color=".1" color=".4 .4 .4 .8" dir="col">
<node dir="row">
<button-custom id="experimental-timelapse" height="40" align="center" color=".2" pad="0 0 0 10" dir="row" grow="1">
<text text="Timelapse" grow="1" margin="0 0 0 5"/>
</button-custom>
<button-custom id="experimental-timelapse-tick" height="40" width="40" align="center" justify="center" color=".2" dir="row">
<icon icon="resultset_next" width="20"/>
</button-custom>
</node>
<button-custom id="experimental-rtl" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
<checkbox id="experimental-rtl-check" width="20" height="20"/>
<text text="Left-handed UI" margin="0 0 0 5"/>
</button-custom>
<button-custom id="experimental-vr" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
<checkbox id="experimental-vr-check" width="20" height="20"/>
<text text="Enable VR" margin="0 0 0 5"/>
</button-custom>
</popup-menu>
</layout>
<!-- MENU TIMELAPSE -->
<layout id="timelapse-menu">
<popup-menu positioning="absolute" position="100 100" width="150" thickness="1" border-color=".1" color=".4 .4 .4 .8" dir="col">
@@ -1536,7 +1559,7 @@ Here's a list of what's available in this release.
<!--main-->
<layout id="main">
<canvas id="paint-canvas" positioning="absolute" width="100%" height="100%" grow="1"/>
<node dir="col" wrap="0" width="100%" height="100%" pad="0">
<node id="ui-root" dir="col" wrap="0" width="100%" height="100%" pad="0">
<!-- content panel -->
<!-- menu bar -->
<border flood-events="1" margin="0 0 0 0" pad="0 0 0 0" color=".1" width="100%" height="30" dir="row" align="center" mouse-capture="true">
@@ -1572,8 +1595,8 @@ Here's a list of what's available in this release.
<button-custom id="menu-layers" width="60" height="100%" margin="0 0 0 0" justify="center" align="center" pad="8" color=".1">
<text text="Layers"/>
</button-custom>
<button-custom id="menu-timelapse" width="80" height="100%" margin="0 0 0 0" justify="center" align="center" pad="8" color=".1">
<text text="Timelapse"/>
<button-custom id="menu-experimental" width="100" height="100%" margin="0 0 0 0" justify="center" align="center" pad="8" color=".1">
<text text="Experimental"/>
</button-custom>
<button-custom id="menu-about" width="60" height="100%" margin="0 0 0 0" justify="center" align="center" pad="8" color=".1">
<text text="About"/>

View File

@@ -57,9 +57,6 @@ public:
LayoutManager layout;
NodeMessageBox* msgbox;
NodeSettings* settings;
NodePopupMenu* menu_file = nullptr;
NodePopupMenu* menu_edit = nullptr;
NodePopupMenu* menu_layers = nullptr;
NodeBorder* sidebar = nullptr;
std::shared_ptr<NodePanelLayer> layers;
std::shared_ptr<NodePanelColor> color;
@@ -68,7 +65,6 @@ public:
std::shared_ptr<NodePanelBrushPreset> presets;
NodePanelQuick* quick;
NodeCanvas* canvas;
Node* current_panel = nullptr;
const uint16_t main_id = const_hash("main");
const std::array<int, 6> res_map{ 512, 1024, 1536, 2048, 4096, 8192 };
const std::array<std::string, 6> res_map_str{ "2K", "4K", "6K", "8K", "16K", "32K" };
@@ -134,6 +130,8 @@ public:
void clear();
void tick(float dt);
void update(float dt);
bool vr_start();
void vr_stop();
void vr_draw(const glm::mat4& proj, const glm::mat4& view, const glm::mat4& pose);
void async_start();
void async_update();
@@ -169,7 +167,7 @@ public:
void init_menu_file();
void init_menu_edit();
void init_menu_layer();
void init_menu_timelapse();
void init_menu_experimental();
void init_menu_about();
void dialog_usermanual();
void dialog_changelog();

View File

@@ -660,50 +660,111 @@ void App::init_menu_edit()
}
}
void App::init_menu_timelapse()
void App::init_menu_experimental()
{
if (auto* menu_file = layout[main_id]->find<NodeButtonCustom>("menu-timelapse"))
auto main = layout[main_id];
if (auto menu_exp = main->find<NodeButtonCustom>("menu-experimental"))
{
menu_file->on_click = [=](Node*) {
glm::vec2 pos = menu_file->m_pos + glm::vec2(0, menu_file->m_size.y);
auto popup = (NodePopupMenu*)layout[const_hash("timelapse-menu")]->m_children[0]->clone();
popup->update();
menu_exp->on_click = [this, menu_exp, main](Node*) {
glm::vec2 pos = menu_exp->m_pos + glm::vec2(0, menu_exp->m_size.y);
auto popup_exp = (NodePopupMenu*)layout[const_hash("experimental-menu")]->m_children[0]->clone();
popup_exp->update();
if (YGNodeStyleGetDirection(layout[main_id]->y_node) == YGDirectionRTL)
pos.x = pos.x - popup->m_size.x + menu_file->m_size.x;
popup->SetPositioning(YGPositionTypeAbsolute);
popup->SetPosition(pos.x, pos.y);
layout[main_id]->add_child(popup);
pos.x = pos.x - popup_exp->m_size.x + menu_exp->m_size.x;
popup_exp->SetPositioning(YGPositionTypeAbsolute);
popup_exp->SetPosition(pos.x, pos.y);
layout[main_id]->add_child(popup_exp);
layout[main_id]->update();
popup->mouse_capture();
popup->m_mouse_ignore = false;
popup->m_flood_events = true;
popup->m_capture_children = false;
if (auto item = popup->find<NodeButtonCustom>("timelapse-start"))
popup_exp->mouse_capture();
popup_exp->m_mouse_ignore = false;
popup_exp->m_flood_events = true;
popup_exp->m_capture_children = false;
if (auto tick = popup_exp->find<NodeButtonCustom>("experimental-timelapse-tick")) tick->on_click = [this, popup_exp](Node* b)
{
if (auto text = popup->find<NodeText>("menu-label"))
if (auto menu_time = popup_exp->find<NodePopupMenu>("experimental-timelapse"))
{
text->set_text(App::I.rec_running ? "Stop Recording" : "Start Recording");
glm::vec2 pos = b->m_pos + glm::vec2(b->m_size.x, 0);
auto popup_time = (NodePopupMenu*)layout[const_hash("timelapse-menu")]->m_children[0]->clone();
popup_time->update();
if (YGNodeStyleGetDirection(layout[main_id]->y_node) == YGDirectionRTL)
pos.x = pos.x - popup_time->m_size.x + b->m_size.x;
popup_time->SetPositioning(YGPositionTypeAbsolute);
popup_time->SetPosition(pos.x, pos.y);
layout[main_id]->add_child(popup_time);
layout[main_id]->update();
popup_time->mouse_capture();
popup_time->m_mouse_ignore = false;
popup_time->m_flood_events = true;
popup_time->m_capture_children = false;
if (auto item = popup_time->find<NodeButtonCustom>("timelapse-start"))
{
if (auto text = popup_time->find<NodeText>("menu-label"))
{
text->set_text(App::I.rec_running ? "Stop Recording" : "Start Recording");
}
}
popup_time->find<NodeButtonCustom>("timelapse-start")->on_click = [this, popup_time, popup_exp](Node*) {
App::I.rec_running ? App::I.rec_stop() : App::I.rec_start();
popup_time->destroy();
popup_exp->destroy();
};
popup_time->find<NodeButtonCustom>("timelapse-clear")->on_click = [this, popup_time, popup_exp](Node*) {
App::I.rec_clear();
popup_time->destroy();
popup_exp->destroy();
};
popup_time->find<NodeButtonCustom>("timelapse-export")->on_click = [this, popup_time, popup_exp](Node*) {
popup_time->destroy();
popup_exp->destroy();
App::I.rec_export("");
};
}
};
if (auto rtl_btn = popup_exp->find<NodeButtonCustom>("experimental-rtl"))
{
rtl_btn->on_click = [this, popup_exp, rtl_btn](Node* b)
{
NodeCheckBox* cb = rtl_btn->find<NodeCheckBox>("experimental-rtl-check");
cb->set_value(!cb->checked, true);
};
rtl_btn->find<NodeCheckBox>("experimental-rtl-check")->on_value_changed = [this, main](Node*, bool checked)
{
auto ui = main->find("ui-root");
ui->SetRTL(checked ? YGDirectionRTL : YGDirectionLTR);
};
}
popup->find<NodeButtonCustom>("timelapse-start")->on_click = [this, popup](Node*) {
App::I.rec_running ? App::I.rec_stop() : App::I.rec_start();
popup->mouse_release();
popup->destroy();
};
popup->find<NodeButtonCustom>("timelapse-clear")->on_click = [this, popup](Node*) {
App::I.rec_clear();
popup->mouse_release();
popup->destroy();
};
popup->find<NodeButtonCustom>("timelapse-export")->on_click = [this, popup](Node*) {
popup->mouse_release();
popup->destroy();
App::I.rec_export("");
};
if (auto vr_btn = popup_exp->find<NodeButtonCustom>("experimental-vr"))
{
vr_btn->on_click = [this, popup_exp, vr_btn](Node* b)
{
NodeCheckBox* cb = vr_btn->find<NodeCheckBox>("experimental-vr-check");
cb->set_value(!cb->checked, true);
};
vr_btn->find<NodeCheckBox>("experimental-vr-check")->on_value_changed = [this, main](Node* target, bool checked)
{
if (checked)
{
if (!App::I.vr_start())
{
auto cb = static_cast<NodeCheckBox*>(target);
cb->set_value(false);
App::I.message_box("VR Failed", "Couldn't start Virtual Reality mode");
}
}
else
{
App::I.vr_stop();
}
};
}
};
}
}
@@ -939,7 +1000,7 @@ void App::initLayout()
init_menu_file();
init_menu_edit();
init_menu_layer();
init_menu_timelapse();
init_menu_experimental();
init_menu_about();
// set version string

View File

@@ -1,6 +1,26 @@
#include "pch.h"
#include "app.h"
#ifdef _WIN32
bool win32_vr_start();
void win32_vr_stop();
#endif
bool App::vr_start()
{
#ifdef _WIN32
return win32_vr_start();
#endif
}
void App::vr_stop()
{
#ifdef _WIN32
win32_vr_stop();
#endif
}
void App::vr_draw(const glm::mat4& proj, const glm::mat4& camera, const glm::mat4& pose)
{
//glm::mat4 ortho_proj = glm::ortho(0.f, box.z, 0.f, box.w, -1000.f, 1000.f);

View File

@@ -446,6 +446,77 @@ void init_vk_map()
}
}
std::mutex hmd_render_mutex;
std::condition_variable hmd_render_cv;
Vive* vive = nullptr;
bool win32_vr_start()
{
if (sandboxed)
return false;
vive = new Vive;
vive->on_draw = [](const glm::mat4& proj, const glm::mat4& view, const glm::mat4& pose) { App::I.vr_draw(proj, view, pose); };
async_lock();
if (!vive->Initialize())
{
delete vive;
vive = nullptr;
LOG("VR: failed to initialize vive");
async_unlock();
return false;
}
async_unlock();
hmd_renderer = std::thread([&] {
if (!vive)
return;
BT_SetTerminate();
LOG("start hmd render thread");
App::I.has_vr = true;
const float target_tick_rate = 90;
unsigned long t0 = GetTickCount();
while (running == 1 && vive->Valid())
{
std::unique_lock<std::mutex> lock(hmd_render_mutex);
unsigned long t1 = GetTickCount();
float dt = (float)(t1 - t0) / 1000.0f;
vive->Update();
App::I.vr_active = vive->m_active;
if (vive->m_active)
{
async_lock();
vive->Draw();
async_unlock();
}
const int framerate = (1.f / target_tick_rate) * 1000;
const int diff = framerate - (t1 - t0);
hmd_render_cv.wait_for(lock, std::chrono::milliseconds(diff));
}
App::I.vr_active = false;
App::I.has_vr = false;
async_lock();
vive->Terminate();
async_unlock();
LOG("hmd renderer terminated");
});
return true;
}
void win32_vr_stop()
{
if (vive)
{
vive->Terminate();
delete vive;
vive = nullptr;
}
}
int main(int argc, char** argv)
{
WNDCLASS wc;
@@ -620,21 +691,6 @@ int main(int argc, char** argv)
LOG("init app");
App::I.init();
Vive* vive = nullptr;
if (!sandboxed)
{
vive = new Vive;
vive->on_draw = [](const glm::mat4& proj, const glm::mat4& view, const glm::mat4& pose) { App::I.vr_draw(proj, view, pose); };
async_lock();
if (!vive->Initialize())
{
delete vive;
vive = nullptr;
LOG("VR: failed to initialize vive");
}
async_unlock();
}
LOG("show main window");
ShowWindow(hWnd, SW_NORMAL);
@@ -654,11 +710,6 @@ int main(int argc, char** argv)
SendMessage(hWnd, WM_SETICON, ICON_SMALL,
(LPARAM)LoadIcon(GetModuleHandle(0), MAKEINTRESOURCE(IDI_ICON1)));
//LOG("set redraw interval");
//SetTimer(hWnd, 1, 500, [](HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) {
// App::I.redraw = true;
//});
running = 1;
renderer = std::thread([&] {
@@ -766,47 +817,6 @@ int main(int argc, char** argv)
LOG("renderer terminated");
});
std::mutex hmd_render_mutex;
std::condition_variable hmd_render_cv;
hmd_renderer = std::thread([&] {
if (!vive)
return;
BT_SetTerminate();
LOG("start hmd render thread");
App::I.has_vr = true;
const float target_tick_rate = 90;
unsigned long t0 = GetTickCount();
while (running == 1 && vive->Valid())
{
std::unique_lock<std::mutex> lock(hmd_render_mutex);
unsigned long t1 = GetTickCount();
float dt = (float)(t1 - t0) / 1000.0f;
vive->Update();
App::I.vr_active = vive->m_active;
if (vive->m_active)
{
async_lock();
vive->Draw();
async_unlock();
}
const int framerate = (1.f / target_tick_rate) * 1000;
const int diff = framerate - (t1 - t0);
hmd_render_cv.wait_for(lock, std::chrono::milliseconds(diff));
}
App::I.vr_active = false;
App::I.has_vr = false;
async_lock();
vive->Terminate();
async_unlock();
LOG("hmd renderer terminated");
});
SetTimer(hWnd, 1, 500, NULL);
MSG msg;