diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index be22e51d..da241218 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -16,7 +16,7 @@ jobs: - uses: actions/checkout@v2 with: submodules: recursive - - run: brew install boost ilmbase openexr tbb@2020 glm libomp eigen libpng + - run: brew install boost ilmbase tbb@2020 glm eigen - name: Run tests run: make test @@ -43,7 +43,7 @@ jobs: with: msystem: MINGW64 update: true - install: "git diffutils mingw-w64-x86_64-clang make mingw-w64-x86_64-cmake mingw-w64-x86_64-boost mingw-w64-x86_64-mesa mingw-w64-x86_64-openexr mingw-w64-x86_64-intel-tbb mingw-w64-x86_64-glm mingw-w64-x86_64-glew mingw-w64-x86_64-dbus patch mingw-w64-x86_64-openvdb mingw-w64-x86_64-ccache mingw-w64-x86_64-libpng mingw-w64-x86_64-eigen3" + install: "git diffutils mingw-w64-x86_64-gcc make mingw-w64-x86_64-cmake mingw-w64-x86_64-boost mingw-w64-x86_64-mesa mingw-w64-x86_64-openexr mingw-w64-x86_64-intel-tbb mingw-w64-x86_64-glm mingw-w64-x86_64-glew mingw-w64-x86_64-dbus patch mingw-w64-x86_64-openvdb mingw-w64-x86_64-ccache mingw-w64-x86_64-libpng mingw-w64-x86_64-eigen3" - name: ccache cache files uses: actions/cache@v2 @@ -86,6 +86,7 @@ jobs: run: | sudo apt install clang cmake git-core libboost-all-dev libopenexr-dev libtbb-dev libglm-dev dbus-x11 sudo apt install libxcursor-dev libxinerama-dev libxrandr-dev libgl-dev libxi-dev libpng-dev libeigen3-dev + sudo apt install libfuse2 - name: Build AppImage run: | diff --git a/.gitmodules b/.gitmodules index d058ce1d..9856965e 100644 --- a/.gitmodules +++ b/.gitmodules @@ -21,4 +21,4 @@ url = https://github.com/g-truc/glm.git [submodule "extern/libfive"] path = extern/libfive - url = https://github.com/curv3d/libfive + url = https://github.com/libfive/libfive diff --git a/CMakeLists.txt b/CMakeLists.txt index d7913313..265777a4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,14 @@ cmake_minimum_required(VERSION 3.12) + +# Thanks https://stackoverflow.com/a/50313990 +# Now how do we make this robust +if (APPLE) + set(CMAKE_C_COMPILER "/usr/local/Cellar/llvm/15.0.7_1/bin/clang") + set(CMAKE_CXX_COMPILER "/usr/local/Cellar/llvm/15.0.7_1/bin/clang++") + set(OPENMP_LIBRARIES "/usr/local/Cellar/llvm/15.0.7_1/lib") + set(OPENMP_INCLUDES "/usr/local/Cellar/llvm/15.0.7_1/include") +endif () + project(curv) if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR) @@ -44,12 +54,9 @@ if (APPLE) # or /opt/homebrew for Apple Silicon (bug #128) # Also, we now depend on tbb@2020, not tbb, due to openvdb not supporting # latest version (June 5 2021). - include_directories(SYSTEM - /usr/local/opt/tbb@2020/include /opt/homebrew/opt/tbb@2020/include - /usr/local/include /opt/homebrew/include) - link_directories( - /usr/local/opt/tbb@2020/lib /opt/homebrew/opt/tbb@2020/lib - /usr/local/lib /opt/homebrew/lib) + include_directories(SYSTEM /usr/local/include) + include_directories(/usr/local/opt/tbb@2020/include) + link_directories(/usr/local/opt/tbb@2020/lib) endif (APPLE) # Libraries @@ -104,14 +111,16 @@ set_property(TARGET glad PROPERTY CXX_STANDARD 17) # Dear IMGUI library add_library(imgui - extern/imgui/examples/imgui_impl_glfw.cpp - extern/imgui/examples/imgui_impl_opengl3.cpp + extern/imgui/backends/imgui_impl_glfw.cpp + extern/imgui/backends/imgui_impl_opengl3.cpp extern/imgui/imgui.cpp extern/imgui/imgui_demo.cpp extern/imgui/imgui_draw.cpp + extern/imgui/imgui_tables.cpp extern/imgui/imgui_widgets.cpp) target_include_directories(imgui - PUBLIC extern/imgui extern/imgui/examples) + PUBLIC extern/imgui extern/imgui/examples + extern/imgui/backends) target_link_libraries(imgui PUBLIC glfw glad) target_compile_definitions(imgui PUBLIC IMGUI_IMPL_OPENGL_LOADER_GLAD ) @@ -145,14 +154,6 @@ endif () # Boost library (Windows port required 1.72, 1.65 is latest for Ubuntu 18.04) find_package(Boost 1.65 REQUIRED COMPONENTS iostreams system) -# imdemo, broken in v1.65 of ImGui, need to upgrade to headrev -#add_executable(imdemo -# extern/imgui/examples/example_glfw_opengl3/main.cpp) -#target_include_directories(imdemo -# PUBLIC extern/imgui/examples/example_glfw_opengl3) -#target_link_libraries(imdemo PUBLIC glfw glad imgui ${LibOpenGL}) -#set_property(TARGET imdemo PROPERTY CXX_STANDARD 17) - # Libraries End # =============================================== @@ -180,11 +181,6 @@ if (MSYS) else () set(LibDl "dl") endif () -if (APPLE) - set(LibOmp "omp") -else () - set(LibOmp "") -endif () if (LEAN_BUILD) set(FatLibraries "") else () @@ -194,7 +190,7 @@ set(Libs libcurv_io libcurv imgui glfw glad ${LibOpenGL} replxx double-conversion tmc ${FatLibraries} Boost::iostreams Boost::system - pthread ${LibDl} ${LibOmp}) + pthread ${LibDl}) target_link_libraries(curv PUBLIC ${Libs}) @@ -204,11 +200,36 @@ target_link_libraries(tester PUBLIC gtest pthread libcurv libcurv_io double-conv set_property(TARGET curv libcurv libcurv_io tester PROPERTY CXX_STANDARD 17) +# Thanks https://stackoverflow.com/a/50313990, and no thanks Apple if (APPLE) - set(ompflags "-Xpreprocessor -fopenmp") + set(ompflags "") + if(CMAKE_C_COMPILER_ID MATCHES "Clang") + set(OpenMP_C "${CMAKE_C_COMPILER}") + set(OpenMP_C_FLAGS "-fopenmp=libomp -Wno-unused-command-line-argument") + set(OpenMP_C_LIB_NAMES "libomp" "libgomp" "libiomp5") + set(OpenMP_libomp_LIBRARY ${OpenMP_C_LIB_NAMES}) + set(OpenMP_libgomp_LIBRARY ${OpenMP_C_LIB_NAMES}) + set(OpenMP_libiomp5_LIBRARY ${OpenMP_C_LIB_NAMES}) + endif() + if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") + set(OpenMP_CXX "${CMAKE_CXX_COMPILER}") + set(OpenMP_CXX_FLAGS "-fopenmp=libomp -Wno-unused-command-line-argument") + set(OpenMP_CXX_LIB_NAMES "libomp" "libgomp" "libiomp5") + set(OpenMP_libomp_LIBRARY ${OpenMP_CXX_LIB_NAMES}) + set(OpenMP_libgomp_LIBRARY ${OpenMP_CXX_LIB_NAMES}) + set(OpenMP_libiomp5_LIBRARY ${OpenMP_CXX_LIB_NAMES}) + endif() + if (OPENMP_FOUND) + include_directories("${OPENMP_INCLUDES}") + link_directories("${OPENMP_LIBRARIES}") + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") + # set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}") + endif(OPENMP_FOUND) else () - set(ompflags "-fopenmp") + set(ompflags ${OpenMP_C_FLAGS}) endif () + set(gccflags "-Wall -Wno-unused-result ${ompflags}" ) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${gccflags}" ) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${gccflags}" ) @@ -234,9 +255,9 @@ endif() if (NOT DEFINED MSYS) # On MSYS we use MinGW packages for OpenVDB and GoogleTest. # Copy or stub definitions from extern/openvdb/CMakeLists.txt - set(OpenVDB_MAJOR_VERSION 8) - set(OpenVDB_MINOR_VERSION 1) - set(OpenVDB_PATCH_VERSION 0) + set(OpenVDB_MAJOR_VERSION 10) + set(OpenVDB_MINOR_VERSION 0) + set(OpenVDB_PATCH_VERSION 1) set(OpenVDB_ABI ${OpenVDB_MAJOR_VERSION}) set(OPENVDB_ABI_VERSION_NUMBER ${OpenVDB_MAJOR_VERSION}) set(OPENVDB_INSTALL_INCLUDEDIR openvdb_install_includedir) @@ -245,7 +266,7 @@ if (NOT DEFINED MSYS) add_library(TBB::tbb ALIAS dummy) if (NOT LEAN_BUILD) add_subdirectory(extern/openvdb/openvdb/openvdb EXCLUDE_FROM_ALL) - set_property(TARGET openvdb_static PROPERTY CXX_STANDARD 14) + set_property(TARGET openvdb_static PROPERTY CXX_STANDARD 17) endif() add_subdirectory(extern/googletest/googletest EXCLUDE_FROM_ALL) endif () diff --git a/curv/repl.cc b/curv/repl.cc index b0ecc82d..e4aab6d0 100644 --- a/curv/repl.cc +++ b/curv/repl.cc @@ -256,7 +256,7 @@ void color_input(std::string const& context, Replxx::colors_t& colors, case Token::k_bad_token: case Token::k_bad_utf8: - col = Color::ERROR; + col = Color::RED; break; // numerals @@ -323,7 +323,7 @@ void color_input(std::string const& context, Replxx::colors_t& colors, } } catch (Exception& e) { auto tok = e.loc_.front().srcloc_.token(); - set_colour(colors, tok, Color::ERROR); + set_colour(colors, tok, Color::RED); } } diff --git a/extern/double-conversion b/extern/double-conversion index 067c8874..256ac809 160000 --- a/extern/double-conversion +++ b/extern/double-conversion @@ -1 +1 @@ -Subproject commit 067c88740377740d9d9c0a44320fac894e9a090d +Subproject commit 256ac809561b756645e73ab7127c2aaaeabaa427 diff --git a/extern/glfw b/extern/glfw index 814b7929..8f470597 160000 --- a/extern/glfw +++ b/extern/glfw @@ -1 +1 @@ -Subproject commit 814b7929c5add4b0541ccad26fb81f28b71dc4d8 +Subproject commit 8f470597d625ae28758c16b4293dd42d63e8a83a diff --git a/extern/glm b/extern/glm index 4db8f89a..efec5db0 160000 --- a/extern/glm +++ b/extern/glm @@ -1 +1 @@ -Subproject commit 4db8f89aace8f04c839b606e15b39fb8383ec732 +Subproject commit efec5db081e3aad807d0731e172ac597f6a39447 diff --git a/extern/imgui b/extern/imgui index e0cab566..d73e3285 160000 --- a/extern/imgui +++ b/extern/imgui @@ -1 +1 @@ -Subproject commit e0cab5664adf02c030f9cf2a05d2c334638a85f8 +Subproject commit d73e3285dea2bb352f3a9c0696120091f0b95f0e diff --git a/extern/libfive b/extern/libfive index 4eb5d64f..394b4631 160000 --- a/extern/libfive +++ b/extern/libfive @@ -1 +1 @@ -Subproject commit 4eb5d64fad4414307d87bd4806fe52cddecc70a0 +Subproject commit 394b4631192f9f1085f13c71129c93ce3eff0cae diff --git a/extern/openvdb b/extern/openvdb index cc126965..cbcf15ff 160000 --- a/extern/openvdb +++ b/extern/openvdb @@ -1 +1 @@ -Subproject commit cc12696522dd317fa606e19bafa8c78bd4319eb0 +Subproject commit cbcf15ff8ba50c7c2ec0d22b5bed2aef657ce3a9 diff --git a/extern/ordered-map b/extern/ordered-map index 4051af7e..eba0b81b 160000 --- a/extern/ordered-map +++ b/extern/ordered-map @@ -1 +1 @@ -Subproject commit 4051af7e344e0c0c6af5573b064342c0987d1028 +Subproject commit eba0b81b89c42232e8a937389be303a33f34a527 diff --git a/extern/replxx b/extern/replxx index b901d5fb..1f149bfe 160000 --- a/extern/replxx +++ b/extern/replxx @@ -1 +1 @@ -Subproject commit b901d5fb03e74ad7ec1db2a3de2cc130f6a205d3 +Subproject commit 1f149bfe20bf6e49c1afd4154eaf0032c8c2fda2 diff --git a/libcurv/viewer/scale_picker.cc b/libcurv/viewer/scale_picker.cc deleted file mode 100644 index fbdbef43..00000000 --- a/libcurv/viewer/scale_picker.cc +++ /dev/null @@ -1,336 +0,0 @@ -// Copyright 2016-2021 Doug Moen -// Licensed under the Apache License, version 2.0 -// See https://www.apache.org/licenses/LICENSE-2.0 - -// Based on code in ImGui v1.65, which is: -// Copyright (c) 2014-2018 Omar Cornut -// Licensed under the MIT Licence -// See https://opensource.org/licenses/MIT - -#include -#ifndef IMGUI_DEFINE_MATH_OPERATORS -#define IMGUI_DEFINE_MATH_OPERATORS -#endif -#include -using namespace ImGui; - -#include "scale_picker.h" - -#include // toupper, isprint -#include // intptr_t -#include - -// Those MIN/MAX values are not define because we need to point to them -#if 0 -static const ImS32 IM_S32_MIN = INT_MIN; // (-2147483647 - 1), (0x80000000); -static const ImS32 IM_S32_MAX = INT_MAX; // (2147483647), (0x7FFFFFFF) -static const ImU32 IM_U32_MIN = 0; -static const ImU32 IM_U32_MAX = UINT_MAX; // (0xFFFFFFFF) -#ifdef LLONG_MIN -static const ImS64 IM_S64_MIN = LLONG_MIN; // (-9223372036854775807ll - 1ll); -static const ImS64 IM_S64_MAX = LLONG_MAX; // (9223372036854775807ll); -#else -static const ImS64 IM_S64_MIN = -9223372036854775807LL - 1; -static const ImS64 IM_S64_MAX = 9223372036854775807LL; -#endif -static const ImU64 IM_U64_MIN = 0; -#ifdef ULLONG_MAX -static const ImU64 IM_U64_MAX = ULLONG_MAX; // (0xFFFFFFFFFFFFFFFFull); -#else -static const ImU64 IM_U64_MAX = (2ULL * 9223372036854775807LL + 1); -#endif -#endif - -struct ImGuiDataTypeInfo -{ - size_t Size; - const char* PrintFmt; // Unused - const char* ScanFmt; -}; - -static const ImGuiDataTypeInfo GDataTypeInfo[] = -{ - { sizeof(int), "%d", "%d" }, - { sizeof(unsigned int), "%u", "%u" }, -#ifdef _MSC_VER - { sizeof(ImS64), "%I64d","%I64d" }, - { sizeof(ImU64), "%I64u","%I64u" }, -#else - { sizeof(ImS64), "%lld", "%lld" }, - { sizeof(ImU64), "%llu", "%llu" }, -#endif - { sizeof(float), "%f", "%f" }, // float are promoted to double in va_arg - { sizeof(double), "%f", "%lf" }, -}; -IM_STATIC_ASSERT(IM_ARRAYSIZE(GDataTypeInfo) == ImGuiDataType_COUNT); - -// FIXME-LEGACY: Prior to 1.61 our DragInt() function internally used floats and because of this the compile-time default value for format was "%.0f". -// Even though we changed the compile-time default, we expect users to have carried %f around, which would break the display of DragInt() calls. -// To honor backward compatibility we are rewriting the format string, unless IMGUI_DISABLE_OBSOLETE_FUNCTIONS is enabled. What could possibly go wrong?! -static const char* -PatchFormatStringFloatToInt(const char* fmt) -{ - if (fmt[0] == '%' && fmt[1] == '.' && fmt[2] == '0' && fmt[3] == 'f' && fmt[4] == 0) // Fast legacy path for "%.0f" which is expected to be the most common case. - return "%d"; - const char* fmt_start = ImParseFormatFindStart(fmt); // Find % (if any, and ignore %%) - const char* fmt_end = ImParseFormatFindEnd(fmt_start); // Find end of format specifier, which itself is an exercise of confidence/recklessness (because snprintf is dependent on libc or user). - if (fmt_end > fmt_start && fmt_end[-1] == 'f') - { -#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS - if (fmt_start == fmt && fmt_end[0] == 0) - return "%d"; - ImGuiContext& g = *GImGui; - ImFormatString(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), "%.*s%%d%s", (int)(fmt_start - fmt), fmt, fmt_end); // Honor leading and trailing decorations, but lose alignment/precision. - return g.TempBuffer; -#else - IM_ASSERT(0 && "DragInt(): Invalid format string!"); // Old versions used a default parameter of "%.0f", please replace with e.g. "%d" -#endif - } - return fmt; -} - -static inline int -DataTypeFormatString(char* buf, int buf_size, ImGuiDataType data_type, const void* data_ptr, const char* format) -{ - if (data_type == ImGuiDataType_S32 || data_type == ImGuiDataType_U32) // Signedness doesn't matter when pushing the argument - return ImFormatString(buf, buf_size, format, *(const ImU32*)data_ptr); - if (data_type == ImGuiDataType_S64 || data_type == ImGuiDataType_U64) // Signedness doesn't matter when pushing the argument - return ImFormatString(buf, buf_size, format, *(const ImU64*)data_ptr); - if (data_type == ImGuiDataType_Float) - return ImFormatString(buf, buf_size, format, *(const float*)data_ptr); - if (data_type == ImGuiDataType_Double) - return ImFormatString(buf, buf_size, format, *(const double*)data_ptr); - IM_ASSERT(0); - return 0; -} - -static float -GetMinimumStepAtDecimalPrecision(int decimal_precision) -{ - static const float min_steps[10] = { 1.0f, 0.1f, 0.01f, 0.001f, 0.0001f, 0.00001f, 0.000001f, 0.0000001f, 0.00000001f, 0.000000001f }; - if (decimal_precision < 0) - return FLT_MIN; - return (decimal_precision >= 0 && decimal_precision < 10) ? min_steps[decimal_precision] : ImPow(10.0f, (float)-decimal_precision); -} - -// This is called by DragBehavior() when the widget is active (held by mouse or being manipulated with Nav controls) -template -bool -MyDragBehaviorT(ImGuiDataType data_type, TYPE* v, float v_speed, const TYPE v_min, const TYPE v_max, const char* format, float power) -{ - ImGuiContext& g = *GImGui; - - // Default tweak speed - bool has_min_max = (v_min != v_max) && (v_max - v_max < FLT_MAX); -#if 0 - if (v_speed == 0.0f && has_min_max) - v_speed = (float)((v_max - v_min) * g.DragSpeedDefaultRatio); -std::cerr << ","< 1.0f*1.0f) - { - adjust_delta = g.IO.MouseDelta.x; - if (g.IO.KeyAlt) - adjust_delta *= 1.0f/10.0f; - if (g.IO.KeyShift) - adjust_delta *= 10.0f; - } - else if (g.ActiveIdSource == ImGuiInputSource_Nav) - { - int decimal_precision = (data_type == ImGuiDataType_Float || data_type == ImGuiDataType_Double) ? ImParseFormatPrecision(format, 3) : 0; - adjust_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_Keyboard|ImGuiNavDirSourceFlags_PadDPad, ImGuiInputReadMode_RepeatFast, 1.0f/10.0f, 10.0f).x; - v_speed = ImMax(v_speed, GetMinimumStepAtDecimalPrecision(decimal_precision)); - } - adjust_delta *= v_speed; - - // Clear current value on activation - // Avoid altering values and clamping when we are _already_ past the limits and heading in the same direction, so e.g. if range is 0..255, current value is 300 and we are pushing to the right side, keep the 300. - bool is_just_activated = g.ActiveIdIsJustActivated; - bool is_already_past_limits_and_pushing_outward = has_min_max && ((*v >= v_max && adjust_delta > 0.0f) || (*v <= v_min && adjust_delta < 0.0f)); - if (is_just_activated || is_already_past_limits_and_pushing_outward) - { - g.DragCurrentAccum = 0.0f; - g.DragCurrentAccumDirty = false; - } - else if (adjust_delta != 0.0f) - { - g.DragCurrentAccum += adjust_delta; - g.DragCurrentAccumDirty = true; - } - - if (!g.DragCurrentAccumDirty) - return false; - - TYPE v_cur = *v; - //FLOATTYPE v_old_ref_for_accum_remainder = (FLOATTYPE)0.0f; - - const bool is_power = (power != 1.0f); - if (is_power) - { - #if 0 - // Offset + round to user desired precision, with a curve on the v_min..v_max range to get more precision on one side of the range - FLOATTYPE v_old_norm_curved = ImPow((FLOATTYPE)(v_cur - v_min) / (FLOATTYPE)(v_max - v_min), (FLOATTYPE)1.0f / power); - FLOATTYPE v_new_norm_curved = v_old_norm_curved + (g.DragCurrentAccum / (v_max - v_min)); - v_cur = v_min + (TYPE)ImPow(ImSaturate((float)v_new_norm_curved), power) * (v_max - v_min); - v_old_ref_for_accum_remainder = v_old_norm_curved; - #else - v_cur *= pow(power, g.DragCurrentAccum); - #endif - } - else - { - v_cur += (TYPE)g.DragCurrentAccum; - } - - // Round to user desired precision based on format string - //v_cur = RoundScalarWithFormatT(format, data_type, v_cur); - -#if 0 - // Preserve remainder after rounding has been applied. This also allow slow tweaking of values. - g.DragCurrentAccumDirty = false; - if (is_power) - { - FLOATTYPE v_cur_norm_curved = ImPow((FLOATTYPE)(v_cur - v_min) / (FLOATTYPE)(v_max - v_min), (FLOATTYPE)1.0f / power); - g.DragCurrentAccum -= (float)(v_cur_norm_curved - v_old_ref_for_accum_remainder); - } - else - { - g.DragCurrentAccum -= (float)((SIGNEDTYPE)v_cur - (SIGNEDTYPE)*v); - } -#endif - - // Lose zero sign for float/double - if (v_cur == (TYPE)-0) - v_cur = (TYPE)0; - - // Clamp values (handle overflow/wrap-around) -#if 0 - if (*v != v_cur && has_min_max) - { - if (v_cur < v_min || (v_cur > *v && adjust_delta < 0.0f)) - v_cur = v_min; - if (v_cur > v_max || (v_cur < *v && adjust_delta > 0.0f)) - v_cur = v_max; - } -#else - if (v_cur < FLT_MIN) v_cur = FLT_MIN; - if (v_cur > FLT_MAX) v_cur = FLT_MAX; -#endif - - // Apply result - if (*v == v_cur) - return false; - *v = v_cur; - return true; -} - -bool -MyDragBehavior(ImGuiID id, ImGuiDataType data_type, void* v, float v_speed, const void* v_min, const void* v_max, const char* format, float power) -{ - ImGuiContext& g = *GImGui; - if (g.ActiveId == id) - { - if (g.ActiveIdSource == ImGuiInputSource_Mouse && !g.IO.MouseDown[0]) - ClearActiveID(); - else if (g.ActiveIdSource == ImGuiInputSource_Nav && g.NavActivatePressedId == id && !g.ActiveIdIsJustActivated) - ClearActiveID(); - } - if (g.ActiveId != id) - return false; - - return MyDragBehaviorT(data_type, (float*)v, v_speed, v_min ? *(const float* )v_min : -FLT_MAX, v_max ? *(const float* )v_max : FLT_MAX, format, power); -} - -bool -MyDragScalar(const char* label, ImGuiDataType data_type, void* v, float v_speed, const void* v_min, const void* v_max, const char* format, float power) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - - if (power != 1.0f) - IM_ASSERT(v_min != NULL && v_max != NULL); // When using a power curve the drag needs to have known bounds - - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; - const ImGuiID id = window->GetID(label); - const float w = CalcItemWidth(); - - const ImVec2 label_size = CalcTextSize(label, NULL, true); - const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y*2.0f)); - const ImRect inner_bb(frame_bb.Min + style.FramePadding, frame_bb.Max - style.FramePadding); - const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f)); - - // NB- we don't call ItemSize() yet because we may turn into a text edit box below - if (!ItemAdd(total_bb, id, &frame_bb)) - { - ItemSize(total_bb, style.FramePadding.y); - return false; - } - const bool hovered = ItemHoverable(frame_bb, id); - - // Default format string when passing NULL - // Patch old "%.0f" format string to use "%d", read function comments for more details. - IM_ASSERT(data_type >= 0 && data_type < ImGuiDataType_COUNT); - if (format == NULL) - format = GDataTypeInfo[data_type].PrintFmt; - else if (data_type == ImGuiDataType_S32 && strcmp(format, "%d") != 0) - format = PatchFormatStringFloatToInt(format); - - // Tabbing or CTRL-clicking on Drag turns it into an input box - bool start_text_input = false; - const bool tab_focus_requested = FocusableItemRegister(window, id); - if (tab_focus_requested || (hovered && (g.IO.MouseClicked[0] || g.IO.MouseDoubleClicked[0])) || g.NavActivateId == id || (g.NavInputId == id && g.ScalarAsInputTextId != id)) - { - SetActiveID(id, window); - SetFocusID(id, window); - FocusWindow(window); - g.ActiveIdAllowNavDirFlags = (1 << ImGuiDir_Up) | (1 << ImGuiDir_Down); - if (tab_focus_requested || g.IO.KeyCtrl || g.IO.MouseDoubleClicked[0] || g.NavInputId == id) - { - start_text_input = true; - g.ScalarAsInputTextId = 0; - } - } - if (start_text_input || (g.ActiveId == id && g.ScalarAsInputTextId == id)) - return InputScalarAsWidgetReplacement(frame_bb, id, label, data_type, v, format); - - // Actual drag behavior - ItemSize(total_bb, style.FramePadding.y); - const bool value_changed = MyDragBehavior(id, data_type, v, v_speed, v_min, v_max, format, power); - if (value_changed) - MarkItemEdited(id); - - // Draw frame - const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : g.HoveredId == id ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg); - RenderNavHighlight(frame_bb, id); - RenderFrame(frame_bb.Min, frame_bb.Max, frame_col, true, style.FrameRounding); - - // Display value using user-provided display format so user can add prefix/suffix/decorations to the value. - char value_buf[64]; - const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_ARRAYSIZE(value_buf), data_type, v, format); - RenderTextClipped(frame_bb.Min, frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f, 0.5f)); - - if (label_size.x > 0.0f) - RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, inner_bb.Min.y), label); - - return value_changed; -} - -bool -run_scale_picker(const char* label, float* v) -{ - float v_min = FLT_MIN; - float v_max = FLT_MAX; - const char* format = "%g"; - float power = 2.0f; - float v_speed = 0.0005f; - bool b = MyDragScalar(label, ImGuiDataType_Float, v, - v_speed, &v_min, &v_max, format, power); - if (*v < FLT_MIN) *v = FLT_MIN; - if (*v > FLT_MAX) *v = FLT_MAX; - return b; -} diff --git a/libcurv/viewer/scale_picker.h b/libcurv/viewer/scale_picker.h deleted file mode 100644 index cecc6269..00000000 --- a/libcurv/viewer/scale_picker.h +++ /dev/null @@ -1 +0,0 @@ -bool run_scale_picker(const char* label, float* v); diff --git a/libcurv/viewer/viewer.cc b/libcurv/viewer/viewer.cc index 2fd1d593..dc4ca132 100644 --- a/libcurv/viewer/viewer.cc +++ b/libcurv/viewer/viewer.cc @@ -26,7 +26,6 @@ #include #include -#include "scale_picker.h" #include "shapes.h" #include @@ -237,7 +236,10 @@ bool Viewer::draw_frame() "CTRL+click to edit value as text.\n"); break; case Picker::Type::scale_picker: - run_scale_picker(i->first.c_str(), &i.value().pstate_.num_); + ImGui::SliderFloat( + i->first.c_str(), &i.value().pstate_.num_, + FLT_MIN, FLT_MAX, "%g", ImGuiSliderFlags_Logarithmic + ); ImGui::SameLine(); ShowHelpMarker( "Drag and hold to adjust value.\n" "SHIFT+drag changes value more quickly.\n"