新增imgui-knobs, 新增释放管理器顺序依赖, 修复plugin_host窗口没有打开的问题
This commit is contained in:
parent
cb3b2e0c6a
commit
c957b60ec8
@ -13,8 +13,8 @@ void window_manager::init(singleton_initliazer& initliazer) {
|
||||
// start_idle_thread();
|
||||
}
|
||||
|
||||
void window_manager::release() {
|
||||
singleton_t<window_manager>::release();
|
||||
void window_manager::release(singleton_release_guard& release_guard) {
|
||||
singleton_t<window_manager>::release(release_guard);
|
||||
if (main_window_)
|
||||
glfwDestroyWindow(main_window_);
|
||||
}
|
||||
@ -53,6 +53,7 @@ GLFWwindow* window_manager::create_plugin_host_window(plugin_host* host) {
|
||||
glfwSetWindowPos(new_window, pos.x, pos.y);
|
||||
}
|
||||
host_window_map_[host] = new_window;
|
||||
glfwShowWindow(new_window);
|
||||
return new_window;
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,7 @@ class window_manager : public singleton_t<window_manager> {
|
||||
public:
|
||||
window_manager();
|
||||
void init(singleton_initliazer& initliazer) override;
|
||||
void release() override;
|
||||
void release(singleton_release_guard& release_guard) override;
|
||||
void tick();
|
||||
bool should_close() const { return glfwWindowShouldClose(main_window_); }
|
||||
void destroy_all_plugin_host_window();
|
||||
|
@ -14,8 +14,9 @@ void audio_device_manager::init(singleton_initliazer& initliazer) {
|
||||
dummy_audio_device_->init();
|
||||
}
|
||||
|
||||
void audio_device_manager::release() {
|
||||
singleton_t<audio_device_manager>::release();
|
||||
void audio_device_manager::release(singleton_release_guard& release_guard) {
|
||||
singleton_t<audio_device_manager>::release(release_guard);
|
||||
release_guard.require_release<mixer>();
|
||||
delete dummy_audio_device_;
|
||||
delete main_audio_device_;
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ class port_audio_device;
|
||||
class audio_device_manager : public singleton_t<audio_device_manager> {
|
||||
public:
|
||||
void init(singleton_initliazer& initliazer) override;
|
||||
void release() override;
|
||||
void release(singleton_release_guard& release_guard) override;
|
||||
|
||||
void start();
|
||||
|
||||
|
@ -14,6 +14,7 @@ int port_audio_callback(const void* Input, void* Output, unsigned long FrameCoun
|
||||
|
||||
port_audio_device::~port_audio_device() {
|
||||
port_audio_device::destroy();
|
||||
stop();
|
||||
}
|
||||
|
||||
bool port_audio_device::init() {
|
||||
|
@ -77,8 +77,8 @@ void mixer::init(singleton_initliazer& initliazer) {
|
||||
device_manager->start();
|
||||
}
|
||||
|
||||
void mixer::release() {
|
||||
singleton_t<mixer>::release();
|
||||
void mixer::release(singleton_release_guard& release_guard) {
|
||||
singleton_t<mixer>::release(release_guard);
|
||||
null_channel_node::destroy();
|
||||
|
||||
for (const mixer_track* track : tracks_) {
|
||||
|
@ -15,7 +15,7 @@ class mixer : public singleton_t<mixer> {
|
||||
|
||||
public:
|
||||
void init(singleton_initliazer& initliazer) override;
|
||||
void release() override;
|
||||
void release(singleton_release_guard& release_guard) override;
|
||||
const char* get_name() override { return "mixer"; }
|
||||
|
||||
dummy_track* create_dummy_track(const std::string& in_name);
|
||||
|
@ -17,9 +17,11 @@ void plugin_host_manager::init(singleton_initliazer& initliazer) {
|
||||
mixer_ptr->on_remove_track.add_raw(this, &plugin_host_manager::on_mixer_track_removed);
|
||||
}
|
||||
|
||||
void plugin_host_manager::release() {
|
||||
singleton_t<plugin_host_manager>::release();
|
||||
for (auto host: plugin_hosts_) {
|
||||
void plugin_host_manager::release(singleton_release_guard& release_guard) {
|
||||
singleton_t<plugin_host_manager>::release(release_guard);
|
||||
release_guard.require_release<audio_device_manager>();
|
||||
|
||||
for (const plugin_host* host: plugin_hosts_) {
|
||||
delete host;
|
||||
}
|
||||
}
|
||||
@ -63,6 +65,7 @@ plugin_host* plugin_host_manager::load_plugin(const char* path) {
|
||||
}
|
||||
|
||||
void plugin_host_manager::register_instrument_plugin(plugin_host* host) {
|
||||
instrument_plugins_.push_back(host);
|
||||
g_audio_thread_hub.push_message([this, host]() {
|
||||
instrument_track* instrument_track = g_mixer.create_instrument_track(host);
|
||||
host->channel->set_input_channel(instrument_track->get_channel_interface()->input_channel_nodes);
|
||||
|
@ -8,7 +8,7 @@ class mixer_track;
|
||||
class CORE_API plugin_host_manager : public singleton_t<plugin_host_manager> {
|
||||
public:
|
||||
void init(singleton_initliazer& initliazer) override;
|
||||
void release() override;
|
||||
void release(singleton_release_guard& release_guard) override;
|
||||
|
||||
|
||||
plugin_host* create_instrument_plugin_host(const char* path);
|
||||
|
@ -28,8 +28,8 @@ public:
|
||||
virtual ~singleton() = default;
|
||||
virtual void init(singleton_initliazer& initliazer) {}
|
||||
virtual void post_init() {}
|
||||
virtual void begin_release() {}
|
||||
virtual void release() {}
|
||||
virtual void begin_release(singleton_release_guard& release_guard) {}
|
||||
virtual void release(singleton_release_guard& release_guard) {}
|
||||
|
||||
virtual const char* get_name() = 0;
|
||||
};
|
||||
|
@ -13,6 +13,20 @@ void singleton_initliazer::init_singleton(singleton* s) {
|
||||
}
|
||||
}
|
||||
|
||||
bool singleton_release_guard::has_release(singleton* s) {
|
||||
return std::ranges::find(release_singletons_, s) != release_singletons_.end();
|
||||
}
|
||||
|
||||
void singleton_release_guard::release_singleton(singleton* s) {
|
||||
if (!has_release(s)) {
|
||||
release_singletons_.push_back(s);
|
||||
if (begin_release_)
|
||||
s->begin_release(*this);
|
||||
else
|
||||
s->release(*this);
|
||||
}
|
||||
}
|
||||
|
||||
void singleton_manager::add(singleton* s) {
|
||||
singletons_.push_back(s);
|
||||
}
|
||||
@ -29,12 +43,18 @@ void singleton_manager::init() {
|
||||
}
|
||||
|
||||
void singleton_manager::release() const {
|
||||
for (int32_t j = singletons_.size() - 1; j >= 0; --j) {
|
||||
auto s = singletons_[j];
|
||||
s->begin_release();
|
||||
{
|
||||
singleton_release_guard release_guard(true);
|
||||
for (int32_t j = singletons_.size() - 1; j >= 0; --j) {
|
||||
auto s = singletons_[j];
|
||||
release_guard.release_singleton(s);
|
||||
}
|
||||
}
|
||||
for (int32_t j = singletons_.size() - 1; j >= 0; --j) {
|
||||
auto s = singletons_[j];
|
||||
s->release();
|
||||
{
|
||||
singleton_release_guard release_guard(false);
|
||||
for (int32_t j = singletons_.size() - 1; j >= 0; --j) {
|
||||
auto s = singletons_[j];
|
||||
release_guard.release_singleton(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,14 +14,36 @@ public:
|
||||
if (has_init(instance)) {
|
||||
return instance;
|
||||
}
|
||||
singletons_.push_back(instance);
|
||||
instance->init(*this);
|
||||
init_singleton(instance);
|
||||
return instance;
|
||||
}
|
||||
|
||||
std::vector<singleton*> singletons_{};
|
||||
};
|
||||
|
||||
class singleton_release_guard {
|
||||
public:
|
||||
singleton_release_guard(bool begin_release)
|
||||
: begin_release_(begin_release) {
|
||||
}
|
||||
|
||||
bool has_release(singleton* s);
|
||||
void release_singleton(singleton* s);
|
||||
|
||||
template<class T>
|
||||
void require_release() {
|
||||
auto instance = T::get();
|
||||
if (has_release(instance)) {
|
||||
return;
|
||||
}
|
||||
release_singleton(instance);
|
||||
}
|
||||
|
||||
std::vector<singleton*> release_singletons_{};
|
||||
private:
|
||||
bool begin_release_;
|
||||
};
|
||||
|
||||
class CORE_API singleton_manager {
|
||||
public:
|
||||
static singleton_manager* get() {
|
||||
|
3
third_party/imgui/CMakeLists.txt
vendored
3
third_party/imgui/CMakeLists.txt
vendored
@ -15,6 +15,8 @@ add_library(${PROJECT_NAME} STATIC
|
||||
imgui/imstb_textedit.h
|
||||
imgui/imstb_truetype.h
|
||||
imgui/imgui_tables.cpp
|
||||
imgui-knobs/imgui-knobs.h
|
||||
imgui-knobs/imgui-knobs.cpp
|
||||
)
|
||||
|
||||
find_package(Vulkan REQUIRED)
|
||||
@ -29,6 +31,7 @@ target_link_libraries(${PROJECT_NAME} PUBLIC glfw ${Vulkan_LIBRARIES})
|
||||
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/imgui)
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/imgui/backends)
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/imgui-knobs)
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} glfw ${Vulkan_INCLUDE_DIRS})
|
||||
|
||||
target_precompile_headers(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/pch.h)
|
||||
|
2
third_party/imgui/imgui
vendored
2
third_party/imgui/imgui
vendored
@ -1 +1 @@
|
||||
Subproject commit 8048b52498a9bf2a9f87b080d43b0bfd7a5d51d8
|
||||
Subproject commit 77dff5a735afd821fea1ac54dda63ef5d8bded96
|
303
third_party/imgui/imgui-knobs/imgui-knobs.cpp
vendored
Normal file
303
third_party/imgui/imgui-knobs/imgui-knobs.cpp
vendored
Normal file
@ -0,0 +1,303 @@
|
||||
#include "imgui-knobs.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
#include <imgui.h>
|
||||
#include <imgui_internal.h>
|
||||
|
||||
#define IMGUIKNOBS_PI 3.14159265358979323846f
|
||||
|
||||
namespace ImGuiKnobs {
|
||||
namespace detail {
|
||||
void draw_arc1(ImVec2 center, float radius, float start_angle, float end_angle, float thickness, ImColor color, int num_segments) {
|
||||
ImVec2 start = {
|
||||
center[0] + cosf(start_angle) * radius,
|
||||
center[1] + sinf(start_angle) * radius,
|
||||
};
|
||||
|
||||
ImVec2 end = {
|
||||
center[0] + cosf(end_angle) * radius,
|
||||
center[1] + sinf(end_angle) * radius,
|
||||
};
|
||||
|
||||
// Calculate bezier arc points
|
||||
auto ax = start[0] - center[0];
|
||||
auto ay = start[1] - center[1];
|
||||
auto bx = end[0] - center[0];
|
||||
auto by = end[1] - center[1];
|
||||
auto q1 = ax * ax + ay * ay;
|
||||
auto q2 = q1 + ax * bx + ay * by;
|
||||
auto k2 = (4.0f / 3.0f) * (sqrtf((2.0f * q1 * q2)) - q2) / (ax * by - ay * bx);
|
||||
auto arc1 = ImVec2{center[0] + ax - k2 * ay, center[1] + ay + k2 * ax};
|
||||
auto arc2 = ImVec2{center[0] + bx + k2 * by, center[1] + by - k2 * bx};
|
||||
|
||||
auto *draw_list = ImGui::GetWindowDrawList();
|
||||
#if IMGUI_VERSION_NUM <= 18000
|
||||
draw_list->AddBezierCurve(start, arc1, arc2, end, color, thickness, num_segments);
|
||||
#else
|
||||
draw_list->AddBezierCubic(start, arc1, arc2, end, color, thickness, num_segments);
|
||||
#endif
|
||||
}
|
||||
|
||||
void draw_arc(ImVec2 center, float radius, float start_angle, float end_angle, float thickness, ImColor color, int num_segments, int bezier_count) {
|
||||
// Overlap and angle of ends of bezier curves needs work, only looks good when not transperant
|
||||
auto overlap = thickness * radius * 0.00001f * IMGUIKNOBS_PI;
|
||||
auto delta = end_angle - start_angle;
|
||||
auto bez_step = 1.0f / bezier_count;
|
||||
auto mid_angle = start_angle + overlap;
|
||||
|
||||
for (auto i = 0; i < bezier_count - 1; i++) {
|
||||
auto mid_angle2 = delta * bez_step + mid_angle;
|
||||
draw_arc1(center, radius, mid_angle - overlap, mid_angle2 + overlap, thickness, color, num_segments);
|
||||
mid_angle = mid_angle2;
|
||||
}
|
||||
|
||||
draw_arc1(center, radius, mid_angle - overlap, end_angle, thickness, color, num_segments);
|
||||
}
|
||||
|
||||
template<typename DataType>
|
||||
struct knob {
|
||||
float radius;
|
||||
bool value_changed;
|
||||
ImVec2 center;
|
||||
bool is_active;
|
||||
bool is_hovered;
|
||||
float angle_min;
|
||||
float angle_max;
|
||||
float t;
|
||||
float angle;
|
||||
float angle_cos;
|
||||
float angle_sin;
|
||||
|
||||
knob(const char *_label, ImGuiDataType data_type, DataType *p_value, DataType v_min, DataType v_max, float speed, float _radius, const char *format, ImGuiKnobFlags flags) {
|
||||
radius = _radius;
|
||||
t = ((float) *p_value - v_min) / (v_max - v_min);
|
||||
auto screen_pos = ImGui::GetCursorScreenPos();
|
||||
|
||||
// Handle dragging
|
||||
ImGui::InvisibleButton(_label, {radius * 2.0f, radius * 2.0f});
|
||||
auto gid = ImGui::GetID(_label);
|
||||
ImGuiSliderFlags drag_flags = 0;
|
||||
if (!(flags & ImGuiKnobFlags_DragHorizontal)) {
|
||||
drag_flags |= ImGuiSliderFlags_Vertical;
|
||||
}
|
||||
value_changed = ImGui::DragBehavior(gid, data_type, p_value, speed, &v_min, &v_max, format, drag_flags);
|
||||
|
||||
angle_min = IMGUIKNOBS_PI * 0.75f;
|
||||
angle_max = IMGUIKNOBS_PI * 2.25f;
|
||||
center = {screen_pos[0] + radius, screen_pos[1] + radius};
|
||||
is_active = ImGui::IsItemActive();
|
||||
is_hovered = ImGui::IsItemHovered();
|
||||
angle = angle_min + (angle_max - angle_min) * t;
|
||||
angle_cos = cosf(angle);
|
||||
angle_sin = sinf(angle);
|
||||
}
|
||||
|
||||
void draw_dot(float size, float radius, float angle, color_set color, bool filled, int segments) {
|
||||
auto dot_size = size * this->radius;
|
||||
auto dot_radius = radius * this->radius;
|
||||
|
||||
ImGui::GetWindowDrawList()->AddCircleFilled(
|
||||
{center[0] + cosf(angle) * dot_radius, center[1] + sinf(angle) * dot_radius},
|
||||
dot_size,
|
||||
is_active ? color.active : (is_hovered ? color.hovered : color.base),
|
||||
segments);
|
||||
}
|
||||
|
||||
void draw_tick(float start, float end, float width, float angle, color_set color) {
|
||||
auto tick_start = start * radius;
|
||||
auto tick_end = end * radius;
|
||||
auto angle_cos = cosf(angle);
|
||||
auto angle_sin = sinf(angle);
|
||||
|
||||
ImGui::GetWindowDrawList()->AddLine(
|
||||
{center[0] + angle_cos * tick_end, center[1] + angle_sin * tick_end},
|
||||
{center[0] + angle_cos * tick_start, center[1] + angle_sin * tick_start},
|
||||
is_active ? color.active : (is_hovered ? color.hovered : color.base),
|
||||
width * radius);
|
||||
}
|
||||
|
||||
void draw_circle(float size, color_set color, bool filled, int segments) {
|
||||
auto circle_radius = size * radius;
|
||||
|
||||
ImGui::GetWindowDrawList()->AddCircleFilled(
|
||||
center,
|
||||
circle_radius,
|
||||
is_active ? color.active : (is_hovered ? color.hovered : color.base));
|
||||
}
|
||||
|
||||
void draw_arc(float radius, float size, float start_angle, float end_angle, color_set color, int segments, int bezier_count) {
|
||||
auto track_radius = radius * this->radius;
|
||||
auto track_size = size * this->radius * 0.5f + 0.0001f;
|
||||
|
||||
detail::draw_arc(
|
||||
center,
|
||||
track_radius,
|
||||
start_angle,
|
||||
end_angle,
|
||||
track_size,
|
||||
is_active ? color.active : (is_hovered ? color.hovered : color.base),
|
||||
segments,
|
||||
bezier_count);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename DataType>
|
||||
knob<DataType> knob_with_drag(const char *label, ImGuiDataType data_type, DataType *p_value, DataType v_min, DataType v_max, float _speed, const char *format, float size, ImGuiKnobFlags flags) {
|
||||
auto speed = _speed == 0 ? (v_max - v_min) / 250.f : _speed;
|
||||
ImGui::PushID(label);
|
||||
auto width = size == 0 ? ImGui::GetTextLineHeight() * 4.0f : size * ImGui::GetIO().FontGlobalScale;
|
||||
ImGui::PushItemWidth(width);
|
||||
|
||||
ImGui::BeginGroup();
|
||||
|
||||
// There's an issue with `SameLine` and Groups, see https://github.com/ocornut/imgui/issues/4190.
|
||||
// This is probably not the best solution, but seems to work for now
|
||||
ImGui::GetCurrentWindow()->DC.CurrLineTextBaseOffset = 0;
|
||||
|
||||
// Draw title
|
||||
if (!(flags & ImGuiKnobFlags_NoTitle)) {
|
||||
auto title_size = ImGui::CalcTextSize(label, NULL, false, width);
|
||||
|
||||
// Center title
|
||||
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + (width - title_size[0]) * 0.5f);
|
||||
|
||||
ImGui::Text("%s", label);
|
||||
}
|
||||
|
||||
// Draw knob
|
||||
knob<DataType> k(label, data_type, p_value, v_min, v_max, speed, width * 0.5f, format, flags);
|
||||
|
||||
// Draw tooltip
|
||||
if (flags & ImGuiKnobFlags_ValueTooltip && (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled) || ImGui::IsItemActive())) {
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::Text(format, *p_value);
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
|
||||
// Draw input
|
||||
if (!(flags & ImGuiKnobFlags_NoInput)) {
|
||||
ImGuiSliderFlags drag_flags = 0;
|
||||
if (!(flags & ImGuiKnobFlags_DragHorizontal)) {
|
||||
drag_flags |= ImGuiSliderFlags_Vertical;
|
||||
}
|
||||
auto changed = ImGui::DragScalar("###knob_drag", data_type, p_value, speed, &v_min, &v_max, format, drag_flags);
|
||||
if (changed) {
|
||||
k.value_changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::EndGroup();
|
||||
ImGui::PopItemWidth();
|
||||
ImGui::PopID();
|
||||
|
||||
return k;
|
||||
}
|
||||
|
||||
color_set GetPrimaryColorSet() {
|
||||
auto *colors = ImGui::GetStyle().Colors;
|
||||
|
||||
return {colors[ImGuiCol_ButtonActive], colors[ImGuiCol_ButtonHovered], colors[ImGuiCol_ButtonHovered]};
|
||||
}
|
||||
|
||||
color_set GetSecondaryColorSet() {
|
||||
auto *colors = ImGui::GetStyle().Colors;
|
||||
auto active = ImVec4(
|
||||
colors[ImGuiCol_ButtonActive].x * 0.5f,
|
||||
colors[ImGuiCol_ButtonActive].y * 0.5f,
|
||||
colors[ImGuiCol_ButtonActive].z * 0.5f,
|
||||
colors[ImGuiCol_ButtonActive].w);
|
||||
|
||||
auto hovered = ImVec4(
|
||||
colors[ImGuiCol_ButtonHovered].x * 0.5f,
|
||||
colors[ImGuiCol_ButtonHovered].y * 0.5f,
|
||||
colors[ImGuiCol_ButtonHovered].z * 0.5f,
|
||||
colors[ImGuiCol_ButtonHovered].w);
|
||||
|
||||
return {active, hovered, hovered};
|
||||
}
|
||||
|
||||
color_set GetTrackColorSet() {
|
||||
auto *colors = ImGui::GetStyle().Colors;
|
||||
|
||||
return {colors[ImGuiCol_FrameBg], colors[ImGuiCol_FrameBg], colors[ImGuiCol_FrameBg]};
|
||||
}
|
||||
}// namespace detail
|
||||
|
||||
|
||||
template<typename DataType>
|
||||
bool BaseKnob(const char *label, ImGuiDataType data_type, DataType *p_value, DataType v_min, DataType v_max, float speed, const char *format, ImGuiKnobVariant variant, float size, ImGuiKnobFlags flags, int steps = 10) {
|
||||
auto knob = detail::knob_with_drag(label, data_type, p_value, v_min, v_max, speed, format, size, flags);
|
||||
|
||||
switch (variant) {
|
||||
case ImGuiKnobVariant_Tick: {
|
||||
knob.draw_circle(0.85f, detail::GetSecondaryColorSet(), true, 32);
|
||||
knob.draw_tick(0.5f, 0.85f, 0.08f, knob.angle, detail::GetPrimaryColorSet());
|
||||
break;
|
||||
}
|
||||
case ImGuiKnobVariant_Dot: {
|
||||
knob.draw_circle(0.85f, detail::GetSecondaryColorSet(), true, 32);
|
||||
knob.draw_dot(0.12f, 0.6f, knob.angle, detail::GetPrimaryColorSet(), true, 12);
|
||||
break;
|
||||
}
|
||||
|
||||
case ImGuiKnobVariant_Wiper: {
|
||||
knob.draw_circle(0.7f, detail::GetSecondaryColorSet(), true, 32);
|
||||
knob.draw_arc(0.8f, 0.41f, knob.angle_min, knob.angle_max, detail::GetTrackColorSet(), 16, 2);
|
||||
|
||||
if (knob.t > 0.01f) {
|
||||
knob.draw_arc(0.8f, 0.43f, knob.angle_min, knob.angle, detail::GetPrimaryColorSet(), 16, 2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ImGuiKnobVariant_WiperOnly: {
|
||||
knob.draw_arc(0.8f, 0.41f, knob.angle_min, knob.angle_max, detail::GetTrackColorSet(), 32, 2);
|
||||
|
||||
if (knob.t > 0.01) {
|
||||
knob.draw_arc(0.8f, 0.43f, knob.angle_min, knob.angle, detail::GetPrimaryColorSet(), 16, 2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ImGuiKnobVariant_WiperDot: {
|
||||
knob.draw_circle(0.6f, detail::GetSecondaryColorSet(), true, 32);
|
||||
knob.draw_arc(0.85f, 0.41f, knob.angle_min, knob.angle_max, detail::GetTrackColorSet(), 16, 2);
|
||||
knob.draw_dot(0.1f, 0.85f, knob.angle, detail::GetPrimaryColorSet(), true, 12);
|
||||
break;
|
||||
}
|
||||
case ImGuiKnobVariant_Stepped: {
|
||||
for (auto n = 0.f; n < steps; n++) {
|
||||
auto a = n / (steps - 1);
|
||||
auto angle = knob.angle_min + (knob.angle_max - knob.angle_min) * a;
|
||||
knob.draw_tick(0.7f, 0.9f, 0.04f, angle, detail::GetPrimaryColorSet());
|
||||
}
|
||||
|
||||
knob.draw_circle(0.6f, detail::GetSecondaryColorSet(), true, 32);
|
||||
knob.draw_dot(0.12f, 0.4f, knob.angle, detail::GetPrimaryColorSet(), true, 12);
|
||||
break;
|
||||
}
|
||||
case ImGuiKnobVariant_Space: {
|
||||
knob.draw_circle(0.3f - knob.t * 0.1f, detail::GetSecondaryColorSet(), true, 16);
|
||||
|
||||
if (knob.t > 0.01f) {
|
||||
knob.draw_arc(0.4f, 0.15f, knob.angle_min - 1.0f, knob.angle - 1.0f, detail::GetPrimaryColorSet(), 16, 2);
|
||||
knob.draw_arc(0.6f, 0.15f, knob.angle_min + 1.0f, knob.angle + 1.0f, detail::GetPrimaryColorSet(), 16, 2);
|
||||
knob.draw_arc(0.8f, 0.15f, knob.angle_min + 3.0f, knob.angle + 3.0f, detail::GetPrimaryColorSet(), 16, 2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return knob.value_changed;
|
||||
}
|
||||
|
||||
bool Knob(const char *label, float *p_value, float v_min, float v_max, float speed, const char *format, ImGuiKnobVariant variant, float size, ImGuiKnobFlags flags, int steps) {
|
||||
const char *_format = format == NULL ? "%.3f" : format;
|
||||
return BaseKnob(label, ImGuiDataType_Float, p_value, v_min, v_max, speed, _format, variant, size, flags, steps);
|
||||
}
|
||||
|
||||
bool KnobInt(const char *label, int *p_value, int v_min, int v_max, float speed, const char *format, ImGuiKnobVariant variant, float size, ImGuiKnobFlags flags, int steps) {
|
||||
const char *_format = format == NULL ? "%i" : format;
|
||||
return BaseKnob(label, ImGuiDataType_S32, p_value, v_min, v_max, speed, _format, variant, size, flags, steps);
|
||||
}
|
||||
|
||||
}// namespace ImGuiKnobs
|
45
third_party/imgui/imgui-knobs/imgui-knobs.h
vendored
Normal file
45
third_party/imgui/imgui-knobs/imgui-knobs.h
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdlib>
|
||||
#include <imgui.h>
|
||||
|
||||
typedef int ImGuiKnobFlags;
|
||||
|
||||
enum ImGuiKnobFlags_ {
|
||||
ImGuiKnobFlags_NoTitle = 1 << 0,
|
||||
ImGuiKnobFlags_NoInput = 1 << 1,
|
||||
ImGuiKnobFlags_ValueTooltip = 1 << 2,
|
||||
ImGuiKnobFlags_DragHorizontal = 1 << 3,
|
||||
};
|
||||
|
||||
typedef int ImGuiKnobVariant;
|
||||
|
||||
enum ImGuiKnobVariant_ {
|
||||
ImGuiKnobVariant_Tick = 1 << 0,
|
||||
ImGuiKnobVariant_Dot = 1 << 1,
|
||||
ImGuiKnobVariant_Wiper = 1 << 2,
|
||||
ImGuiKnobVariant_WiperOnly = 1 << 3,
|
||||
ImGuiKnobVariant_WiperDot = 1 << 4,
|
||||
ImGuiKnobVariant_Stepped = 1 << 5,
|
||||
ImGuiKnobVariant_Space = 1 << 6,
|
||||
};
|
||||
|
||||
namespace ImGuiKnobs {
|
||||
|
||||
struct color_set {
|
||||
ImColor base;
|
||||
ImColor hovered;
|
||||
ImColor active;
|
||||
|
||||
color_set(ImColor base, ImColor hovered, ImColor active) : base(base), hovered(hovered), active(active) {}
|
||||
|
||||
color_set(ImColor color) {
|
||||
base = color;
|
||||
hovered = color;
|
||||
active = color;
|
||||
}
|
||||
};
|
||||
|
||||
bool Knob(const char *label, float *p_value, float v_min, float v_max, float speed = 0, const char *format = NULL, ImGuiKnobVariant variant = ImGuiKnobVariant_Tick, float size = 0, ImGuiKnobFlags flags = 0, int steps = 10);
|
||||
bool KnobInt(const char *label, int *p_value, int v_min, int v_max, float speed = 0, const char *format = NULL, ImGuiKnobVariant variant = ImGuiKnobVariant_Tick, float size = 0, ImGuiKnobFlags flags = 0, int steps = 10);
|
||||
}// namespace ImGuiKnobs
|
Loading…
x
Reference in New Issue
Block a user