add experimental menu
This commit is contained in:
@@ -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"/>
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
132
src/main.cpp
132
src/main.cpp
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user