cleanup and refactoring
This commit is contained in:
parent
2302158928
commit
76f6bf62a4
1285 changed files with 757994 additions and 8 deletions
43
raytracer/nvpro_core/imgui/README.md
Normal file
43
raytracer/nvpro_core/imgui/README.md
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
## Table of Contents
|
||||
- [imgui_axis.hpp](#imgui_axishpp)
|
||||
- [imgui_camera_widget.h](#imgui_camera_widgeth)
|
||||
- [imgui_orient.h](#imgui_orienth)
|
||||
|
||||
## imgui_axis.hpp
|
||||
|
||||
Function `Axis(ImVec2 pos, const glm::mat4& modelView, float size = 20.f)`
|
||||
which display right-handed axis in a ImGui window.
|
||||
|
||||
Example
|
||||
|
||||
```cpp
|
||||
{ // Display orientation axis at the bottom left corner of the window
|
||||
float axisSize = 25.F;
|
||||
ImVec2 pos = ImGui::GetWindowPos();
|
||||
pos.y += ImGui::GetWindowSize().y;
|
||||
pos += ImVec2(axisSize * 1.1F, -axisSize * 1.1F) * ImGui::GetWindowDpiScale(); // Offset
|
||||
ImGuiH::Axis(pos, CameraManip.getMatrix(), axisSize);
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## imgui_camera_widget.h
|
||||
|
||||
### functions in ImGuiH
|
||||
|
||||
|
||||
- CameraWidget : CameraWidget is a Camera widget for the the Camera Manipulator
|
||||
- SetCameraJsonFile : set the name (without .json) of the setting file. It will load and replace all camera and settings
|
||||
- SetHomeCamera : set the home camera - replace the one on load
|
||||
- AddCamera : adding a camera to the list of cameras
|
||||
|
||||
|
||||
## imgui_orient.h
|
||||
|
||||
### struct ImOrient
|
||||
|
||||
> brief This is a really nice implementation of an orientation widget; all due respect to the original author ;)
|
||||
|
||||
This is a port of the AntTweakBar orientation widget, which is a 3D orientation widget that allows the user to specify a
|
||||
3D orientation using a quaternion, axis-angle, or direction vector. It is a very useful widget for 3D applications.
|
||||
|
||||
11
raytracer/nvpro_core/imgui/backends/README.md
Normal file
11
raytracer/nvpro_core/imgui/backends/README.md
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
## Table of Contents
|
||||
- [imgui_impl_gl.h](#imgui_impl_glh)
|
||||
- [imgui_vk_extra.h](#imgui_vk_extrah)
|
||||
|
||||
## imgui_impl_gl.h
|
||||
|
||||
> Todo: Add documentation
|
||||
|
||||
## imgui_vk_extra.h
|
||||
|
||||
> Todo: Add documentation
|
||||
289
raytracer/nvpro_core/imgui/backends/imgui_impl_gl.cpp
Normal file
289
raytracer/nvpro_core/imgui/backends/imgui_impl_gl.cpp
Normal file
|
|
@ -0,0 +1,289 @@
|
|||
#include "imgui/backends/imgui_impl_gl.h"
|
||||
#include "imgui.h"
|
||||
#include <include_gl.h>
|
||||
|
||||
// ImGui GLFW binding with OpenGL3 + shaders
|
||||
// More or less copy-pasted from https://raw.githubusercontent.com/ocornut/imgui/master/examples/opengl3_example/imgui_impl_glfw_gl3.cpp
|
||||
|
||||
namespace {
|
||||
const char* g_GlslVersion = "#version 450\n";
|
||||
GLuint g_FontTexture = 0;
|
||||
int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0;
|
||||
int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0;
|
||||
int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0;
|
||||
unsigned int g_VboHandle = 0, g_ElementsHandle = 0;
|
||||
} // namespace
|
||||
|
||||
void ImGui::InitGL()
|
||||
{
|
||||
// Backup GL state
|
||||
GLint last_texture, last_array_buffer, last_vertex_array;
|
||||
glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
|
||||
glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer);
|
||||
glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array);
|
||||
|
||||
const GLchar* vertex_shader =
|
||||
"layout(location=0) uniform mat4 ProjMtx;\n"
|
||||
"layout(location=0) in vec2 Position;\n"
|
||||
"layout(location=1) in vec2 UV;\n"
|
||||
"layout(location=2) in vec4 Color;\n"
|
||||
"out vec2 Frag_UV;\n"
|
||||
"out vec4 Frag_Color;\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" Frag_UV = UV;\n"
|
||||
" Frag_Color = Color;\n"
|
||||
" gl_Position = ProjMtx * vec4(Position.xy,0,1);\n"
|
||||
"}\n";
|
||||
|
||||
const GLchar* fragment_shader =
|
||||
"layout(location=1, binding=0) uniform sampler2D Texture;\n"
|
||||
"in vec2 Frag_UV;\n"
|
||||
"in vec4 Frag_Color;\n"
|
||||
"layout(location=0, index=0) out vec4 Out_Color;\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" Out_Color = Frag_Color * texture( Texture, Frag_UV.st);\n"
|
||||
"}\n";
|
||||
|
||||
const GLchar* vertex_shader_with_version[2] = {g_GlslVersion, vertex_shader};
|
||||
const GLchar* fragment_shader_with_version[2] = {g_GlslVersion, fragment_shader};
|
||||
|
||||
g_ShaderHandle = glCreateProgram();
|
||||
g_VertHandle = glCreateShader(GL_VERTEX_SHADER);
|
||||
g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
glShaderSource(g_VertHandle, 2, vertex_shader_with_version, NULL);
|
||||
glShaderSource(g_FragHandle, 2, fragment_shader_with_version, NULL);
|
||||
glCompileShader(g_VertHandle);
|
||||
glCompileShader(g_FragHandle);
|
||||
glAttachShader(g_ShaderHandle, g_VertHandle);
|
||||
glAttachShader(g_ShaderHandle, g_FragHandle);
|
||||
glLinkProgram(g_ShaderHandle);
|
||||
|
||||
// check if program linked
|
||||
GLint success = 0;
|
||||
glGetProgramiv(g_ShaderHandle, GL_LINK_STATUS, &success);
|
||||
if(!success)
|
||||
{
|
||||
char temp[1024];
|
||||
glGetProgramInfoLog(g_ShaderHandle, 1024, 0, temp);
|
||||
success = success;
|
||||
}
|
||||
|
||||
g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture");
|
||||
g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx");
|
||||
g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position");
|
||||
g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV");
|
||||
g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color");
|
||||
|
||||
glGenBuffers(1, &g_VboHandle);
|
||||
glGenBuffers(1, &g_ElementsHandle);
|
||||
|
||||
// Build texture atlas
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
unsigned char* pixels;
|
||||
int width, height;
|
||||
// Load as RGBA 32-bits (75% of the memory is wasted, but default font is so small) because it is more likely to be compatible with user's existing shaders. If your ImTextureId represent a higher-level concept than just a GL texture id, consider calling GetTexDataAsAlpha8() instead to save on GPU memory.
|
||||
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
|
||||
|
||||
// Upload texture to graphics system
|
||||
glGenTextures(1, &g_FontTexture);
|
||||
glBindTexture(GL_TEXTURE_2D, g_FontTexture);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
|
||||
|
||||
// Store our identifier
|
||||
io.Fonts->TexID = (void*)(intptr_t)g_FontTexture;
|
||||
|
||||
// Restore state
|
||||
glBindTexture(GL_TEXTURE_2D, last_texture);
|
||||
|
||||
// Restore modified GL state
|
||||
glBindTexture(GL_TEXTURE_2D, last_texture);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer);
|
||||
glBindVertexArray(last_vertex_array);
|
||||
}
|
||||
void ImGui::ShutdownGL()
|
||||
{
|
||||
if(g_VboHandle)
|
||||
glDeleteBuffers(1, &g_VboHandle);
|
||||
if(g_ElementsHandle)
|
||||
glDeleteBuffers(1, &g_ElementsHandle);
|
||||
g_VboHandle = g_ElementsHandle = 0;
|
||||
|
||||
if(g_ShaderHandle && g_VertHandle)
|
||||
glDetachShader(g_ShaderHandle, g_VertHandle);
|
||||
if(g_VertHandle)
|
||||
glDeleteShader(g_VertHandle);
|
||||
g_VertHandle = 0;
|
||||
|
||||
if(g_ShaderHandle && g_FragHandle)
|
||||
glDetachShader(g_ShaderHandle, g_FragHandle);
|
||||
if(g_FragHandle)
|
||||
glDeleteShader(g_FragHandle);
|
||||
g_FragHandle = 0;
|
||||
|
||||
if(g_ShaderHandle)
|
||||
glDeleteProgram(g_ShaderHandle);
|
||||
g_ShaderHandle = 0;
|
||||
|
||||
if(g_FontTexture)
|
||||
{
|
||||
glDeleteTextures(1, &g_FontTexture);
|
||||
ImGui::GetIO().Fonts->TexID = 0;
|
||||
g_FontTexture = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void ImGui::RenderDrawDataGL(const ImDrawData* drawData)
|
||||
{
|
||||
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
int fb_width = (int)(io.DisplaySize.x * io.DisplayFramebufferScale.x);
|
||||
int fb_height = (int)(io.DisplaySize.y * io.DisplayFramebufferScale.y);
|
||||
if(fb_width == 0 || fb_height == 0)
|
||||
return;
|
||||
// evil
|
||||
((ImDrawData*)drawData)->ScaleClipRects(io.DisplayFramebufferScale);
|
||||
|
||||
// Backup GL state
|
||||
GLenum last_active_texture;
|
||||
glGetIntegerv(GL_ACTIVE_TEXTURE, (GLint*)&last_active_texture);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
GLint last_program;
|
||||
glGetIntegerv(GL_CURRENT_PROGRAM, &last_program);
|
||||
GLint last_texture;
|
||||
glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
|
||||
GLint last_sampler;
|
||||
glGetIntegerv(GL_SAMPLER_BINDING, &last_sampler);
|
||||
GLint last_array_buffer;
|
||||
glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer);
|
||||
GLint last_element_array_buffer;
|
||||
glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &last_element_array_buffer);
|
||||
GLint last_vertex_array;
|
||||
glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array);
|
||||
GLint last_polygon_mode[2];
|
||||
glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode);
|
||||
GLint last_viewport[4];
|
||||
glGetIntegerv(GL_VIEWPORT, last_viewport);
|
||||
GLint last_scissor_box[4];
|
||||
glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box);
|
||||
GLenum last_blend_src_rgb;
|
||||
glGetIntegerv(GL_BLEND_SRC_RGB, (GLint*)&last_blend_src_rgb);
|
||||
GLenum last_blend_dst_rgb;
|
||||
glGetIntegerv(GL_BLEND_DST_RGB, (GLint*)&last_blend_dst_rgb);
|
||||
GLenum last_blend_src_alpha;
|
||||
glGetIntegerv(GL_BLEND_SRC_ALPHA, (GLint*)&last_blend_src_alpha);
|
||||
GLenum last_blend_dst_alpha;
|
||||
glGetIntegerv(GL_BLEND_DST_ALPHA, (GLint*)&last_blend_dst_alpha);
|
||||
GLenum last_blend_equation_rgb;
|
||||
glGetIntegerv(GL_BLEND_EQUATION_RGB, (GLint*)&last_blend_equation_rgb);
|
||||
GLenum last_blend_equation_alpha;
|
||||
glGetIntegerv(GL_BLEND_EQUATION_ALPHA, (GLint*)&last_blend_equation_alpha);
|
||||
GLboolean last_enable_blend = glIsEnabled(GL_BLEND);
|
||||
GLboolean last_enable_cull_face = glIsEnabled(GL_CULL_FACE);
|
||||
GLboolean last_enable_depth_test = glIsEnabled(GL_DEPTH_TEST);
|
||||
GLboolean last_enable_scissor_test = glIsEnabled(GL_SCISSOR_TEST);
|
||||
|
||||
// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, polygon fill
|
||||
glEnable(GL_BLEND);
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glDisable(GL_CULL_FACE);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
|
||||
// Setup viewport, orthographic projection matrix
|
||||
glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height);
|
||||
const float ortho_projection[4][4] = {
|
||||
{2.0f / io.DisplaySize.x, 0.0f, 0.0f, 0.0f},
|
||||
{0.0f, 2.0f / -io.DisplaySize.y, 0.0f, 0.0f},
|
||||
{0.0f, 0.0f, -1.0f, 0.0f},
|
||||
{-1.0f, 1.0f, 0.0f, 1.0f},
|
||||
};
|
||||
glUseProgram(g_ShaderHandle);
|
||||
glUniform1i(g_AttribLocationTex, 0);
|
||||
glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]);
|
||||
glBindSampler(0, 0); // We use combined texture/sampler state. Applications using GL 3.3 may set that otherwise.
|
||||
|
||||
// Recreate the VAO every time
|
||||
// (This is to easily allow multiple GL contexts. VAO are not shared among GL contexts, and we don't track creation/deletion of windows so we don't have an obvious key to use to cache them.)
|
||||
GLuint vao_handle = 0;
|
||||
glGenVertexArrays(1, &vao_handle);
|
||||
glBindVertexArray(vao_handle);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle);
|
||||
glEnableVertexAttribArray(g_AttribLocationPosition);
|
||||
glEnableVertexAttribArray(g_AttribLocationUV);
|
||||
glEnableVertexAttribArray(g_AttribLocationColor);
|
||||
glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, pos));
|
||||
glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, uv));
|
||||
glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert),
|
||||
(GLvoid*)IM_OFFSETOF(ImDrawVert, col));
|
||||
|
||||
// Draw
|
||||
for(int n = 0; n < drawData->CmdListsCount; n++)
|
||||
{
|
||||
const ImDrawList* cmd_list = drawData->CmdLists[n];
|
||||
const ImDrawIdx* idx_buffer_offset = 0;
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle);
|
||||
glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)cmd_list->VtxBuffer.Size * sizeof(ImDrawVert),
|
||||
(const GLvoid*)cmd_list->VtxBuffer.Data, GL_STREAM_DRAW);
|
||||
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_ElementsHandle);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx),
|
||||
(const GLvoid*)cmd_list->IdxBuffer.Data, GL_STREAM_DRAW);
|
||||
|
||||
for(int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
|
||||
{
|
||||
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
|
||||
if(pcmd->UserCallback)
|
||||
{
|
||||
pcmd->UserCallback(cmd_list, pcmd);
|
||||
}
|
||||
else
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId);
|
||||
glScissor((int)pcmd->ClipRect.x, (int)(fb_height - pcmd->ClipRect.w),
|
||||
(int)(pcmd->ClipRect.z - pcmd->ClipRect.x), (int)(pcmd->ClipRect.w - pcmd->ClipRect.y));
|
||||
glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount,
|
||||
sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer_offset);
|
||||
}
|
||||
idx_buffer_offset += pcmd->ElemCount;
|
||||
}
|
||||
}
|
||||
glDeleteVertexArrays(1, &vao_handle);
|
||||
|
||||
// Restore modified GL state
|
||||
glUseProgram(last_program);
|
||||
glBindTexture(GL_TEXTURE_2D, last_texture);
|
||||
glBindSampler(0, last_sampler);
|
||||
glActiveTexture(last_active_texture);
|
||||
glBindVertexArray(last_vertex_array);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, last_element_array_buffer);
|
||||
glBlendEquationSeparate(last_blend_equation_rgb, last_blend_equation_alpha);
|
||||
glBlendFuncSeparate(last_blend_src_rgb, last_blend_dst_rgb, last_blend_src_alpha, last_blend_dst_alpha);
|
||||
if(last_enable_blend)
|
||||
glEnable(GL_BLEND);
|
||||
else
|
||||
glDisable(GL_BLEND);
|
||||
if(last_enable_cull_face)
|
||||
glEnable(GL_CULL_FACE);
|
||||
else
|
||||
glDisable(GL_CULL_FACE);
|
||||
if(last_enable_depth_test)
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
else
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
if(last_enable_scissor_test)
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
else
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, (GLenum)last_polygon_mode[0]);
|
||||
glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]);
|
||||
glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]);
|
||||
}
|
||||
12
raytracer/nvpro_core/imgui/backends/imgui_impl_gl.h
Normal file
12
raytracer/nvpro_core/imgui/backends/imgui_impl_gl.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
#pragma once
|
||||
|
||||
/// @DOC_SKIP (keyword to exclude this file from automatic README.md generation)
|
||||
|
||||
struct ImDrawData;
|
||||
|
||||
namespace ImGui {
|
||||
void InitGL();
|
||||
void ShutdownGL();
|
||||
|
||||
void RenderDrawDataGL(const ImDrawData* drawData);
|
||||
} // namespace ImGui
|
||||
105
raytracer/nvpro_core/imgui/backends/imgui_vk_extra.cpp
Normal file
105
raytracer/nvpro_core/imgui/backends/imgui_vk_extra.cpp
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2021 NVIDIA CORPORATION
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "imgui/backends/imgui_vk_extra.h"
|
||||
#include "imgui/imgui_helper.h"
|
||||
#include <backends/imgui_impl_vulkan.h>
|
||||
|
||||
static ImGui_ImplVulkan_InitInfo g_VulkanInitInfo = {};
|
||||
|
||||
static void check_vk_result(VkResult err)
|
||||
{
|
||||
assert(err == VK_SUCCESS);
|
||||
}
|
||||
|
||||
void ImGui::InitVK(VkDevice device, VkPhysicalDevice physicalDevice, VkQueue queue, uint32_t queueFamilyIndex, VkRenderPass pass, int subPassIndex)
|
||||
{
|
||||
VkResult err = VK_RESULT_MAX_ENUM;
|
||||
|
||||
std::vector<VkDescriptorPoolSize> poolSize{{VK_DESCRIPTOR_TYPE_SAMPLER, 1}, {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1}};
|
||||
VkDescriptorPoolCreateInfo poolInfo{VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO};
|
||||
poolInfo.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
|
||||
poolInfo.maxSets = 2;
|
||||
poolInfo.poolSizeCount = static_cast<uint32_t>(poolSize.size());
|
||||
poolInfo.pPoolSizes = poolSize.data();
|
||||
vkCreateDescriptorPool(device, &poolInfo, nullptr, &g_VulkanInitInfo.DescriptorPool);
|
||||
|
||||
// Setup Platform/Renderer backends
|
||||
ImGui_ImplVulkan_InitInfo init_info = {};
|
||||
init_info.Instance = VkInstance(666); // <--- WRONG need argument
|
||||
init_info.PhysicalDevice = physicalDevice;
|
||||
init_info.Device = device;
|
||||
init_info.QueueFamily = queueFamilyIndex;
|
||||
init_info.Queue = queue;
|
||||
init_info.PipelineCache = VK_NULL_HANDLE;
|
||||
init_info.DescriptorPool = g_VulkanInitInfo.DescriptorPool;
|
||||
init_info.RenderPass = pass;
|
||||
init_info.Subpass = subPassIndex;
|
||||
init_info.MinImageCount = 2;
|
||||
init_info.ImageCount = 3; // <--- WRONG need argument
|
||||
init_info.MSAASamples = VK_SAMPLE_COUNT_1_BIT; // <--- need argument?
|
||||
init_info.Allocator = nullptr;
|
||||
init_info.CheckVkResultFn = nullptr;
|
||||
ImGui_ImplVulkan_Init(&init_info);
|
||||
g_VulkanInitInfo = init_info;
|
||||
|
||||
// Upload Fonts
|
||||
VkCommandPool pool = VK_NULL_HANDLE;
|
||||
VkCommandPoolCreateInfo createInfo{VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO};
|
||||
createInfo.queueFamilyIndex = queueFamilyIndex;
|
||||
err = vkCreateCommandPool(device, &createInfo, nullptr, &pool);
|
||||
check_vk_result(err);
|
||||
|
||||
VkCommandBuffer cmd = VK_NULL_HANDLE;
|
||||
VkCommandBufferAllocateInfo allocInfo{VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO};
|
||||
allocInfo.commandPool = pool;
|
||||
allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
|
||||
allocInfo.commandBufferCount = 1;
|
||||
err = vkAllocateCommandBuffers(device, &allocInfo, &cmd);
|
||||
check_vk_result(err);
|
||||
|
||||
VkCommandBufferBeginInfo beginInfo{VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO};
|
||||
beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
|
||||
err = vkBeginCommandBuffer(cmd, &beginInfo);
|
||||
check_vk_result(err);
|
||||
|
||||
ImGui_ImplVulkan_CreateFontsTexture();
|
||||
|
||||
err = vkEndCommandBuffer(cmd);
|
||||
check_vk_result(err);
|
||||
|
||||
VkSubmitInfo submit{VK_STRUCTURE_TYPE_SUBMIT_INFO};
|
||||
submit.commandBufferCount = 1;
|
||||
submit.pCommandBuffers = &cmd;
|
||||
err = vkQueueSubmit(queue, 1, &submit, VK_NULL_HANDLE);
|
||||
check_vk_result(err);
|
||||
|
||||
err = vkDeviceWaitIdle(device);
|
||||
check_vk_result(err);
|
||||
vkFreeCommandBuffers(device, pool, 1, &cmd);
|
||||
vkDestroyCommandPool(device, pool, nullptr);
|
||||
}
|
||||
|
||||
|
||||
void ImGui::ShutdownVK()
|
||||
{
|
||||
ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo;
|
||||
ImGui_ImplVulkan_Shutdown();
|
||||
vkDestroyDescriptorPool(v->Device, v->DescriptorPool, v->Allocator);
|
||||
}
|
||||
26
raytracer/nvpro_core/imgui/backends/imgui_vk_extra.h
Normal file
26
raytracer/nvpro_core/imgui/backends/imgui_vk_extra.h
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2021 NVIDIA CORPORATION
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/// @DOC_SKIP (keyword to exclude this file from automatic README.md generation)
|
||||
|
||||
#include <backends/imgui_impl_vulkan.h>
|
||||
namespace ImGui {
|
||||
void InitVK(VkDevice device, VkPhysicalDevice physicalDevice, VkQueue queue, uint32_t queueFamilyIndex, VkRenderPass pass, int subPassIndex = 0);
|
||||
void ShutdownVK();
|
||||
} // namespace ImGui
|
||||
189
raytracer/nvpro_core/imgui/imgui_axis.cpp
Normal file
189
raytracer/nvpro_core/imgui/imgui_axis.cpp
Normal file
|
|
@ -0,0 +1,189 @@
|
|||
/*
|
||||
* Copyright (c) 2022-2023, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2014-2022 NVIDIA CORPORATION
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <vector>
|
||||
#include <array>
|
||||
|
||||
#define _USE_MATH_DEFINES
|
||||
#include <math.h>
|
||||
|
||||
#include "imgui_axis.hpp"
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// This IMGUI widget draw axis in red, green and blue at the position
|
||||
// defined.
|
||||
//
|
||||
|
||||
struct AxisGeom
|
||||
{
|
||||
AxisGeom()
|
||||
{
|
||||
const float asize = 1.0f; // length of arrow
|
||||
const float aradius = 0.11f; // width of arrow tip
|
||||
const float abase = 0.66f; // 1/3 of arrow length
|
||||
const int asubdiv = 8;
|
||||
|
||||
// Cone
|
||||
red.push_back({asize, 0, 0}); // 0 Tip
|
||||
for(int i = 0; i <= asubdiv; ++i)
|
||||
{
|
||||
float a0 = 2.0F * float(M_PI) * (float(i)) / asubdiv; // Counter-clockwise
|
||||
float y0 = cosf(a0) * aradius;
|
||||
float z0 = sinf(a0) * aradius;
|
||||
red.push_back({abase, y0, z0});
|
||||
}
|
||||
for(int i = 0; i <= asubdiv - 1; ++i) // Triangle fan
|
||||
{
|
||||
indices.push_back(0);
|
||||
indices.push_back(i + 1);
|
||||
indices.push_back(i + 2);
|
||||
}
|
||||
|
||||
// Under Cap
|
||||
int center = static_cast<int>(red.size());
|
||||
red.push_back({abase, 0, 0}); // Center of cap
|
||||
for(int i = 0; i <= asubdiv; ++i)
|
||||
{
|
||||
float a0 = -2.0F * float(M_PI) * (float(i)) / asubdiv; // Clockwise
|
||||
float y0 = cosf(a0) * aradius;
|
||||
float z0 = sinf(a0) * aradius;
|
||||
red.push_back({abase, y0, z0});
|
||||
}
|
||||
for(int i = 0; i <= asubdiv - 1; ++i)
|
||||
{
|
||||
indices.push_back(center);
|
||||
indices.push_back(center + i + 1);
|
||||
indices.push_back(center + i + 2);
|
||||
}
|
||||
|
||||
// Start of arrow
|
||||
red.push_back({0, 0, 0});
|
||||
|
||||
// Other arrows are permutations of the Red arrow
|
||||
for(const auto& v : red)
|
||||
{
|
||||
green.push_back({v.z, v.x, v.y});
|
||||
blue.push_back({v.y, v.z, v.x});
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<glm::vec3> red;
|
||||
std::vector<glm::vec3> green;
|
||||
std::vector<glm::vec3> blue;
|
||||
std::vector<int> indices;
|
||||
|
||||
// Return the transformed arrow
|
||||
std::vector<glm::vec3> transform(const std::vector<glm::vec3>& in_vec, const ImVec2& pos, const glm::mat4& modelView, float size)
|
||||
{
|
||||
std::vector<glm::vec3> temp(in_vec.size());
|
||||
|
||||
for(size_t i = 0; i < in_vec.size(); ++i)
|
||||
{
|
||||
temp[i] = glm::vec3(modelView * glm::vec4(in_vec[i], 0.F)); // Rotate
|
||||
temp[i].x *= size; // Scale
|
||||
temp[i].y *= -size; // - invert Y
|
||||
temp[i].x += pos.x; // Translate
|
||||
temp[i].y += pos.y;
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
|
||||
void drawTriangle(ImVec2 v0, ImVec2 v1, ImVec2 v2, const ImVec2& uv, ImU32 col)
|
||||
{
|
||||
auto draw_list = ImGui::GetWindowDrawList();
|
||||
|
||||
ImVec2 d0 = ImVec2(v1.x - v0.x, v1.y - v0.y);
|
||||
ImVec2 d1 = ImVec2(v2.x - v0.x, v2.y - v0.y);
|
||||
float c = (d0.x * d1.y) - (d0.y * d1.x); // Cross
|
||||
|
||||
if(c > 0.0f) // Culling to avoid z-fighting
|
||||
{
|
||||
v1 = v0; // Culled triangles are degenerated to
|
||||
v2 = v0; // avoid displaying them
|
||||
}
|
||||
|
||||
draw_list->PrimVtx(v0, uv, col);
|
||||
draw_list->PrimVtx(v1, uv, col);
|
||||
draw_list->PrimVtx(v2, uv, col);
|
||||
}
|
||||
|
||||
// Draw the arrow
|
||||
void draw(const std::vector<glm::vec3>& vertex, ImU32 col)
|
||||
{
|
||||
auto draw_list = ImGui::GetWindowDrawList();
|
||||
const ImVec2 uv = ImGui::GetFontTexUvWhitePixel();
|
||||
|
||||
int num_indices = static_cast<int>(indices.size());
|
||||
draw_list->PrimReserve(num_indices, num_indices); // num vert/indices
|
||||
|
||||
// Draw all triangles
|
||||
for(int i = 0; i < num_indices; i += 3)
|
||||
{
|
||||
int i0 = indices[i];
|
||||
int i1 = indices[i + 1];
|
||||
int i2 = indices[i + 2];
|
||||
ImVec2 v0 = {vertex[i0].x, vertex[i0].y};
|
||||
ImVec2 v1 = {vertex[i1].x, vertex[i1].y};
|
||||
ImVec2 v2 = {vertex[i2].x, vertex[i2].y};
|
||||
drawTriangle(v0, v1, v2, uv, col);
|
||||
}
|
||||
|
||||
// Draw the line
|
||||
draw_list->AddLine(ImVec2(vertex[0].x, vertex[0].y), ImVec2(vertex.back().x, vertex.back().y), col,
|
||||
1.0F * ImGui::GetWindowDpiScale());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void ImGuiH::Axis(ImVec2 pos, const glm::mat4& modelView, float size /*= 20.f*/)
|
||||
{
|
||||
static AxisGeom a;
|
||||
|
||||
struct Arrow
|
||||
{
|
||||
std::vector<glm::vec3> v;
|
||||
ImU32 c{0};
|
||||
};
|
||||
|
||||
size *= ImGui::GetWindowDpiScale();
|
||||
|
||||
std::array<Arrow, 3> arrow;
|
||||
arrow[0].v = a.transform(a.red, pos, modelView, size);
|
||||
arrow[0].c = IM_COL32(200, 0, 0, 255);
|
||||
arrow[1].v = a.transform(a.green, pos, modelView, size);
|
||||
arrow[1].c = IM_COL32(0, 200, 0, 255);
|
||||
arrow[2].v = a.transform(a.blue, pos, modelView, size);
|
||||
arrow[2].c = IM_COL32(0, 0, 200, 255);
|
||||
|
||||
// Sort from smallest Z to nearest (Painter algorithm)
|
||||
if(arrow[1].v[0].z < arrow[0].v[0].z)
|
||||
std::swap(arrow[0], arrow[1]);
|
||||
if(arrow[2].v[0].z < arrow[1].v[0].z)
|
||||
{
|
||||
std::swap(arrow[1], arrow[2]);
|
||||
if(arrow[1].v[0].z < arrow[0].v[0].z)
|
||||
std::swap(arrow[1], arrow[0]);
|
||||
}
|
||||
|
||||
// Draw all axis
|
||||
a.draw(arrow[0].v, arrow[0].c);
|
||||
a.draw(arrow[1].v, arrow[1].c);
|
||||
a.draw(arrow[2].v, arrow[2].c);
|
||||
}
|
||||
48
raytracer/nvpro_core/imgui/imgui_axis.hpp
Normal file
48
raytracer/nvpro_core/imgui/imgui_axis.hpp
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright (c) 2022-2023, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2014-2022 NVIDIA CORPORATION
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "imgui.h"
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
/* @DOC_START -------------------------------------------------------
|
||||
|
||||
Function `Axis(ImVec2 pos, const glm::mat4& modelView, float size = 20.f)`
|
||||
which display right-handed axis in a ImGui window.
|
||||
|
||||
Example
|
||||
|
||||
```cpp
|
||||
{ // Display orientation axis at the bottom left corner of the window
|
||||
float axisSize = 25.F;
|
||||
ImVec2 pos = ImGui::GetWindowPos();
|
||||
pos.y += ImGui::GetWindowSize().y;
|
||||
pos += ImVec2(axisSize * 1.1F, -axisSize * 1.1F) * ImGui::GetWindowDpiScale(); // Offset
|
||||
ImGuiH::Axis(pos, CameraManip.getMatrix(), axisSize);
|
||||
}
|
||||
```
|
||||
|
||||
--- @DOC_END ------------------------------------------------------- */
|
||||
|
||||
// The API
|
||||
namespace ImGuiH {
|
||||
|
||||
// This utility is adding the 3D axis at `pos`, using the matrix `modelView`
|
||||
IMGUI_API void Axis(ImVec2 pos, const glm::mat4& modelView, float size = 20.f);
|
||||
|
||||
}; // namespace ImGuiH
|
||||
511
raytracer/nvpro_core/imgui/imgui_camera_widget.cpp
Normal file
511
raytracer/nvpro_core/imgui/imgui_camera_widget.cpp
Normal file
|
|
@ -0,0 +1,511 @@
|
|||
/*
|
||||
* Copyright (c) 2014-2021, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* NVIDIA CORPORATION and its licensors retain all intellectual property
|
||||
* and proprietary rights in and to this software, related documentation
|
||||
* and any modifications thereto. Any use, reproduction, disclosure or
|
||||
* distribution of this software and related documentation without an express
|
||||
* license agreement from NVIDIA CORPORATION is strictly prohibited.
|
||||
*/
|
||||
|
||||
|
||||
#include "json.hpp"
|
||||
|
||||
#include "imgui.h"
|
||||
#include "imgui/imgui_camera_widget.h"
|
||||
#include "imgui_helper.h"
|
||||
#include "nvh/cameramanipulator.hpp"
|
||||
#include "nvh/misc.hpp"
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
|
||||
namespace ImGuiH {
|
||||
|
||||
using nlohmann::json;
|
||||
using Gui = ImGuiH::Control;
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
// Holds all saved cameras in a vector of Cameras
|
||||
// - The first camera in the list is the HOME camera, the one that was set before this is called.
|
||||
// - The update function will check if something has changed and will save the JSON to disk, only
|
||||
// once in a while.
|
||||
// - Adding a camera will be added only if it is different from all other saved cameras
|
||||
// - load/save Setting will load next to the executable, the "jsonFilename" + ".json"
|
||||
//
|
||||
struct CameraManager
|
||||
{
|
||||
CameraManager() = default;
|
||||
~CameraManager()
|
||||
{
|
||||
if(m_settingsDirtyTimer > 0.0f)
|
||||
saveSetting(nvh::CameraManipulator::Singleton());
|
||||
};
|
||||
|
||||
|
||||
// update setting, load or save
|
||||
void update(nvh::CameraManipulator& cameraM)
|
||||
{
|
||||
// Push the HOME camera and load default setting
|
||||
if(m_cameras.empty())
|
||||
{
|
||||
m_cameras.emplace_back(cameraM.getCamera());
|
||||
}
|
||||
if(m_doLoadSetting)
|
||||
loadSetting(cameraM);
|
||||
|
||||
// Save settings (with a delay after the last modification, so we don't spam disk too much)
|
||||
auto& IO = ImGui::GetIO();
|
||||
if(m_settingsDirtyTimer > 0.0f)
|
||||
{
|
||||
m_settingsDirtyTimer -= IO.DeltaTime;
|
||||
if(m_settingsDirtyTimer <= 0.0f)
|
||||
{
|
||||
saveSetting(cameraM);
|
||||
m_settingsDirtyTimer = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clear all cameras except the HOME
|
||||
void removedSavedCameras()
|
||||
{
|
||||
if(m_cameras.size() > 1)
|
||||
m_cameras.erase(m_cameras.begin() + 1, m_cameras.end());
|
||||
}
|
||||
|
||||
void setCameraJsonFile(const std::string& filename)
|
||||
{
|
||||
m_jsonFilename = NVPSystem::exePath() + filename + ".json";
|
||||
m_doLoadSetting = true;
|
||||
removedSavedCameras();
|
||||
}
|
||||
|
||||
|
||||
void setHomeCamera(const nvh::CameraManipulator::Camera& camera)
|
||||
{
|
||||
if(m_cameras.empty())
|
||||
m_cameras.resize(1);
|
||||
m_cameras[0] = camera;
|
||||
}
|
||||
|
||||
// Adding a camera only if it different from all the saved ones
|
||||
void addCamera(const nvh::CameraManipulator::Camera& camera)
|
||||
{
|
||||
bool unique = true;
|
||||
for(const auto& c : m_cameras)
|
||||
{
|
||||
if(c == camera)
|
||||
{
|
||||
unique = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(unique)
|
||||
{
|
||||
m_cameras.emplace_back(camera);
|
||||
markIniSettingsDirty();
|
||||
}
|
||||
}
|
||||
|
||||
// Removing a camera
|
||||
void removeCamera(int delete_item)
|
||||
{
|
||||
m_cameras.erase(m_cameras.begin() + delete_item);
|
||||
markIniSettingsDirty();
|
||||
}
|
||||
|
||||
void markIniSettingsDirty()
|
||||
{
|
||||
if(m_settingsDirtyTimer <= 0.0f)
|
||||
m_settingsDirtyTimer = 0.1f;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool getJsonValue(const json& j, const std::string& name, T& value)
|
||||
{
|
||||
auto fieldIt = j.find(name);
|
||||
if(fieldIt != j.end())
|
||||
{
|
||||
value = (*fieldIt);
|
||||
return true;
|
||||
}
|
||||
LOGE("Could not find JSON field %s", name.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool getJsonArray(const json& j, const std::string& name, T& value)
|
||||
{
|
||||
auto fieldIt = j.find(name);
|
||||
if(fieldIt != j.end())
|
||||
{
|
||||
value = T((*fieldIt).begin(), (*fieldIt).end());
|
||||
return true;
|
||||
}
|
||||
LOGE("Could not find JSON field %s", name.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void loadSetting(nvh::CameraManipulator& cameraM)
|
||||
{
|
||||
if(m_jsonFilename.empty() || m_cameras.empty() || m_doLoadSetting == false)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
m_doLoadSetting = false;
|
||||
|
||||
// Clear all cameras except the HOME
|
||||
removedSavedCameras();
|
||||
|
||||
std::ifstream i(m_jsonFilename);
|
||||
if(!i.is_open())
|
||||
return;
|
||||
|
||||
// Parsing the file
|
||||
json j;
|
||||
i >> j;
|
||||
|
||||
// Temp
|
||||
int iVal;
|
||||
float fVal;
|
||||
std::vector<float> vfVal;
|
||||
|
||||
// Settings
|
||||
if(getJsonValue(j, "mode", iVal))
|
||||
cameraM.setMode(static_cast<nvh::CameraManipulator::Modes>(iVal));
|
||||
if(getJsonValue(j, "speed", fVal))
|
||||
cameraM.setSpeed(fVal);
|
||||
if(getJsonValue(j, "anim_duration", fVal))
|
||||
cameraM.setAnimationDuration(fVal);
|
||||
|
||||
// All cameras
|
||||
std::vector<json> cc;
|
||||
getJsonArray(j, "cameras", cc);
|
||||
for(auto& c : cc)
|
||||
{
|
||||
nvh::CameraManipulator::Camera camera;
|
||||
if(getJsonArray(c, "eye", vfVal))
|
||||
camera.eye = {vfVal[0], vfVal[1], vfVal[2]};
|
||||
if(getJsonArray(c, "ctr", vfVal))
|
||||
camera.ctr = {vfVal[0], vfVal[1], vfVal[2]};
|
||||
if(getJsonArray(c, "up", vfVal))
|
||||
camera.up = {vfVal[0], vfVal[1], vfVal[2]};
|
||||
if(getJsonValue(c, "fov", fVal))
|
||||
camera.fov = fVal;
|
||||
m_cameras.emplace_back(camera);
|
||||
}
|
||||
i.close();
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void saveSetting(nvh::CameraManipulator& cameraM) noexcept
|
||||
{
|
||||
if(m_jsonFilename.empty())
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
json j;
|
||||
j["mode"] = cameraM.getMode();
|
||||
j["speed"] = cameraM.getSpeed();
|
||||
j["anim_duration"] = cameraM.getAnimationDuration();
|
||||
|
||||
// Save all extra cameras
|
||||
json cc = json::array();
|
||||
for(size_t n = 1; n < m_cameras.size(); n++)
|
||||
{
|
||||
auto& c = m_cameras[n];
|
||||
json jo = json::object();
|
||||
jo["eye"] = std::vector<float>{c.eye.x, c.eye.y, c.eye.z};
|
||||
jo["up"] = std::vector<float>{c.up.x, c.up.y, c.up.z};
|
||||
jo["ctr"] = std::vector<float>{c.ctr.x, c.ctr.y, c.ctr.z};
|
||||
jo["fov"] = c.fov;
|
||||
cc.push_back(jo);
|
||||
}
|
||||
j["cameras"] = cc;
|
||||
|
||||
std::ofstream o(m_jsonFilename);
|
||||
if(o.is_open())
|
||||
{
|
||||
o << j.dump(2) << std::endl;
|
||||
o.close();
|
||||
}
|
||||
}
|
||||
catch(const std::exception& e)
|
||||
{
|
||||
LOGE("Could not save camera settings to %s: %s\n", m_jsonFilename.c_str(), e.what());
|
||||
}
|
||||
}
|
||||
|
||||
// Holds all cameras. [0] == HOME
|
||||
std::vector<nvh::CameraManipulator::Camera> m_cameras;
|
||||
float m_settingsDirtyTimer{0};
|
||||
std::string m_jsonFilename;
|
||||
bool m_doLoadSetting{true};
|
||||
};
|
||||
|
||||
static std::unique_ptr<CameraManager> sCamMgr;
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
// Display the values of the current camera: position, center, up and FOV
|
||||
//
|
||||
void CurrentCameraTab(nvh::CameraManipulator& cameraM, nvh::CameraManipulator::Camera& camera, bool& changed, bool& instantSet)
|
||||
{
|
||||
|
||||
bool y_is_up = camera.up.y == 1;
|
||||
|
||||
PropertyEditor::begin();
|
||||
PropertyEditor::entry(
|
||||
"Eye", [&] { return ImGui::InputFloat3("##Eye", &camera.eye.x, "%.5f"); }, "Position of the Camera");
|
||||
changed |= ImGui::IsItemDeactivatedAfterEdit();
|
||||
PropertyEditor::entry(
|
||||
"Center", [&] { return ImGui::InputFloat3("##Ctr", &camera.ctr.x, "%.5f"); }, "Center of camera interest");
|
||||
changed |= ImGui::IsItemDeactivatedAfterEdit();
|
||||
changed |= PropertyEditor::entry(
|
||||
"Y is UP", [&] { return ImGui::Checkbox("##Y", &y_is_up); }, "Is Y pointing up or Z?");
|
||||
if(PropertyEditor::entry(
|
||||
"FOV",
|
||||
[&] { return ImGui::SliderFloat("##Y", &camera.fov, 1.F, 179.F, "%.1f deg", ImGuiSliderFlags_Logarithmic); },
|
||||
"Field of view in degrees"))
|
||||
{
|
||||
instantSet = true;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if(PropertyEditor::treeNode("Clip planes"))
|
||||
{
|
||||
glm::vec2 clip = cameraM.getClipPlanes();
|
||||
PropertyEditor::entry("Near", [&] { return ImGui::InputFloat("##CN", &clip.x); });
|
||||
changed |= ImGui::IsItemDeactivatedAfterEdit();
|
||||
PropertyEditor::entry("Far", [&] { return ImGui::InputFloat("##CF", &clip.y); });
|
||||
changed |= ImGui::IsItemDeactivatedAfterEdit();
|
||||
PropertyEditor::treePop();
|
||||
cameraM.setClipPlanes(clip);
|
||||
}
|
||||
|
||||
camera.up = y_is_up ? glm::vec3(0, 1, 0) : glm::vec3(0, 0, 1);
|
||||
|
||||
if(cameraM.isAnimated())
|
||||
{
|
||||
// Ignoring any changes while the camera is moving to the goal.
|
||||
// The camera has to be in the new position before setting a new value.
|
||||
changed = false;
|
||||
}
|
||||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::TextDisabled("(?)");
|
||||
ImGuiH::tooltip(cameraM.getHelp().c_str(), false, 0.0f);
|
||||
ImGui::TableNextColumn();
|
||||
if(ImGui::SmallButton("Copy"))
|
||||
{
|
||||
std::string text = nvh::stringFormat("{%.5f, %.5f, %.5f}, {%.5f, %.5f, %.5f}, {%.5f, %.5f, %.5f}", //
|
||||
camera.eye.x, camera.eye.y, camera.eye.z, //
|
||||
camera.ctr.x, camera.ctr.y, camera.ctr.z, //
|
||||
camera.up.x, camera.up.y, camera.up.z);
|
||||
ImGui::SetClipboardText(text.c_str());
|
||||
}
|
||||
ImGuiH::tooltip("Copy to the clipboard the current camera: {eye}, {ctr}, {up}");
|
||||
ImGui::SameLine();
|
||||
const char* pPastedString;
|
||||
if(ImGui::SmallButton("Paste") && (pPastedString = ImGui::GetClipboardText()))
|
||||
{
|
||||
float val[9]{};
|
||||
int result = sscanf(pPastedString, "{%f, %f, %f}, {%f, %f, %f}, {%f, %f, %f}", &val[0], &val[1], &val[2], &val[3],
|
||||
&val[4], &val[5], &val[6], &val[7], &val[8]);
|
||||
if(result == 9) // 9 value properly scanned
|
||||
{
|
||||
camera.eye = glm::vec3{val[0], val[1], val[2]};
|
||||
camera.ctr = glm::vec3{val[3], val[4], val[5]};
|
||||
camera.up = glm::vec3{val[6], val[7], val[8]};
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
ImGuiH::tooltip("Paste from the clipboard the current camera: {eye}, {ctr}, {up}");
|
||||
PropertyEditor::end();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
// Display buttons for all saved cameras. Allow to create and delete saved cameras
|
||||
//
|
||||
void SavedCameraTab(nvh::CameraManipulator& cameraM, nvh::CameraManipulator::Camera& camera, bool& changed)
|
||||
{
|
||||
// Dummy
|
||||
ImVec2 button_sz(50, 30);
|
||||
char label[128];
|
||||
ImGuiStyle& style = ImGui::GetStyle();
|
||||
int buttons_count = (int)sCamMgr->m_cameras.size();
|
||||
float window_visible_x2 = ImGui::GetWindowPos().x + ImGui::GetWindowContentRegionMax().x;
|
||||
|
||||
// The HOME camera button, different from the other ones
|
||||
if(ImGui::Button("Home", ImVec2(ImGui::GetWindowContentRegionMax().x, 50)))
|
||||
{
|
||||
camera = sCamMgr->m_cameras[0];
|
||||
changed = true;
|
||||
}
|
||||
ImGuiH::tooltip("Reset the camera to its origin");
|
||||
|
||||
// Display all the saved camera in an array of buttons
|
||||
int delete_item = -1;
|
||||
for(int n = 1; n < buttons_count; n++)
|
||||
{
|
||||
ImGui::PushID(n);
|
||||
sprintf(label, "# %d", n);
|
||||
if(ImGui::Button(label, button_sz))
|
||||
{
|
||||
camera = sCamMgr->m_cameras[n];
|
||||
changed = true;
|
||||
}
|
||||
|
||||
// Middle click to delete a camera
|
||||
if(ImGui::IsItemHovered() && ImGui::GetIO().MouseClicked[NVPWindow::MOUSE_BUTTON_MIDDLE])
|
||||
delete_item = n;
|
||||
|
||||
// Displaying the position of the camera when hovering the button
|
||||
sprintf(label, "Pos: %3.5f, %3.5f, %3.5f", sCamMgr->m_cameras[n].eye.x, sCamMgr->m_cameras[n].eye.y,
|
||||
sCamMgr->m_cameras[n].eye.z);
|
||||
ImGuiH::tooltip(label);
|
||||
|
||||
// Wrapping all buttons (see ImGUI Demo)
|
||||
float last_button_x2 = ImGui::GetItemRectMax().x;
|
||||
float next_button_x2 = last_button_x2 + style.ItemSpacing.x + button_sz.x; // Expected position if next button was on same line
|
||||
if(n + 1 < buttons_count && next_button_x2 < window_visible_x2)
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::PopID();
|
||||
}
|
||||
|
||||
// Adding a camera button
|
||||
if(ImGui::Button("+"))
|
||||
{
|
||||
sCamMgr->addCamera(cameraM.getCamera());
|
||||
}
|
||||
ImGuiH::tooltip("Add a new saved camera");
|
||||
ImGui::SameLine();
|
||||
ImGui::TextDisabled("(?)");
|
||||
ImGuiH::tooltip("Middle-click a camera to delete it", false, 0.0f);
|
||||
|
||||
// Remove element
|
||||
if(delete_item > 0)
|
||||
{
|
||||
sCamMgr->removeCamera(delete_item);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
// This holds all camera setting, like the speed, the movement mode, transition duration
|
||||
//
|
||||
void CameraExtraTab(nvh::CameraManipulator& cameraM, bool& changed)
|
||||
{
|
||||
// Navigation Mode
|
||||
PropertyEditor::begin();
|
||||
auto mode = cameraM.getMode();
|
||||
auto speed = cameraM.getSpeed();
|
||||
auto duration = static_cast<float>(cameraM.getAnimationDuration());
|
||||
|
||||
changed |= PropertyEditor::entry(
|
||||
"Navigation",
|
||||
[&] {
|
||||
int rmode = static_cast<int>(mode);
|
||||
changed |= ImGui::RadioButton("Examine", &rmode, nvh::CameraManipulator::Examine);
|
||||
ImGuiH::tooltip("The camera orbit around a point of interest");
|
||||
changed |= ImGui::RadioButton("Fly", &rmode, nvh::CameraManipulator::Fly);
|
||||
ImGuiH::tooltip("The camera is free and move toward the looking direction");
|
||||
changed |= ImGui::RadioButton("Walk", &rmode, nvh::CameraManipulator::Walk);
|
||||
ImGuiH::tooltip("The camera is free but stay on a plane");
|
||||
cameraM.setMode(static_cast<nvh::CameraManipulator::Modes>(rmode));
|
||||
return changed;
|
||||
},
|
||||
"Camera Navigation Mode");
|
||||
|
||||
changed |= PropertyEditor::entry(
|
||||
"Speed", [&] { return ImGui::SliderFloat("##S", &speed, 0.01F, 10.0F); }, "Changing the default speed movement");
|
||||
changed |= PropertyEditor::entry(
|
||||
"Transition", [&] { return ImGui::SliderFloat("##S", &duration, 0.0F, 2.0F); }, "Nb seconds to move to new position");
|
||||
|
||||
cameraM.setSpeed(speed);
|
||||
cameraM.setAnimationDuration(duration);
|
||||
|
||||
PropertyEditor::end();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
// Display the camera eye and center of interest position of the camera (nvh::CameraManipulator)
|
||||
// Allow also to modify the field-of-view (FOV)
|
||||
// And basic control information is displayed
|
||||
bool CameraWidget(nvh::CameraManipulator& cameraM /*= nvh::CameraManipulator::Singleton()*/)
|
||||
{
|
||||
if(!sCamMgr)
|
||||
sCamMgr = std::make_unique<CameraManager>();
|
||||
|
||||
bool changed{false};
|
||||
bool instantSet{false};
|
||||
auto camera = cameraM.getCamera();
|
||||
|
||||
// Updating the camera manager
|
||||
sCamMgr->update(cameraM);
|
||||
|
||||
// Starting UI
|
||||
if(ImGui::BeginTabBar("Hello"))
|
||||
{
|
||||
if(ImGui::BeginTabItem("Current"))
|
||||
{
|
||||
CurrentCameraTab(cameraM, camera, changed, instantSet);
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
if(ImGui::BeginTabItem("Cameras"))
|
||||
{
|
||||
SavedCameraTab(cameraM, camera, changed);
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
if(ImGui::BeginTabItem("Extra"))
|
||||
{
|
||||
CameraExtraTab(cameraM, changed);
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
ImGui::EndTabBar();
|
||||
}
|
||||
|
||||
// Apply the change back to the camera
|
||||
if(changed)
|
||||
{
|
||||
cameraM.setCamera(camera, instantSet);
|
||||
}
|
||||
ImGui::Separator();
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
void SetCameraJsonFile(const std::string& filename)
|
||||
{
|
||||
if(!sCamMgr)
|
||||
sCamMgr = std::make_unique<CameraManager>();
|
||||
sCamMgr->setCameraJsonFile(filename);
|
||||
}
|
||||
|
||||
void SetHomeCamera(const nvh::CameraManipulator::Camera& camera)
|
||||
{
|
||||
if(!sCamMgr)
|
||||
sCamMgr = std::make_unique<CameraManager>();
|
||||
sCamMgr->setHomeCamera(camera);
|
||||
}
|
||||
|
||||
void AddCamera(const nvh::CameraManipulator::Camera& camera)
|
||||
{
|
||||
if(!sCamMgr)
|
||||
sCamMgr = std::make_unique<CameraManager>();
|
||||
sCamMgr->addCamera(camera);
|
||||
}
|
||||
|
||||
} // namespace ImGuiH
|
||||
36
raytracer/nvpro_core/imgui/imgui_camera_widget.h
Normal file
36
raytracer/nvpro_core/imgui/imgui_camera_widget.h
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright (c) 2014-2021, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* NVIDIA CORPORATION and its licensors retain all intellectual property
|
||||
* and proprietary rights in and to this software, related documentation
|
||||
* and any modifications thereto. Any use, reproduction, disclosure or
|
||||
* distribution of this software and related documentation without an express
|
||||
* license agreement from NVIDIA CORPORATION is strictly prohibited.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "nvh/cameramanipulator.hpp"
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
namespace ImGuiH {
|
||||
|
||||
/* @DOC_START -------------------------------------------------------
|
||||
|
||||
# functions in ImGuiH
|
||||
|
||||
- CameraWidget : CameraWidget is a Camera widget for the the Camera Manipulator
|
||||
- SetCameraJsonFile : set the name (without .json) of the setting file. It will load and replace all camera and settings
|
||||
- SetHomeCamera : set the home camera - replace the one on load
|
||||
- AddCamera : adding a camera to the list of cameras
|
||||
|
||||
--- @DOC_END ------------------------------------------------------- */
|
||||
|
||||
bool CameraWidget(nvh::CameraManipulator& cameraM = nvh::CameraManipulator::Singleton());
|
||||
|
||||
void SetCameraJsonFile(const std::string& filename);
|
||||
|
||||
void SetHomeCamera(const nvh::CameraManipulator::Camera& camera);
|
||||
|
||||
void AddCamera(const nvh::CameraManipulator::Camera& camera);
|
||||
|
||||
} // namespace ImGuiH
|
||||
690
raytracer/nvpro_core/imgui/imgui_helper.cpp
Normal file
690
raytracer/nvpro_core/imgui/imgui_helper.cpp
Normal file
|
|
@ -0,0 +1,690 @@
|
|||
/*
|
||||
* Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2018 NVIDIA CORPORATION
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define GLFW_INCLUDE_NONE
|
||||
#include "imgui/imgui_helper.h"
|
||||
#include <backends/imgui_impl_glfw.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <math.h>
|
||||
|
||||
|
||||
#include <fstream>
|
||||
|
||||
namespace ImGuiH {
|
||||
|
||||
void Init(int width, int height, void* userData, FontMode fontmode)
|
||||
{
|
||||
ImGui::CreateContext();
|
||||
setFonts(fontmode);
|
||||
auto& imgui_io = ImGui::GetIO();
|
||||
imgui_io.IniFilename = nullptr;
|
||||
imgui_io.UserData = userData;
|
||||
imgui_io.DisplaySize = ImVec2(float(width), float(height));
|
||||
imgui_io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable keyboard controls (tab, space, arrow keys)
|
||||
|
||||
// Scale style sizes for high-DPI monitors
|
||||
ImGuiStyle& imgui_style = ImGui::GetStyle();
|
||||
imgui_style.ScaleAllSizes(getDPIScale());
|
||||
}
|
||||
|
||||
void Deinit()
|
||||
{
|
||||
ImGui::DestroyContext(nullptr);
|
||||
}
|
||||
|
||||
|
||||
bool Combo(const char* label, size_t numEnums, const Enum* enums, void* valuePtr, ImGuiComboFlags flags, ValueType valueType, bool* valueChanged)
|
||||
{
|
||||
int* ivalue = (int*)valuePtr;
|
||||
float* fvalue = (float*)valuePtr;
|
||||
|
||||
size_t idx = 0;
|
||||
bool found = false;
|
||||
bool changed = false;
|
||||
for(size_t i = 0; i < numEnums; i++)
|
||||
{
|
||||
switch(valueType)
|
||||
{
|
||||
case TYPE_INT:
|
||||
if(enums[i].ivalue == *ivalue)
|
||||
{
|
||||
idx = i;
|
||||
found = true;
|
||||
}
|
||||
break;
|
||||
case TYPE_FLOAT:
|
||||
if(enums[i].fvalue == *fvalue)
|
||||
{
|
||||
idx = i;
|
||||
found = true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!found)
|
||||
{
|
||||
assert(!"No such value in combo!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(ImGui::BeginCombo(label, enums[idx].name.c_str(), flags)) // The second parameter is the label previewed before opening the combo.
|
||||
{
|
||||
for(size_t i = 0; i < numEnums; i++)
|
||||
{
|
||||
ImGui::BeginDisabled(enums[i].disabled);
|
||||
bool is_selected = i == idx;
|
||||
if(ImGui::Selectable(enums[i].name.c_str(), is_selected))
|
||||
{
|
||||
switch(valueType)
|
||||
{
|
||||
case TYPE_INT:
|
||||
*ivalue = enums[i].ivalue;
|
||||
break;
|
||||
case TYPE_FLOAT:
|
||||
*fvalue = enums[i].fvalue;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
changed = true;
|
||||
}
|
||||
if(is_selected)
|
||||
{
|
||||
ImGui::SetItemDefaultFocus(); // Set the initial focus when opening the combo (scrolling + for keyboard navigation support in the upcoming navigation branch)
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
|
||||
if(valueChanged)
|
||||
*valueChanged = changed;
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
//
|
||||
// If GLFW has been initialized, returns the DPI scale of the primary monitor. Otherwise, returns 1.
|
||||
//
|
||||
float getDPIScale()
|
||||
{
|
||||
// Cached DPI scale, so that this doesn't change after the first time code calls getDPIScale.
|
||||
// A negative value indicates that the value hasn't been computed yet.
|
||||
static float cached_dpi_scale = -1.0f;
|
||||
|
||||
if(cached_dpi_scale < 0.0f)
|
||||
{
|
||||
// Compute the product of the monitor DPI scale and any DPI scale
|
||||
// set in the NVPRO_DPI_SCALE variable.
|
||||
cached_dpi_scale = 1.0f;
|
||||
|
||||
GLFWmonitor* monitor = glfwGetPrimaryMonitor();
|
||||
assert(monitor);
|
||||
if(monitor != nullptr)
|
||||
{
|
||||
float y_scale;
|
||||
glfwGetMonitorContentScale(monitor, &cached_dpi_scale, &y_scale);
|
||||
}
|
||||
// Otherwise, GLFW isn't initialized yet, but might be in the future.
|
||||
// (Note that this code assumes all samples use GLFW.)
|
||||
|
||||
// Multiply by the value of the NVPRO_DPI_SCALE environment variable.
|
||||
const char* dpi_env = getenv("NVPRO_DPI_SCALE");
|
||||
if(dpi_env)
|
||||
{
|
||||
const float parsed_dpi_env = strtof(dpi_env, nullptr);
|
||||
if(parsed_dpi_env != 0.0f)
|
||||
{
|
||||
cached_dpi_scale *= parsed_dpi_env;
|
||||
}
|
||||
}
|
||||
|
||||
cached_dpi_scale = (cached_dpi_scale > 0.0f ? cached_dpi_scale : 1.0f);
|
||||
}
|
||||
|
||||
return cached_dpi_scale;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
// Setting a dark style for the GUI
|
||||
// The colors were coded in sRGB color space, set the useLinearColor
|
||||
// flag to convert to linear color space.
|
||||
void setStyle(bool useLinearColor)
|
||||
{
|
||||
typedef ImVec4 (*srgbFunction)(float, float, float, float);
|
||||
srgbFunction passthrough = [](float r, float g, float b, float a) -> ImVec4 { return ImVec4(r, g, b, a); };
|
||||
srgbFunction toLinear = [](float r, float g, float b, float a) -> ImVec4 {
|
||||
auto toLinearScalar = [](float u) -> float {
|
||||
return u <= 0.04045 ? 25 * u / 323.f : powf((200 * u + 11) / 211.f, 2.4f);
|
||||
};
|
||||
return ImVec4(toLinearScalar(r), toLinearScalar(g), toLinearScalar(b), a);
|
||||
};
|
||||
srgbFunction srgb = useLinearColor ? toLinear : passthrough;
|
||||
|
||||
ImGui::StyleColorsDark();
|
||||
|
||||
ImGuiStyle& style = ImGui::GetStyle();
|
||||
style.WindowRounding = 0.0f;
|
||||
style.WindowBorderSize = 0.0f;
|
||||
style.ColorButtonPosition = ImGuiDir_Right;
|
||||
style.FrameRounding = 2.0f;
|
||||
style.FrameBorderSize = 1.0f;
|
||||
style.GrabRounding = 4.0f;
|
||||
style.IndentSpacing = 12.0f;
|
||||
style.Colors[ImGuiCol_WindowBg] = srgb(0.2f, 0.2f, 0.2f, 1.0f);
|
||||
style.Colors[ImGuiCol_MenuBarBg] = srgb(0.2f, 0.2f, 0.2f, 1.0f);
|
||||
style.Colors[ImGuiCol_ScrollbarBg] = srgb(0.2f, 0.2f, 0.2f, 1.0f);
|
||||
style.Colors[ImGuiCol_PopupBg] = srgb(0.135f, 0.135f, 0.135f, 1.0f);
|
||||
style.Colors[ImGuiCol_Border] = srgb(0.4f, 0.4f, 0.4f, 0.5f);
|
||||
style.Colors[ImGuiCol_FrameBg] = srgb(0.05f, 0.05f, 0.05f, 0.5f);
|
||||
|
||||
// Normal
|
||||
ImVec4 normal_color = srgb(0.465f, 0.465f, 0.525f, 1.0f);
|
||||
std::vector<ImGuiCol> to_change_nrm;
|
||||
to_change_nrm.push_back(ImGuiCol_Header);
|
||||
to_change_nrm.push_back(ImGuiCol_SliderGrab);
|
||||
to_change_nrm.push_back(ImGuiCol_Button);
|
||||
to_change_nrm.push_back(ImGuiCol_CheckMark);
|
||||
to_change_nrm.push_back(ImGuiCol_ResizeGrip);
|
||||
to_change_nrm.push_back(ImGuiCol_TextSelectedBg);
|
||||
to_change_nrm.push_back(ImGuiCol_Separator);
|
||||
to_change_nrm.push_back(ImGuiCol_FrameBgActive);
|
||||
for(auto c : to_change_nrm)
|
||||
{
|
||||
style.Colors[c] = normal_color;
|
||||
}
|
||||
|
||||
// Active
|
||||
ImVec4 active_color = srgb(0.365f, 0.365f, 0.425f, 1.0f);
|
||||
std::vector<ImGuiCol> to_change_act;
|
||||
to_change_act.push_back(ImGuiCol_HeaderActive);
|
||||
to_change_act.push_back(ImGuiCol_SliderGrabActive);
|
||||
to_change_act.push_back(ImGuiCol_ButtonActive);
|
||||
to_change_act.push_back(ImGuiCol_ResizeGripActive);
|
||||
to_change_act.push_back(ImGuiCol_SeparatorActive);
|
||||
for(auto c : to_change_act)
|
||||
{
|
||||
style.Colors[c] = active_color;
|
||||
}
|
||||
|
||||
// Hovered
|
||||
ImVec4 hovered_color = srgb(0.565f, 0.565f, 0.625f, 1.0f);
|
||||
std::vector<ImGuiCol> to_change_hover;
|
||||
to_change_hover.push_back(ImGuiCol_HeaderHovered);
|
||||
to_change_hover.push_back(ImGuiCol_ButtonHovered);
|
||||
to_change_hover.push_back(ImGuiCol_FrameBgHovered);
|
||||
to_change_hover.push_back(ImGuiCol_ResizeGripHovered);
|
||||
to_change_hover.push_back(ImGuiCol_SeparatorHovered);
|
||||
for(auto c : to_change_hover)
|
||||
{
|
||||
style.Colors[c] = hovered_color;
|
||||
}
|
||||
|
||||
|
||||
style.Colors[ImGuiCol_TitleBgActive] = srgb(0.465f, 0.465f, 0.465f, 1.0f);
|
||||
style.Colors[ImGuiCol_TitleBg] = srgb(0.125f, 0.125f, 0.125f, 1.0f);
|
||||
style.Colors[ImGuiCol_Tab] = srgb(0.05f, 0.05f, 0.05f, 0.5f);
|
||||
style.Colors[ImGuiCol_TabHovered] = srgb(0.465f, 0.495f, 0.525f, 1.0f);
|
||||
style.Colors[ImGuiCol_TabActive] = srgb(0.282f, 0.290f, 0.302f, 1.0f);
|
||||
style.Colors[ImGuiCol_ModalWindowDimBg] = srgb(0.465f, 0.465f, 0.465f, 0.350f);
|
||||
|
||||
//Colors_ext[ImGuiColExt_Warning] = srgb (1.0f, 0.43f, 0.35f, 1.0f);
|
||||
|
||||
ImGui::SetColorEditOptions(ImGuiColorEditFlags_Float | ImGuiColorEditFlags_PickerHueWheel);
|
||||
}
|
||||
|
||||
//
|
||||
// Local, return true if the filename exist
|
||||
//
|
||||
static bool fileExists(const char* filename)
|
||||
{
|
||||
std::ifstream stream;
|
||||
stream.open(filename);
|
||||
return stream.is_open();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
// Looking for TTF fonts, first on the VULKAN SDK, then Windows default fonts
|
||||
//
|
||||
void setFonts(FontMode fontmode)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
const float high_dpi_scale = getDPIScale();
|
||||
|
||||
|
||||
// Nicer fonts
|
||||
ImFont* font = nullptr;
|
||||
if(fontmode == FONT_MONOSPACED_SCALED)
|
||||
{
|
||||
if(font == nullptr)
|
||||
{
|
||||
const std::string p = R"(C:/Windows/Fonts/consola.ttf)";
|
||||
if(fileExists(p.c_str()))
|
||||
font = io.Fonts->AddFontFromFileTTF(p.c_str(), 12.0f * high_dpi_scale);
|
||||
}
|
||||
if(font == nullptr)
|
||||
{
|
||||
const std::string p = "/usr/share/fonts/truetype/ubuntu/UbuntuMono-R.ttf";
|
||||
if(fileExists(p.c_str()))
|
||||
font = io.Fonts->AddFontFromFileTTF(p.c_str(), 12.0f * high_dpi_scale);
|
||||
}
|
||||
}
|
||||
else if(fontmode == FONT_PROPORTIONAL_SCALED)
|
||||
{
|
||||
const char* vk_path = getenv("VK_SDK_PATH");
|
||||
if(vk_path)
|
||||
{
|
||||
const std::string p = std::string(vk_path) + R"(/Samples/Layer-Samples/data/FreeSans.ttf)";
|
||||
if(fileExists(p.c_str()))
|
||||
font = io.Fonts->AddFontFromFileTTF(p.c_str(), 16.0f * high_dpi_scale);
|
||||
}
|
||||
if(font == nullptr)
|
||||
{
|
||||
const std::string p = R"(C:/Windows/Fonts/segoeui.ttf)";
|
||||
if(fileExists(p.c_str()))
|
||||
font = io.Fonts->AddFontFromFileTTF(p.c_str(), 16.0f * high_dpi_scale);
|
||||
}
|
||||
if(font == nullptr)
|
||||
{
|
||||
const std::string p = "/usr/share/fonts/truetype/ubuntu/Ubuntu-R.ttf";
|
||||
if(fileExists(p.c_str()))
|
||||
font = io.Fonts->AddFontFromFileTTF(p.c_str(), 16.0f * high_dpi_scale);
|
||||
}
|
||||
}
|
||||
|
||||
if(font == nullptr)
|
||||
{
|
||||
ImFontConfig font_config = ImFontConfig();
|
||||
font_config.SizePixels = 13.0f * high_dpi_scale; // 13 is the default font size
|
||||
io.Fonts->AddFontDefault(&font_config);
|
||||
}
|
||||
}
|
||||
|
||||
void tooltip(const char* description, bool questionMark /*= false*/, float timerThreshold /*= 0.5f*/)
|
||||
{
|
||||
bool passTimer = GImGui->HoveredIdTimer >= timerThreshold && GImGui->ActiveIdTimer == 0.0f;
|
||||
if(questionMark)
|
||||
{
|
||||
ImGui::SameLine();
|
||||
ImGui::TextDisabled("(?)");
|
||||
passTimer = true;
|
||||
}
|
||||
|
||||
if(ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled) && passTimer)
|
||||
{
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
|
||||
ImGui::TextUnformatted(description);
|
||||
ImGui::PopTextWrapPos();
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
namespace {
|
||||
|
||||
template <typename TScalar, ImGuiDataType type, uint8_t dim>
|
||||
bool show_slider_control_scalar(TScalar* value, TScalar* min, TScalar* max, const char* format)
|
||||
{
|
||||
static const char* visible_labels[] = {"x:", "y:", "z:", "w:"};
|
||||
|
||||
if(dim == 1)
|
||||
return ImGui::SliderScalar("##hidden", type, &value[0], &min[0], &max[0], format);
|
||||
|
||||
float indent = ImGui::GetCursorPos().x;
|
||||
bool changed = false;
|
||||
for(uint8_t c = 0; c < dim; ++c)
|
||||
{
|
||||
ImGui::PushID(c);
|
||||
if(c > 0)
|
||||
{
|
||||
ImGui::NewLine();
|
||||
ImGui::SameLine(indent);
|
||||
}
|
||||
ImGui::Text("%s", visible_labels[c]);
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
changed |= ImGui::SliderScalar("##hidden", type, &value[c], &min[c], &max[c], format);
|
||||
ImGui::PopID();
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
template <>
|
||||
bool Control::show_slider_control<float>(float* value, float& min, float& max, const char* format)
|
||||
{
|
||||
return show_slider_control_scalar<float, ImGuiDataType_Float, 1>(value, &min, &max, format ? format : "%.3f");
|
||||
}
|
||||
|
||||
template <>
|
||||
bool Control::show_slider_control<glm::vec2>(glm::vec2* value, glm::vec2& min, glm::vec2& max, const char* format)
|
||||
{
|
||||
return show_slider_control_scalar<float, ImGuiDataType_Float, 2>(&value->x, &min.x, &max.x, format ? format : "%.3f");
|
||||
}
|
||||
|
||||
template <>
|
||||
bool Control::show_slider_control<glm::vec3>(glm::vec3* value, glm::vec3& min, glm::vec3& max, const char* format)
|
||||
{
|
||||
return show_slider_control_scalar<float, ImGuiDataType_Float, 3>(&value->x, &min.x, &max.x, format ? format : "%.3f");
|
||||
}
|
||||
|
||||
template <>
|
||||
bool Control::show_slider_control<glm::vec4>(glm::vec4* value, glm::vec4& min, glm::vec4& max, const char* format)
|
||||
{
|
||||
return show_slider_control_scalar<float, ImGuiDataType_Float, 4>(&value->x, &min.x, &max.x, format ? format : "%.3f");
|
||||
}
|
||||
|
||||
template <>
|
||||
bool Control::show_drag_control<float>(float* value, float speed, float& min, float& max, const char* format)
|
||||
{
|
||||
return show_drag_control_scalar<float, ImGuiDataType_Float, 1>(value, speed, &min, &max, format ? format : "%.3f");
|
||||
}
|
||||
|
||||
template <>
|
||||
bool Control::show_drag_control<glm::vec2>(glm::vec2* value, float speed, glm::vec2& min, glm::vec2& max, const char* format)
|
||||
{
|
||||
return show_drag_control_scalar<float, ImGuiDataType_Float, 2>(&value->x, speed, &min.x, &max.x, format ? format : "%.3f");
|
||||
}
|
||||
|
||||
template <>
|
||||
bool Control::show_drag_control<glm::vec3>(glm::vec3* value, float speed, glm::vec3& min, glm::vec3& max, const char* format)
|
||||
{
|
||||
return show_drag_control_scalar<float, ImGuiDataType_Float, 3>(&value->x, speed, &min.x, &max.x, format ? format : "%.3f");
|
||||
}
|
||||
|
||||
template <>
|
||||
bool Control::show_drag_control<glm::vec4>(glm::vec4* value, float speed, glm::vec4& min, glm::vec4& max, const char* format)
|
||||
{
|
||||
return show_drag_control_scalar<float, ImGuiDataType_Float, 4>(&value->x, speed, &min.x, &max.x, format ? format : "%.3f");
|
||||
}
|
||||
|
||||
|
||||
template <>
|
||||
bool Control::show_slider_control<int>(int* value, int& min, int& max, const char* format)
|
||||
{
|
||||
return show_slider_control_scalar<int, ImGuiDataType_S32, 1>(value, &min, &max, format ? format : "%d");
|
||||
}
|
||||
|
||||
template <>
|
||||
bool Control::show_slider_control<glm::ivec2>(glm::ivec2* value, glm::ivec2& min, glm::ivec2& max, const char* format)
|
||||
{
|
||||
return show_slider_control_scalar<int, ImGuiDataType_S32, 2>(&value->x, &min.x, &max.x, format ? format : "%d");
|
||||
}
|
||||
|
||||
template <>
|
||||
bool Control::show_slider_control<glm::ivec3>(glm::ivec3* value, glm::ivec3& min, glm::ivec3& max, const char* format)
|
||||
{
|
||||
return show_slider_control_scalar<int, ImGuiDataType_S32, 3>(&value->x, &min.x, &max.x, format ? format : "%d");
|
||||
}
|
||||
|
||||
template <>
|
||||
bool Control::show_slider_control<glm::ivec4>(glm::ivec4* value, glm::ivec4& min, glm::ivec4& max, const char* format)
|
||||
{
|
||||
return show_slider_control_scalar<int, ImGuiDataType_S32, 4>(&value->x, &min.x, &max.x, format ? format : "%d");
|
||||
}
|
||||
|
||||
template <>
|
||||
bool Control::show_drag_control<int>(int* value, float speed, int& min, int& max, const char* format)
|
||||
{
|
||||
return show_drag_control_scalar<int, ImGuiDataType_S32, 1>(value, speed, &min, &max, format ? format : "%d");
|
||||
}
|
||||
|
||||
template <>
|
||||
bool Control::show_drag_control<glm::ivec2>(glm::ivec2* value, float speed, glm::ivec2& min, glm::ivec2& max, const char* format)
|
||||
{
|
||||
return show_drag_control_scalar<int, ImGuiDataType_S32, 2>(&value->x, speed, &min.x, &max.x, format ? format : "%d");
|
||||
}
|
||||
|
||||
template <>
|
||||
bool Control::show_drag_control<glm::ivec3>(glm::ivec3* value, float speed, glm::ivec3& min, glm::ivec3& max, const char* format)
|
||||
{
|
||||
return show_drag_control_scalar<int, ImGuiDataType_S32, 3>(&value->x, speed, &min.x, &max.x, format ? format : "%d");
|
||||
}
|
||||
|
||||
template <>
|
||||
bool Control::show_drag_control<glm::ivec4>(glm::ivec4* value, float speed, glm::ivec4& min, glm::ivec4& max, const char* format)
|
||||
{
|
||||
return show_drag_control_scalar<int, ImGuiDataType_S32, 4>(&value->x, speed, &min.x, &max.x, format ? format : "%d");
|
||||
}
|
||||
|
||||
|
||||
template <>
|
||||
bool Control::show_slider_control<uint32_t>(uint32_t* value, uint32_t& min, uint32_t& max, const char* format)
|
||||
{
|
||||
return show_slider_control_scalar<uint32_t, ImGuiDataType_U32, 1>(value, &min, &max, format ? format : "%d");
|
||||
}
|
||||
//
|
||||
//template <>
|
||||
//bool Control::show_slider_control<uint32_t_2>(uint32_t_2* value, uint32_t_2& min, uint32_t_2& max, const char* format)
|
||||
//{
|
||||
// return show_slider_control_scalar<uint32_t, ImGuiDataType_U32, 2>(&value->x, &min.x, &max.x, format ? format : "%d");
|
||||
//}
|
||||
//
|
||||
//template <>
|
||||
//bool Control::show_slider_control<uint32_t_3>(uint32_t_3* value, uint32_t_3& min, uint32_t_3& max, const char* format)
|
||||
//{
|
||||
// return show_slider_control_scalar<uint32_t, ImGuiDataType_U32, 3>(&value->x, &min.x, &max.x, format ? format : "%d");
|
||||
//}
|
||||
//
|
||||
//template <>
|
||||
//bool Control::show_slider_control<uint32_t_4>(uint32_t_4* value, uint32_t_4& min, uint32_t_4& max, const char* format)
|
||||
//{
|
||||
// return show_slider_control_scalar<uint32_t, ImGuiDataType_U32, 4>(&value->x, &min.x, &max.x, format ? format : "%d");
|
||||
//}
|
||||
//
|
||||
//template <>
|
||||
//bool Control::show_drag_control<uint32_t>(uint32_t* value, float speed, uint32_t& min, uint32_t& max, const char* format)
|
||||
//{
|
||||
// return show_drag_control_scalar<uint32_t, ImGuiDataType_U32, 1>(value, speed, &min, &max, format ? format : "%d");
|
||||
//}
|
||||
//
|
||||
//template <>
|
||||
//bool Control::show_drag_control<uint32_t_2>(uint32_t_2* value, float speed, uint32_t_2& min, uint32_t_2& max, const char* format)
|
||||
//{
|
||||
// return show_drag_control_scalar<uint32_t, ImGuiDataType_U32, 2>(&value->x, speed, &min.x, &max.x, format ? format : "%d");
|
||||
//}
|
||||
//
|
||||
//template <>
|
||||
//bool Control::show_drag_control<uint32_t_3>(uint32_t_3* value, float speed, uint32_t_3& min, uint32_t_3& max, const char* format)
|
||||
//{
|
||||
// return show_drag_control_scalar<uint32_t, ImGuiDataType_U32, 3>(&value->x, speed, &min.x, &max.x, format ? format : "%d");
|
||||
//}
|
||||
//
|
||||
//template <>
|
||||
//bool Control::show_drag_control<uint32_t_4>(uint32_t_4* value, float speed, uint32_t_4& min, uint32_t_4& max, const char* format)
|
||||
//{
|
||||
// return show_drag_control_scalar<uint32_t, ImGuiDataType_U32, 4>(&value->x, speed, &min.x, &max.x, format ? format : "%d");
|
||||
//}
|
||||
|
||||
|
||||
template <>
|
||||
bool Control::show_slider_control<size_t>(size_t* value, size_t& min, size_t& max, const char* format)
|
||||
{
|
||||
return show_slider_control_scalar<size_t, ImGuiDataType_U64, 1>(value, &min, &max, format ? format : "%d");
|
||||
}
|
||||
|
||||
template <>
|
||||
bool Control::show_drag_control<size_t>(size_t* value, float speed, size_t& min, size_t& max, const char* format)
|
||||
{
|
||||
return show_drag_control_scalar<size_t, ImGuiDataType_U64, 1>(value, speed, &min, &max, format ? format : "%d");
|
||||
}
|
||||
|
||||
// Static member declaration
|
||||
ImGuiID Panel::dockspaceID{0};
|
||||
|
||||
void Panel::Begin(Side side /*= Side::Right*/, float alpha /*= 0.5f*/, char* name /*= nullptr*/)
|
||||
{
|
||||
// Keeping the unique ID of the dock space
|
||||
dockspaceID = ImGui::GetID("DockSpace");
|
||||
|
||||
// The dock need a dummy window covering the entire viewport.
|
||||
ImGuiViewport* viewport = ImGui::GetMainViewport();
|
||||
ImGui::SetNextWindowPos(viewport->WorkPos);
|
||||
ImGui::SetNextWindowSize(viewport->WorkSize);
|
||||
ImGui::SetNextWindowViewport(viewport->ID);
|
||||
|
||||
// All flags to dummy window
|
||||
ImGuiWindowFlags host_window_flags = 0;
|
||||
host_window_flags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize;
|
||||
host_window_flags |= ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDocking;
|
||||
host_window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus;
|
||||
host_window_flags |= ImGuiWindowFlags_NoBackground;
|
||||
|
||||
// Starting dummy window
|
||||
char label[32];
|
||||
ImFormatString(label, IM_ARRAYSIZE(label), "DockSpaceViewport_%08X", viewport->ID);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
|
||||
ImGui::Begin(label, nullptr, host_window_flags);
|
||||
ImGui::PopStyleVar(3);
|
||||
|
||||
// The central node is transparent, so that when UI is draw after, the image is visible
|
||||
// Auto Hide Bar, no title of the panel
|
||||
// Center is not dockable, that is for the scene
|
||||
ImGuiDockNodeFlags dockspaceFlags = ImGuiDockNodeFlags_PassthruCentralNode | ImGuiDockNodeFlags_AutoHideTabBar
|
||||
| ImGuiDockNodeFlags_NoDockingOverCentralNode;
|
||||
|
||||
// Default panel/window is name setting
|
||||
std::string dock_name("Settings");
|
||||
if(name != nullptr)
|
||||
dock_name = name;
|
||||
|
||||
// Building the splitting of the dock space is done only once
|
||||
if(!ImGui::DockBuilderGetNode(dockspaceID))
|
||||
{
|
||||
ImGui::DockBuilderRemoveNode(dockspaceID);
|
||||
ImGui::DockBuilderAddNode(dockspaceID, dockspaceFlags | ImGuiDockNodeFlags_DockSpace);
|
||||
ImGui::DockBuilderSetNodeSize(dockspaceID, viewport->Size);
|
||||
|
||||
ImGuiID dock_main_id = dockspaceID;
|
||||
|
||||
// Slitting all 4 directions, targetting (320 pixel * DPI) panel width, (180 pixel * DPI) panel height.
|
||||
const float xRatio = glm::clamp<float>(320.0f * getDPIScale() / viewport->WorkSize[0], 0.01f, 0.499f);
|
||||
const float yRatio = glm::clamp<float>(180.0f * getDPIScale() / viewport->WorkSize[1], 0.01f, 0.499f);
|
||||
ImGuiID id_left, id_right, id_up, id_down;
|
||||
|
||||
// Note, for right, down panels, we use the n / (1 - n) formula to correctly split the space remaining from the left, up panels.
|
||||
id_left = ImGui::DockBuilderSplitNode(dock_main_id, ImGuiDir_Left, xRatio, nullptr, &dock_main_id);
|
||||
id_right = ImGui::DockBuilderSplitNode(dock_main_id, ImGuiDir_Right, xRatio / (1 - xRatio), nullptr, &dock_main_id);
|
||||
id_up = ImGui::DockBuilderSplitNode(dock_main_id, ImGuiDir_Up, yRatio, nullptr, &dock_main_id);
|
||||
id_down = ImGui::DockBuilderSplitNode(dock_main_id, ImGuiDir_Down, yRatio / (1 - yRatio), nullptr, &dock_main_id);
|
||||
|
||||
ImGui::DockBuilderDockWindow(side == Side::Left ? dock_name.c_str() : "Dock_left", id_left);
|
||||
ImGui::DockBuilderDockWindow(side == Side::Right ? dock_name.c_str() : "Dock_right", id_right);
|
||||
ImGui::DockBuilderDockWindow("Dock_up", id_up);
|
||||
ImGui::DockBuilderDockWindow("Dock_down", id_down);
|
||||
ImGui::DockBuilderDockWindow("Scene", dock_main_id); // Center
|
||||
|
||||
ImGui::DockBuilderFinish(dock_main_id);
|
||||
}
|
||||
|
||||
// Setting the panel to blend with alpha
|
||||
ImVec4 col = ImGui::GetStyleColorVec4(ImGuiCol_WindowBg);
|
||||
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(col.x, col.y, col.z, alpha));
|
||||
|
||||
ImGui::DockSpace(dockspaceID, ImVec2(0.0f, 0.0f), dockspaceFlags);
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::End();
|
||||
|
||||
// The panel
|
||||
if(alpha < 1)
|
||||
ImGui::SetNextWindowBgAlpha(alpha); // For when the panel becomes a floating window
|
||||
ImGui::Begin(dock_name.c_str());
|
||||
}
|
||||
|
||||
Control::Style Control::style{};
|
||||
|
||||
} // namespace ImGuiH
|
||||
|
||||
|
||||
bool ImGuiH::azimuthElevationSliders(glm::vec3& direction, bool negative, bool yIsUp /*=true*/)
|
||||
{
|
||||
glm::vec3 normalized_dir = normalize(direction);
|
||||
if(negative)
|
||||
{
|
||||
normalized_dir = -normalized_dir;
|
||||
}
|
||||
|
||||
double azimuth;
|
||||
double elevation;
|
||||
const double min_azimuth = -180.0;
|
||||
const double max_azimuth = 180.0;
|
||||
const double min_elevation = -90.0;
|
||||
const double max_elevation = 90.0;
|
||||
|
||||
if(yIsUp)
|
||||
{
|
||||
azimuth = glm::degrees(atan2(normalized_dir.z, normalized_dir.x));
|
||||
elevation = glm::degrees(asin(normalized_dir.y));
|
||||
}
|
||||
else
|
||||
{
|
||||
azimuth = glm::degrees(atan2(normalized_dir.y, normalized_dir.x));
|
||||
elevation = glm::degrees(asin(normalized_dir.z));
|
||||
}
|
||||
|
||||
|
||||
bool changed = false;
|
||||
changed |= PropertyEditor::entry("Azimuth", [&]() {
|
||||
return ImGui::SliderScalar("Azimuth", ImGuiDataType_Double, &azimuth, &min_azimuth, &max_azimuth, "%.1f deg",
|
||||
ImGuiSliderFlags_NoRoundToFormat);
|
||||
});
|
||||
changed |= PropertyEditor::entry("Elevation", [&]() {
|
||||
return ImGui::SliderScalar("Elevation", ImGuiDataType_Double, &elevation, &min_elevation, &max_elevation,
|
||||
"%.1f deg", ImGuiSliderFlags_NoRoundToFormat);
|
||||
});
|
||||
|
||||
if(changed)
|
||||
{
|
||||
azimuth = glm::radians(azimuth);
|
||||
elevation = glm::radians(elevation);
|
||||
double cos_elevation = cos(elevation);
|
||||
|
||||
if(yIsUp)
|
||||
{
|
||||
direction.y = static_cast<float>(sin(elevation));
|
||||
direction.x = static_cast<float>(cos(azimuth) * cos_elevation);
|
||||
direction.z = static_cast<float>(sin(azimuth) * cos_elevation);
|
||||
}
|
||||
else
|
||||
{
|
||||
direction.z = static_cast<float>(sin(elevation));
|
||||
direction.x = static_cast<float>(cos(azimuth) * cos_elevation);
|
||||
direction.y = static_cast<float>(sin(azimuth) * cos_elevation);
|
||||
}
|
||||
|
||||
if(negative)
|
||||
{
|
||||
direction = -direction;
|
||||
}
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
1302
raytracer/nvpro_core/imgui/imgui_helper.h
Normal file
1302
raytracer/nvpro_core/imgui/imgui_helper.h
Normal file
File diff suppressed because it is too large
Load diff
326
raytracer/nvpro_core/imgui/imgui_icon.cpp
Normal file
326
raytracer/nvpro_core/imgui/imgui_icon.cpp
Normal file
|
|
@ -0,0 +1,326 @@
|
|||
/*
|
||||
* Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <imgui.h>
|
||||
#include "imgui_icon.h"
|
||||
|
||||
namespace ImGuiH {
|
||||
ImFont* g_iconicFont = nullptr;
|
||||
}
|
||||
|
||||
// Forward declaration
|
||||
const char* getOpenIconicFontCompressedBase85TTF();
|
||||
|
||||
|
||||
void ImGuiH::addIconicFont(float fontSize)
|
||||
{
|
||||
if(g_iconicFont == nullptr)
|
||||
{
|
||||
ImFontConfig fontConfig;
|
||||
static uint16_t const range[] = {0xE000, 0xE0DF, 0};
|
||||
char const* glyphsData = getOpenIconicFontCompressedBase85TTF();
|
||||
g_iconicFont =
|
||||
ImGui::GetIO().Fonts->AddFontFromMemoryCompressedBase85TTF(glyphsData, fontSize, &fontConfig, (const ImWchar*)range);
|
||||
}
|
||||
}
|
||||
|
||||
ImFont* ImGuiH::getIconicFont()
|
||||
{
|
||||
return g_iconicFont;
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
const char* getOpenIconicFontCompressedBase85TTF()
|
||||
{
|
||||
// TTF font data for OpenIconic font TTF
|
||||
|
||||
// SIL OPEN FONT LICENSE Version 1.1
|
||||
// https://github.com/iconic/open-iconic/blob/master/FONT-LICENSE
|
||||
|
||||
// The MIT License(MIT)
|
||||
// https://github.com/iconic/open-iconic/blob/master/ICON-LICENSE
|
||||
//
|
||||
// Copyright(c) 2014 Waybury
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this softwareand associated documentation files(the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and /or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions :
|
||||
//
|
||||
// The above copyright noticeand this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
// File: 'open-iconic.ttf' (28028 bytes)
|
||||
// Exported using binary_to_compressed_c.cpp
|
||||
static const char openIconic_compressed_data_base85[25385 + 1] =
|
||||
"7])#######cl1xJ'/###W),##2(V$#Q6>##u@;*>#ovW#&6)=-'OE/1gZn426mL&=1->>#JqEn/aNV=B28=<m_)m<-EZlS._0XGH`$vhL0IbjN=pb:&$jg0Fr9eV5oQQ^RE6WaE%J%/G"
|
||||
"BgO2(UC72LFAuY%,5LsCDEw5[7)1G`8@Ei*b';9Co/(F9LFS7hr1dD4Eo3R/f@h>#/;pu&V3dW.;h^`IwBAA+k%HL2WF')No6Q<BUs$&94b(8_mQf^c0iR/GMxKghV8C5M9ANDF;),eP"
|
||||
"s=L%Mv6QwLYcv/GiF#>pfe->#G:%&#P$;-GItJ1kmO31#r$pBABLTsL:+:%/-p5m6#aJ_&FZ;#jL-gF%N55YueXZV$l`+W%G'7*.p+AGM%rs.Lx0KfLwF6##_OB`N1^*bNYU$##.,<6C"
|
||||
"pYw:#[MW;-$_C2:01XMCH]/F%@oj>-Wmf*%%q8.$F`7@'.B.;6_Du'&hF;;$63Mk+MS:;$l9r&lW+>>#YvEuu=m*.-H####Y4+GMQrus-Su[fLK=6##'DbA#bFw8'tB6##Lhdk%Nb#d)"
|
||||
"-l68%<a60%*8YY#ksnO(meGH3D@dOgq#Sk#<@KZ+^2bY#t=58.Z42G`R5pP'R#k8&1p^w0%2tM(TDl-$nq@8%uP&<6FMsFrkg%;Qk:MEd]'CJ#q4cQumLuFroPu>C&8FB-#@'$.8mwiL"
|
||||
"KO2EOR.tB-1N5</<PQ?SQlRfL^5fQMK4X$#8e`##9Q@k(xsFA#cFGH3*/rv-@0steAL@&Mt98'RE:6G`(q1@doX]'R>$hiPchu,MLY5;-]Xo34camA#@YqlLLxQ2MIMh1MB2tuLjV;;$"
|
||||
"PE)B4-Mc##=(V$#3JRN'GRes$-M:;$eN;hLGSrhL)kL)Nv$Q;-h8Ee#OYLxL/qPW-+l*hcw3Tt:K=/g)&QD.$s@o6<40)V;=6axT1F<U;2OWq;.]BxTR2###;:U;-<3]V$]V@^FJR@%#"
|
||||
"8l#U7uUO.)Y9kT%1YUV$Yp()3GU1E4m3[5/sgw,*wqq8.5&7C#)#xP'hT%;Q<a&buYwaVaJjAZ#/7:*j>[x@A1P&,;nl8IW*Yn36=b/(G*8FW.KkqrUgt]_uR0.g>Z>,%&$),##50ED#"
|
||||
";EFEaP]UkIJ1P*nO(@nBD3gp/Ys%*c,/Wp`IhM]^'/B67gL0mM<%9@RS%EE.<$(iNn0&DJ1(*O13(0&Ws%C8I6oF'XMon(BW#Ej5/1#iK#$V@pgL5W=huZXAwR'qAZPH(<?#%G3]-"
|
||||
"R4B>QW<Q]uIvg_-5Or`S*J);;RmwiL*BauPcOB_-66lKYg,3^#r+TV-jO@mk5ImO($FKx9R:xIQTCfd4XcE,#8EaP]VkIJ1W9m9MqiRdF#jaIhUm9DC)Pb3Fq';dMJ:>GMU'MHME]sFr"
|
||||
"$#bIh$ErFrtE)Xu*S.GMsFZY#xx'&(-hBD3O4g]uc_.08/tf2`_^7I-PK7I-dn6]-TYwTM9en9M3*-&4%lQDO]H1[MO@YoPM8,,MU#<?#0q3L#r&_B#Gk5`-+XV$^wAI&#MgwGMe/=fM"
|
||||
"%2rAMwM,i87d0^#(tAh8IG1B#8E_#$uLbA#=2vg)<j8>CoeY9C3[-CuBu[*$#xYr#2w@P#3(CJ#G*2GMlH^v-KV;;?BT_c)lH*20%'%<&DI$,*DiY##=Z[0)jiWI)qV6C#2-#Q/8bCE4"
|
||||
"d.fZ$aSIWABTgk0;-LD?7L1a#d:+d4.:L^u@Ft%,O27>>$/Ib%@s@8:JrksLPQuP=Wj&2XY'f*.W>%H?Jo*50D@N'6@:&&6Mj;5:[G>',%/5##sIkA#?V)2/9(V$#rA+KWNVB.*0Zc8/"
|
||||
"_YWF3p;:R/g;2.I07b2CAZAb4hLY['IR(<)[8UCCx5B58Xatm'Dn35&+^L-M&J_P8H79v-P>/B#9]SfLYWY95F5kWo[iJdo7PFa[Nk9:<bmp2<`1g2$^kYhLMbQb[P)^F#&fAguE8*C&"
|
||||
".'wwB_B(7#1Yu##;PF$/GRes$c^HwBH$nO(gv8s7EPdO(jW4G`Lq#Gr3RgIht28G`]n&=(Vu_?###b9#`KGf%;T<A+&Zu(3%'%<&_T/a+bhV?#+crB#;0l]#P#G:.rkh8.mNv)4kDsI3"
|
||||
"5;`:%q2Qv$lf/+*u?lD#g48`&/0*>P^-R`E7+R<C0F91p*AM9LpLL=Q3H?.q]PMP0*+_HM3bQ;-`78JL$R]duA'OI)ZFX:CxH#OKvCnf)Gd(APJCZY#)J/-2IdS2^M4v##;Z[0)?sGA#"
|
||||
"vx:g)Z4jd%lUFb3(ctM(7'$,&H$^>u=NxH#6J8I&tS?.&(w?w%M&CJ#nxkT9HoMs%Ri,#:fs0c7fGA_#kSuIUZ42G`#?#,2'ti21;ix+MG3gF4`cJ,3)_Aj0cI9F*jpB:%cn4[$UJ,G4"
|
||||
"[uUv-?]d8/hJL:%+SN/2X,n.)1Yl>#4a&m%;Bjo*G6'j0DTnr6>vl[P^Su>#D5UlSjXT)5er^)%7R2=-kL)APv<qa4<IK60tY#c4<q@?PW;e+WLuuEm05Vm&fK(,)nM5N(f%JfL`Lu(3"
|
||||
"9UsNOj/@tLh]8f3.m(u$Uxor6]]DC8ukm/N3vOG=Mo&vHc2Ii4iJ<cFuP@+`E'flLbcK`$v)$$$PrC$#e28]%/5:$)V'+X$)lNn0vpf8%B:Y)4ZE>V/isSi)XSf_4Kj+5A3/mCW-nm<S"
|
||||
"`Tr6C?9%0$lKTATZ(N=(=BPEd++wH?Ukx/1U'+&#`,Gj^8%L+**<m`-0]kHZ(LOA#vkh8.7/TF4o=]:/Z(OF3kl-F%3F6eMJGsFrY3Kt7lAkHuNBAJ.3dT3C7Ot2CSeKD?]a;*eB[f%-"
|
||||
"6K^'RB,aB#FP*2MSiaIhwq$vJZTEV&biqr$07>>#8EQJ(6uv9.nXAouu[XO%s[?>#p?_&#aJxjt^;>_/^1[d+=7B_4s7En3+I@X-vu/+*X0fX-]p*P(&,]]4qio05A@N@,.>T@,(r?5/"
|
||||
"=KeA?u>kB,pSaIhUT%/2.dOCjA/#2C7CA5//`Nw$*jnA#abDE-)aDE-/MXZ/8N9R//G/JdTa+W-@Isp^Z_?##EdS2^4;5##af[^$/6fX-m'4]-7^9Z-HLQ;-.`6/1xq7t%uR$w#tPR6D"
|
||||
"CIm,&=G4?Is8K%#fd0'#$sb&,`X2$#p%c00gEW@,QFVC,732m$ic``3t<7f3I.=h>K7)qiFe8V8CwBB#'8:$6-^J6atvN@,P;I80eF&b*l-AU+Q1(`.JLR$&cIqH1Vec<066V9CIBkp%"
|
||||
",<$'85fK>?uxwV.fE4g)Een2B,R(f)o77<.hp?d)BiaF3iEo8%Z_G)4@O'>.g:S_#OJ,G4oHl2Eq<@12u)Yx#IM6u?b%]=YnAv6Jex/U%ZRQ;-P2>.3hC7),'BW<BvIo#';9l<'$<=8A"
|
||||
"QI%##SJ%?R#H0%#hj9'#G`gT7LoqZ-$QdR&*oNn0@hmV-+NTj`qc=00vc%H)+,Bf3rQim$VKi9/(o?X-^hDv#@81G`Ig2Au0aYK)uXAA,/Pg;M+q//1gFB,j<34G`R=wP/ji1G`]d`oA"
|
||||
"Q$1i#`M66CL=6##)CQ$$^0+&#Kqn%#7mJR8@R6C#a?T:%cKff16t'E#E%D'S1lh8.VntD#$be#5@=e/1#6RCsVJ$F<tI`?#Of6'5r0Er:3MBk;spA/1cbg@OmWuI<^'s?#FWS5<3QP-."
|
||||
"DM_*597on2$&###ZYw4fITr+De1'<3S=>6sG)'J3W#[]4<PsD#%f%s$PL?lL14(f)MCr?#sX.r8aa#K)Nl/BHERX/2ucJ:/mu[:/vBo8%r:#?,h6n5/s39tU3*Y<UZ?85/Q4vr-VSi/:"
|
||||
"#b<c4-[xo%ls>n&;[qu$0FLS:/.r%,&@ed)$QlvG@5uj)Oi3+3G0Z**uJMk'^@3B6.xl$,eAru51Qkp'&.-,*dLW)3.,RW%EUu^$sZG0(pS4=-JvW@,8PQc4RT8,*IPgf)3;N#5G&MP0"
|
||||
"U`2p/Qkf34,N_2:o76HN7.7W$]YO@,_NG/(,a'W$%'N50ohYgL_IGG,<;:v-2@`[,=bT]$?/5##'AlY#ID(7#Fww%#QYmq%WqRJ1`tC.33Tlk0[IBN(3pm;%`ni?#A=M8.cc``3eN:;?"
|
||||
"AWw8@k%#s-00J,;4YIQ0&Z?X('P7G`C)j-&JPciuqvC)*#BU3(UH5/(omLgL0G5gLMQ(]$Y$3$#E@%%#Uqn%#fKb&#Rp8X-@[v(+vuRL(QknW$-xNn0WTP$KC[/Q/:%xC#)vsI33E0N("
|
||||
"H1:)N]*WZ#1H(0aVHt1':Z/GM%7Q;-%#h3&F'Bq%n1Goub&]:.CCK?d$SF&#T=P#$b,`tL)V[*._1x+MPr@X-Uokl8JJK/)$8h9MO4G^#P^.3M>7(#&S:A2CmEx>dOI5r%:^iqM&_V;:"
|
||||
"i51g*lBel/a)12'oon60Jn))+`'fJ1`tC.3?l0x5oSEU-a1M9.F)E`#dDp;-JY#<-GOH&%H0B^^<5=E$`Ge,Mu%2&7&bsZ5oYAA,?J<MKYsslWoV[(6DE;&$b/<-&hpE$M$oO07*pcW-"
|
||||
"j:?NMCQFv-(oHhLL2JG=$,>>#B$k>dKV;;?/addFXh)v#`._f#q%KoMhC?>#[CNJMf:-##-Q-E0rB%;QaVS;-#'e32tYg59ZF;s%BOP]uA_$'Q)uCt/OKkA#Bua1uiRJF-[d'-%q%5kO"
|
||||
"vfP&#(K6(#=3CR0*_S[#:H%O(xNUA$6*YA#Fr/l'V::8._%NT/-K?C#ued;-1rru$JMQF%'1u.)M[4;dv<[5/H5_T%:='d)/OTF&*j`B4')?N#]_h[,>eq/3l;pNM1'A5/rM?R&*dgAt"
|
||||
"UZg6&7NF*+?jTx=EIIW-@NSKug0pTV.52G`4CNP&?&3-&?A/'H2Bx9.^1tM(b,sFrjv'Q/'ZedubwtBC/:CB#jI:0C6CBh5E8I/(dcT5',m?T%eee@#.N?C#qw6u68AB-QI`_M:lpZEP"
|
||||
"sTK^P9?%RPLu6j:kmQEPKF^w'?7%-3KV;;?J(WqgNt#`40<t4SYG,juMZfF-)dGW-^Wk2DNLZY#Kp+)O8pID*IF)?#h:VX1@93/M]VXKM_oX02SkIJ1lF;?#?W$9S$tn=GE$M#$Q#HpL"
|
||||
"<D%/O(n)U/[[2Q/8a&;Q%a3^#RWU@-nR.K9u?:@IY3E$#;P6*<TH+O4hKr0aWl;;?xpSBZ,K<@I_3EiM(IkB-/RkB-,J'O.kE$`4(9a;%a0x8.>+nDS2BI4=E&=h>]^'Q/Z9V;-YOho."
|
||||
"<TqA,B/^q'%vGA#gEW@,YG8f3vf%&4O$/i)cn=X(eOnH+s1gF4`XdB,1>MZu]8+-;]kFF#'''k0[gX7IMhIw#Ri3+3Og<X(+gpk9QrD7*416AO7CsEI@cR30R,Gj^]9kT%d`>qpfnQQ%"
|
||||
"e/0i)(@n5/6a=a;KfZ_#4p#g[oEkCWnP%3:)puH;f3Yn*q=jg.:KVK2HR+8&5R&/1t.b8/mRXR-Oh#L/lYWI)*^iF=t%'Z--nii/S;3,)s<RF4#pMB,1H4Q/m$UfL_qtFb-:jB5l.$vJ"
|
||||
"2uY<,7;IwPvMc>#^XL@,709JSBlvuQ#sj?>drN+3Pr3&7b&WF=b'4fur>gf)?N=v-=Kjr7wv#K)LVsQNXSlwPPaE<%%H>[01lXI)YAOZ6#FPcMnGkIdt'e'Jh)MUdPco=d`X@>d_d?]/"
|
||||
"NX.i)Oi3+3AS.n/DEaP]ZkIJ1Bd]N/:2Cv-6I7lLg%J#/Lcp77DsX<h3KKwMOw^A?,C1na;s4T&x6v^]$@O9%(iNn0L#>u-=Fn8%$t)Z$<QJ&OvDrkJbb>a03c7uQOP]'RsxS@B+w<2C"
|
||||
"$eXw,3d]'R]'^F-LvKl3WU'^#87>##;(V$#QJZ6&0;5##@%Yw2(k^#$BUW:.eAgI*074D#;9ovektS9Ce*loL*uLp.2w@P#gO:1#/s#t-AQWjLA1(?-G-ml$c#[]4bQXA#`&ID*bQs?#"
|
||||
"(LA8%]CAC#kHSP/GI0P:?fHC#4(=(,wB3r&PC:*31Nw+33Ij,WxMvuJ3)WVRh5l?-mO4Z-Nv4wgwMPT.,GY##TFk3.je'dMT,AX-<<xX-c#g*%k*f%u_I,;Q'rw^$`Pvf;E9Z.6aq#.6"
|
||||
"d*6.6Xax9.wF5s-6/XjLdX2DdG*B_8%oK^#_.kFdx-Ns->0niLBpID>e9+@nf*,s/aNP;dextBCY?:@-[x%d=<x&#_4:ww^.oQ<_G.4[^n,?2CDOUEn's[j0Kb7G`%K>G2DLKV6dl5D<"
|
||||
"-W<T'5ek#7T#=i26k/%#>Q@k(4tFA#K;gF4C'+W-`+[^Z2UkD#A.xJ1u3YD#o]d8/@jQv$0/D_&(C=m/H,Bf3Pv@+4*ZKW$RbZV-:'ihLO`6<.`6?8C&)$?\?Yo-x6KZn^43YAA,4&huG"
|
||||
"]g&i)#VWECnp@A,Be//1?`wA,4lW0R8MnA-kvjS8ln3B,mbX9CkF:@-bI`t-[I?M93+s20jbP;-3xqr$4FG>#l7Fb3js&i)I>Cv-s$gM'OcO4]O^>r%3^lSdq_adth<e##E@%%#6`gT7"
|
||||
"l1oh(KF.<$^&ACmmE<R%v-sV$95<+MKDlh':E1qLZMCsLb7cB,H]0hL6w//1g0Vk+]gK6/7rC$#0KAN93TkM(GPS8/nr@B=5bOAu&J[n[d2&Z$tCF&#b(p#$5FNP&IeJH*)?[s&N:+A["
|
||||
"HdF)</.'Z-^I-/:#@-$$xn>V#fnG688MFAu.Zo?NosS9C+Wq-$,kq0Y5rJ&vJao,;#(C7'I]>c*ed^6&Y'fJ1`=K,3cX.f$^#lP9TAu`4/I#H28)qj&s8Kf'clnP'IEPR&-<m`-LH.wI"
|
||||
"mIAou)ouN'uK,:)0h#h1JL7%#R,Gj^x44.)_xefLa#1i)D>`:%J#G:.]L3]-kDsI3d,ID*dkS9C(8_33L#v20_gB_u(%x)$>m;U)Y12mLS2sFr,bdt(LF.[B_Tr22kHe##IXI%#.^Q(#"
|
||||
"Z=sd2PC:J)KF.<$U^nVoVB:=%iZeF4uP2)3i%7V87:Y)4/D-HN<&iM'Fvnb0O)cB,4&Jw#R>iO'Q'4$6Ga7#%-DDJ:j'VhLirMP0v$C>$lD.gL*kC80AYlN9qjTn/3`($#Fg99%OT(]$"
|
||||
"K1>u%$CZV-1q//13RgIh(17I$E/<v>8QX]u.d*X8AI]v$d>f;%XtRb%]:75)Vi-]-(^&@93_V;-YG^e6J7ws-f$L-MDMYGM_0SX-(=.p.n5UQ/D/)GuI/15AV?96/3BZ=Yxo[F:HQXLs"
|
||||
"Yw2$#/h>%.HvC;?'*Zg)n.rv-dh.T%ve#`4lYWI)QNv)4%ZFW#o(p^[2I(I#-l*#7Y<2.Is;#eoQOuf[c%q=?;5T[8`6gM=>-Q2iiO2G`K[VV$7Rjl&FnfL))?[s&bvY3'CI[s$Y-oJ1"
|
||||
"E=R<_2pDs%*$[g)mBmGMN?H)47p&;Q;GB0uwRE2CsIkA#NKX_$>aKs-8(P6MjL1_%D&###aMwFrsqou5P']m,'fNn0]_OF3JIV@,M$g://]v.4i'mG*e4B>,j^Aj0<kY)4ax;9/Tn.i)"
|
||||
"RJ))3wc``3onXj1:s?^4_Bq:d$PJ@-xq=K(NljE*b<bc2(3D1;8uO]uFf<C4](e3*4`[?AuS-*3;1(p78]F.3C;TBR6%>H&Ul68%=jQK%r$'et1-;hLRZ/@#$#bIhP$+W-U9:wpx215M"
|
||||
"t'918/Tbk4tJ*B.^,QJ(29'.$Xd`#$XoI08&s9B#Lu@P#h(>(.p9_hLxT?R&=.:%/bfQv$&tc05&1=]-6C_B#6G<GdT4Nm#Dvu8.cYxi=+'a216a.c%f#ak=dbI<$RnsK)_;W.3^J)B#"
|
||||
"=;`C&I0@)KG(@$g]s9wgaGA*n2Lh'#%&>uulY@)$U:r$#7Yvh-t'YKj*$&],+3j'%j7o]4apCg%q]WF3;X^:/oNv)4QdPw-L%O;9`H[n[ww:v/,FeB,tKO@,ep3$6vqf5'nBI(R>Nuf["
|
||||
"4:#mFxCEZuG5EC=S*cB,vj%.MMJ$291i9^#q1:kFNMY>#=5^s%2H`hLf%f^$2om8.]^C8#Qnh9VLVUV$i8SC#(<0/1$J@;?p/W;-jWGouR7Fv/Pb./1<)sFr^n-q$NsLB:K(Hg)$%nhM"
|
||||
"0U.Pd/A:.$b)g;-w#Sv&R+no%:x,W%6oiu$/%@p./6tM(.@wq$tTQ^#+r0Pds@O]u@#pG&i435&<U35&Q/bT%-Duu#,.aV$6<Xq.aXa>.>c5g)NEFs-_gPS@:;xp&FI2Pd=1.AMUV7>S"
|
||||
"un$W`w5V9CQ7T&#h-7m%qnrr$>i7@%PBBN*#DRv$t0;W-wod;%m^D.3Coh8._V_Z->-w)4D.7x67gurBK[3Ib(/&,;MV0?)<-OBkvmYf>e_VX^m'1,)0D>;+1H:q#`63.5($(U1roT3<"
|
||||
"IA]C@PGd2CKoxEI.*nMjpg&%#6x5U7n+oh(qe)<-]VsR'e)ahLKZP8.$ed19p_v;-Bviu$vj4N9G'Z'?>IKC-#_@S/j;1g:?@(XS<U?a$K5>_?tor#($o@g:1gF>d_[i5r_A-$$LYu##"
|
||||
"FdS2^Crl##9H%O(J%1N(m`0i)x1tM(Zk_a4U&>;?`04]<<Lt2CP#=2C*S+RNPjo@S(9a=#95>%&g&p%#&dZ(#:efX.mqD$#*crB#AY>v,YLU8.Od5,2]AtJ:cT3T@D&Du$@]WF3cb(f)"
|
||||
"0Zc8/xS#8RJ40:95nkp%;Omb>igZKN>P9L(44'k1K_K6MYsslW)aog(:_i[,p)IG=X13G`O39Z70$Qn&D.4x71Y=)-G@-u6KU4x-aSDe$)D([,.rbi(jEelL+iZY#kSuIU^CMc`j*io."
|
||||
".Y=W.9offL&(tu5kiE.3[Z*G4AMbI)#R6.Mp?Uv-&cUNtQ/TP/>;gF4See@#v2=v#RD.l'ncgQK=SHt7prgf)3lW`uE=AX#TVGe)B[0DLu33G`))[#8xf8qJSKOW',rKJ)=CEL#FRGE7"
|
||||
"tql?,Du5]MwY1f+TRQ##XmWF.4MG##Z.n#nW(hh&fK8<-]Cex-Ap/kLfQAa+pNq12nS.d)a5eD*jE7f3EsmC#2RQv$KVM_&:OQ^+IL>n0/[?U&FF76/5vai26bZIMaWPv.5Kuw'#h^>$"
|
||||
"jP$ND.cTs9FnNp1ZN%q/7kgv7[RiXu>['jC<;v<-OH(5'YsrQN,GkWSF&oO(:76g).CwX-DrS9CYI[i.51Gou46E/%<gOSc'cWj&%ZI*-PX=F3>GVD3<Qwb4-Pu>Cnn(ju%'DC8oA5>d"
|
||||
"Kn6mA^I6Z$(rQ-HmA4K3,0fX-H_$gL*]d8/sRh`.N-v7$hXWY$+w<2C)+r772=hf)qx8;-UsgY>FPaJ2tKZt.'fNn0=R(f)YsHd)7>1p$V>%&4&=(u(7_Aj0Y$n;'&QVA.OGg+4GF[?\?"
|
||||
"]g8P133'#*)LwLM@/2&74jj6/id1*3URQ;-8khh;$p8?,%>2e;pFNPM&+*#7;Lo0:X(Z<-8,pL:8PQv$2+:wg%&>s6t++E*$C;W-NZAX-ia&;QK=S?SF5nNSkko@SbCNJMYI(q7.uR_8"
|
||||
"`4`v#(iNn0)+niM^uQ2MgN&;Qi2_$9,lO]uKmWnLQE%q&=M.>>6oA9=AZ$B=`82t.$5K+*X:Ls-4h&K1`1[s$q[2Q/$8^F*rHNh#S5WF3NP,G4hO=j1HZU&$ZktD#5>PjL=`n]4pqi?#"
|
||||
"H&,J*/]&E#AIwZ&#s<h<PaM4'*4$O(FEPN'm4#(+:LL;&E9gq%/i1E4>E(1;>'SD*kZdh2`Dxu,mpP3',XTE#8O*t$5`tFb2_Nv#nI3p%YPw)*k9ob%$XA=1ruVs%a7kI)@=.<$kGiE#"
|
||||
"N4GD4RSE**[haR8;0h:%71#m'N1gT&f;m7&Ze7W$TmLg(ZHj@&W+2?#Mp:4'M9=x#%Sdi&ZFNP&DTo&Cft9B#jPD<%TbsJ1'<1^#_<m=Ga:)I#h_/rB.xCT.dC)I#Ulu8.3.`$#v_B^#"
|
||||
";r_':cKQYS,v:T/(N#,28YR]4He,87UH^#.f1))5EK[L2%f8q/Z)l>-:CHc*qsJ<-hHFg$?:fpg2-RAOi-5.Vx^WR%.eY9C%mD('cFM<-;^TV-<KtglJFlW?62vG*&)t.dDjZ-d<pW,M"
|
||||
"jcNK:SK4Au9^)t-=1.AM2k^KOVj*J-hVOJ-S@jM'''lA#&K-Z$3.5F%F9OW-n=.`&i<F]uSwY<-Ot/gL3S$m8N(:7'^CPV-XK+n,gBFt$)lNn0k?8m85dTN(]SWF3]+:]?q0PCHuG^[#"
|
||||
"Tvgf)QQR@,ZD;;?g$a?u3*&v5P]sD3U%-w)tWS@#@nh(*iip[krQSQ,VHf;-Dwd]/k(@D3LXDT+['uJ1.;Rv$BxF)4TMrB#`i.@'3)4I)5Djc)4gE.3jLBk$dGG)4[V)60B>'i)56tB,"
|
||||
"M(w'&xOO]uW?DX-2'B(&-C$_#wkjf)-pQ@,2W>W-u/KF%3.(B#j_n.M8=kf-XLL-Q%]L-QbiT-Q8n@.*u^Op.jAqB#aU%LGDF,gL>fxd;]Fl)4fc5bsDdQ]/$'Cn)'<)iHRp)IHIgdsL"
|
||||
"T;I]MOjNg=aupbu,6^gL5D6wJ>%r;-Jr+G-Lq;Y0`qIJ1tveF4Y0%.MiMC:%HeolWDgC5/^%AluJ<cwLI[qI=j@[#6$,vx=Fh6gLY&_mA2VLv%*<x9._HF:.>T&;Q7CNEdqDDe#b?^6$"
|
||||
"w71Pd(l*3ia0E$#JepeF9HAX-*V3D#?Kaa4o4P;-uYZ9Cj)?2COqf5/ZQdduCLk%Mew%bO>x2$#u'B?.CfP##$#d;-=5ZX$[aoI*]kbF3]%p-)F53.)62m'=WlK#$U=#-ML(i%MOA#I#"
|
||||
"nPj#$A4f:d&?-9.;M7%#o&U'#,]ZZ-^L)$#<Z[0)lw6u6J]B.*-<Tv-*Lj?#f1ie3CmQv$^^D.3k=8C#tBo8%gYiM1'cl>du@cI3,o(NE#Po'&^)T1Mf;*i29Q4;7c'(E#ANp;-PwNn/"
|
||||
"MgAa5balSVO>.Q/P0_C6AWae36C(C&G/5###oKB#,DF&#'EEjL?YqU%Y]J3%;cLs-aSV)3ig'u$?S<+3FLRLMIU8f3w<7f3owsM0`0S(6]u&)GiLY<Bm@j;7c4.1MqeP;-*[9%6wP%a6"
|
||||
"3::e)[*%u67N[v.(q3HMikT]82^03(9W?K%Q93-v7*7g).$$E3m>sI3NY&E#Z%#Gr1qD)Wv^m).Hx&;%Nx<2CFm70C?\?1(q2:d*7#Xc2:Ti>g)6sLlMl0.q$e6AwY2^P[PAa;;?enPE>"
|
||||
"(cS,&01em8Q``'8(8F`S<3KV;0M<dteWj$#OdS2^B=qp7p-m<.3,Jd)]_G)4_V8f37'Hd2Frj2RMR7m'nOgIhWwZ>#S)oShe#s%gvs4/C:12,2>Bfq1%%).M%DYcMWg;;?[75;-CdU&,"
|
||||
",h:_A2bAW-HXKZf?dnO(/,-J*AeL`$/DZ;$x,rFrXkuT:X^d4C`,LEdTCYG,qA6FS2=hf)qq[d#Gi<?8jPC*6Z[?##;(V$#PDQ6&5a_m/X36H3VF3]-`(`5/$tn=GUM6qL=LL?d,:-$$"
|
||||
"&.kFd>VAt9<NN)#'/###h=PxtIMMJ(.`JV6+522'PUX[7T=(/)F?r`$l]B.*1Wj;%I/X'%SSK5Bm;pY(uf]Y,LVZ9/eIfm0+LTfLvO5J*2u%T.jAqB#1Il805cVQ&q>6R&e^B<B0N&;Q"
|
||||
":s,W-/Snx'@^s'+^I%s$sMA@,g7,_+Br$W$+'&gL6hM@,b.$$J@%uAB_m$%'N3c%'Z:U>,jvOA#b`vn&JCf*)R)cB,]7s^oQ>uu#eBF&#Od0'#oLXs50>cQ1=G5##=Z[0)okY)4:Z]F4"
|
||||
"(cK+*x_OcM&t'E#x.<9/8C)X-fpPA[Rp7jL&c6lL#0E.35MI[')J+gL2a+c43Fa$72r.DC*Pr+M>Up_4X(';S+RM@,FQTA#&$_f+Q6@iL^^Q-3cF@q%J(oQ-5W:V%sa;e33a_`5a<=DC"
|
||||
"tT3>dE-lV$8wMfW*+n@,OuH6S'8_],G(hKMb#<e3Z],@#.TW'8kT6%-3gc40udp(PAR&##%)###QwqjtEUai0*jTS%.E-x%)iNn0mf4K0K_`8.>;gF4`m]Ku[+'b?fo+G4X_giBJ[lS/"
|
||||
"ctMm'P[cQsYx6W-VU>qrSK;^#X]J$pm2>w&]3FX$jt$A,bs(k'.e3.NO6Q$,UG(.3AV)d*m0V@,kY[-).UwHN<CUf)-_`3t0<R($@uvE2,W(v#8=nS%-bi[,;uL;$``F'oS#Gd3=F=gL"
|
||||
"2%52(8UYgLL8,LN5`SP':,:W-6wpgucHh@.Jn@X-sBj;-9a^s$J)Z20$#bIhFH*;Qu5p'&FKEx'00O$MGoU3C37PF%MSl##./Sj0Z42G`5FNP&M,@D*fh18.(N#,252Tm(u4eW.D[Zc*"
|
||||
"j,Qn&9SG##@Q@k(#dCp.pN7g)Mkgb&T)cB,@qa>d$jV=YDmZW-?kWX1RLg+uKI%>Qx$EM-+61d/IIvu#3wFQ#K%9g1oqP;-K#adun,f%ut1c98B[X&#-,K9iW*+T.ElY##>]&(10ImO("
|
||||
"ij@+4auRv$#@F,4Mk5.I=Jr@Cn=#AdU_iM=M&CJ#':Po(P1T9ChDUO&9&:Xo)sLh$+6)Z-hfDu$kDjB#'1Lc5wo&vHYA,C8v4(_5-+7f=-YV(ZW4a?>^qD<%=5gF4c<lA><J<?Q<.R?S"
|
||||
"%-/Q#@<^;-WiE30g.(bH/Dv+Kj/w-$br^+>?1DR<RA?fX39MhLO:pk2]BF:.&cGg)m`0i)2^X2COZo6<rOt:C(23qL;A]/0pSaIhFY?DCP5T;->$u$%&WO;-BjTP&B[RS%RmrZ#(iNn0"
|
||||
"q3P,MRT8f3Y8mA#r8oQWXg^R/eJ0Pd#gL*6p)M*MM4N*MZNt1'-2O$Mq&T9C[PbIh3^Ps-L5k+MHH6uulhP;-`U18.>gQ#-%ua-?=7H,*jPe)*ow3c%=CAC#DOi8.'U&@#J29f30d%H)"
|
||||
"*t%s--sxs$7)(=6@rFq&6l<d;2d8T#eGv+RrkU/$NYwi>pUHh,^26O07+20C1#kjLC^GrHoV_'R;FG&#,0,t-#L$iL<N]L(LeCH-#7w&/C7r?#41X<8W<orsneKD?A<B30+-2QC)Aa%$"
|
||||
"St005lZxF-MaI6K6?TrJV<2.I#S.3VB8xiL7Tn##a^''#I`gT7IS($-cEk9%*oNn0>0;hLs,Jd))afF4EZ$@'vKCo0o+`^#D.Cv$X>a(66hQ;-XV>=lFcof)f$Y=Yo8Yg$LiY,Kh=+9/"
|
||||
"DX=r/e0P[$snP;-f.vS%mH-Zt<E&;QK.xH,.n4&7tS2q/c=-a5)[Is&A/#2C'7O2CI+M3M_uT2^SJx/&>ImO(.@cS#GJ(p#Enk$/uw(##TQj-$cehZfWq;?#UZZ;?n_oF.Roqr$W`qP8"
|
||||
"Q@dV[Q]Th#2B0[M^eDJ'$Gb;?pFqB#W@.@#$'CJ#HSGJ?e]O&#b=Pk%Wg@?$*;YY#S1U;0e%l0M+b;;?Vs9:2rvKLNOUZ##EtTs'1-;hL6aA@#`r(kkv9L(ARc`:2mLm]ODknO($o%2'"
|
||||
";6jl?&G4Aucr?T-d$EE%4ctM(Ev>X$;FV@.PV?B=b/'Z-cpfZ0]Xj=.1(^S#FBlo>q/#+%/6B2#T++,MkeP;-:ar;?EdkfGUJK_%/XSHc91lQMS'wIU@WK`apr.;6;hV/2;s,t$w]B.*"
|
||||
"]-'u$Un0a#Mq?jBP2QK)4(7]6gH7lL$KMG)sN_hLREfX-u3YD#aUp+M=)/)*HH3$6puxl1ULY>#=<a*cOrcB,$_I70_2n+6$N&+QOg?O$Tt5;dKJDW-8biV-=xG>,jBhb=>?l132=hf)"
|
||||
"'RMx(q@K60,YpBX;s13aJ:?>#gxqs--d0)<J#tY-CgrA#/a3b$M6Ts-?\?<jLP.1Z-OYC]&6_Aj0(_JJ.oNv)4V%%aED-PEt?JxCu?W;3CetKJ)s>W]$h)*e)adwKP$.5nWHgsKPm7m=G"
|
||||
"sOY-QUt'3$AB(7#,Fil%BY6W-j9uBA#f+D#0sqYXG-Xpf%SN/Tc#Pv7CU`UI%k9xLI%###wF5s-e/O$MrQrhLhn(-M3uID*ov@+4Nf,lL$k3Q/UP5W-jkx<(v:+5A7uMvL/xocMa:2G`"
|
||||
"-DR'OK?CU9o][A,%fQ2(4b/O(0Zc8/HjE.3%q]8%MM?O(3dO;-SuMD?=[o[u.26(&io3=?N_W;-=KeA?:3js%#5L^uLJ76/%3uM'OKIIMBt;fUld%_]U8JwB8@bqg?4aY$+%^=7Kwr?#"
|
||||
"0S<+3MPsD#+IA8%J#ID*,+:^#Ka`6N_j5D#PRC16bR2o.W;LpA&H$9%KlKAt%1@A,+lbOoi0%f3hgv;Hq9<Cm+90)*X*3&6q/Qn.XLi5B'EqS%I>XDs#)LA,/0_LpO6*f3W4OrLMhgKm"
|
||||
"/2`$#>@<9..Sl##/It/1jH3Q/fU:8.&N1Dd/NYS._J@5$Ii5<-+2)2'$RCG)lNEM0%'%<&A+Cf)EcG##+crB#%1]5/?29f3^*6,MgTdP.e4B>,7u>X(>&<+3G@oT%5H8f3k?jv6,:tG+"
|
||||
"o;An1//DH?Rk)d#S>1?dn3A+`O#N$.+4J30c#HMXRpRQ0`o=8CQr,[H7uw97%3)6:wAi$>'vus-fR(dOg.:a<mUve43w?AOMgSV6`xn<:](&8q9F7.uASS;-W<ZGRJnu?CPn+2=[KA(H"
|
||||
"2lMY$>tqFrSO9MB:s79&b7m3'h`)fO=2:Z-F9B+%RS/H2oW&B)%RM1)6kjNL]PMP0^SY%&dfv1'GZWCj$kuY>fx;[$Hm$)*L4:$)G.Vv#n6+T.-E?A4)T9s$4fMB#?3Gg19[oC#^RS[u"
|
||||
"4rpl/Zw2mQi;8/(LrsGhfhQ;-D7_J#11F7)tZp(fW?A3g2IK9JCao3%C;Dk#ID(7#UEaP]&(;]/2[9&$,CTm/_R(f).73Q/W:`e$@DUv-?]d8/[Xxw#iN%;Q2=hf)t_6$6[1+51[(J80"
|
||||
"lL&s$X#c]#bcHs-I;:-<h)r50F@dY,q@M<-j6We$Z,g;-6-0b%NRg(Q%G%C#Jr0[%-'k=GYS`m$Ygh>-(7,h%6ImO(4`%b/XRG)4:AK?dU]Op@P@Wt(29:N0XDF&#D-4&#@Y:l95Y^-6"
|
||||
".p[D*MkJv$&O(02qNh'HVIR8/OM>c4o6T9Ci#:9AM68p3/bc;/wwpouVuP$7U2t(G<h4(-91`'Rlg22D(q5(-t:'`QM7`P=+WvNFLNPN09@%%#Q,Gj^..GgL?7^J1<5'eZ1Ar`FXq*,4"
|
||||
"IjTv-`aoI*?/=>d$tn=GR)Bq%.sV=Yp/R['?T3>dw]I7nr2</&fdc;d+J*F@-__$Bpi5<-92SB.;%'h(]:nW-vP8-u>)0i)<W9.$nj@e#RS`du%k=DC$fB^#QgINMEaIa$J),##^9)8$"
|
||||
"U<_+mic.)*W+]]4[*QZ%JRo8%Tc:Z#Ei?<.V,ZA#]%-29Es.[53B'EY3d$=/Xac_=V8w@HP/,j':Vh3?;a5WRYG4=CG_(T:IZ1aue)q%[6k:d2+5t9Dwfx9D1[sr$N.2KEKPB.*[hi?#"
|
||||
"#,NF357[x6[bZN))c7C#S'Ig)dk=X(pu8f31m@d)nSID*-%1N(5Llj1(7U`>#f[w#*CAu$l%W4'AWio0lV?;%*HW8$rN$ENF%mW-1h;N,fW2^#Soq68;vv$v`=At#a(U'#fdS2^7XW$#"
|
||||
";Z[0)1RL9Mc%g<$D.Y)4#,]]4(R7f3_Jp5AYFn8%CP,G4L#G:.l@h&6]?wG*^Tbp%Pp$[-YJ.d)@LR8%gTl&>bdh:%Zj::86k@e#S0P%?ZhN_,$(Q,*@:Z(+ZhEC,U;rG)cxN**5'A*+"
|
||||
"ZfrL1G9=:8ej_<9w5-%-H?[i96V22'dA4P;Ar3X.oCt$%4dChN,ZGg1AG+jLs:Rv$0DHb%/W8f3w<uD#.B8$&wLU*N`$o>QO(g^$/N]O(*X/A,7PGk<Lw(A5IrdM=&Qg1:>l*B,91Jh_"
|
||||
"1rtA#n-[F69bi=-)Y8#%%9ve<EHDr&YoBj2-BHM;`ATcGLVA>,mE&#*;a%=d]d`oA&a:%I-rY<-YwhQ8mAT;.>v:Q/xrZ&4nQXA#mJvJ1'LA8%55%&4iCAC#o4/B7@N<$6GM1Ddh10H["
|
||||
"&..Pd1MBDXp&r3C*cF1$:40@-C3A/2e:88SWq,IfiBj*%Isn<a<BsYad+m8])0KfL2=LP8ew^#$J$ok9NHSj0`N<P(p@7<.vu/+*T5Du$IU13(8E%8W;]dIh4hC#K+.VU?.MU7XtuW;-"
|
||||
"9id;@U&@#MDvEW#:,Wl=wC*-?7huM(.1wX-MxG>#Ak<PXnK[h#OUvcMK''P#vUJM&#ITa+:.OF3)DYo.ZcRUdb*(m8cKW9`%0S;-[PE`N<dic)Dqa?#aZ'r.gUMW-<SEL5:)ap^]q)$#"
|
||||
"6o/k$/k#R&Xw[J1@SW@$.kE:.K?#<.BRKfLIVOjLrND-*ThWO#leFHdT+U#X7uj>dodG%I9mqlKtE`?W(H0IV0:(Lf+hB'IWR#S&#C(,)b[18.%'%<&5ckI)A]G##=Z[0)<L:_ALR^fL"
|
||||
"fEPA#d?8d3W6[UT..;3a27wBC(DeLJ(8;=C7@Ga[$Cw:0Gu8Z$&feCa2*n_VTF^*nL'sGCo^5`HJ-(k&9D@j0SEaP]ckIJ1M]J,3x/_5/9`p>,VCs?>/>uo1NXFb329$C#mS=`uM*cB,"
|
||||
"oWG80=W3$6DC5-2hX6#6lrfs)n$wBt[_:$624L^#XX=)#o_d;-L=2e$'a8>,PkVT+BSYY#39Ks-5seC>h/>)47?v20BsZ&4vBo8%6VA1;`I,;Q'_>]u.ob318q.PdYkZ:([v'k#Ohv1'"
|
||||
"Fd<U)8:@5/U'xU.c_$<SHQ6=&&'grKV$WZ#fS6g3BgdC#D,_^usT6^gWNGFdt=(nu?+hOdteMGZh$,qKfW/%#/S2I.ZXM?#*gJD#6hX=$kpB:%X:Ls-i.<9/g]7Y.c;R)*qO`S%FpD9)"
|
||||
"kmTM')>wY7el.[7?R:F#C(ZCj^0v.3r^>r%xkkf,8>b:=AW[128wZ7-eaCo@OWe>^DKd#-sOQ-H7q/W-,hrR8[,lA#G[+Y$)?PF%Q0'#A[/_#$0CpFCUxT<hh&eA#(JU5'$fTB#agfI*"
|
||||
"66;hLQm`a4=dT3C_Z3>dg2N#$Df(T.3tuFrpD5T'd:35&CEcf(%'%<&[WpQ&Nhi2M@mnO(cFGH3L#G:.#&%Q/1r7DCUeRUdRY0[K20Biu`4+Aux$jrF;,$eko_g1<++pE@#DSq;;S?>d"
|
||||
"DA-D-FdC>8lpBmVREIU7IKh;I@^2<%-xNn0,Mp+'$,-J*)vsI3>I9]$,'30;PcD218NY7I_iq&5(p(;QX4;f$00O$M$R>L8k-=2C:L3>dw8_+$R8La<6w9B#r]i,)Lx$m/:j8>CZkTIC"
|
||||
"o:gV-ks*6L5[.Pdo_A8#.+SaExR?T.jd0'#4pm(#T%T*#(pkn8bVTf3w4eW.6itI)KF.<$/(On0xJ0s$-Q'<-)noH;HBIT*#7=.-F3OZ0O)cB,VR,W-lS#+%)[txW+=2.Itn@&FBD4Au"
|
||||
"qCxfM@fP;-tNpA,tC`e$$jE_&uh1vH?JreMiMrtOo3NK:Som_#XDF&#E@%%#S,Gj^pVr0(.j^s$uS52=34pL($A(s-R&SF4#':Z'WO2?u^GwM0GbN?k(C.>6:0niLPJ=jLiK/[#oxBI;"
|
||||
"9rS,3:wd3`g-I##BdS2^4D>##9H%O(03HA47FUhL&5oC#D6&tu&VZTIcm'^uY+'U#3CU9'Gs0&=S8-?\?1435&[,mQWh0bT%bvD#$@@.H3Q7qo.GXuS/L-YG%<j5/1wBw]-LW1F%a,bfu"
|
||||
"jn4[$rRcIhWQO>d:ThxM>rmh'*,pu,%'%<&eWAW-]VT49m:ge?M$nDNLt2.(Aa2.IRjjrq@)#)>/Gj.(Vf9vHuDPn*w9m1<BC$_#>[u##EdS2^wVvw$t4e;%VRG)48'lA#DX_a4%#q3C"
|
||||
"]DwFrwxxa#_Em=G8PL6MLnx,VR#O=(F`Aq^c93$#IL7%#`bkh(Z`#&)&*nD3BnPu%F*kp%^/p5S'9]9:KO1/1U)6<-+].:.tW`-#6,NH2KEaP]_kIJ1@16g)w*gm0dG`9&wgx9..FE:."
|
||||
"_r0%6kUlf)L6#53kw*B0_CQ;-NKxCug1uV$T$n#6PEpOMB[vY#'`87.qjQiLX5P=$Tr[fL<knO(W=K,3he9:@bb5g)-24m$=FS_#MGY2CZ.15A,m7I,Vqd[,;O&7/=,xr6Vs$21QMp=G"
|
||||
"(6B]uOTM@,d*,5T$v`K(tj;TD38t9D/9s9D,D5;-OG[#-.Y]fLB?@A4;'PA#YiWI)N_h&]cZs?#)CuM(xQ:a#2aTb%@rJ>(%seh(5qUJ)v>^c30C%X-cl^',K<Y`uak@e#8Z;v#Qts3T"
|
||||
"aCOC,/U]w:sH&;Q+^>[J6_r=G:1PG-[Hof$9REM0`:t;.2VJfLG7SX-1(:+*]R?tJec]+4wVp.*4+h$[N_j=.(0rC$G,^w6%4^S#QFD.*[h3LDVCi2Rva)re&YiPZSMuFrt^#l'**Lq%"
|
||||
"S>4G`HYET%41*I-1O/72D1IE5704mQ-Xuw#@awX)0@lm'L?^<8mIgZf^gO9%)O$]%I>mA#2K4L#5m;;?[iZ=YBul=G$jV=YA<pHS,S`du%8V9CsdVU%OYl;-jf[m-XaI_8l]B.*.eBN0"
|
||||
"oPVD3;S<+3*akBO<5:Z-tUXEeq645Cu3`19'gM*6o(PP0F7I20%RM1)UZC80bmOh#]PbIhL?R@,`f*5AIuN#-U=*OWaEj$#Xq$*..C(-M]-'CO3@Bj0LNv)4]MUM73vOG=6UfM=`ZW>C"
|
||||
"$ed19avj=GAWD80$tn=G`9#j=w[)_f-u13Vm^3$#^Kb&#B`gT7?v+B,^wnW$*oNn0]K)%%Zd*P(d+8`&3,7`&5ptNFd/<-&vX0^#0W5W-6q3+%TEKNrWtvYuT(;?#HYYF%mZ&ZulT7U."
|
||||
"a0j=GTu_H-'NA[9j=%a+0QSn0ji),)$S'41TH8&,2xg%%_c^-Q2i:8.AKwUMe8nqMST3F.?FYI)Q#P)4XIVp.`8i;dd*3I$PUSCMbV0K-Ag=,/xZ6/&n=ge$f>s-&/>i,MfER$&V)f;d"
|
||||
"'41@'_imp%Pcd/:q;h^#87>##9hVr7Fa,[-njTq%-M:;$eN;hLq[3r725Ld4ukP;-n-cp0,s$&4oLc'&*rB^#?PH$8^+Na,AX,hL(-[pgPGE,#PSuD%`=K,39sZ]4]52T/&@Rq$rUFb3"
|
||||
",asFr<o.qL0whf)a$M@,cBYG,2>bduvuMvLjmS@#+.,59+SJ=%dhLS._,$h.^LVZ#)lNn0-%.+5V`v[-kT&],Enn8%O=Y)4wHuD#v.<9/tgOU%U`G>#'6h/N7l5/1PcvsK*=4s-hN<r7"
|
||||
"'1Xg*L]rP0UXtUI7`d4Cd>O'gL/m/C2$).P`YP/CTCRr8RMB58uVZ?\?Mn78%:CRS%366Q8]`O_J>,guC(pH@9SZK<-Oe/;%>H&7WT4T&#HYTd'&fB9rp`UWf<;DD3/?ID*;^9Z-f(]]4"
|
||||
"s@&d)hJu-$6LhF=V765/.?Gu>V465/F`R9C-1niLpXn'=D(`4)-U%Zu33GouI(*kNmv2*M$tv##'X6iL%pO.)jH_Lj+wn5/Ak3Q/`W]I*=sG,*Z96a3mtIpYRxed]@86M?DrZ4:Tw/I4"
|
||||
"(cKs$l=i@@=R[euf5*523C)-::KF&#qt)W-1;b9D5DPV-T9om,NcYY#TCTfL<,OF3*wRa$)+&s$rTZd3b@u)4+Rw.:XJa`#0LQ3B9978R9j._u?5?,,,i:8..pK+`Y+Xj$::h0,CjTJD"
|
||||
"P*U@k$1P]>;>WJ2Gk<MuPQvt$N&###8&M/(N+FD*pk8K1;F9a#AM>Z,r2Gg1Y5#kkf^#;/+gOxtq6:].3fWiCR;dc.J>V@uP<[:t9KCR#Gv8h=Ed[x+:[K#Qw3l-,SUY$dp2QD-*/Zp%"
|
||||
"7L[Q''fNn0RsMhL(mUD34WFL#jL3]-``1I3(Ci;nJj+ru$,_^u=W/+%JTW;-9Ib2C(q0Pd[Ln;-`b(g@`CrT/am45&O[l^,tGn,Z.s_A*[L2*m%],G4$L[+4p/0i)NIHg))wZ)4Gt%s-"
|
||||
"*^JW$<Utn%V:.%@J@?Yc,RhVD;>tK(m-2hPZwO3C#-grec;uC$K8wp@aST/D420kL2Hf'R/ogJ*v:P^?f,Q_/P%5p@Qk(T/uxmQWl/]VW,c5g)QO*e.k*_^uV9RH.jZA>#ma;C#aOk9&"
|
||||
"I5ts'alVP&/.=X(,3cv*0NcT.m=V0$V_`=-Wwnf$P####'>uu#4#Z3#v6QtLUOvu#AbW3M1ilS.&?F&#D+2t-[.JfLf:qV-6680-XEM_&5xkA#R&+>.F.$##ejZF%Bk60Hi^u-$&m_#C"
|
||||
"NpaR3U)'#_rvg=MHu)?7]f`;Y8NkfMB8O?R4IsJ%JImQWHqPF%5lQ78Kqe`];>%RP@q44N$en]-3I^l4[1ivPx:K-MF1:x&mp`gL)7GcMZaA%#r&3aaaBV,#4e53#wDmV#*OGF#fejL#"
|
||||
"Q$bT#*1rZ#,8W`#/B=e#0@gi#5Iuu#JBr($iT<5$&IR<$ULaH$jx%T$Vl;[$uAXa$Lvc3%R)=&%*TT:%tJ%H%bCUn%Qj,V%+XAa%+%wg%8/]l%<<Bq%qrp#&HjuJ&8B[<&Bc9F&bGgQ&"
|
||||
"VZ3X&('i_&H#dn&KLSx&]ieH'NXD<'ZogB'K*<h'/?(Z')1j`'l)p.(qY,r',Knw'XP[D(,6*5(fW_;(5n+B(D9_N(:&tX(S*a))vB$k(Jo>v(>+^2)([g^)VflN)@+'#*l*qf)5@=m)"
|
||||
"B7B>*$h)-*d235*[:B>*q^vG*Wv#c*i62<+efC,+8cl3+(FD<+=u_G+uFNT+XExX+Z_p^+e(%d+hp;h+um9n+Lxsx+A3?,,9Ss5,wv%A,N$4M,[rds,meEa,PaBj,h4<9-ObL,-csjA-"
|
||||
")#NL-N^'R-uibY-T#-g-dfv4.oKp#.RTT+.pd(S.h.QG.f(Wl.o>D[.#//e..qL4/rmj&/;fDL/e>V</6]2L/Ys(W/L$9^/M48.0'W7t/RMgF0/#####YlS.oC+.#2M#<-MeR+%h)'##"
|
||||
"&/YaE0]Wh#WtLrZ[dM_&dQd(N/(1B#SdrIh01L^#iq<on1:h#$-MWY52C-?$KTfuG3LHZ$##QiT:$Ew$G%w@b'5>>#]F[0>M3o-$.(1B#L[+Vd<UL^#aYkCj1:h#$]xR.q2C-?$@fEPA"
|
||||
"3LHZ$i=w1K><jw$:n>YY.JCYG?mv1BujNe$#t7;-T<XoIu5Ad<FKWf:D49?-6J,AF8k)F.D/Wq)&APcDU^UJDk$cP9GWMDF;F5F%uuo+D#ql>-]tn92gdMk++I2GDYo'?H#-QY5+v4L#"
|
||||
"[Z'x0_6qw0>j^uG9T9X1lrIk4+-E/#:,BP8&dCEHp4`PB;^5o1a:XG<2/_oDCt7FHbmndFgkqdF-4%F-)G@@-G3FGH,C%12AMM=-H1F7/Y1Vq1CTnrL'Ch*#D):@/5d:J:<N7rL9et3N"
|
||||
"5Y>W-xrv9)iaV-#Cv#O-iBGO-aqdT-$GqS-'?Z-.;9^kLJ*xU.,3h'#WG5s-^2TkLcU$lLp6mp3Ai0JF7DmlE>FK@-1CUO1?6[L28V7ZQpRC`Nn4$##+0A'.6sarLNf=rL]3oiLPVZ-N"
|
||||
">2oiL?Z/eG38vLF%fCkL-:Mt-0aErLc_4rL0)Uk.,gpKF,r0o-T?*1#u<*1#rENvPWpT(MT)rR#(AcY#,VC;$0o$s$41[S%8I<5&tU^l8Ym@M9^/x.:$sul&@$TM'D<5/(HTlf(LmLG)"
|
||||
"P/.)*TGe`*X`EA+]x&#,a:^Y,eR>;-ikur-m-VS.qE75/u^nl/#wNM0'90/1+Qgf1/jGG23,))37D``3;]@A4?uwx4C7XY5GO9;6Khpr6O*QS7SB258WZil8[sIM9`5+/:dMbf:hfBG;"
|
||||
"l($)<p@Z`<tX;A=xqrx=&4SY>*L4;?.ekr?2'LS@6?-5A:WdlA>pDMBB2&/CFJ]fCJc=GDN%u(ER=U`EVU6AFZnmxF_0NYGcH/;HgafrHk#GSIo;(5JsS_lJwl?MK%/w.L)GWfL-`8GM"
|
||||
"1xo(N5:P`N9R1AO=khxOA-IYPEE*;QI^arQMvASRQ8#5SUPYlSYi:MT^+r.UbCRfUf[3GVjtj(Wn6K`WrN,AXvgcxXot*GV&6`uY*N@VZ.gw7[2)Xo[6A9P]:Yp1^>rPi^B42J_FLi+`"
|
||||
"JeIc`N'+DaR?b%bVWB]bZp#>c_2ZuccJ;Vdgcr7ek%Soeo=4PfsUk1gwnKig%1-Jh)Id+i-bDciu&FS()Foc2cblh25Lx_#f/mc2k0.+49eF`#j;mc2sTEC5eh#e#?inc2t/-4Ci*He#"
|
||||
"D(4)3dhuh26Ox_#h82)3l67+4:hF`#lD2)3tZNC5fk#e#Ar3)3u564Cj-He#F1OD3en(i27Rx_#jAMD3m<@+4;kF`#nMMD3uaWC5gn#e#C%OD3v;?4Ck0He#H:k`3ft1i28Ux_#lJi`3"
|
||||
"nBI+4<nF`#pVi`3vgaC5hq#e#E.k`3wAH4Cl3He#JC0&4g$;i29Xx_#nS.&4oHR+4=qF`#r`.&4wmjC5it#e#G70&4xGQ4Cm6He#LLKA4h*Di2:[x_#p]IA4pN[+4>tF`#tiIA4xssC5"
|
||||
"jw#e#I@KA4#NZ4Cn9He#NUg]4i0Mi2;_x_#rfe]4qTe+4?wF`#vre]4#$'D5k$$e#KIg]4$Td4Co<He#P_,#5j6Vi2<bx_#to*#5rZn+4@$G`#x%+#5$*0D5l'$e#MR,#5%Zm4Cp?He#"
|
||||
"RhG>5k<`i2=ex_#vxE>5saw+4A'G`#$/F>5%09D5m*$e#O[G>5&av4CqBHe#&'32B=.wm2f2$`#q712BER804jJH`#uC12BMwOH5?N%e#Jq22BNQ79CDmRe#p7LMB@=E33h;-`#tCLMB"
|
||||
"Hb]K4lSQ`#xOLMBx;D<BAW.e#M'NMBQa[TCEpRe#r@hiBACN33i>-`#vLhiBIhfK4mVQ`#$YhiB#BM<BBZ.e#O0jiBRgeTCFsRe#tI-/CBIW33jA-`#xU-/CJnoK4nYQ`#&c-/C$HV<B"
|
||||
"C^.e#Q9//CSmnTC$),##$)>>#hda1#mPh5#vTg5#pHf^?ht^6_#2S4;2ZR%@&g6c+aq-vA4rkL>S=*p.F.s##GM.tB:oHY-N]IV?:K=?.Ao.R<ZjfsAD0-Q#+^+pAj9Hm#IVoE-@/c[["
|
||||
"ZTC>]DlGQ8d*RH=q1a;.B'hI?\?C-i<8F4g7ioQV[b+MT..lbD-Lx'<.m7T)0KNI@'F]+Z2.HZV[#9U<.WKXD-1*6EO`ZwG&Y_bpLx;4/MAbl,M[kQ1MW6ErAQ.r`?IO,Q#$1_A.'$VC?"
|
||||
"i6oS1#Yp?-=$)N$hpjHQ<E[g<T=e8.?Cn8.$<*+09MglA13P/11>;E/_UOj$lM5/Mis]Z0'f:Z[$tOZ[IVxiLkEBB-0_3uL8;5Z2)[S4=Gs2f+3QUD?=5Ok+1KtC?Nx%a+t9_eH7TDj$"
|
||||
"Jk2Q8XO`Y#_0>?84I1gLq.h88mTg5#EmM^[I@'_[0c._J*'#N04El/18x7F/8o99_b`qpL7]2..KU=5Ma1tv8%N+X%jv>Q&C8H<8ng,ND,K#01`SY<-o*t^-TM@tLL_K?pewI59RNSE-"
|
||||
"7lS?-H-^V[uL+Z2@vv>-qZXv7rR)W[%)^5Bp&aE-$44^-Z,g34B3lV7G),^O[^>01hM8;]+o>290h';.>X&[-:jL01tQ5293Y)w8;pU01Z,[?-C3aQ8oaT`<*#DT.=<Z][6uY<-%sY<-"
|
||||
"7.;t-=*.hLR_vNB0G/?-C[SiB61BQ/0HesAN)NE-Gxf884cpA(Gs'D?,IAw8_,tD'QN1W1]^W0;l6Ne=Nr.a+SX`=-d[Y=6i)q5##a0D?6avQ8#rD?8h%wZ?sF:Z[>cMv[,>^;-0`uS."
|
||||
"d>N:.fIY`1)d7Q#xiD^[oV(HOtxa*I_P_;.oYs_&XZ*.-Wdi^#iB;a'J8voL,v&nLXJ4tAm`/aYx*RV[A)eU%Z:)##N`DZ[nih5#lLM>#`0>?8@8.11,L`Y#qmQ][c<9B-GbE9.C[<9."
|
||||
"wh;?8Ou*[K08o0(2xL$#=;B%BnYAj07v7b+'#vW[h6mh/?BtW[m26Q#<)d,*1=(,M;PM11c.5F%<b/t[*lu8.uVMj$@M%E+5UL,M?ir11g:5F%@n/t[.lu8.'&f,&F(O^,cjrD'T>gI-"
|
||||
"nWeI-mWeI-'-@:MC8xiLVQ#<-)-@:MED4jLVQ#<-+-@:MGPFjLVQ#<---@:MI]XjLVQ#<-/-@:MT'G311^-Q#6N3a0KJco.LeiS8PF%U.>=*p.Cb_&4Ht$[-Xt^31/5bW[U?tW[g5Y>-"
|
||||
":E%HF:/^5B)/HDO9[4h-3bqY?p=Vt7/ChB#@h0R0pXQI2Ok5R*sIZj)NQx:.)I?)4J;gJ2@_lA#lL$^(xmoi0WLq-MtS%)*[;w0#ENh>.=`EC#O5`P-Qmm*MmfC12x@HP8EktW[r89I*"
|
||||
"qI(W3lYnV[M0'qLCKV41BG$)*bf-@->u68.==*p.t2Gx9h:_5B+ktpLK&-Q#o?;W3NYWI),p,*4lS*)**SEjLLYDm0KYmp0em-=.*$GGOG[[D4bhb>-nQ=v-%=ufL]hev6ONjj<7C4g7"
|
||||
"-#fm#,7%a+W+$$$qi-<8uG@g%>^3uLVPq%/HsD^[*8WW/>+KE-vLg?-e0WE-$$esA_$d2$'#6k<+vlW--?D_&]A[][djPS3e,K*R&RW5/&;7-5Eai?B9KJ9io/vERAcM>CQ@#B#sg([K"
|
||||
">0]3FwNEp.DxvuP$.0oLGD7p._FOe$E50HbJ3jU1<o?p4lS*)*4(RV[=9q&$X/o>6rwZ55<smV[i^NmLumY?.s28b-A)8R*ma?R*X#<s.t+SW[S)+p1o+;Z->R/N-AqYhL,?(&&GWEjL"
|
||||
"nkHq9ohN)Y-Z9T(_eMs7]:^;.*dKK-0:%I-S;m)/u7%N-]_Bil[TXp.#Hu>-*D,XCBWkC?]<3p1kbMG)iEsM62Qsc<xOnY6J=rh55CXv6aQHo0$s%=7bWQo0*fR>6=Yf88F&eG.@XmP8"
|
||||
"Z(-kLE]o;8+dUv@[V[,&cHV].&,*=.V=SF/JsIg%&w+<8LV'HOK0Y<8hbxV[GQF9B&0:?6fDGY-?)1pprsqY?_?u88aQHo05nw;-a2gr-Skt)#U7[uNRdamL9dWR8O8S9]:?hc))U&X["
|
||||
"]?tW[>3:o/G*q5#Q`0U[tgt;.&PCs3j-C2:ebE-*/D+j17uqF.IiF<%$BlW[AS2Z[uBtW[L0$6#D@Ib%o_Ib%%0Pb%r]L9]/:)=-*2#HM%HgnLK1(588pWG<$]bA#u&sc<U)OX(uqIb%"
|
||||
"+TSD=6:P&#'Lx>-wS,<-%V,<-CIrIM,sPoL6:)=-7u@Y-_1(F.%.Jb%%0Pb%8)4O+2>hY?CHNX(:/4O+`OVmLDA2pL%+p+M*G;pLH:)=-:2#HM5SMpLHl+87HUaSA$]bA#/c%pAU)OX("
|
||||
"/LJb%>LxPB#%]u7k'xlB/HZV[2KL@-5a5<-e(MT.f$h5#UT=Z-JZa$'4DmW[1E(@-IMGHM^L4RMa0nlLQR=RMR>_<.N(wP5b,RGEb6L[0=-#(&_>3)Fd(nY6lxjDFndXfNanX7MS&c?-"
|
||||
"Aa5<-x9]>-P5g,Mg&5;1;k(Z#tco;6Ij@g%a:nS.Hi/Q#@oi'#Ebl:d+d7Q#hw]][rwB`$nLs5#rlq5#/YHF%4s1G%VR)##mINX(=3<%$=cDg.VndC?J7VI?+FAw86$/@':bc/Li+kS7"
|
||||
";8JoLHF_l8.V&,2a>]N0c3X(NmpL(]jh8*#1J>lLR[+##";
|
||||
|
||||
return openIconic_compressed_data_base85;
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
|
||||
void ImGuiH::showDemoIcons()
|
||||
{
|
||||
// clang-format off
|
||||
static const char* text_icon_[] = {
|
||||
"account_login", "account_logout", "action_redo", "action_undo", "align_center",
|
||||
"align_left","align_right","aperture","arrow_bottom","arrow_circle_bottom","arrow_circle_left",
|
||||
"arrow_circle_right","arrow_circle_top","arrow_left","arrow_right","arrow_thick_bottom","arrow_thick_left",
|
||||
"arrow_thick_right","arrow_thick_top","arrow_top","audio","audio_spectrum","badge","ban","bar_chart","basket",
|
||||
"battery_empty","battery_full","beaker","bell","bluetooth","bold","bolt","book","bookmark","box","briefcase",
|
||||
"british_pound","browser","brush","bug","bullhorn","calculator","calendar","camera_slr","caret_bottom",
|
||||
"caret_left","caret_right","caret_top","cart","chat","check","chevron_bottom","chevron_left","chevron_right",
|
||||
"chevron_top","circle_check","circle_x","clipboard","clock","cloud","cloud_download","cloud_upload","cloudy",
|
||||
"code","cog","collapse_down","collapse_left","collapse_right","collapse_up","command","comment_square",
|
||||
"compass","contrast","copywriting","credit_card","crop","dashboard","data_transfer_download","data_transfer_upload",
|
||||
"delete","dial","document","dollar","double_quote_sans_left","double_quote_sans_right","double_quote_serif_left",
|
||||
"double_quote_serif_right","droplet","eject","elevator","ellipses","envelope_closed","envelope_open","euro",
|
||||
"excerpt", "expend_down", "expend_left", "expend_right", "expend_up", "external_link", "eye", "eyedropper", "file", "fire", "flag", "flash",
|
||||
"folder", "fork", "fullscreen_enter", "fullscreen_exit", "globe", "graph", "grid_four_up", "grid_three_up", "grid_two_up", "hard_drive", "header",
|
||||
"headphones", "heart", "home", "image", "inbox", "infinity", "info", "italic", "justify_center", "justify_left", "justify_right",
|
||||
"key", "laptop", "layers", "lightbulb", "link_broken", "link_intact", "list", "list_rich", "location", "lock_locked", "lock_unlocked", "loop_circular",
|
||||
"loop_square", "loop", "magnifying_glass",
|
||||
"map", "map_marquer", "media_pause", "media_play", "media_record", "media_skip_backward", "media_skip_forward", "media_step_backward", "media_step_forward",
|
||||
"media_stop", "medical_cross", "menu", "microphone", "minus", "monitor", "moon", "move", "musical_note", "paperclip",
|
||||
"pencil", "people", "person", "phone", "pie_chart", "pin", "play_circle", "plus", "power_standby", "print", "project", "pulse", "puzzle_piece",
|
||||
"question_mark", "rain", "random", "reload", "resize_both", "resize_height",
|
||||
"resize_width", "rss", "rss_alt", "script", "share", "share_boxed", "shield", "signal", "signpost", "sort_ascending", "sort_descending", "spreadsheet",
|
||||
"star", "sun", "tablet", "tag", "tags", "target", "task", "terminal",
|
||||
"text", "thumb_down", "thumb_up", "timer", "transfer", "trash", "underline", "vertical_align_bottom", "vertical_align_center", "vertical_align_top", "video",
|
||||
"volume_high", "volume_low", "volume_off", "warning", "wifi", "wrench", "x", "yen", "zoom_in", "zoom_out"
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
ImGui::SetNextWindowSize(ImVec2(700, 500), ImGuiCond_FirstUseEver);
|
||||
if(!ImGui::Begin("Icons"))
|
||||
{
|
||||
ImGui::End();
|
||||
return;
|
||||
}
|
||||
|
||||
// From 0xE000 to 0xE0DF
|
||||
for(int i = 0; i < 223; i++)
|
||||
{
|
||||
std::string utf8String;
|
||||
int codePoint = i + 0xE000;
|
||||
utf8String += static_cast<char>(0xE0 | (codePoint >> 12));
|
||||
utf8String += static_cast<char>(0x80 | ((codePoint >> 6) & 0x3F));
|
||||
utf8String += static_cast<char>(0x80 | (codePoint & 0x3F));
|
||||
|
||||
ImGui::PushFont(ImGuiH::getIconicFont());
|
||||
ImGui::Text("%s", utf8String.c_str()); // Show icon
|
||||
if(((i + 1) % 20) != 0)
|
||||
ImGui::SameLine();
|
||||
ImGui::PopFont();
|
||||
ImGui::SetItemTooltip("%s", text_icon_[i]);
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
258
raytracer/nvpro_core/imgui/imgui_icon.h
Normal file
258
raytracer/nvpro_core/imgui/imgui_icon.h
Normal file
|
|
@ -0,0 +1,258 @@
|
|||
/*
|
||||
* Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/// @DOC_SKIP
|
||||
|
||||
#pragma once
|
||||
#include <imgui.h>
|
||||
|
||||
|
||||
namespace ImGuiH {
|
||||
void addIconicFont(float fontSize = 14.F); // Call this once in the application after ImGui is initialized
|
||||
void showDemoIcons(); // Show all icons in a separated window
|
||||
ImFont* getIconicFont(); // Return the iconic font
|
||||
// Ex: ImGui::PushFont(ImGuiH::getIconicFont());
|
||||
// ImGui::Button(ImGuiH::icon_account_login);
|
||||
// ImGui::PopFont();
|
||||
|
||||
[[maybe_unused]] static const char* icon_account_login = (char*)u8"\ue000";
|
||||
[[maybe_unused]] static const char* icon_account_logout = (char*)u8"\ue001";
|
||||
[[maybe_unused]] static const char* icon_action_redo = (char*)u8"\ue002";
|
||||
[[maybe_unused]] static const char* icon_action_undo = (char*)u8"\ue003";
|
||||
[[maybe_unused]] static const char* icon_align_center = (char*)u8"\ue004";
|
||||
[[maybe_unused]] static const char* icon_align_left = (char*)u8"\ue005";
|
||||
[[maybe_unused]] static const char* icon_align_right = (char*)u8"\ue006";
|
||||
[[maybe_unused]] static const char* icon_aperture = (char*)u8"\ue007";
|
||||
[[maybe_unused]] static const char* icon_arrow_bottom = (char*)u8"\ue008";
|
||||
[[maybe_unused]] static const char* icon_arrow_circle_bottom = (char*)u8"\ue009";
|
||||
[[maybe_unused]] static const char* icon_arrow_circle_left = (char*)u8"\ue00A";
|
||||
[[maybe_unused]] static const char* icon_arrow_circle_right = (char*)u8"\ue00B";
|
||||
[[maybe_unused]] static const char* icon_arrow_circle_top = (char*)u8"\ue00C";
|
||||
[[maybe_unused]] static const char* icon_arrow_left = (char*)u8"\ue00D";
|
||||
[[maybe_unused]] static const char* icon_arrow_right = (char*)u8"\ue00E";
|
||||
[[maybe_unused]] static const char* icon_arrow_thick_bottom = (char*)u8"\ue00F";
|
||||
[[maybe_unused]] static const char* icon_arrow_thick_left = (char*)u8"\ue010";
|
||||
[[maybe_unused]] static const char* icon_arrow_thick_right = (char*)u8"\ue011";
|
||||
[[maybe_unused]] static const char* icon_arrow_thick_top = (char*)u8"\ue012";
|
||||
[[maybe_unused]] static const char* icon_arrow_top = (char*)u8"\ue013";
|
||||
[[maybe_unused]] static const char* icon_audio = (char*)u8"\ue014";
|
||||
[[maybe_unused]] static const char* icon_audio_spectrum = (char*)u8"\ue015";
|
||||
[[maybe_unused]] static const char* icon_badge = (char*)u8"\ue016";
|
||||
[[maybe_unused]] static const char* icon_ban = (char*)u8"\ue017";
|
||||
[[maybe_unused]] static const char* icon_bar_chart = (char*)u8"\ue018";
|
||||
[[maybe_unused]] static const char* icon_basket = (char*)u8"\ue019";
|
||||
[[maybe_unused]] static const char* icon_battery_empty = (char*)u8"\ue01A";
|
||||
[[maybe_unused]] static const char* icon_battery_full = (char*)u8"\ue01B";
|
||||
[[maybe_unused]] static const char* icon_beaker = (char*)u8"\ue01C";
|
||||
[[maybe_unused]] static const char* icon_bell = (char*)u8"\ue01D";
|
||||
[[maybe_unused]] static const char* icon_bluetooth = (char*)u8"\ue01E";
|
||||
[[maybe_unused]] static const char* icon_bold = (char*)u8"\ue01F";
|
||||
[[maybe_unused]] static const char* icon_bolt = (char*)u8"\ue020";
|
||||
[[maybe_unused]] static const char* icon_book = (char*)u8"\ue021";
|
||||
[[maybe_unused]] static const char* icon_bookmark = (char*)u8"\ue022";
|
||||
[[maybe_unused]] static const char* icon_box = (char*)u8"\ue023";
|
||||
[[maybe_unused]] static const char* icon_briefcase = (char*)u8"\ue024";
|
||||
[[maybe_unused]] static const char* icon_british_pound = (char*)u8"\ue025";
|
||||
[[maybe_unused]] static const char* icon_browser = (char*)u8"\ue026";
|
||||
[[maybe_unused]] static const char* icon_brush = (char*)u8"\ue027";
|
||||
[[maybe_unused]] static const char* icon_bug = (char*)u8"\ue028";
|
||||
[[maybe_unused]] static const char* icon_bullhorn = (char*)u8"\ue029";
|
||||
[[maybe_unused]] static const char* icon_calculator = (char*)u8"\ue02A";
|
||||
[[maybe_unused]] static const char* icon_calendar = (char*)u8"\ue02B";
|
||||
[[maybe_unused]] static const char* icon_camera_slr = (char*)u8"\ue02C";
|
||||
[[maybe_unused]] static const char* icon_caret_bottom = (char*)u8"\ue02D";
|
||||
[[maybe_unused]] static const char* icon_caret_left = (char*)u8"\ue02E";
|
||||
[[maybe_unused]] static const char* icon_caret_right = (char*)u8"\ue02F";
|
||||
[[maybe_unused]] static const char* icon_caret_top = (char*)u8"\ue030";
|
||||
[[maybe_unused]] static const char* icon_cart = (char*)u8"\ue031";
|
||||
[[maybe_unused]] static const char* icon_chat = (char*)u8"\ue032";
|
||||
[[maybe_unused]] static const char* icon_check = (char*)u8"\ue033";
|
||||
[[maybe_unused]] static const char* icon_chevron_bottom = (char*)u8"\ue034";
|
||||
[[maybe_unused]] static const char* icon_chevron_left = (char*)u8"\ue035";
|
||||
[[maybe_unused]] static const char* icon_chevron_right = (char*)u8"\ue036";
|
||||
[[maybe_unused]] static const char* icon_chevron_top = (char*)u8"\ue037";
|
||||
[[maybe_unused]] static const char* icon_circle_check = (char*)u8"\ue038";
|
||||
[[maybe_unused]] static const char* icon_circle_x = (char*)u8"\ue039";
|
||||
[[maybe_unused]] static const char* icon_clipboard = (char*)u8"\ue03A";
|
||||
[[maybe_unused]] static const char* icon_clock = (char*)u8"\ue03B";
|
||||
[[maybe_unused]] static const char* icon_cloud_download = (char*)u8"\ue03C";
|
||||
[[maybe_unused]] static const char* icon_cloud_upload = (char*)u8"\ue03D";
|
||||
[[maybe_unused]] static const char* icon_cloud = (char*)u8"\ue03E";
|
||||
[[maybe_unused]] static const char* icon_cloudy = (char*)u8"\ue03F";
|
||||
[[maybe_unused]] static const char* icon_code = (char*)u8"\ue040";
|
||||
[[maybe_unused]] static const char* icon_cog = (char*)u8"\ue041";
|
||||
[[maybe_unused]] static const char* icon_collapse_down = (char*)u8"\ue042";
|
||||
[[maybe_unused]] static const char* icon_collapse_left = (char*)u8"\ue043";
|
||||
[[maybe_unused]] static const char* icon_collapse_right = (char*)u8"\ue044";
|
||||
[[maybe_unused]] static const char* icon_collapse_up = (char*)u8"\ue045";
|
||||
[[maybe_unused]] static const char* icon_command = (char*)u8"\ue046";
|
||||
[[maybe_unused]] static const char* icon_comment_square = (char*)u8"\ue047";
|
||||
[[maybe_unused]] static const char* icon_compass = (char*)u8"\ue048";
|
||||
[[maybe_unused]] static const char* icon_contrast = (char*)u8"\ue049";
|
||||
[[maybe_unused]] static const char* icon_copywriting = (char*)u8"\ue04A";
|
||||
[[maybe_unused]] static const char* icon_credit_card = (char*)u8"\ue04B";
|
||||
[[maybe_unused]] static const char* icon_crop = (char*)u8"\ue04C";
|
||||
[[maybe_unused]] static const char* icon_dashboard = (char*)u8"\ue04D";
|
||||
[[maybe_unused]] static const char* icon_data_transfer_download = (char*)u8"\ue04E";
|
||||
[[maybe_unused]] static const char* icon_data_transfer_upload = (char*)u8"\ue04F";
|
||||
[[maybe_unused]] static const char* icon_delete = (char*)u8"\ue050";
|
||||
[[maybe_unused]] static const char* icon_dial = (char*)u8"\ue051";
|
||||
[[maybe_unused]] static const char* icon_document = (char*)u8"\ue052";
|
||||
[[maybe_unused]] static const char* icon_dollar = (char*)u8"\ue053";
|
||||
[[maybe_unused]] static const char* icon_double_quote_sans_left = (char*)u8"\ue054";
|
||||
[[maybe_unused]] static const char* icon_double_quote_sans_right = (char*)u8"\ue055";
|
||||
[[maybe_unused]] static const char* icon_double_quote_serif_left = (char*)u8"\ue056";
|
||||
[[maybe_unused]] static const char* icon_double_quote_serif_right = (char*)u8"\ue057";
|
||||
[[maybe_unused]] static const char* icon_droplet = (char*)u8"\ue058";
|
||||
[[maybe_unused]] static const char* icon_eject = (char*)u8"\ue059";
|
||||
[[maybe_unused]] static const char* icon_elevator = (char*)u8"\ue05A";
|
||||
[[maybe_unused]] static const char* icon_ellipses = (char*)u8"\ue05B";
|
||||
[[maybe_unused]] static const char* icon_envelope_closed = (char*)u8"\ue05C";
|
||||
[[maybe_unused]] static const char* icon_envelope_open = (char*)u8"\ue05D";
|
||||
[[maybe_unused]] static const char* icon_euro = (char*)u8"\ue05E";
|
||||
[[maybe_unused]] static const char* icon_excerpt = (char*)u8"\ue05F";
|
||||
[[maybe_unused]] static const char* icon_expend_down = (char*)u8"\ue060";
|
||||
[[maybe_unused]] static const char* icon_expend_left = (char*)u8"\ue061";
|
||||
[[maybe_unused]] static const char* icon_expend_right = (char*)u8"\ue062";
|
||||
[[maybe_unused]] static const char* icon_expend_up = (char*)u8"\ue063";
|
||||
[[maybe_unused]] static const char* icon_external_link = (char*)u8"\ue064";
|
||||
[[maybe_unused]] static const char* icon_eye = (char*)u8"\ue065";
|
||||
[[maybe_unused]] static const char* icon_eyedropper = (char*)u8"\ue066";
|
||||
[[maybe_unused]] static const char* icon_file = (char*)u8"\ue067";
|
||||
[[maybe_unused]] static const char* icon_fire = (char*)u8"\ue068";
|
||||
[[maybe_unused]] static const char* icon_flag = (char*)u8"\ue069";
|
||||
[[maybe_unused]] static const char* icon_flash = (char*)u8"\ue06A";
|
||||
[[maybe_unused]] static const char* icon_folder = (char*)u8"\ue06B";
|
||||
[[maybe_unused]] static const char* icon_fork = (char*)u8"\ue06C";
|
||||
[[maybe_unused]] static const char* icon_fullscreen_enter = (char*)u8"\ue06D";
|
||||
[[maybe_unused]] static const char* icon_fullscreen_exit = (char*)u8"\ue06E";
|
||||
[[maybe_unused]] static const char* icon_globe = (char*)u8"\ue06F";
|
||||
[[maybe_unused]] static const char* icon_graph = (char*)u8"\ue070";
|
||||
[[maybe_unused]] static const char* icon_grid_four_up = (char*)u8"\ue071";
|
||||
[[maybe_unused]] static const char* icon_grid_three_up = (char*)u8"\ue072";
|
||||
[[maybe_unused]] static const char* icon_grid_two_up = (char*)u8"\ue073";
|
||||
[[maybe_unused]] static const char* icon_hard_drive = (char*)u8"\ue074";
|
||||
[[maybe_unused]] static const char* icon_header = (char*)u8"\ue075";
|
||||
[[maybe_unused]] static const char* icon_headphones = (char*)u8"\ue076";
|
||||
[[maybe_unused]] static const char* icon_heart = (char*)u8"\ue077";
|
||||
[[maybe_unused]] static const char* icon_home = (char*)u8"\ue078";
|
||||
[[maybe_unused]] static const char* icon_image = (char*)u8"\ue079";
|
||||
[[maybe_unused]] static const char* icon_inbox = (char*)u8"\ue07A";
|
||||
[[maybe_unused]] static const char* icon_infinity = (char*)u8"\ue07B";
|
||||
[[maybe_unused]] static const char* icon_info = (char*)u8"\ue07C";
|
||||
[[maybe_unused]] static const char* icon_italic = (char*)u8"\ue07D";
|
||||
[[maybe_unused]] static const char* icon_justify_center = (char*)u8"\ue07E";
|
||||
[[maybe_unused]] static const char* icon_justify_left = (char*)u8"\ue07F";
|
||||
[[maybe_unused]] static const char* icon_justify_right = (char*)u8"\ue080";
|
||||
[[maybe_unused]] static const char* icon_key = (char*)u8"\ue081";
|
||||
[[maybe_unused]] static const char* icon_laptop = (char*)u8"\ue082";
|
||||
[[maybe_unused]] static const char* icon_layers = (char*)u8"\ue083";
|
||||
[[maybe_unused]] static const char* icon_lightbulb = (char*)u8"\ue084";
|
||||
[[maybe_unused]] static const char* icon_link_broken = (char*)u8"\ue085";
|
||||
[[maybe_unused]] static const char* icon_link_intact = (char*)u8"\ue086";
|
||||
[[maybe_unused]] static const char* icon_list = (char*)u8"\ue087";
|
||||
[[maybe_unused]] static const char* icon_list_rich = (char*)u8"\ue088";
|
||||
[[maybe_unused]] static const char* icon_location = (char*)u8"\ue089";
|
||||
[[maybe_unused]] static const char* icon_lock_locked = (char*)u8"\ue08A";
|
||||
[[maybe_unused]] static const char* icon_lock_unlocked = (char*)u8"\ue08B";
|
||||
[[maybe_unused]] static const char* icon_loop_circular = (char*)u8"\ue08C";
|
||||
[[maybe_unused]] static const char* icon_loop_square = (char*)u8"\ue08D";
|
||||
[[maybe_unused]] static const char* icon_loop = (char*)u8"\ue08E";
|
||||
[[maybe_unused]] static const char* icon_magnifying_glass = (char*)u8"\ue08F";
|
||||
[[maybe_unused]] static const char* icon_map = (char*)u8"\ue090";
|
||||
[[maybe_unused]] static const char* icon_map_marquer = (char*)u8"\ue091";
|
||||
[[maybe_unused]] static const char* icon_media_pause = (char*)u8"\ue092";
|
||||
[[maybe_unused]] static const char* icon_media_play = (char*)u8"\ue093";
|
||||
[[maybe_unused]] static const char* icon_media_record = (char*)u8"\ue094";
|
||||
[[maybe_unused]] static const char* icon_media_skip_backward = (char*)u8"\ue095";
|
||||
[[maybe_unused]] static const char* icon_media_skip_forward = (char*)u8"\ue096";
|
||||
[[maybe_unused]] static const char* icon_media_step_backward = (char*)u8"\ue097";
|
||||
[[maybe_unused]] static const char* icon_media_step_forward = (char*)u8"\ue098";
|
||||
[[maybe_unused]] static const char* icon_media_stop = (char*)u8"\ue099";
|
||||
[[maybe_unused]] static const char* icon_medical_cross = (char*)u8"\ue09A";
|
||||
[[maybe_unused]] static const char* icon_menu = (char*)u8"\ue09B";
|
||||
[[maybe_unused]] static const char* icon_microphone = (char*)u8"\ue09C";
|
||||
[[maybe_unused]] static const char* icon_minus = (char*)u8"\ue09D";
|
||||
[[maybe_unused]] static const char* icon_monitor = (char*)u8"\ue09E";
|
||||
[[maybe_unused]] static const char* icon_moon = (char*)u8"\ue09F";
|
||||
[[maybe_unused]] static const char* icon_move = (char*)u8"\ue0A0";
|
||||
[[maybe_unused]] static const char* icon_musical_note = (char*)u8"\ue0A1";
|
||||
[[maybe_unused]] static const char* icon_paperclip = (char*)u8"\ue0A2";
|
||||
[[maybe_unused]] static const char* icon_pencil = (char*)u8"\ue0A3";
|
||||
[[maybe_unused]] static const char* icon_people = (char*)u8"\ue0A4";
|
||||
[[maybe_unused]] static const char* icon_person = (char*)u8"\ue0A5";
|
||||
[[maybe_unused]] static const char* icon_phone = (char*)u8"\ue0A6";
|
||||
[[maybe_unused]] static const char* icon_pie_chart = (char*)u8"\ue0A7";
|
||||
[[maybe_unused]] static const char* icon_pin = (char*)u8"\ue0A8";
|
||||
[[maybe_unused]] static const char* icon_play_circle = (char*)u8"\ue0A9";
|
||||
[[maybe_unused]] static const char* icon_plus = (char*)u8"\ue0AA";
|
||||
[[maybe_unused]] static const char* icon_power_standby = (char*)u8"\ue0AB";
|
||||
[[maybe_unused]] static const char* icon_print = (char*)u8"\ue0AC";
|
||||
[[maybe_unused]] static const char* icon_project = (char*)u8"\ue0AD";
|
||||
[[maybe_unused]] static const char* icon_pulse = (char*)u8"\ue0AE";
|
||||
[[maybe_unused]] static const char* icon_puzzle_piece = (char*)u8"\ue0AF";
|
||||
[[maybe_unused]] static const char* icon_question_mark = (char*)u8"\ue0B0";
|
||||
[[maybe_unused]] static const char* icon_rain = (char*)u8"\ue0B1";
|
||||
[[maybe_unused]] static const char* icon_random = (char*)u8"\ue0B2";
|
||||
[[maybe_unused]] static const char* icon_reload = (char*)u8"\ue0B3";
|
||||
[[maybe_unused]] static const char* icon_resize_both = (char*)u8"\ue0B4";
|
||||
[[maybe_unused]] static const char* icon_resize_height = (char*)u8"\ue0B5";
|
||||
[[maybe_unused]] static const char* icon_resize_width = (char*)u8"\ue0B6";
|
||||
[[maybe_unused]] static const char* icon_rss = (char*)u8"\ue0B7";
|
||||
[[maybe_unused]] static const char* icon_rss_alt = (char*)u8"\ue0B8";
|
||||
[[maybe_unused]] static const char* icon_script = (char*)u8"\ue0B9";
|
||||
[[maybe_unused]] static const char* icon_share = (char*)u8"\ue0BA";
|
||||
[[maybe_unused]] static const char* icon_share_boxed = (char*)u8"\ue0BB";
|
||||
[[maybe_unused]] static const char* icon_shield = (char*)u8"\ue0BC";
|
||||
[[maybe_unused]] static const char* icon_signal = (char*)u8"\ue0BD";
|
||||
[[maybe_unused]] static const char* icon_signpost = (char*)u8"\ue0BE";
|
||||
[[maybe_unused]] static const char* icon_sort_ascending = (char*)u8"\ue0BF";
|
||||
[[maybe_unused]] static const char* icon_sort_descending = (char*)u8"\ue0C0";
|
||||
[[maybe_unused]] static const char* icon_spreadsheet = (char*)u8"\ue0C1";
|
||||
[[maybe_unused]] static const char* icon_star = (char*)u8"\ue0C2";
|
||||
[[maybe_unused]] static const char* icon_sun = (char*)u8"\ue0C3";
|
||||
[[maybe_unused]] static const char* icon_tablet = (char*)u8"\ue0C4";
|
||||
[[maybe_unused]] static const char* icon_tag = (char*)u8"\ue0C5";
|
||||
[[maybe_unused]] static const char* icon_tags = (char*)u8"\ue0C6";
|
||||
[[maybe_unused]] static const char* icon_target = (char*)u8"\ue0C7";
|
||||
[[maybe_unused]] static const char* icon_task = (char*)u8"\ue0C8";
|
||||
[[maybe_unused]] static const char* icon_terminal = (char*)u8"\ue0C9";
|
||||
[[maybe_unused]] static const char* icon_text = (char*)u8"\ue0CA";
|
||||
[[maybe_unused]] static const char* icon_thumb_down = (char*)u8"\ue0CB";
|
||||
[[maybe_unused]] static const char* icon_thumb_up = (char*)u8"\ue0CC";
|
||||
[[maybe_unused]] static const char* icon_timer = (char*)u8"\ue0CD";
|
||||
[[maybe_unused]] static const char* icon_transfer = (char*)u8"\ue0CE";
|
||||
[[maybe_unused]] static const char* icon_trash = (char*)u8"\ue0CF";
|
||||
[[maybe_unused]] static const char* icon_underline = (char*)u8"\ue0D0";
|
||||
[[maybe_unused]] static const char* icon_vertical_align_bottom = (char*)u8"\ue0D1";
|
||||
[[maybe_unused]] static const char* icon_vertical_align_center = (char*)u8"\ue0D2";
|
||||
[[maybe_unused]] static const char* icon_vertical_align_top = (char*)u8"\ue0D3";
|
||||
[[maybe_unused]] static const char* icon_video = (char*)u8"\ue0D4";
|
||||
[[maybe_unused]] static const char* icon_volume_high = (char*)u8"\ue0D5";
|
||||
[[maybe_unused]] static const char* icon_volume_low = (char*)u8"\ue0D6";
|
||||
[[maybe_unused]] static const char* icon_volume_off = (char*)u8"\ue0D7";
|
||||
[[maybe_unused]] static const char* icon_warning = (char*)u8"\ue0D8";
|
||||
[[maybe_unused]] static const char* icon_wifi = (char*)u8"\ue0D9";
|
||||
[[maybe_unused]] static const char* icon_wrench = (char*)u8"\ue0DA";
|
||||
[[maybe_unused]] static const char* icon_x = (char*)u8"\ue0DB";
|
||||
[[maybe_unused]] static const char* icon_yen = (char*)u8"\ue0DC";
|
||||
[[maybe_unused]] static const char* icon_zoom_in = (char*)u8"\ue0DD";
|
||||
[[maybe_unused]] static const char* icon_zoom_out = (char*)u8"\ue0DE";
|
||||
|
||||
} // namespace ImGuiH
|
||||
806
raytracer/nvpro_core/imgui/imgui_orient.cpp
Normal file
806
raytracer/nvpro_core/imgui/imgui_orient.cpp
Normal file
|
|
@ -0,0 +1,806 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2023, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2021 NVIDIA CORPORATION
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "imgui.h"
|
||||
#include "imgui/imgui_orient.h"
|
||||
#include "imgui_internal.h" // ImSaturate
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
ImVector<ImVec3> ImOrient::s_SphTri;
|
||||
ImVector<ImU32> ImOrient::s_SphCol;
|
||||
ImVector<ImVec2> ImOrient::s_SphTriProj;
|
||||
ImVector<ImU32> ImOrient::s_SphColLight;
|
||||
ImVector<ImVec3> ImOrient::s_ArrowTri[4];
|
||||
ImVector<ImVec2> ImOrient::s_ArrowTriProj[4];
|
||||
ImVector<ImVec3> ImOrient::s_ArrowNorm[4];
|
||||
ImVector<ImU32> ImOrient::s_ArrowColLight[4];
|
||||
|
||||
namespace ImGui {
|
||||
IMGUI_API bool QuaternionGizmo(const char* label, ImQuat& quat)
|
||||
{
|
||||
ImOrient orient;
|
||||
orient.Qt = quat;
|
||||
orient.Axis = ImVec3(1.0f, 0.0f, 0.0f);
|
||||
orient.Angle = 0;
|
||||
orient.Dir.x = orient.Dir.y = orient.Dir.z = 0;
|
||||
|
||||
orient.m_AAMode = false; // Axis & angle mode hidden
|
||||
orient.m_IsDir = false;
|
||||
orient.m_ShowDir = ImVec3(0.0f, 0.0f, 0.0f);
|
||||
orient.m_DirColor = 0xff00ffff;
|
||||
orient.ConvertToAxisAngle();
|
||||
|
||||
bool ret = orient.Draw(label);
|
||||
if(ret)
|
||||
{
|
||||
quat = orient.Qt;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
IMGUI_API bool AxisAngleGizmo(const char* label, ImVec3& axis, float& angle)
|
||||
{
|
||||
ImOrient orient;
|
||||
orient.Qt = ImQuat();
|
||||
orient.Axis = axis;
|
||||
orient.Angle = angle;
|
||||
orient.Dir = ImVec3(0.0f, 0.0f, 0.0f);
|
||||
|
||||
orient.m_AAMode = true; // Axis & angle mode hidden
|
||||
orient.m_IsDir = true;
|
||||
orient.m_ShowDir = ImVec3(0.0f, 0.0f, 0.0f);
|
||||
orient.m_DirColor = 0xff00ffff;
|
||||
orient.ConvertFromAxisAngle();
|
||||
|
||||
bool ret = orient.Draw(label);
|
||||
if(ret)
|
||||
{
|
||||
orient.ConvertToAxisAngle();
|
||||
axis = orient.Axis;
|
||||
angle = orient.Angle;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
IMGUI_API bool DirectionGizmo(const char* label, float* dir, bool flip /*= false*/, bool show_info /*= false*/)
|
||||
{
|
||||
ImOrient orient;
|
||||
orient.Qt = ImQuat();
|
||||
if(flip)
|
||||
orient.Dir = {-dir[0], -dir[1], -dir[2]};
|
||||
else
|
||||
orient.Dir = {dir[0], dir[1], dir[2]};
|
||||
orient.Axis = ImVec3(1.0f, 0.0f, 0.0f);
|
||||
orient.Angle = 0.0f;
|
||||
|
||||
|
||||
orient.m_AAMode = false; // Axis & angle mode hidden
|
||||
orient.m_IsDir = true;
|
||||
orient.m_ShowDir = ImVec3(1.0f, 0.0f, 0.0f);
|
||||
orient.m_DirColor = 0xffff0000;
|
||||
orient.QuatFromDir(orient.Qt, orient.Dir);
|
||||
orient.ConvertToAxisAngle();
|
||||
|
||||
bool ret = orient.Draw(label, show_info);
|
||||
if(ret)
|
||||
{
|
||||
ImVec3 d = orient.Qt.Rotate(ImVec3(1, 0, 0));
|
||||
d = d.Div(d.Length());
|
||||
if(flip)
|
||||
orient.Dir = {-d.x, -d.y, -d.z};
|
||||
else
|
||||
orient.Dir = d;
|
||||
dir[0] = orient.Dir.x;
|
||||
dir[1] = orient.Dir.y;
|
||||
dir[2] = orient.Dir.z;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace ImGui
|
||||
|
||||
IMGUI_API bool ImOrient::Draw(const char* label, bool show_info /*= false*/)
|
||||
{
|
||||
// ImGuiIO& io = ImGui::GetIO();
|
||||
ImGuiStyle& style = ImGui::GetStyle();
|
||||
ImDrawList* draw_list = ImGui::GetWindowDrawList();
|
||||
|
||||
if(ImOrient::s_SphTri.empty())
|
||||
{
|
||||
ImOrient::CreateArrow();
|
||||
ImOrient::CreateSphere();
|
||||
}
|
||||
|
||||
ImGui::PushID(label);
|
||||
ImGui::BeginGroup();
|
||||
|
||||
bool value_changed = false;
|
||||
|
||||
ImGui::Text("%s", label);
|
||||
if(show_info)
|
||||
{
|
||||
// Summary
|
||||
if(m_AAMode)
|
||||
{
|
||||
ImGui::Text("Axis={%.2f,%.2f,%.2f} Angle=%.0f%c", Axis.x, Axis.y, Axis.z, Angle, 176);
|
||||
}
|
||||
else if(m_IsDir)
|
||||
{
|
||||
ImGui::Text("Dir={%.2f,%.2f,%.2f}", Dir.x, Dir.y, Dir.z);
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui::Text("Quat={x:%.2f,y:%.2f,z:%.2f,s:%.2f}", Qt.x, Qt.y, Qt.z, Qt.w);
|
||||
}
|
||||
}
|
||||
|
||||
ImVec2 orient_pos = ImGui::GetCursorScreenPos();
|
||||
|
||||
float sv_orient_size = std::min(ImGui::CalcItemWidth(), float(GIZMO_SIZE));
|
||||
float w = sv_orient_size;
|
||||
float h = sv_orient_size;
|
||||
|
||||
// We want to generate quaternion rotations relative to the quaternion in the 'down' press state.
|
||||
// This gives us cleaner control over rotation (it feels better/more natural)
|
||||
static ImQuat origQuat;
|
||||
static ImVec3 coordOld;
|
||||
bool highlighted = false;
|
||||
ImGui::InvisibleButton("orient", ImVec2(sv_orient_size, sv_orient_size));
|
||||
if(ImGui::IsItemActive())
|
||||
{
|
||||
highlighted = true;
|
||||
ImVec2 mouse = ImGui::GetMousePos() - orient_pos;
|
||||
if(ImGui::IsMouseClicked(0))
|
||||
{
|
||||
origQuat = Qt;
|
||||
coordOld = ImVec3(QuatIX((int)mouse.x, w, h), QuatIY((int)mouse.y, w, h), 1.0f);
|
||||
}
|
||||
else if(ImGui::IsMouseDragging(0))
|
||||
{
|
||||
//ImGui::ResetMouseDragDelta(0);
|
||||
ImVec3 coord(QuatIX((int)mouse.x, w, h), QuatIY((int)mouse.y, w, h), 1.0f);
|
||||
ImVec3 pVec = AxisTransform.Transform(coord);
|
||||
ImVec3 oVec = AxisTransform.Transform(coordOld);
|
||||
coord.z = 0.0f;
|
||||
float n0 = oVec.Length();
|
||||
float n1 = pVec.Length();
|
||||
if(n0 > FLT_EPSILON && n1 > FLT_EPSILON)
|
||||
{
|
||||
ImVec3 v0 = oVec.Div(n0);
|
||||
ImVec3 v1 = pVec.Div(n1);
|
||||
ImVec3 axis = v0.Cross(v1);
|
||||
float sa = axis.Length();
|
||||
float ca = v0.Dot(v1);
|
||||
float angle = (float)atan2(sa, ca);
|
||||
if(coord.x * coord.x + coord.y * coord.y > 1.0f)
|
||||
angle *= 1.0f + 1.5f * (coord.Length() - 1.0f);
|
||||
ImQuat qrot, qres, qorig;
|
||||
QuatFromAxisAngle(qrot, axis, angle);
|
||||
float nqorig =
|
||||
sqrtf(origQuat.x * origQuat.x + origQuat.y * origQuat.y + origQuat.z * origQuat.z + origQuat.w * origQuat.w);
|
||||
if(fabsf(nqorig) > FLT_EPSILON * FLT_EPSILON)
|
||||
{
|
||||
qorig = origQuat.Div(nqorig);
|
||||
qres = qrot.Mult(qorig);
|
||||
Qt = qres;
|
||||
}
|
||||
else
|
||||
{
|
||||
Qt = qrot;
|
||||
}
|
||||
//origQuat = Qt;
|
||||
value_changed = true;
|
||||
}
|
||||
}
|
||||
draw_list->AddRectFilled(orient_pos, orient_pos + ImVec2(sv_orient_size, sv_orient_size),
|
||||
ImColor(style.Colors[ImGuiCol_FrameBgActive]), style.FrameRounding);
|
||||
}
|
||||
else
|
||||
{
|
||||
highlighted = ImGui::IsItemHovered();
|
||||
draw_list->AddRectFilled(orient_pos, orient_pos + ImVec2(sv_orient_size, sv_orient_size),
|
||||
ImColor(highlighted ? style.Colors[ImGuiCol_FrameBgHovered] : style.Colors[ImGuiCol_FrameBg]),
|
||||
style.FrameRounding);
|
||||
}
|
||||
|
||||
|
||||
float normDir = m_ShowDir.Length();
|
||||
bool drawDir = m_IsDir || (normDir > FLT_EPSILON);
|
||||
|
||||
ImVec2 inner_pos = orient_pos;
|
||||
float inner_size = w;
|
||||
if(drawDir)
|
||||
{
|
||||
inner_size = sv_orient_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
inner_pos.x += sv_orient_size * .25f * .5f;
|
||||
inner_pos.y += sv_orient_size * .25f * .5f;
|
||||
inner_size *= .75f;
|
||||
}
|
||||
|
||||
ImQuat quat;
|
||||
int i, j, k, l, m;
|
||||
|
||||
// normalize quaternion
|
||||
float qn = sqrtf(Qt.w * Qt.w + Qt.x * Qt.x + Qt.y * Qt.y + Qt.z * Qt.z);
|
||||
if(qn > FLT_EPSILON)
|
||||
{
|
||||
quat.x = (float)Qt.x / qn;
|
||||
quat.y = (float)Qt.y / qn;
|
||||
quat.z = (float)Qt.z / qn;
|
||||
quat.w = (float)Qt.w / qn;
|
||||
}
|
||||
else
|
||||
{
|
||||
quat.x = quat.y = quat.z = 0.0f;
|
||||
quat.w = 1.0f;
|
||||
}
|
||||
|
||||
ImColor alpha(1.0f, 1.0f, 1.0f, highlighted ? 1.0f : 0.75f);
|
||||
|
||||
// check if frame is right-handed
|
||||
ImVec3 px = AxisTransform.Transform(ImVec3(1.0f, 0.0f, 0.0f));
|
||||
ImVec3 py = AxisTransform.Transform(ImVec3(0.0f, 1.0f, 0.0f));
|
||||
ImVec3 pz = AxisTransform.Transform(ImVec3(0.0f, 0.0f, 1.0f));
|
||||
|
||||
ImVec3 ez = px.Cross(py);
|
||||
|
||||
// Use the handedness of the frame matrix to determine cull direction
|
||||
bool frameRightHanded = pz.Dot(ez) >= 0;
|
||||
float cullDir = frameRightHanded ? 1.0f : -1.0f;
|
||||
|
||||
// Drawing an arrow
|
||||
if(drawDir)
|
||||
{
|
||||
ImVec3 dir = m_ShowDir;
|
||||
if(normDir < FLT_EPSILON)
|
||||
{
|
||||
normDir = 1;
|
||||
dir.x = 1;
|
||||
}
|
||||
ImVec3 kVec = dir;
|
||||
|
||||
ImVec3 rotDirAxis = {0, -kVec.z, kVec.y};
|
||||
if(rotDirAxis.Dot(rotDirAxis) < FLT_EPSILON * FLT_EPSILON)
|
||||
{
|
||||
rotDirAxis.x = rotDirAxis.y = 0;
|
||||
rotDirAxis.z = 1;
|
||||
}
|
||||
float rotDirAngle = (float)acos(kVec.x / normDir);
|
||||
ImQuat rotDirQuat;
|
||||
QuatFromAxisAngle(rotDirQuat, rotDirAxis, rotDirAngle);
|
||||
|
||||
kVec = ImVec3(1.0f, 0.0f, 0.0f);
|
||||
kVec = rotDirQuat.Rotate(kVec);
|
||||
kVec = quat.Rotate(kVec);
|
||||
for(k = 0; k < 4; ++k) // 4 parts of the arrow
|
||||
{
|
||||
// draw order
|
||||
ImVec3 arrowDir = AxisTransform.Transform(kVec);
|
||||
j = (arrowDir.z > 0) ? 3 - k : k;
|
||||
|
||||
assert(s_ArrowTriProj[j].size() == (s_ArrowTri[j].size()) && s_ArrowColLight[j].size() == s_ArrowTri[j].size()
|
||||
&& s_ArrowNorm[j].size() == s_ArrowTri[j].size());
|
||||
|
||||
const int ntri = (int)s_ArrowTri[j].size();
|
||||
for(i = 0; i < ntri; ++i)
|
||||
{
|
||||
ImVec3 coord = s_ArrowTri[j][i];
|
||||
ImVec3 norm = s_ArrowNorm[j][i];
|
||||
|
||||
if(coord.x > 0)
|
||||
coord.x = 2.5f * coord.x - 2.0f;
|
||||
else
|
||||
coord.x += 0.2f;
|
||||
coord.y *= 1.5f;
|
||||
coord.z *= 1.5f;
|
||||
|
||||
coord = rotDirQuat.Rotate(coord);
|
||||
coord = quat.Rotate(coord);
|
||||
coord = AxisTransform.Transform(coord);
|
||||
|
||||
norm = rotDirQuat.Rotate(norm);
|
||||
norm = quat.Rotate(norm);
|
||||
norm = AxisTransform.Transform(norm);
|
||||
|
||||
s_ArrowTriProj[j][i] = ImVec2(QuatPX(coord.x, w, h), QuatPY(coord.y, w, h));
|
||||
ImU32 col = (m_DirColor | 0xff000000) & alpha;
|
||||
s_ArrowColLight[j][i] = ColorBlend(0xff000000, col, fabsf(ImClamp(norm.z, -1.0f, 1.0f)));
|
||||
}
|
||||
DrawTriangles(draw_list, inner_pos, s_ArrowTriProj[j], s_ArrowColLight[j], ntri, cullDir);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// draw arrows & sphere
|
||||
const float SPH_RADIUS = 0.75f;
|
||||
for(m = 0; m < 2; ++m) // m=0: back, m=1: front
|
||||
{
|
||||
for(l = 0; l < 3; ++l) // draw 3 arrows
|
||||
{
|
||||
ImVec3 kVec(1, 0, 0);
|
||||
if(l == 1)
|
||||
{
|
||||
kVec = kVec.RotZ();
|
||||
}
|
||||
else if(l == 2)
|
||||
{
|
||||
kVec = kVec.RotY();
|
||||
}
|
||||
kVec = quat.Rotate(kVec);
|
||||
for(k = 0; k < 4; ++k) // 4 parts of the arrow
|
||||
{
|
||||
// draw order
|
||||
ImVec3 arrowCoord = AxisTransform.Transform(kVec);
|
||||
j = (arrowCoord.z > 0) ? 3 - k : k;
|
||||
|
||||
bool cone = true;
|
||||
if((m == 0 && arrowCoord.z > 0) || (m == 1 && arrowCoord.z <= 0))
|
||||
{
|
||||
if(j == ImOrient::ARROW_CONE || j == ImOrient::ARROW_CONE_CAP) // do not draw cone
|
||||
continue;
|
||||
else
|
||||
cone = false;
|
||||
}
|
||||
assert(ImOrient::s_ArrowTriProj[j].size() == (ImOrient::s_ArrowTri[j].size())
|
||||
&& ImOrient::s_ArrowColLight[j].size() == ImOrient::s_ArrowTri[j].size()
|
||||
&& ImOrient::s_ArrowNorm[j].size() == ImOrient::s_ArrowTri[j].size());
|
||||
const int ntri = (int)ImOrient::s_ArrowTri[j].size();
|
||||
for(i = 0; i < ntri; ++i)
|
||||
{
|
||||
ImVec3 coord = s_ArrowTri[j][i];
|
||||
if(cone && coord.x <= 0)
|
||||
coord.x = SPH_RADIUS;
|
||||
else if(!cone && coord.x > 0)
|
||||
coord.x = -SPH_RADIUS;
|
||||
ImVec3 norm = s_ArrowNorm[j][i];
|
||||
if(l == 1)
|
||||
{
|
||||
coord = coord.RotZ();
|
||||
norm = norm.RotZ();
|
||||
}
|
||||
else if(l == 2)
|
||||
{
|
||||
coord = coord.RotY();
|
||||
norm = norm.RotY();
|
||||
}
|
||||
coord = quat.Rotate(coord);
|
||||
coord = AxisTransform.Transform(coord);
|
||||
norm = quat.Rotate(norm);
|
||||
norm = AxisTransform.Transform(norm);
|
||||
s_ArrowTriProj[j][i] = ImVec2(QuatPX(coord.x, inner_size, inner_size), QuatPY(coord.y, inner_size, inner_size));
|
||||
float fade = (m == 0 && coord.z < 0) ? ImClamp(2.0f * coord.z * coord.z, 0.0f, 1.0f) : 0;
|
||||
float alphaFade = 1.0f;
|
||||
alphaFade = alpha.Value.w;
|
||||
alphaFade *= (1.0f - fade);
|
||||
ImColor alphaFadeCol(1.0f, 1.0f, 1.0f, alphaFade);
|
||||
ImU32 col = (l == 0) ? 0xffff0000 : ((l == 1) ? 0xff00ff00 : 0xff0000ff);
|
||||
s_ArrowColLight[j][i] = ColorBlend(0xff000000, col, fabsf(ImClamp(norm.z, -1.0f, 1.0f))) & ImU32(alphaFadeCol);
|
||||
}
|
||||
DrawTriangles(draw_list, inner_pos, s_ArrowTriProj[j], s_ArrowColLight[j], ntri, cullDir);
|
||||
}
|
||||
}
|
||||
|
||||
if(m == 0)
|
||||
{
|
||||
const int ntri = (int)ImOrient::s_SphTri.size();
|
||||
for(i = 0; i < ntri; ++i) // draw sphere
|
||||
{
|
||||
ImVec3 coord = s_SphTri[i].Mult(SPH_RADIUS);
|
||||
coord = quat.Rotate(coord);
|
||||
coord = AxisTransform.Transform(coord);
|
||||
s_SphTriProj[i] = ImVec2(QuatPX(coord.x, inner_size, inner_size), QuatPY(coord.y, inner_size, inner_size));
|
||||
s_SphColLight[i] = ColorBlend(0xff000000, s_SphCol[i], fabsf(ImClamp(coord.z / SPH_RADIUS, -1.0f, 1.0f))) & ImU32(alpha);
|
||||
}
|
||||
|
||||
DrawTriangles(draw_list, inner_pos, s_SphTriProj, s_SphColLight, ntri, cullDir);
|
||||
}
|
||||
}
|
||||
|
||||
// draw x
|
||||
draw_list->AddLine(orient_pos + ImVec2(w - 12, h - 36), orient_pos + ImVec2(w - 12 + 5, h - 36 + 5), 0xff0000c0);
|
||||
draw_list->AddLine(orient_pos + ImVec2(w - 12 + 5, h - 36), orient_pos + ImVec2(w - 12, h - 36 + 5), 0xff0000c0);
|
||||
// draw y
|
||||
draw_list->AddLine(orient_pos + ImVec2(w - 12, h - 25), orient_pos + ImVec2(w - 12 + 3, h - 25 + 4), 0xff00c000);
|
||||
draw_list->AddLine(orient_pos + ImVec2(w - 12 + 5, h - 25), orient_pos + ImVec2(w - 12, h - 25 + 7), 0xff00c000);
|
||||
// draw z
|
||||
draw_list->AddLine(orient_pos + ImVec2(w - 12, h - 12), orient_pos + ImVec2(w - 12 + 5, h - 12), 0xffc00000);
|
||||
draw_list->AddLine(orient_pos + ImVec2(w - 12, h - 12 + 5), orient_pos + ImVec2(w - 12 + 5, h - 12 + 5), 0xffc00000);
|
||||
draw_list->AddLine(orient_pos + ImVec2(w - 12, h - 12 + 5), orient_pos + ImVec2(w - 12 + 5, h - 12), 0xffc00000);
|
||||
}
|
||||
|
||||
ImGui::EndGroup();
|
||||
ImGui::PopID();
|
||||
|
||||
return value_changed;
|
||||
}
|
||||
|
||||
|
||||
void ImOrient::DrawTriangles(ImDrawList* draw_list,
|
||||
const ImVec2& offset,
|
||||
const ImVector<ImVec2>& triProj,
|
||||
const ImVector<ImU32>& colLight,
|
||||
int numVertices,
|
||||
float cullDir)
|
||||
{
|
||||
const ImVec2 uv = ImGui::GetFontTexUvWhitePixel();
|
||||
assert(numVertices % 3 == 0);
|
||||
draw_list->PrimReserve(numVertices, numVertices); // num vert/indices
|
||||
for(int ii = 0; ii < numVertices / 3; ii++)
|
||||
{
|
||||
ImVec2 v1 = offset + triProj[ii * 3];
|
||||
ImVec2 v2 = offset + triProj[ii * 3 + 1];
|
||||
ImVec2 v3 = offset + triProj[ii * 3 + 2];
|
||||
|
||||
// 2D cross product to do culling
|
||||
ImVec2 d1 = ImVec2Subtract(v2, v1);
|
||||
ImVec2 d2 = ImVec2Subtract(v3, v1);
|
||||
float c = ImVec2Cross(d1, d2) * cullDir;
|
||||
if(c > 0.0f)
|
||||
{
|
||||
v2 = v1;
|
||||
v3 = v1;
|
||||
}
|
||||
|
||||
draw_list->PrimWriteIdx(ImDrawIdx(draw_list->_VtxCurrentIdx));
|
||||
draw_list->PrimWriteIdx(ImDrawIdx(draw_list->_VtxCurrentIdx + 1));
|
||||
draw_list->PrimWriteIdx(ImDrawIdx(draw_list->_VtxCurrentIdx + 2));
|
||||
draw_list->PrimWriteVtx(v1, uv, colLight[ii * 3]);
|
||||
draw_list->PrimWriteVtx(v2, uv, colLight[ii * 3 + 1]);
|
||||
draw_list->PrimWriteVtx(v3, uv, colLight[ii * 3 + 2]);
|
||||
}
|
||||
}
|
||||
|
||||
void ImOrient::CreateSphere()
|
||||
{
|
||||
const int SUBDIV = 7;
|
||||
s_SphTri.clear();
|
||||
s_SphCol.clear();
|
||||
|
||||
const float A[8 * 3] = {1, 0, 0, 0, 0, -1, -1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, -1, -1, 0, 0};
|
||||
const float B[8 * 3] = {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0};
|
||||
const float C[8 * 3] = {0, 0, 1, 1, 0, 0, 0, 0, -1, -1, 0, 0, 1, 0, 0, 0, 0, -1, -1, 0, 0, 0, 0, 1};
|
||||
const ImU32 COL_A[8] = {0xffffffff, 0xffffff40, 0xff40ff40, 0xff40ffff,
|
||||
0xffff40ff, 0xffff4040, 0xff404040, 0xff4040ff};
|
||||
const ImU32 COL_B[8] = {0xffffffff, 0xffffff40, 0xff40ff40, 0xff40ffff,
|
||||
0xffff40ff, 0xffff4040, 0xff404040, 0xff4040ff};
|
||||
const ImU32 COL_C[8] = {0xffffffff, 0xffffff40, 0xff40ff40, 0xff40ffff,
|
||||
0xffff40ff, 0xffff4040, 0xff404040, 0xff4040ff};
|
||||
|
||||
int i, j, k, l;
|
||||
float xa, ya, za, xb, yb, zb, xc, yc, zc, x, y, z, norm, u[3], v[3];
|
||||
ImU32 col;
|
||||
for(i = 0; i < 8; ++i)
|
||||
{
|
||||
xa = A[3 * i + 0];
|
||||
ya = A[3 * i + 1];
|
||||
za = A[3 * i + 2];
|
||||
xb = B[3 * i + 0];
|
||||
yb = B[3 * i + 1];
|
||||
zb = B[3 * i + 2];
|
||||
xc = C[3 * i + 0];
|
||||
yc = C[3 * i + 1];
|
||||
zc = C[3 * i + 2];
|
||||
for(j = 0; j <= SUBDIV; ++j)
|
||||
for(k = 0; k <= 2 * (SUBDIV - j); ++k)
|
||||
{
|
||||
if(k % 2 == 0)
|
||||
{
|
||||
u[0] = ((float)j) / (SUBDIV + 1);
|
||||
v[0] = ((float)(k / 2)) / (SUBDIV + 1);
|
||||
u[1] = ((float)(j + 1)) / (SUBDIV + 1);
|
||||
v[1] = ((float)(k / 2)) / (SUBDIV + 1);
|
||||
u[2] = ((float)j) / (SUBDIV + 1);
|
||||
v[2] = ((float)(k / 2 + 1)) / (SUBDIV + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
u[0] = ((float)j) / (SUBDIV + 1);
|
||||
v[0] = ((float)(k / 2 + 1)) / (SUBDIV + 1);
|
||||
u[1] = ((float)(j + 1)) / (SUBDIV + 1);
|
||||
v[1] = ((float)(k / 2)) / (SUBDIV + 1);
|
||||
u[2] = ((float)(j + 1)) / (SUBDIV + 1);
|
||||
v[2] = ((float)(k / 2 + 1)) / (SUBDIV + 1);
|
||||
}
|
||||
|
||||
for(l = 0; l < 3; ++l)
|
||||
{
|
||||
x = (1.0f - u[l] - v[l]) * xa + u[l] * xb + v[l] * xc;
|
||||
y = (1.0f - u[l] - v[l]) * ya + u[l] * yb + v[l] * yc;
|
||||
z = (1.0f - u[l] - v[l]) * za + u[l] * zb + v[l] * zc;
|
||||
norm = sqrtf(x * x + y * y + z * z);
|
||||
x /= norm;
|
||||
y /= norm;
|
||||
z /= norm;
|
||||
s_SphTri.push_back(ImVec3(x, y, z));
|
||||
if(u[l] + v[l] > FLT_EPSILON)
|
||||
col = ColorBlend(COL_A[i], ColorBlend(COL_B[i], COL_C[i], v[l] / (u[l] + v[l])), u[l] + v[l]);
|
||||
else
|
||||
col = COL_A[i];
|
||||
s_SphCol.push_back(col);
|
||||
}
|
||||
}
|
||||
}
|
||||
s_SphTriProj.clear();
|
||||
s_SphTriProj.resize(s_SphTri.size());
|
||||
s_SphColLight.clear();
|
||||
s_SphColLight.resize(s_SphCol.size());
|
||||
}
|
||||
|
||||
void ImOrient::CreateArrow()
|
||||
{
|
||||
const int SUBDIV = 15;
|
||||
const float CYL_RADIUS = 0.08f;
|
||||
const float CONE_RADIUS = 0.16f;
|
||||
const float CONE_LENGTH = 0.25f;
|
||||
const float ARROW_BGN = -1.1f;
|
||||
const float ARROW_END = 1.15f;
|
||||
int i;
|
||||
|
||||
for(i = 0; i < 4; ++i)
|
||||
{
|
||||
s_ArrowTri[i].clear();
|
||||
s_ArrowNorm[i].clear();
|
||||
}
|
||||
|
||||
float x0, x1, y0, y1, z0, z1, a0, a1, nx, nn;
|
||||
for(i = 0; i < SUBDIV; ++i)
|
||||
{
|
||||
a0 = 2.0f * float(M_PI) * (float(i)) / SUBDIV;
|
||||
a1 = 2.0f * float(M_PI) * (float(i + 1)) / SUBDIV;
|
||||
x0 = ARROW_BGN;
|
||||
x1 = ARROW_END - CONE_LENGTH;
|
||||
y0 = cosf(a0);
|
||||
z0 = sinf(a0);
|
||||
y1 = cosf(a1);
|
||||
z1 = sinf(a1);
|
||||
s_ArrowTri[ARROW_CYL].push_back(ImVec3(x1, CYL_RADIUS * y0, CYL_RADIUS * z0));
|
||||
s_ArrowTri[ARROW_CYL].push_back(ImVec3(x0, CYL_RADIUS * y0, CYL_RADIUS * z0));
|
||||
s_ArrowTri[ARROW_CYL].push_back(ImVec3(x0, CYL_RADIUS * y1, CYL_RADIUS * z1));
|
||||
s_ArrowTri[ARROW_CYL].push_back(ImVec3(x1, CYL_RADIUS * y0, CYL_RADIUS * z0));
|
||||
s_ArrowTri[ARROW_CYL].push_back(ImVec3(x0, CYL_RADIUS * y1, CYL_RADIUS * z1));
|
||||
s_ArrowTri[ARROW_CYL].push_back(ImVec3(x1, CYL_RADIUS * y1, CYL_RADIUS * z1));
|
||||
s_ArrowNorm[ARROW_CYL].push_back(ImVec3(0, y0, z0));
|
||||
s_ArrowNorm[ARROW_CYL].push_back(ImVec3(0, y0, z0));
|
||||
s_ArrowNorm[ARROW_CYL].push_back(ImVec3(0, y1, z1));
|
||||
s_ArrowNorm[ARROW_CYL].push_back(ImVec3(0, y0, z0));
|
||||
s_ArrowNorm[ARROW_CYL].push_back(ImVec3(0, y1, z1));
|
||||
s_ArrowNorm[ARROW_CYL].push_back(ImVec3(0, y1, z1));
|
||||
s_ArrowTri[ARROW_CYL_CAP].push_back(ImVec3(x0, 0, 0));
|
||||
s_ArrowTri[ARROW_CYL_CAP].push_back(ImVec3(x0, CYL_RADIUS * y1, CYL_RADIUS * z1));
|
||||
s_ArrowTri[ARROW_CYL_CAP].push_back(ImVec3(x0, CYL_RADIUS * y0, CYL_RADIUS * z0));
|
||||
s_ArrowNorm[ARROW_CYL_CAP].push_back(ImVec3(-1, 0, 0));
|
||||
s_ArrowNorm[ARROW_CYL_CAP].push_back(ImVec3(-1, 0, 0));
|
||||
s_ArrowNorm[ARROW_CYL_CAP].push_back(ImVec3(-1, 0, 0));
|
||||
x0 = ARROW_END - CONE_LENGTH;
|
||||
x1 = ARROW_END;
|
||||
nx = CONE_RADIUS / (x1 - x0);
|
||||
nn = 1.0f / sqrtf(nx * nx + 1);
|
||||
s_ArrowTri[ARROW_CONE].push_back(ImVec3(x1, 0, 0));
|
||||
s_ArrowTri[ARROW_CONE].push_back(ImVec3(x0, CONE_RADIUS * y0, CONE_RADIUS * z0));
|
||||
s_ArrowTri[ARROW_CONE].push_back(ImVec3(x0, CONE_RADIUS * y1, CONE_RADIUS * z1));
|
||||
s_ArrowTri[ARROW_CONE].push_back(ImVec3(x1, 0, 0));
|
||||
s_ArrowTri[ARROW_CONE].push_back(ImVec3(x0, CONE_RADIUS * y1, CONE_RADIUS * z1));
|
||||
s_ArrowTri[ARROW_CONE].push_back(ImVec3(x1, 0, 0));
|
||||
s_ArrowNorm[ARROW_CONE].push_back(ImVec3(nn * nx, nn * y0, nn * z0));
|
||||
s_ArrowNorm[ARROW_CONE].push_back(ImVec3(nn * nx, nn * y0, nn * z0));
|
||||
s_ArrowNorm[ARROW_CONE].push_back(ImVec3(nn * nx, nn * y1, nn * z1));
|
||||
s_ArrowNorm[ARROW_CONE].push_back(ImVec3(nn * nx, nn * y0, nn * z0));
|
||||
s_ArrowNorm[ARROW_CONE].push_back(ImVec3(nn * nx, nn * y1, nn * z1));
|
||||
s_ArrowNorm[ARROW_CONE].push_back(ImVec3(nn * nx, nn * y1, nn * z1));
|
||||
s_ArrowTri[ARROW_CONE_CAP].push_back(ImVec3(x0, 0, 0));
|
||||
s_ArrowTri[ARROW_CONE_CAP].push_back(ImVec3(x0, CONE_RADIUS * y1, CONE_RADIUS * z1));
|
||||
s_ArrowTri[ARROW_CONE_CAP].push_back(ImVec3(x0, CONE_RADIUS * y0, CONE_RADIUS * z0));
|
||||
s_ArrowNorm[ARROW_CONE_CAP].push_back(ImVec3(-1, 0, 0));
|
||||
s_ArrowNorm[ARROW_CONE_CAP].push_back(ImVec3(-1, 0, 0));
|
||||
s_ArrowNorm[ARROW_CONE_CAP].push_back(ImVec3(-1, 0, 0));
|
||||
}
|
||||
|
||||
for(i = 0; i < 4; ++i)
|
||||
{
|
||||
s_ArrowTriProj[i].clear();
|
||||
s_ArrowTriProj[i].resize(s_ArrowTri[i].size());
|
||||
s_ArrowColLight[i].clear();
|
||||
s_ArrowColLight[i].resize(s_ArrowTri[i].size());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ImOrient::ConvertToAxisAngle()
|
||||
{
|
||||
if(fabs(Qt.w) > (1.0 + FLT_EPSILON))
|
||||
{
|
||||
//Axis.x = Axis.y = Axis.z = 0; // no, keep the previous value
|
||||
Angle = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
float a;
|
||||
if(Qt.w >= 1.0f)
|
||||
a = 0.0f; // and keep V
|
||||
else if(Qt.w <= -1.0f)
|
||||
a = float(M_PI); // and keep V
|
||||
else if(fabsf(Qt.x * Qt.x + Qt.y * Qt.y + Qt.z * Qt.z + Qt.w * Qt.w) < (FLT_EPSILON * FLT_EPSILON))
|
||||
a = 0.0f;
|
||||
else
|
||||
{
|
||||
a = (float)acos(Qt.w);
|
||||
if(a * Angle < 0) // Preserve the sign of Angle
|
||||
a = -a;
|
||||
float f = 1.0f / (float)sin(a);
|
||||
Axis.x = Qt.x * f;
|
||||
Axis.y = Qt.y * f;
|
||||
Axis.z = Qt.z * f;
|
||||
}
|
||||
Angle = 2.0f * a;
|
||||
}
|
||||
|
||||
Angle = ImRadToDeg(Angle);
|
||||
|
||||
if(fabsf(Angle) < FLT_EPSILON && fabsf(Axis.x * Axis.x + Axis.y * Axis.y + Axis.z * Axis.z) < FLT_EPSILON * FLT_EPSILON)
|
||||
Axis.x = FLT_MIN; // all components cannot be null
|
||||
}
|
||||
|
||||
void ImOrient::ConvertFromAxisAngle()
|
||||
{
|
||||
float n = Axis.x * Axis.x + Axis.y * Axis.y + Axis.z * Axis.z;
|
||||
if(fabsf(n) > (FLT_EPSILON * FLT_EPSILON))
|
||||
{
|
||||
float f = 0.5f * ImDegToRad(Angle);
|
||||
Qt.w = (float)cos(f);
|
||||
f = (float)sin(f);
|
||||
|
||||
Qt.x = Axis.x * f;
|
||||
Qt.y = Axis.y * f;
|
||||
Qt.z = Axis.z * f;
|
||||
}
|
||||
else
|
||||
{
|
||||
Qt.w = 1.0;
|
||||
Qt.x = Qt.y = Qt.z = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
void ImGui_Orient::CopyToVar()
|
||||
{
|
||||
if( m_StructProxy!=NULL )
|
||||
{
|
||||
if( m_StructProxy->m_StructSetCallback!=NULL )
|
||||
{
|
||||
if( m_IsFloat )
|
||||
{
|
||||
if( m_IsDir )
|
||||
{
|
||||
float d[] = {1, 0, 0};
|
||||
ApplyQuat(d+0, d+1, d+2, 1, 0, 0, (float)Qt.x, (float)Qt.y, (float)Qt.z, (float)Qt.w);
|
||||
float l = (float)sqrt(Dir.x*Dir.x + Dir.y*Dir.y + Dir.z*Dir.z);
|
||||
d[0] *= l; d[1] *= l; d[2] *= l;
|
||||
Dir.x = d[0]; Dir.y = d[1]; Dir.z = d[2]; // update also Dir.x,Dir.y,Dir.z
|
||||
m_StructProxy->m_StructSetCallback(d, m_StructProxy->m_StructClientData);
|
||||
}
|
||||
else
|
||||
{
|
||||
float q[] = { (float)Qt.x, (float)Qt.y, (float)Qt.z, (float)Qt.w };
|
||||
m_StructProxy->m_StructSetCallback(q, m_StructProxy->m_StructClientData);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( m_StructProxy->m_StructData!=NULL )
|
||||
{
|
||||
if( m_IsFloat )
|
||||
{
|
||||
if( m_IsDir )
|
||||
{
|
||||
float *d = static_cast<float *>(m_StructProxy->m_StructData);
|
||||
ApplyQuat(d+0, d+1, d+2, 1, 0, 0, (float)Qt.x, (float)Qt.y, (float)Qt.z, (float)Qt.w);
|
||||
float l = (float)sqrt(Dir.x*Dir.x + Dir.y*Dir.y + Dir.z*Dir.z);
|
||||
d[0] *= l; d[1] *= l; d[2] *= l;
|
||||
Dir.x = d[0]; Dir.y = d[1]; Dir.z = d[2]; // update also Dir.x,Dir.y,Dir.z
|
||||
}
|
||||
else
|
||||
{
|
||||
float *q = static_cast<float *>(m_StructProxy->m_StructData);
|
||||
q[0] = (float)Qt.x; q[1] = (float)Qt.y; q[2] = (float)Qt.z; q[3] = (float)Qt.w;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( m_IsDir )
|
||||
{
|
||||
float *dd = static_cast<float *>(m_StructProxy->m_StructData);
|
||||
float d[] = {1, 0, 0};
|
||||
ApplyQuat(d+0, d+1, d+2, 1, 0, 0, (float)Qt.x, (float)Qt.y, (float)Qt.z, (float)Qt.w);
|
||||
float l = sqrt(Dir.x*Dir.x + Dir.y*Dir.y + Dir.z*Dir.z);
|
||||
dd[0] = l*d[0]; dd[1] = l*d[1]; dd[2] = l*d[2];
|
||||
Dir.x = dd[0]; Dir.y = dd[1]; Dir.z = dd[2]; // update also Dir.x,Dir.y,Dir.z
|
||||
}
|
||||
else
|
||||
{
|
||||
float *q = static_cast<float *>(m_StructProxy->m_StructData);
|
||||
q[0] = Qt.x; q[1] = Qt.y; q[2] = Qt.z; q[3] = Qt.w;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
ImU32 ImOrient::ColorBlend(ImU32 _Color1, ImU32 _Color2, float sigma)
|
||||
{
|
||||
ImColor color1(_Color1);
|
||||
ImColor color2(_Color2);
|
||||
float invSigma = 1.0f - sigma;
|
||||
|
||||
color1 =
|
||||
ImColor((color1.Value.x * invSigma) + (color2.Value.x * sigma), (color1.Value.y * invSigma) + (color2.Value.y * sigma),
|
||||
(color1.Value.z * invSigma) + (color2.Value.z * sigma), (color1.Value.w * invSigma) + (color2.Value.w * sigma));
|
||||
|
||||
return color1;
|
||||
}
|
||||
|
||||
|
||||
void ImOrient::QuatFromAxisAngle(ImQuat& out, const ImVec3& axis, float angle)
|
||||
{
|
||||
float n = axis.x * axis.x + axis.y * axis.y + axis.z * axis.z;
|
||||
if(fabs(n) > FLT_EPSILON)
|
||||
{
|
||||
float f = 0.5f * angle;
|
||||
out.w = (float)cos(f);
|
||||
f = (float)(sin(f) / sqrt(n));
|
||||
out.x = axis.x * f;
|
||||
out.y = axis.y * f;
|
||||
out.z = axis.z * f;
|
||||
}
|
||||
else
|
||||
{
|
||||
out.w = 1.0;
|
||||
out.x = out.y = out.z = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
void ImOrient::QuatFromDir(ImQuat& out, const ImVec3& dir)
|
||||
{
|
||||
// compute a quaternion that rotates (1,0,0) to (dx,dy,dz)
|
||||
float dn = sqrtf(dir.x * dir.x + dir.y * dir.y + dir.z * dir.z);
|
||||
if(dn < FLT_EPSILON * FLT_EPSILON)
|
||||
{
|
||||
out.x = out.y = out.z = 0;
|
||||
out.w = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
ImVec3 rotAxis = {0, -dir.z, dir.y};
|
||||
if(rotAxis.x * rotAxis.x + rotAxis.y * rotAxis.y + rotAxis.z * rotAxis.z < (FLT_EPSILON * FLT_EPSILON))
|
||||
{
|
||||
rotAxis.x = rotAxis.y = 0;
|
||||
rotAxis.z = 1;
|
||||
}
|
||||
float rotAngle = (float)acos(dir.x / dn);
|
||||
ImQuat rotQuat;
|
||||
QuatFromAxisAngle(rotQuat, rotAxis, rotAngle);
|
||||
out.x = rotQuat.x;
|
||||
out.y = rotQuat.y;
|
||||
out.z = rotQuat.z;
|
||||
out.w = rotQuat.w;
|
||||
}
|
||||
}
|
||||
254
raytracer/nvpro_core/imgui/imgui_orient.h
Normal file
254
raytracer/nvpro_core/imgui/imgui_orient.h
Normal file
|
|
@ -0,0 +1,254 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2023, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2021 NVIDIA CORPORATION
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <cfloat>
|
||||
#include <cmath>
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.1415926535
|
||||
#endif
|
||||
|
||||
/* @DOC_START
|
||||
|
||||
# struct ImOrient
|
||||
> brief This is a really nice implementation of an orientation widget; all due respect to the original author ;)
|
||||
|
||||
This is a port of the AntTweakBar orientation widget, which is a 3D orientation widget that allows the user to specify a
|
||||
3D orientation using a quaternion, axis-angle, or direction vector. It is a very useful widget for 3D applications.
|
||||
|
||||
--- @DOC_END ------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
Notes from: www.github.com/cmaughan
|
||||
|
||||
Ported from AntTweakBar
|
||||
|
||||
Dependencies kept to a minimum. I basically vectorized the original code, added a few math types, cleaned things up and
|
||||
made it clearer what the maths was doing.
|
||||
|
||||
I tried to make it more imgui-like, and removed all the excess stuff not needed here. This still needs work.
|
||||
|
||||
I also added triangle culling because ImGui doesn't support winding clip
|
||||
|
||||
The widget works by transforming the 3D object to screen space and clipping the triangles. This makes it work with any
|
||||
imgui back end, without modifications to the renderers.
|
||||
|
||||
\todo More cleanup.
|
||||
\todo Figure out what ShowDir is for.
|
||||
\todo Test direction vectors more
|
||||
*/
|
||||
|
||||
// --------------------------
|
||||
// Firstly, a little math, missing from ImGui but needed for this widget
|
||||
// A Vec3, Matrix 3x3, Dot & Cross products, A Quaternion. Some helper functions, bare minimum
|
||||
struct ImVec3
|
||||
{
|
||||
float x, y, z;
|
||||
ImVec3() { x = y = z = 0.0f; }
|
||||
ImVec3(float _x, float _y, float _z)
|
||||
{
|
||||
x = _x;
|
||||
y = _y;
|
||||
z = _z;
|
||||
}
|
||||
|
||||
ImVec3 RotY() const { return ImVec3(-z, y, x); }
|
||||
ImVec3 RotZ() const { return ImVec3(-y, x, z); }
|
||||
ImVec3 Cross(const ImVec3& b) const { return ImVec3(y * b.z - z * b.y, z * b.x - x * b.z, x * b.y - y * b.x); }
|
||||
float Dot(const ImVec3& b) const { return x * b.x + y * b.y + z * b.z; }
|
||||
ImVec3 Mult(float val) const { return ImVec3(x * val, y * val, z * val); }
|
||||
ImVec3 Div(float val) const { return ImVec3(x / val, y / val, z / val); }
|
||||
float Length() const { return sqrtf(x * x + y * y + z * z); }
|
||||
#ifdef IM_VEC3_CLASS_EXTRA // Define constructor and implicit cast operators in imconfig.h to convert back<>forth from your math types and ImVec2.
|
||||
IM_VEC3_CLASS_EXTRA
|
||||
#endif
|
||||
};
|
||||
|
||||
// Added to the existing ImVec2 vector
|
||||
inline ImVec2 ImVec2Subtract(const ImVec2& left, const ImVec2& right)
|
||||
{
|
||||
return ImVec2(left.x - right.x, left.y - right.y);
|
||||
}
|
||||
inline float ImVec2Cross(const ImVec2& left, const ImVec2& right)
|
||||
{
|
||||
return (left.x * right.y) - (left.y * right.x);
|
||||
}
|
||||
|
||||
struct ImQuat
|
||||
{
|
||||
float x, y, z, w;
|
||||
ImQuat()
|
||||
{
|
||||
x = y = z = 0.0f;
|
||||
w = 1.0f;
|
||||
}
|
||||
ImQuat(float _x, float _y, float _z, float _w)
|
||||
{
|
||||
x = _x;
|
||||
y = _y;
|
||||
z = _z;
|
||||
w = _w;
|
||||
}
|
||||
|
||||
ImQuat Div(float val) { return ImQuat(x / val, y / val, z / val, w / val); }
|
||||
ImVec3 Rotate(const ImVec3& dir)
|
||||
{
|
||||
float ps = -x * dir.x - y * dir.y - z * dir.z;
|
||||
float px = w * dir.x + y * dir.z - z * dir.y;
|
||||
float py = w * dir.y + z * dir.x - x * dir.z;
|
||||
float pz = w * dir.z + x * dir.y - y * dir.x;
|
||||
return ImVec3(-ps * x + px * w - py * z + pz * y, -ps * y + py * w - pz * x + px * z, -ps * z + pz * w - px * y + py * x);
|
||||
}
|
||||
|
||||
ImQuat Mult(const ImQuat& q2)
|
||||
{
|
||||
ImQuat out;
|
||||
out.x = w * q2.x + x * q2.w + y * q2.z - z * q2.y;
|
||||
out.y = w * q2.y + y * q2.w + z * q2.x - x * q2.z;
|
||||
out.z = w * q2.z + z * q2.w + x * q2.y - y * q2.x;
|
||||
out.w = w * q2.w - (x * q2.x + y * q2.y + z * q2.z);
|
||||
return out;
|
||||
}
|
||||
#ifdef IM_QUAT_CLASS_EXTRA // Define constructor and implicit cast operators in imconfig.h to convert back<>forth from your math types and ImVec2.
|
||||
IM_QUAT_CLASS_EXTRA
|
||||
#endif
|
||||
};
|
||||
|
||||
// Matrix used to allow user to specify axis orientation
|
||||
struct ImMat3x3
|
||||
{
|
||||
float m[3][3];
|
||||
ImMat3x3()
|
||||
{
|
||||
for(int x = 0; x < 3; x++)
|
||||
{
|
||||
for(int y = 0; y < 3; y++)
|
||||
{
|
||||
m[y][x] = (x == y) ? 1.0f : 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ImVec3 Transform(const ImVec3& vec)
|
||||
{
|
||||
ImVec3 out;
|
||||
out.x = m[0][0] * vec.x + m[1][0] * vec.y + m[2][0] * vec.z;
|
||||
out.y = m[0][1] * vec.x + m[1][1] * vec.y + m[2][1] * vec.z;
|
||||
out.z = m[0][2] * vec.x + m[1][2] * vec.y + m[2][2] * vec.z;
|
||||
return out;
|
||||
}
|
||||
|
||||
ImVec3 TransformInv(const ImVec3& vec)
|
||||
{
|
||||
ImVec3 out;
|
||||
out.x = m[0][0] * vec.x + m[0][1] * vec.y + m[0][2] * vec.z;
|
||||
out.y = m[1][0] * vec.x + m[1][1] * vec.y + m[1][2] * vec.z;
|
||||
out.z = m[2][0] * vec.x + m[2][1] * vec.y + m[2][2] * vec.z;
|
||||
return out;
|
||||
}
|
||||
};
|
||||
|
||||
inline float ImDegToRad(float degree)
|
||||
{
|
||||
return degree * (float(M_PI) / 180.0f);
|
||||
}
|
||||
inline float ImRadToDeg(float radian)
|
||||
{
|
||||
return radian * (180.0f / float(M_PI));
|
||||
}
|
||||
|
||||
// The data structure that holds the orientation among other things
|
||||
struct ImOrient
|
||||
{
|
||||
ImQuat Qt; // Quaternion value
|
||||
|
||||
ImVec3 Axis; // Axis and Angle
|
||||
float Angle = 0.0f;
|
||||
|
||||
ImVec3 Dir; // Dir value set when used as a direction
|
||||
bool m_AAMode = false; // Axis & angle mode
|
||||
bool m_IsDir = false; // Mapped to a dir vector instead of a quat
|
||||
ImVec3 m_ShowDir; // CM: Not sure what this is all about?
|
||||
ImU32 m_DirColor{}; // Direction vector color
|
||||
|
||||
ImMat3x3 AxisTransform; // Transform to required axis frame
|
||||
|
||||
// For the geometry
|
||||
enum EArrowParts
|
||||
{
|
||||
ARROW_CONE,
|
||||
ARROW_CONE_CAP,
|
||||
ARROW_CYL,
|
||||
ARROW_CYL_CAP
|
||||
};
|
||||
static ImVector<ImVec3> s_SphTri;
|
||||
static ImVector<ImU32> s_SphCol;
|
||||
static ImVector<ImVec2> s_SphTriProj;
|
||||
static ImVector<ImU32> s_SphColLight;
|
||||
static ImVector<ImVec3> s_ArrowTri[4];
|
||||
static ImVector<ImVec2> s_ArrowTriProj[4];
|
||||
static ImVector<ImVec3> s_ArrowNorm[4];
|
||||
static ImVector<ImU32> s_ArrowColLight[4];
|
||||
static void CreateSphere();
|
||||
static void CreateArrow();
|
||||
|
||||
IMGUI_API bool Draw(const char* label, bool show_info = false);
|
||||
IMGUI_API void DrawTriangles(ImDrawList* draw_list,
|
||||
const ImVec2& offset,
|
||||
const ImVector<ImVec2>& triProj,
|
||||
const ImVector<ImU32>& colLight,
|
||||
int numVertices,
|
||||
float cullDir);
|
||||
IMGUI_API void ConvertToAxisAngle();
|
||||
IMGUI_API void ConvertFromAxisAngle();
|
||||
|
||||
// Quaternions
|
||||
inline float QuatD(float w, float h) { return (float)std::min(std::abs(w), std::abs(h)) - 4.0f; }
|
||||
inline float QuatPX(float x, float w, float h) { return (x * 0.5f * QuatD(w, h) + w * 0.5f + 0.5f); }
|
||||
inline float QuatPY(float y, float w, float h) { return (-y * 0.5f * QuatD(w, h) + h * 0.5f - 0.5f); }
|
||||
inline float QuatIX(int x, float w, float h) { return (2.0f * x - w - 1.0f) / QuatD(w, h); }
|
||||
inline float QuatIY(int y, float w, float h) { return (-2.0f * y + h - 1.0f) / QuatD(w, h); }
|
||||
IMGUI_API void QuatFromDir(ImQuat& quat, const ImVec3& dir);
|
||||
IMGUI_API static void QuatFromAxisAngle(ImQuat& qt, const ImVec3& axis, float angle);
|
||||
|
||||
// Useful colors
|
||||
IMGUI_API static ImU32 ColorBlend(ImU32 _Color1, ImU32 _Color2, float _S);
|
||||
|
||||
typedef unsigned int color32;
|
||||
const ImU32 COLOR32_BLACK = 0xff000000; // Black
|
||||
const ImU32 COLOR32_WHITE = 0xffffffff; // White
|
||||
const ImU32 COLOR32_ZERO = 0x00000000; // Zero
|
||||
const ImU32 COLOR32_RED = 0xffff0000; // Red
|
||||
const ImU32 COLOR32_GREEN = 0xff00ff00; // Green
|
||||
const ImU32 COLOR32_BLUE = 0xff0000ff; // Blue
|
||||
|
||||
const int GIZMO_SIZE = 100;
|
||||
};
|
||||
|
||||
// The API
|
||||
namespace ImGui {
|
||||
|
||||
IMGUI_API bool QuaternionGizmo(const char* label, ImQuat& quat);
|
||||
IMGUI_API bool AxisAngleGizmo(const char* label, ImVec3& axis, float& angle);
|
||||
IMGUI_API bool DirectionGizmo(const char* label, float* dir, bool flip = false, bool show_info = false);
|
||||
|
||||
}; // namespace ImGui
|
||||
Loading…
Add table
Add a link
Reference in a new issue