├── LICENSE ├── README.md ├── im_docs ├── IMPROFX_DOC.md ├── IMPROFX_IPFC1.png ├── IMPROFX_IPFC2.png ├── IMPROFX_IPFC3.png └── IMPROFX_IPFC4.png └── improfx_control_src ├── improfx_control.h ├── improfx_control_animaxis.cpp ├── improfx_control_base.cpp ├── improfx_control_base.h ├── improfx_control_base_ms.h ├── improfx_control_dashboard.cpp ├── improfx_control_flateditor.cpp ├── improfx_control_menu.cpp └── improfx_control_shortcut.cpp /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 ཫཌཟRCSZཇདཀ 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ImProFXcontrol 2 | > 只依赖 ImGui核心 与 标准库 的ImGui自制控件. 3 | 4 | - __新增:__ 组合快捷键编辑器. 5 | - __公告:__ 当前项目状态 __维护暂停__ ... 如果有新增控件[BiliBili](https://space.bilibili.com/475659860)会同步发视频. 6 | - __更新:__ --- 7 | 8 | > Code: 2024.05.30 Docs: 2024.05.30 RCSZ 9 | 10 | __文档:__ [里边请~](https://github.com/rcszc/ImProFXcontrol/blob/main/im_docs/IMPROFX_DOC.md) 11 | 12 |

13 | 14 | 15 |

16 |

17 | 18 | 19 |

20 | 21 | --- 22 | -------------------------------------------------------------------------------- /im_docs/IMPROFX_DOC.md: -------------------------------------------------------------------------------- 1 | # ImProFXcontrol 2 | 3 | > improfx_control_src/improfx_control.h 4 | 5 | ```RCSZ``` 6 | - [x] __Update:__ 2024.05.30 7 | --- 8 | 9 | - 标准库: ```string``` ```vector``` ```cstdio``` ```chrono``` ```functional``` 10 | - ImGui: ```imgui_glfw/imgui.h``` ```imgui_glfw/imgui_internal.h``` 11 | 12 | > 使用时记得前往 improfx_control_base.h 把imgui替换为自己的路径, 然后引入 improfx_control.h 即可 ~ 13 | 14 | __说明:__ ImProFXcontrol 是独立于ImProFX框架的ImGui自制控件, 只依赖于ImGui核心和标准库, 可以容易的集成到自己的C++ImGui项目中. 15 | 16 | | Control | Time | Developers | Status | 17 | | :---: | :---: | :---: | :---: | 18 | | SmoothMenuChildWindow | 2023.12.21 | RCSZ | √ 19 | | AnimAxisEditorWindow | 2023.12.21 | RCSZ | √ 20 | | FlatEditorWindow | 2023.12.25 | RCSZ | √ 21 | | DashboardChildWindow | 2024.02.18 | RCSZ | x 22 | | ShortcutKeyEditorWindow | 2024.05.30 | RCSZ | √ 23 | 24 | --- 25 | 26 | ## 平滑(纵向)菜单 27 | > - 子窗口: 函数内会调用 ImGui::BeginChild - ImGui::EndChild 28 | > - Update: 2023.12.24 修改类名,优化样式 29 | 30 | __类定义:__ 31 | ```cpp 32 | class IMFXC_CWIN::SmoothMenuChildWindow; 33 | ``` 34 | 35 | __调用成员:__ 36 | ```cpp 37 | // 绘制菜单. 38 | void DrawMenuWindow( 39 | const char* name, // 菜单子窗口名称 40 | const std::vector& items, // 菜单选项 41 | uint32_t& count, // 菜单选项位置(索引) 42 | const ImVec4& color = ImVec4(0.55f, 0.12f, 1.0f, 0.72f), // 菜单色系 43 | const ImVec2& size = ImVec2(256.0f, 384.0f), // 菜单子窗口大小 44 | float speed = 1.0f, // 动画速度缩放 45 | float text_scale = 1.2f // 菜单子窗口内字体缩放 46 | ); 47 | ``` 48 | 49 | --- 50 | 51 | ## 动画轴编辑器 52 | > - 窗口: 函数内会调用 ImGui::Begin - ImGui::End 53 | > - Update: 2024.04.21 修复了许多Bug, 每个按钮引入渐变动画 54 | 55 | __类定义:__ 56 | ```cpp 57 | class IMFXC_WIN::AnimAxisEditorWindow; 58 | ``` 59 | 60 | __数据结构:__ 61 | ```cpp 62 | #define ANE_COORD_PARAM 6 63 | // 输入引用动画采样点. 64 | struct AnimCoordSample { 65 | // 0:x轴, 1:y轴, 2:z轴, 3:pitch俯仰轴, 4:yaw偏航轴, 5:roll横滚轴 66 | float AnimSamplePoints[ANE_COORD_PARAM]; // 动画坐标采样点 67 | float TimePosition; // 采样点时间位置(虚拟Tick) 68 | 69 | uint32_t PlayerSamplingRate; // 播放(视图)绘制曲线节点采样率 70 | uint32_t BakeSamplingRate; // 烘焙曲线节点采样率 71 | }; 72 | 73 | // 输出烘焙曲线变换数据. 74 | struct AnimGenCoord { 75 | // 0:x轴, 1:y轴, 2:z轴, 3:pitch俯仰轴, 4:yaw偏航轴, 5:roll横滚轴 76 | float AnimGenVector[ANE_COORD_PARAM]; // 输出采样点 77 | }; 78 | 79 | ``` 80 | 81 | __调用成员:__ 82 | ```cpp 83 | // 绘制编辑器. 84 | void DrawEditorWindow( 85 | uint32_t unqiue_id, // ImGui帧内唯一ID 86 | const char* name, // 窗口名称 87 | float track_length, // 动画轨道长度 88 | float player_step, // 播放动画步长(每帧) 89 | std::vector& sample, // 输入动画采样点 90 | bool fixed_window = false, // 固定窗口(大小&位置) 91 | bool* p_open = (bool*)0, // 与ImGui::Begin的"p_open"参数相同 92 | ImGuiWindowFlags flags = 0 // 与ImGui::Begin的"flags"参数相同 93 | ); 94 | 95 | // 获取播放器运行时变换位置. 96 | // @param "CoordParam" 获取位置 97 | // @return 播放状态, true:播放中, false:停止播放 98 | bool PlayerRunSample(AnimGenCoord& CoordParam); 99 | 100 | // 生成烘焙的贝塞尔曲线点. 101 | // 采样根据以上讲解"AnimCoordSample"的"BakeSamplingRate". 102 | std::vector GenerateBakedBezierCurve(); 103 | 104 | float TrackWidthValueScale = 1.0f; // 动画轨道宽度缩放 105 | float TrackHeightValueScale = 1.0f; // 动画轨道高度缩放 106 | 107 | // 编辑器色系, 所有控件的颜色会围绕这个颜色进行变换 108 | ImVec4 EditorColorSystem = ImVec4(0.85f, 0.85f, 0.85f, 1.0f); 109 | ``` 110 | 111 | __PS:__ 这个更像是一个节点展示器, 每个时间点必须具备6个坐标向量, 如果需要更加强大的动画编辑器请前往: [动画编辑器ultra版本](https://github.com/rcszc/AnimCurvesEditor) 112 | 113 | --- 114 | 115 | ## 2D平面编辑器 116 | > - 窗口: 函数内会调用 ImGui::Begin - ImGui::End 117 | > - Update: 2024.02.18 修改类名, 修复一些bug 118 | 119 | __类定义:__ 120 | ```cpp 121 | class IMFXC_WIN::FlatEditorWindow; 122 | ``` 123 | 124 | __数据结构:__ 125 | ```cpp 126 | // 函数对象传入坐标系信息. 127 | struct CoordSystemInfo { 128 | ImVec2 CenterPosition; // 虚拟坐标系网格中心位置坐标 129 | ImVec2 MouseCoordPos; // 虚拟坐标系虚拟鼠标坐标(当前鼠标在网格上的位置) 130 | 131 | ImVec2 SelectionBoxPoint0; // 选择框矩形对角点A(网格虚拟坐标系) 132 | ImVec2 SelectionBoxPoint1; // 选择框矩形对角点B(网格虚拟坐标系) 133 | 134 | float ScaleCoord; // 虚拟坐标系缩放 135 | } 136 | ``` 137 | 138 | __调用成员:__ 139 | ```cpp 140 | // 绘制编辑器. 141 | void DrawEditorWindow( 142 | uint32_t unqiue_id, // ImGui帧内唯一ID 143 | const char* name, // 窗口名称 144 | std::function draw, // 坐标系子窗口绘制回调函数 145 | ImTextureID poswin_image = nullptr, // 工具定位窗口背景图片 146 | bool fixed_window = true, // 固定窗口(大小&位置) 147 | float speed = 1.0f, // 动画速度缩放 148 | const ImVec2& coord_size = ImVec2(1200.0f, 1200.0f), // 虚拟坐标系大小 149 | const ImVec2& coord_winsize = ImVec2(640.0f, 640.0f) // 坐标系子窗口大小 150 | bool* p_open = (bool*)0, // 与ImGui::Begin的"p_open"参数相同 151 | ImGuiWindowFlags flags = 0 // 与ImGui::Begin的"flags"参数相同 152 | ); 153 | // 注: 在编辑器内会统一使用中心坐标, 就是说 size = [1000,1000] 那么 limit = [-500 ~ +500, -500 ~ +500] 154 | 155 | // 工具栏子窗口绘制回调函数 156 | std::function EditorToolbar = []() {}; 157 | 158 | // 编辑器色系, 所有控件的颜色会围绕这个颜色进行变换 159 | ImVec4 EditorColorSystem = ImVec4(0.85f, 0.85f, 0.85f, 1.0f); 160 | ``` 161 | 162 | __简单例子(坐标计算):__ 163 | ```cpp 164 | // 在编辑器坐标系中绘制中心点居中图片: 165 | auto DemoFunc = [&](CoordSystemInfo INFO) { 166 | 167 | // 绘制图片大小 168 | ImVec2 RenderSize(1000.0f, 1000.0f); 169 | // 绘制图片位置 170 | ImVec2 ImgPos(INFO.CenterPosition.x - RenderSize.x * 0.5f * INFO.ScaleCoord, INFO.CenterPosition.y - RenderSize.y * 0.5f * INFO.ScaleCoord); 171 | 172 | // 绘制图片(或者其他控件也用同样方法计算)... 173 | }; 174 | ``` 175 | 176 | --- 177 | 178 | ## 模拟仪表盘 179 | ### [warning]: 已被列入弃用控件 180 | __可以在引入头时定义"ENABLE_OLD_CONTROL_DASHBOAR"启用__ 181 | 182 | > - 子窗口: 函数内会调用 ImGui::BeginChild - ImGui::EndChild 183 | > - Update: 2024.04.21 弃用停止维护控件 184 | 185 | __类定义:__ 186 | ```cpp 187 | class IMFXC_CWIN::DashboardChildWindow; 188 | ``` 189 | 190 | __调用成员:__ 191 | ```cpp 192 | // 绘制仪表盘. 193 | bool DrawDashboardWindow( 194 | const char* name, // 仪表盘窗口名称 195 | float value, // 输入值 196 | uint32_t ruler = 10, // 主刻度数量 197 | const ImVec4& color = ImVec4(0.0f, 1.0f, 1.0f, 0.92f), // 仪表色系 198 | const ImVec2& size = ImVec2(768.0f, 768.0f), // 仪表子窗口大小 199 | float speed = 1.0f // 动画速度缩放 200 | ); 201 | 202 | // 设置仪表显示值范围(返回设置后的limit). 203 | ImVec2 SetDashboardValueLimit(const ImVec2& limit); 204 | 205 | // 仪表启动标志(启动动画) 206 | bool DashboardStart = false; 207 | ``` 208 | 209 | --- 210 | 211 | ## 组合快捷键编辑器 212 | > - 窗口: 函数内会调用 ImGui::Begin - ImGui::End 213 | > - Update: 2024.05.30 214 | 215 | __类定义:__ 216 | ```cpp 217 | class IMFXC_WIN::ShortcutKeyEditorWindow; 218 | ``` 219 | 220 | __数据结构:__ 221 | ```cpp 222 | // 快捷键的所有主键, 也是头键: 223 | // 0: ImGuiKey_LeftCtrl, 1: ImGuiKey_LeftShift, 2: ImGuiKey_LeftAlt, 224 | // 3: ImGuiKey_RightCtrl, 4: ImGuiKey_RightShift, 5: ImGuiKey_RightAlt 225 | struct ShortcutKeyInfo { 226 | int MainKeyIndex; // 快捷键主键索引 227 | std::string KeyShortcutName; // 快捷键名称 228 | std::vector KeyCombination; // 快捷键组合 229 | }; 230 | ``` 231 | 232 | __调用成员:__ 233 | ```cpp 234 | // 获取快捷键源数据指针 235 | std::vector* GetSourceData(); 236 | 237 | // 上一次命中索引(ID). 238 | int32_t LAST_HIT = -1; 239 | // 更新快捷键(运行判断系统), 快捷键判定可以在不绘制窗口情况下运行 240 | int32_t UpdateShortcutKey(); 241 | 242 | void DrawEditorWindow( 243 | uint32_t unqiue_id, // ImGui帧内唯一ID 244 | const char* name, // 窗口名称 245 | float interval, // 快捷键组合按键时间间隔, 单位:秒(s), 精度:毫秒(ms) 246 | bool fixed_window = false, // 固定窗口(大小&位置) 247 | bool* p_open = (bool*)0, // 与ImGui::Begin的"p_open"参数相同 248 | ImGuiWindowFlags flags = NULL // 与ImGui::Begin的"flags"参数相同 249 | ); 250 | 251 | // 组合键命名最大字符串长度 252 | size_t KeyNameLength = 256; 253 | 254 | // 编辑器色系, 所有控件的颜色会围绕这个颜色进行变换 255 | ImVec4 EditorColorSystem = ImVec4(0.85f, 0.85f, 0.85f, 1.0f); 256 | ``` 257 | 258 | __界面操作:__ "+"添加键, "-"删除键, 使用鼠标左键长按"SET"按钮同时按下键盘想设置的键. 259 | 260 | --- 261 | 262 | ```END``` -------------------------------------------------------------------------------- /im_docs/IMPROFX_IPFC1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rcszc/ImProFXcontrol/0f76b75bf839f06904d07fe9f9a5e7aed2c0a8c7/im_docs/IMPROFX_IPFC1.png -------------------------------------------------------------------------------- /im_docs/IMPROFX_IPFC2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rcszc/ImProFXcontrol/0f76b75bf839f06904d07fe9f9a5e7aed2c0a8c7/im_docs/IMPROFX_IPFC2.png -------------------------------------------------------------------------------- /im_docs/IMPROFX_IPFC3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rcszc/ImProFXcontrol/0f76b75bf839f06904d07fe9f9a5e7aed2c0a8c7/im_docs/IMPROFX_IPFC3.png -------------------------------------------------------------------------------- /im_docs/IMPROFX_IPFC4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rcszc/ImProFXcontrol/0f76b75bf839f06904d07fe9f9a5e7aed2c0a8c7/im_docs/IMPROFX_IPFC4.png -------------------------------------------------------------------------------- /improfx_control_src/improfx_control.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rcszc/ImProFXcontrol/0f76b75bf839f06904d07fe9f9a5e7aed2c0a8c7/improfx_control_src/improfx_control.h -------------------------------------------------------------------------------- /improfx_control_src/improfx_control_animaxis.cpp: -------------------------------------------------------------------------------- 1 | // improfx_control_animaxis. RCSZ. [20231220] 2 | // ImGui: [Window(Begin_End)], Animation Axis Editor, Update: 20240216. 3 | #include "improfx_control.h" 4 | 5 | #include 6 | using namespace std; 7 | 8 | constexpr ImVec4 XYZCOL[3] = { ImVec4(1.0f, 0.2f, 0.2f, 1.0f), ImVec4(0.2f, 1.0f, 0.2f, 1.0f), ImVec4(0.5f, 0.5f, 1.0f, 1.0f) }; 9 | constexpr ImVec4 PYRCOL[3] = { ImVec4(1.0f, 0.0f, 1.0f, 1.0f), ImVec4(1.0f, 1.0f, 0.0f, 1.0f), ImVec4(0.0f, 1.0f, 1.0f, 1.0f) }; 10 | 11 | constexpr const char* XYZTEXT[3] = { "Xaxis: %.2f","Yaxis: %.2f","Zaxis: %.2f" }; 12 | constexpr const char* PYRTEXT[3] = { "Pitch: %.2f","Yaw: %.2f","Roll: %.2f" }; 13 | 14 | constexpr float EditorSpaceLeft = 200.0f; 15 | constexpr float EditorSpaceBelow = 32.0f; 16 | 17 | namespace IMFXC_WIN { 18 | AnimAxisEditorWindow::AnimAxisEditorWindow() { 19 | // config anim_button color & size. 20 | for (size_t i = 0; i < 6; i++) { 21 | AnimButton[i].SetButtonStatColor( 22 | IM_CONTROL_BASE::ColorBrightnesScale(EditorColorSystem, 0.58f), 23 | IM_CONTROL_BASE::ColorBrightnesScale(EditorColorSystem, 0.2f), 24 | EditorColorSystem 25 | ); 26 | } 27 | 28 | float ButtonWidthA = (EditorSpaceLeft - IMGUI_ITEM_SPAC * 3.0f) * 0.5f; 29 | AnimButton[0].SetButtonStatSize(ImVec2(ButtonWidthA, 28.0f), ImVec2(ButtonWidthA, 28.0f), ImVec2(ButtonWidthA, 28.0f)); 30 | AnimButton[1].SetButtonStatSize(ImVec2(ButtonWidthA, 28.0f), ImVec2(ButtonWidthA, 28.0f), ImVec2(ButtonWidthA, 28.0f)); 31 | 32 | float ButtonWidthB = ButtonWidthA * 2.0f + IMGUI_ITEM_SPAC; 33 | AnimButton[2].SetButtonStatSize(ImVec2(ButtonWidthB, 28.0f), ImVec2(ButtonWidthB, 28.0f), ImVec2(ButtonWidthB, 28.0f)); 34 | AnimButton[3].SetButtonStatSize(ImVec2(ButtonWidthB, 28.0f), ImVec2(ButtonWidthB, 28.0f), ImVec2(ButtonWidthB, 28.0f)); 35 | 36 | AnimButton[4].SetButtonStatSize(ImVec2(34.0f, 26.0f), ImVec2(32.0f, 26.0f), ImVec2(32.0f, 26.0f)); 37 | AnimButton[5].SetButtonStatSize(ImVec2(34.0f, 26.0f), ImVec2(32.0f, 26.0f), ImVec2(32.0f, 26.0f)); 38 | } 39 | 40 | void AnimAxisEditorWindow::MouseSetPointValue() { 41 | if (NodeSetValuePointer && ImGui::IsMouseDown(0)) { 42 | *NodeSetValuePointer -= ImGui::GetIO().MouseDelta.y * 0.92f; 43 | 44 | // floating window(view value). 45 | ImGui::PushStyleColor(ImGuiCol_PopupBg, ImVec4(0.25f, 0.25f, 0.25f, 0.72f)); 46 | ImGui::BeginTooltip(); 47 | ImGui::Text("Value:%.1f", *NodeSetValuePointer); 48 | ImGui::EndTooltip(); 49 | ImGui::PopStyleColor(); 50 | } 51 | else 52 | NodeSetValuePointer = nullptr; 53 | } 54 | 55 | void AnimAxisEditorWindow::SpacingLine(float space_left, const ImVec4& color) { 56 | ImGui::Spacing(); 57 | IM_CONTROL_BASE::ListDrawLine( 58 | ImVec2(ImGui::GetCursorPosX(), ImGui::GetCursorPosY() - ImGui::GetScrollY()), 59 | ImVec2(ImGui::GetCursorPosX() + space_left - IMGUI_ITEM_SPAC * 2.0f, ImGui::GetCursorPosY() - ImGui::GetScrollY()), 60 | color, 2.0f 61 | ); 62 | ImGui::Spacing(); 63 | } 64 | 65 | void AnimAxisEditorWindow::DrawCubicBezierCurve( 66 | const ImVec2& point0, const ImVec2& point1, const ImVec4& color, const ImVec2& scale, 67 | float offset, int sample, float centerh 68 | ) { 69 | // calculate bessel_curve draw_points. 70 | ImVec2 DrawPoint0(point0.x * scale.x - offset, centerh - point0.y * scale.y); 71 | ImVec2 DrawPoint1(point1.x * scale.x - offset, centerh - point1.y * scale.y); 72 | 73 | ImVec2 MidPoint = (DrawPoint0 + DrawPoint1) * 0.5f; 74 | ImVec2 ControlPointA = MidPoint - ImVec2(0.0f, (DrawPoint1 - MidPoint).y); 75 | ImVec2 ControlPointB = MidPoint + ImVec2(0.0f, (DrawPoint1 - MidPoint).y); 76 | 77 | ImVec2 BeginPointTemp = ImBezierCubicCalc(DrawPoint0, ControlPointA, ControlPointB, DrawPoint1, 0.0f); 78 | for (int i = 0; i < sample; ++i) { 79 | 80 | ImVec2 DrawPoint = ImBezierCubicCalc(DrawPoint0, ControlPointA, ControlPointB, DrawPoint1, (float)i / (float)sample); 81 | IM_CONTROL_BASE::ListDrawLine(BeginPointTemp, DrawPoint, color, EditorScaleLinesWidth * 2.0f); 82 | BeginPointTemp = DrawPoint; 83 | } 84 | } 85 | 86 | void AnimAxisEditorWindow::DrawAnimationPoints(const ImVec2& position, float size, const ImVec4& color, float& value) { 87 | if (&value == NodeSetValuePointer) 88 | IM_CONTROL_BASE::ListDrawCircleFill(position, size, ImVec4(0.5f, 0.5f, 0.5f, 1.0f)); 89 | else 90 | IM_CONTROL_BASE::ListDrawCircleFill(position, size, color); 91 | 92 | ImGui::SetCursorPos(ImVec2(position.x - size, position.y - size)); 93 | ImGui::InvisibleButton("@SETVALUE", ImVec2(size * 2.0f, size * 2.0f)); 94 | 95 | if (ImGui::IsItemHovered() && ImGui::IsMouseDown(0) && !NodeSetValuePointer && !PlayerSetScrollyFlag) 96 | NodeSetValuePointer = &value; 97 | } 98 | 99 | void AnimAxisEditorWindow::DrawPlayerLine(ImVec2& position, float offset, float max, const ImVec4& color, float xscale) { 100 | float PlayerRectWidth = IMGUI_ITEM_SPAC * 3.2f; 101 | float PlayerLineWidth = 2.2f; 102 | 103 | IM_CONTROL_BASE::ListDrawLine( 104 | ImVec2(position.y * xscale - offset - PlayerLineWidth * 0.5f, IMGUI_ITEM_SPAC + PlayerRectWidth * 0.5f), 105 | ImVec2(position.y * xscale - offset - PlayerLineWidth * 0.5f, ImGui::GetWindowHeight() - IMGUI_ITEM_SPAC * 4.0f), 106 | color, 107 | EditorScaleLinesWidth * 2.2f 108 | ); 109 | IM_CONTROL_BASE::ListDrawLine( 110 | ImVec2(position.y * xscale - offset + IMGUI_ITEM_SPAC, ImGui::GetWindowHeight() - IMGUI_ITEM_SPAC * 4.0f), 111 | ImVec2(position.y * xscale - offset - IMGUI_ITEM_SPAC, ImGui::GetWindowHeight() - IMGUI_ITEM_SPAC * 4.0f), 112 | color, 113 | EditorScaleLinesWidth * 2.2f 114 | ); 115 | 116 | IM_CONTROL_BASE::ListDrawRectangleFill( 117 | ImVec2(position.y * xscale - offset - PlayerRectWidth * 0.5f, IMGUI_ITEM_SPAC), 118 | ImVec2(PlayerRectWidth, IMGUI_ITEM_SPAC * 2.0f), 119 | color 120 | ); 121 | ImGui::SetCursorPos(ImVec2(position.y * xscale - offset - PlayerRectWidth * 0.5f, IMGUI_ITEM_SPAC)); 122 | ImGui::InvisibleButton("@SETPLAYER", ImVec2(PlayerRectWidth, IMGUI_ITEM_SPAC * 2.0f)); 123 | 124 | if (ImGui::IsItemHovered() && ImGui::IsMouseDown(0) && !NodeSetValuePointer) 125 | PlayerSetScrollyFlag = true; 126 | if (PlayerSetScrollyFlag && !ImGui::IsMouseDown(0)) 127 | PlayerSetScrollyFlag = false; 128 | if (PlayerSetScrollyFlag) 129 | position.x += ImGui::GetIO().MouseDelta.x / xscale; 130 | 131 | position.x = position.x < 0.0f ? 0.0f : position.x; 132 | position.x = position.x > max ? max : position.x; 133 | } 134 | 135 | bool AnimAxisEditorWindow::RunGetCubicBezierCurve( 136 | const ImVec2& point0, const ImVec2& point1, float& value, float playerpos, float centerh, 137 | vector& src, size_t index 138 | ) { 139 | // calculate bessel_curve resul_value. 140 | ImVec2 CalcPoint0(point0.x, centerh - point0.y); 141 | ImVec2 CalcPoint1(point1.x, centerh - point1.y); 142 | 143 | float PrevDist = src[index].TimePosition; 144 | 145 | if (CalcPoint0.x < playerpos && CalcPoint1.x > playerpos) { 146 | // bessel_curve control_points. 147 | ImVec2 MidPoint = (CalcPoint0 + CalcPoint1) * 0.5f; 148 | ImVec2 ControlPointA = MidPoint - ImVec2(0.0f, (CalcPoint1 - MidPoint).y); 149 | ImVec2 ControlPointB = MidPoint + ImVec2(0.0f, (CalcPoint1 - MidPoint).y); 150 | 151 | value = ImBezierCubicCalc( 152 | CalcPoint0, ControlPointA, ControlPointB, CalcPoint1, float((int)playerpos - PrevDist) / (CalcPoint1.x - CalcPoint0.x) 153 | ).y; 154 | return true; 155 | } 156 | else { 157 | value = 0.0f; 158 | return false; 159 | } 160 | } 161 | 162 | bool AnimAxisEditorWindow::PlayerRunSample(AnimGenCoord& CoordParam) { 163 | CoordParam = PlayerRunCoord; 164 | return PlayerFlag; 165 | }; 166 | 167 | std::vector AnimAxisEditorWindow::GenerateBakedBezierCurve() { 168 | std::vector BakeGenerate = {}; 169 | 170 | for (size_t i = 0; i < AnimDataIndex->size() - 1; ++i) { 171 | AnimCoordSample DatTempA = (*AnimDataIndex)[i]; 172 | AnimCoordSample DatTempB = (*AnimDataIndex)[i + 1]; 173 | 174 | for (uint32_t smp = 0; smp < (*AnimDataIndex)[i].BakeSamplingRate; ++smp) { 175 | AnimGenCoord CoordTemp = {}; 176 | 177 | for (size_t j = 0; j < ANE_COORD_PARAMS; ++j) { 178 | ImVec2 BezPoint0(DatTempA.TimePosition, DatTempA.AnimSamplePoints[j]); 179 | ImVec2 BezPoint1(DatTempB.TimePosition, DatTempB.AnimSamplePoints[j]); 180 | 181 | ImVec2 MidPoint = (BezPoint0 + BezPoint1) * 0.5f; 182 | ImVec2 ControlPointA = MidPoint - ImVec2(0.0f, (BezPoint1 - MidPoint).y); 183 | ImVec2 ControlPointB = MidPoint + ImVec2(0.0f, (BezPoint1 - MidPoint).y); 184 | 185 | ImVec2 DrawPoint = ImBezierCubicCalc(BezPoint0, ControlPointA, ControlPointB, BezPoint1, (float)smp / (float)DatTempA.BakeSamplingRate); 186 | CoordTemp.AnimGenVector[j] = DrawPoint.x; 187 | } 188 | BakeGenerate.push_back(CoordTemp); 189 | } 190 | } 191 | return BakeGenerate; 192 | } 193 | 194 | void AnimAxisEditorWindow::DrawEditorWindow( 195 | uint32_t unqiue_id, 196 | const char* name, 197 | float track_length, 198 | float player_step, 199 | vector& sample, 200 | bool fixed_window, 201 | bool* p_open, 202 | ImGuiWindowFlags flags 203 | ) { 204 | AnimDataIndex = &sample; 205 | 206 | ImGuiWindowFlags WindowFlags = ImGuiWindowFlags_None; 207 | if (fixed_window) 208 | WindowFlags = ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize; 209 | ImGui::PushID(unqiue_id); 210 | 211 | // frame_background color. 212 | ImGui::PushStyleColor(ImGuiCol_FrameBg, IM_CONTROL_BASE::ColorBrightnesScale(EditorColorSystem, 0.58f)); 213 | ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, IM_CONTROL_BASE::ColorBrightnesScale(EditorColorSystem, 0.58f)); 214 | ImGui::PushStyleColor(ImGuiCol_FrameBgActive, IM_CONTROL_BASE::ColorBrightnesScale(EditorColorSystem, 0.58f)); 215 | // slider_block color. 216 | ImGui::PushStyleColor(ImGuiCol_SliderGrab, IM_CONTROL_BASE::ColorBrightnesScale(EditorColorSystem, 0.16f)); 217 | ImGui::PushStyleColor(ImGuiCol_SliderGrabActive, IM_CONTROL_BASE::ColorBrightnesScale(EditorColorSystem, 0.16f)); 218 | ImGui::PushStyleColor(ImGuiCol_Text, IM_CONTROL_BASE::ColorBrightnesScale(EditorColorSystem, 0.24f)); 219 | 220 | ImGui::Begin(name, p_open, WindowFlags | flags); 221 | { 222 | ImVec2 ChildWindowSize = ImVec2(ImGui::GetWindowSize().x - EditorSpaceLeft, ImGui::GetWindowSize().y - EditorSpaceBelow); 223 | 224 | ImGui::SetCursorPos(ImVec2(EditorSpaceLeft, ImGui::GetWindowSize().y - EditorSpaceBelow - IMGUI_ITEM_SPAC * 0.5f)); 225 | ImGui::SetNextItemWidth(ChildWindowSize.x - ImGui::CalcTextSize("TRACK").x - IMGUI_ITEM_SPAC * 2.0f); 226 | 227 | TrackWindowScrollx.y = track_length * TrackWidthValueScale - ChildWindowSize.x * 0.85f; 228 | TrackWindowScrollx.y = TrackWindowScrollx.y < 0.0f ? 0.0f : TrackWindowScrollx.y; 229 | 230 | ImGui::SliderFloat("TRACK", &TrackWindowScrollx.x, 0.0f, TrackWindowScrollx.y, ""); 231 | 232 | ImGui::SetCursorPos(ImVec2(EditorSpaceLeft, IMGUI_ITEM_SPAC * 4.32f)); 233 | // draw animation_track editor window. 234 | ImVec2 WindowSizeTemp(ChildWindowSize.x - IMGUI_ITEM_SPAC, ChildWindowSize.y - IMGUI_ITEM_SPAC * 5.5f); 235 | ImGui::BeginChild("@ANIMTRACK", WindowSizeTemp, false); 236 | 237 | // track window background rect. 238 | IM_CONTROL_BASE::ListDrawRectangleFill(ImVec2(0.0f, 0.0f), WindowSizeTemp, IM_CONTROL_BASE::ColorBrightnesScale(EditorColorSystem, 0.65f)); 239 | 240 | ImVec4 LinesColor = IM_CONTROL_BASE::ColorBrightnesScale(EditorColorSystem, 0.42f); 241 | // value_zero base_line. 242 | float HighCenterPosition = ImGui::GetWindowHeight() * 0.5f; 243 | TrackScrollx += (TrackWindowScrollx.x - IMGUI_ITEM_SPAC * 4.0f - TrackScrollx) * 0.1f; 244 | 245 | for (float i = 50.0f; i <= track_length; i += 100.0f) { 246 | float LinesScrollxTemp = i * TrackWidthValueScale - TrackScrollx; 247 | 248 | LinesColor.w = 0.32f; 249 | IM_CONTROL_BASE::ListDrawLine( 250 | ImVec2(LinesScrollxTemp, IMGUI_ITEM_SPAC * 7.0f), 251 | ImVec2(LinesScrollxTemp, ImGui::GetWindowHeight() - IMGUI_ITEM_SPAC * 10.0f), 252 | LinesColor, 253 | EditorScaleLinesWidth 254 | ); 255 | } 256 | 257 | char TimeTickText[8] = {}; // char_array. 258 | for (float i = 0.0f; i <= track_length; i += 100.0f) { 259 | sprintf_s(TimeTickText, "%.0f", i); 260 | 261 | float LinesScrollxTemp = i * TrackWidthValueScale - TrackScrollx; 262 | 263 | // draw time_tick text. 264 | ImVec2 TextPos(LinesScrollxTemp - ImGui::CalcTextSize(TimeTickText).x * 0.5f, ImGui::GetWindowHeight() - IMGUI_ITEM_SPAC * 3.5f); 265 | LinesColor.w = 0.92f; // color ahpla. 266 | IM_CONTROL_BASE::ListDrawText(TextPos, LinesColor, "%.0f", i); 267 | 268 | LinesColor.w = 0.32f; 269 | IM_CONTROL_BASE::ListDrawLine( 270 | ImVec2(LinesScrollxTemp, IMGUI_ITEM_SPAC), 271 | ImVec2(LinesScrollxTemp, ImGui::GetWindowHeight() - IMGUI_ITEM_SPAC * 4.0f), 272 | LinesColor, 273 | EditorScaleLinesWidth * 3.2f 274 | ); 275 | } 276 | 277 | // draw centerline[value: 0.0f]. 278 | IM_CONTROL_BASE::ListDrawLine( 279 | ImVec2(0.0f, HighCenterPosition), 280 | ImVec2(ImGui::GetWindowWidth(), HighCenterPosition), 281 | LinesColor, 282 | EditorScaleLinesWidth * 1.8f 283 | ); 284 | 285 | if (EditorModeType) { 286 | std::copy(std::begin(PYRCOL), std::end(PYRCOL), std::begin(SystemAsixColors)); 287 | std::copy(std::begin(PYRTEXT), std::end(PYRTEXT), std::begin(SystemAsixTexts)); 288 | } 289 | else { 290 | std::copy(std::begin(XYZCOL), std::end(XYZCOL), std::begin(SystemAsixColors)); 291 | std::copy(std::begin(XYZTEXT), std::end(XYZTEXT), std::begin(SystemAsixTexts)); 292 | } 293 | 294 | if (!sample.empty()) { 295 | size_t AnimCount = size_t(sample.size() >= 2); 296 | 297 | for (size_t i = 0; i < sample.size() - 1; ++i) { 298 | float SampleCoordIndex[ANE_COORD_PARAMS] = {}; 299 | // animation points. 300 | for (size_t j = 0; j < 3; ++j) { 301 | size_t ParamCount = j + (size_t)EditorModeType * 3; 302 | 303 | DrawCubicBezierCurve( 304 | ImVec2(sample[i].TimePosition, sample[i].AnimSamplePoints[ParamCount]), 305 | ImVec2(sample[i + AnimCount].TimePosition, sample[i + AnimCount].AnimSamplePoints[ParamCount]), 306 | SystemAsixColors[j], 307 | ImVec2(TrackWidthValueScale, TrackHeightValueScale), 308 | TrackScrollx, 309 | sample[i].PlayerSamplingRate, 310 | HighCenterPosition 311 | ); 312 | DrawAnimationPoints( 313 | ImVec2(sample[i].TimePosition * TrackWidthValueScale - TrackScrollx, HighCenterPosition - sample[i].AnimSamplePoints[ParamCount] * TrackHeightValueScale), 314 | 4.2f, 315 | SystemAsixColors[j], 316 | sample[i].AnimSamplePoints[ParamCount] 317 | ); 318 | } 319 | 320 | // animation bezier_curve. 321 | for (size_t j = 0; j < 6; ++j) { 322 | if (RunGetCubicBezierCurve( 323 | ImVec2(sample[i].TimePosition, sample[i].AnimSamplePoints[j]), 324 | ImVec2(sample[i + AnimCount].TimePosition, sample[i + AnimCount].AnimSamplePoints[j]), 325 | SampleCoordIndex[j], 326 | PlayerLineScrollx.y, 327 | HighCenterPosition, 328 | sample, i 329 | )) 330 | PlayerRunCoord.AnimGenVector[j] = HighCenterPosition - SampleCoordIndex[j]; 331 | } 332 | } 333 | size_t Last = sample.size() - 1; 334 | for (size_t j = 0; j < 3; ++j) { 335 | size_t ParamCount = j + (size_t)EditorModeType * 3; 336 | 337 | DrawAnimationPoints( 338 | ImVec2(sample[Last].TimePosition * TrackWidthValueScale - TrackScrollx, HighCenterPosition - sample[Last].AnimSamplePoints[ParamCount] * TrackHeightValueScale), 339 | 4.2f, 340 | SystemAsixColors[j], 341 | sample[Last].AnimSamplePoints[ParamCount] 342 | ); 343 | } 344 | } 345 | MouseSetPointValue(); 346 | DrawPlayerLine(PlayerLineScrollx, TrackScrollx, track_length, EditorColorPlayer, TrackWidthValueScale); 347 | 348 | ImGui::EndChild(); 349 | 350 | PlayerLineScrollx.y += (PlayerLineScrollx.x - PlayerLineScrollx.y) * 0.12f; 351 | PlayerLineScrollx.y = abs(PlayerLineScrollx.x - PlayerLineScrollx.y) < 0.01f ? PlayerLineScrollx.x : PlayerLineScrollx.y; 352 | 353 | ImGui::SetCursorPos(ImVec2(IMGUI_ITEM_SPAC, IMGUI_ITEM_SPAC * 4.32f)); 354 | ImGui::Text("TICK: %.1f", PlayerLineScrollx.y); 355 | ImGui::Spacing(); 356 | 357 | if (AnimButton[0].DrawButton("Begin")) { 358 | PlayerLineScrollx.x = 0.0f; 359 | PlayerLineScrollx.y = 0.0f; 360 | } 361 | ImGui::SameLine(); 362 | if (AnimButton[1].DrawButton("End")) { 363 | PlayerLineScrollx.x = track_length; 364 | PlayerLineScrollx.y = track_length; 365 | } 366 | ImGui::Spacing(); 367 | 368 | auto ModeButtonFunc = [&](bool& mode_flag, const char* fname, const char* tname, size_t butidx) { 369 | if (mode_flag) { 370 | if (AnimButton[butidx].DrawButton(fname)) 371 | mode_flag = !mode_flag; 372 | } 373 | else 374 | if (AnimButton[butidx].DrawButton(tname)) 375 | mode_flag = !mode_flag; 376 | }; 377 | 378 | ModeButtonFunc(PlayerFlag, "STOP", "PLAY", 2); 379 | if (PlayerFlag) 380 | PlayerLineScrollx.x += player_step * TrackWidthValueScale; 381 | 382 | ImGui::Spacing(); 383 | ModeButtonFunc(EditorModeType, "X.Y.Z", "P.Y.R", 3); 384 | 385 | float SpaceItemLeft = EditorSpaceLeft - IMGUI_ITEM_SPAC * 2.0f; 386 | 387 | ImGui::Spacing(); 388 | if (AnimButton[4].DrawButton("RH")) 389 | TrackHeightValueScale = 1.0f; 390 | 391 | ImGui::SameLine(); 392 | ImGui::SetNextItemWidth(SpaceItemLeft - 32.0f - IMGUI_ITEM_SPAC); 393 | ImGui::SliderFloat("##HIGHSCALE", &TrackHeightValueScale, 0.02f, 2.0f, "%.2f"); 394 | 395 | ImGui::Spacing(); 396 | if (AnimButton[5].DrawButton("RW")) 397 | TrackWidthValueScale = 1.0f; 398 | 399 | ImGui::SameLine(); 400 | ImGui::SetNextItemWidth(SpaceItemLeft - 32.0f - IMGUI_ITEM_SPAC); 401 | ImGui::SliderFloat("##WIDTHSCALE", &TrackWidthValueScale, 0.5f, 2.0f, "%.2f"); 402 | 403 | ImGui::Spacing(); 404 | ImGui::SetNextItemWidth(SpaceItemLeft); 405 | ImGui::InputFloat("##SETPOS", &PlayerLineScrollx.x, 0.0f, 0.0f, "%.1f"); 406 | 407 | SpacingLine(EditorSpaceLeft, LinesColor); 408 | { 409 | for (size_t i = 0; i < 3; ++i) 410 | ImGui::TextColored(SystemAsixColors[i], SystemAsixTexts[i], PlayerRunCoord.AnimGenVector[i + (size_t)EditorModeType * 3]); 411 | } 412 | SpacingLine(EditorSpaceLeft, LinesColor); 413 | ImGui::Text("Animations:%u", sample.size()); 414 | } 415 | ImGui::End(); 416 | ImGui::PopStyleColor(9); 417 | ImGui::PopID(); 418 | } 419 | } -------------------------------------------------------------------------------- /improfx_control_src/improfx_control_base.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rcszc/ImProFXcontrol/0f76b75bf839f06904d07fe9f9a5e7aed2c0a8c7/improfx_control_src/improfx_control_base.cpp -------------------------------------------------------------------------------- /improfx_control_src/improfx_control_base.h: -------------------------------------------------------------------------------- 1 | // improfx_control_base. RCSZ. 2 | 3 | #ifndef _IMPROFX_CONTROL_BASE_HPP 4 | #define _IMPROFX_CONTROL_BASE_HPP 5 | 6 | #define IMPROFX_CONTROL_BASE_MATHS 7 | #include "improfx_control_base_ms.h" 8 | 9 | namespace IM_CONTROL_BASE { 10 | 11 | ImVec4 ColorBrightnesScale(const ImVec4& color, float value); 12 | float ItemCenteredCalc(float width); 13 | 14 | void ListDrawLine(const ImVec2& point0, const ImVec2& point1, const ImVec4& color, float width); 15 | void ListDrawText(const ImVec2& position, const ImVec4& color, const char* text, ...); 16 | 17 | void ListDrawRectangle(const ImVec2& position, const ImVec2& size, const ImVec4& color, float width); 18 | void ListDrawRectangleFill(const ImVec2& position, const ImVec2& size, const ImVec4& color); 19 | void ListDrawCircleFill(const ImVec2& position, float size, const ImVec4& color); 20 | void ListDrawTriangleFill(const ImVec2& position, const ImVec2& offset1, const ImVec2& offset2, const ImVec4& color); 21 | 22 | namespace IM_ANIM { 23 | #define ANIM_BUTTON_STEP 0.078f 24 | class ButtonAnim { 25 | protected: 26 | ImVec4 ButtonAnimColor = {}; 27 | ImVec2 ButtonAnimSize = {}; 28 | 29 | ImVec4 AnimStatColor[3] = {}; 30 | ImVec2 AnimStatSize[3] = {}; 31 | public: 32 | bool DrawButton(const char* name, float speed = 1.0f); 33 | 34 | void SetButtonStatColor(const ImVec4& normal, const ImVec4& hover, const ImVec4& active); 35 | void SetButtonStatSize(const ImVec2& normal, const ImVec2& hover, const ImVec2& active); 36 | }; 37 | } 38 | } 39 | 40 | #endif -------------------------------------------------------------------------------- /improfx_control_src/improfx_control_base_ms.h: -------------------------------------------------------------------------------- 1 | // improfx_control_base_ms. RCSZ. 2 | // version: [x] NORMAL [ ] SIMD [ ] INTEL_SIMD [ ] AMD_SIMD 3 | // update: 2024.04.20, v0.1 4 | 5 | #ifndef _IMPROFX_CONTROL_BASE_MS_H 6 | #define _IMPROFX_CONTROL_BASE_MS_H 7 | 8 | #include "imgui_glfw/imgui.h" 9 | #include "imgui_glfw/imgui_internal.h" 10 | 11 | #define IMGUI_ITEM_SPAC ImGui::GetStyle().ItemSpacing.x 12 | 13 | #define IMFXC_V_CLAMP(value, min, max) ((value) < (min) ? (min) : ((value) > (max) ? (max) : (value))) 14 | #define IMFXC_PI 3.14159265f 15 | #define IMFXC_DEGTORAD(deg) ((deg) * IMFXC_PI / 180.0f) 16 | 17 | #define IMVEC2_DISTANCE(pos1, pos2) std::sqrt((pos1.x - pos2.x) * (pos1.x - pos2.x) + (pos1.y - pos2.y) * (pos1.y - pos2.y)) 18 | 19 | #define IMFP32_TO_COLU32(R, G, B, A) IM_COL32(ImU32(R * 255.0f), ImU32(G * 255.0f), ImU32(B * 255.0f), ImU32(A * 255.0f)) 20 | #define COL_TO_FP32(V) ImU32((V) * 255.0f) 21 | #define IMVEC4_TO_COLU32(COL) IM_COL32(COL_TO_FP32((COL).x), COL_TO_FP32((COL).y), COL_TO_FP32((COL).z), COL_TO_FP32((COL).w)) 22 | 23 | 24 | #ifdef IMPROFX_CONTROL_BASE_MATHS 25 | static inline ImVec2 operator+(const ImVec2& v, const ImVec2& s) { return ImVec2(v.x + s.x, v.y + s.y); } 26 | static inline ImVec2 operator+(const ImVec2& v, float s) { return ImVec2(v.x + s, v.y + s); } 27 | 28 | static inline ImVec2 operator-(const ImVec2& v, const ImVec2& s) { return ImVec2(v.x - s.x, v.y - s.y); } 29 | static inline ImVec2 operator-(const ImVec2& v, float s) { return ImVec2(v.x - s, v.y - s); } 30 | static inline ImVec2 operator-(float s, const ImVec2& v) { return ImVec2(s - v.x, s - v.y); } 31 | 32 | static inline ImVec2 operator*(const ImVec2& v, const ImVec2& s) { return ImVec2(v.x * s.x, v.y * s.y); } 33 | static inline ImVec2 operator*(const ImVec2& v, float s) { return ImVec2(v.x * s, v.y * s); } 34 | 35 | static inline ImVec2 operator/(const ImVec2& v, const ImVec2& s) { return ImVec2(v.x / s.x, v.y / s.y); } 36 | static inline ImVec2 operator/(const ImVec2& v, float s) { return ImVec2(v.x / s, v.y / s); } 37 | static inline ImVec2 operator/(float s, const ImVec2& v) { return ImVec2(s / v.x, s / v.y); } 38 | 39 | static inline ImVec2& operator+=(ImVec2& v1, const ImVec2& v2) { return v1 = v1 + v2; } 40 | static inline ImVec2& operator-=(ImVec2& v1, const ImVec2& v2) { return v1 = v1 - v2; } 41 | static inline ImVec2& operator*=(ImVec2& v1, const ImVec2& v2) { return v1 = v1 * v2; } 42 | static inline ImVec2& operator/=(ImVec2& v1, const ImVec2& v2) { return v1 = v1 / v2; } 43 | 44 | static inline ImVec4 operator+(const ImVec4& v, const ImVec4& s) { return ImVec4(v.x + s.x, v.y + s.y, v.z + s.z, v.w + s.w); } 45 | static inline ImVec4 operator+(const ImVec4& v, float s) { return ImVec4(v.x + s, v.y + s, v.z + s, v.w + s); } 46 | 47 | static inline ImVec4 operator-(const ImVec4& v, const ImVec4& s) { return ImVec4(v.x - s.x, v.y - s.y, v.z - s.z, v.w - s.w); } 48 | static inline ImVec4 operator-(const ImVec4& v, float s) { return ImVec4(v.x - s, v.y - s, v.z - s, v.w - s); } 49 | static inline ImVec4 operator-(float s, const ImVec4& v) { return ImVec4(s - v.x, s - v.y, s - v.z, s - v.w); } 50 | 51 | static inline ImVec4 operator*(const ImVec4& v, const ImVec4& s) { return ImVec4(v.x * s.x, v.y * s.y, v.z * s.z, v.w * s.w); } 52 | static inline ImVec4 operator*(const ImVec4& v, float s) { return ImVec4(v.x * s, v.y * s, v.z * s, v.w * s); } 53 | 54 | static inline ImVec4 operator/(const ImVec4& v, const ImVec4& s) { return ImVec4(v.x / s.x, v.y / s.y, v.z / s.z, v.w / s.w); } 55 | static inline ImVec4 operator/(const ImVec4& v, float s) { return ImVec4(v.x / s, v.y / s, v.z / s, v.w / s); } 56 | static inline ImVec4 operator/(float s, const ImVec4& v) { return ImVec4(s / v.x, s / v.y, s / v.z, s / v.w); } 57 | 58 | static inline ImVec4& operator+=(ImVec4& v1, const ImVec4& v2) { return v1 = v1 + v2; } 59 | static inline ImVec4& operator-=(ImVec4& v1, const ImVec4& v2) { return v1 = v1 - v2; } 60 | static inline ImVec4& operator*=(ImVec4& v1, const ImVec4& v2) { return v1 = v1 * v2; } 61 | static inline ImVec4& operator/=(ImVec4& v1, const ImVec4& v2) { return v1 = v1 / v2; } 62 | #endif 63 | #endif -------------------------------------------------------------------------------- /improfx_control_src/improfx_control_dashboard.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rcszc/ImProFXcontrol/0f76b75bf839f06904d07fe9f9a5e7aed2c0a8c7/improfx_control_src/improfx_control_dashboard.cpp -------------------------------------------------------------------------------- /improfx_control_src/improfx_control_flateditor.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rcszc/ImProFXcontrol/0f76b75bf839f06904d07fe9f9a5e7aed2c0a8c7/improfx_control_src/improfx_control_flateditor.cpp -------------------------------------------------------------------------------- /improfx_control_src/improfx_control_menu.cpp: -------------------------------------------------------------------------------- 1 | // improfx_control_menu. RCSZ. [20231220] 2 | // ImGui: [ChildWindow(BeginChild_EndChild)], Animation Menu, Update: 20240216. 3 | #include "improfx_control.h" 4 | 5 | namespace IMFXC_CWIN { 6 | void SmoothMenuChildWindow::DrawMenuTypeRect(float rect_height, const ImVec4& color) { 7 | if (MenuBufferWidthType.y > 0.1f) { 8 | // fill selection_box. 9 | IM_CONTROL_BASE::ListDrawRectangleFill( 10 | ImVec2(IM_CONTROL_BASE::ItemCenteredCalc(MenuBufferWidthType.y), MenuBufferTypeScroll.y), 11 | ImVec2(MenuBufferWidthType.y, rect_height + 2.0f), 12 | color 13 | ); 14 | ImGui::SetCursorPos(ImVec2(0.0f, 0.0f)); 15 | } 16 | } 17 | 18 | void SmoothMenuChildWindow::DrawMenuItemRect(float rect_height, const ImVec4& color) { 19 | // fill item_box. 20 | IM_CONTROL_BASE::ListDrawRectangleFill( 21 | ImVec2(IM_CONTROL_BASE::ItemCenteredCalc(MenuBufferWidthItem.y), MenuBufferItemScroll.y), 22 | ImVec2(MenuBufferWidthItem.y, rect_height + 2.0f), 23 | color 24 | ); 25 | ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 1.2f); 26 | // fill item_location_box. 27 | IM_CONTROL_BASE::ListDrawRectangleFill( 28 | ImVec2(ImGui::GetWindowSize().x - 12.0f, MenuBufferItemScroll.y), 29 | ImVec2(IMGUI_ITEM_SPAC, rect_height + 2.0f), 30 | color 31 | ); 32 | // fill item_location_dir. 33 | IM_CONTROL_BASE::ListDrawTriangleFill( 34 | ImVec2(IMGUI_ITEM_SPAC * 2.0f, MenuBufferItemScroll.y + (rect_height + 2.0f) * 0.5f), 35 | ImVec2(-rect_height / 2.0f, -rect_height / 2.0f), 36 | ImVec2(-rect_height / 2.0f, rect_height / 2.0f), 37 | color 38 | ); 39 | ImGui::PopStyleVar(); 40 | ImGui::SetCursorPos(ImVec2(0.0f, 0.0f)); 41 | } 42 | 43 | void SmoothMenuChildWindow::MenuInterCalc(ImVec2& posy_calc, ImVec2& width_calc, float speed) { 44 | // inter: result = y + (x − y) * t. 45 | posy_calc.y += (posy_calc.x - posy_calc.y) * 0.072f * speed; 46 | width_calc.y += (width_calc.x - width_calc.y) * 0.072f * speed; 47 | } 48 | 49 | bool SmoothMenuChildWindow::DrawMenuWindow( 50 | const char* name, 51 | const std::vector& items, 52 | uint32_t& count, 53 | const ImVec4& color, 54 | const ImVec2& size, 55 | float speed, 56 | float text_scale 57 | ) { 58 | ImGui::BeginChild(name, size); 59 | IM_CONTROL_BASE::ListDrawRectangleFill(ImVec2(), size, IM_CONTROL_BASE::ColorBrightnesScale(color, 0.65f)); 60 | ImGui::SetWindowFontScale(text_scale); 61 | 62 | if (ImGui::IsWindowHovered()) 63 | DrawMenuTypeRect(TextDrawHeight, IM_CONTROL_BASE::ColorBrightnesScale(color, 0.32f)); 64 | DrawMenuItemRect(TextDrawHeight, IM_CONTROL_BASE::ColorBrightnesScale(color, 0.42f)); 65 | 66 | bool ReturnTypeFlag = false; 67 | // draw menu_items. 68 | for (size_t i = 0; i < items.size(); ++i) { 69 | 70 | ImVec2 ItemTextSize = ImGui::CalcTextSize(items[i].c_str()); 71 | float DrawHeightPosition = ImGui::GetCursorPosY(); 72 | 73 | ImGui::SetCursorPosX(IM_CONTROL_BASE::ItemCenteredCalc(ItemTextSize.x)); 74 | ImGui::Text(items[i].c_str()); 75 | 76 | if (ImGui::IsItemHovered()) { 77 | MenuBufferTypeScroll.x = DrawHeightPosition - ImGui::GetScrollY(); 78 | MenuBufferWidthType.x = ItemTextSize.x + IMGUI_ITEM_SPAC * 2.0f; 79 | 80 | if (ImGui::GetMouseClickedCount(0)) { 81 | count = (uint32_t)i; 82 | ReturnTypeFlag = true; 83 | } 84 | } 85 | if (count == (uint32_t)i) { 86 | MenuBufferItemScroll.x = DrawHeightPosition - ImGui::GetScrollY(); 87 | MenuBufferWidthItem.x = ItemTextSize.x + IMGUI_ITEM_SPAC * 2.0f; 88 | } 89 | TextDrawHeight = ItemTextSize.y; 90 | } 91 | MenuInterCalc(MenuBufferTypeScroll, MenuBufferWidthType, speed); 92 | MenuInterCalc(MenuBufferItemScroll, MenuBufferWidthItem, speed); 93 | 94 | ImGui::PopStyleColor(); 95 | ImGui::EndChild(); 96 | 97 | return ReturnTypeFlag; 98 | } 99 | } -------------------------------------------------------------------------------- /improfx_control_src/improfx_control_shortcut.cpp: -------------------------------------------------------------------------------- 1 | // improfx_control_shortcut. RCSZ. [20240530] 2 | // ImGui: [Window(Begin_End)], Shortcut Key Editor, Update: 20240530. 3 | #include "improfx_control.h" 4 | #include 5 | using namespace std; 6 | 7 | namespace IMFXC_WIN { 8 | constexpr const char* MainKeys[] = { 9 | "L-CTRL", "L-SHIFT", "L-ALT", "R-CTRL", "R-SHIFT", "R-ALT" 10 | }; 11 | constexpr ImGuiKey MainKeysFlags[] = { 12 | ImGuiKey_LeftCtrl, ImGuiKey_LeftShift, ImGuiKey_LeftAlt, 13 | ImGuiKey_RightCtrl, ImGuiKey_RightShift, ImGuiKey_RightAlt 14 | }; 15 | 16 | ImGuiKey ShortcutKeyEditorWindow::PressWhichKey(bool repeat) { 17 | for (int It = ImGuiKey_NamedKey_BEGIN; It < ImGuiKey_NamedKey_END; ++It) { 18 | // ignore mouse keys, get this_key. 19 | if (It >= ImGuiKey_MouseLeft && It <= ImGuiKey_MouseWheelY) continue; 20 | if (ImGui::IsKeyPressed((ImGuiKey)It, repeat)) return (ImGuiKey)It; 21 | } 22 | return ImGuiKey_None; 23 | } 24 | 25 | bool ShortcutKeyEditorWindow::IfCombinationKey(const std::vector& keys) { 26 | bool ResultKeysFlag = true; 27 | if (keys.size() == CombinationKey.size() && keys.size() > 1) { 28 | for (size_t i = 0; i < keys.size(); ++i) 29 | if (keys[i] != CombinationKey[i]) 30 | ResultKeysFlag = false; 31 | return ResultKeysFlag; 32 | } 33 | return false; 34 | } 35 | 36 | int32_t ShortcutKeyEditorWindow::UpdateShortcutKey() { 37 | int32_t ReturnCountID = -1; 38 | bool MainKeyDownFlag = false; 39 | 40 | for (size_t i = 0; i < 6; ++i) 41 | if (ImGui::IsKeyPressed((ImGuiKey)MainKeysFlags[i], false)) 42 | MainKeyDownFlag |= true; 43 | 44 | if (MainKeyDownFlag && !CombinationKeyFlag) { 45 | CombinationKeyFlag = true; 46 | CombinationKeyTimer = std::chrono::steady_clock::now(); 47 | } 48 | 49 | if (CombinationKeyFlag) { 50 | ImGuiKey KeyTemp = PressWhichKey(false); 51 | if (KeyTemp != ImGuiKey_None) { 52 | CombinationKey.push_back(KeyTemp); 53 | CombinationKeyTimer = std::chrono::steady_clock::now(); 54 | } 55 | } 56 | if (chrono::duration_cast(chrono::steady_clock::now() - CombinationKeyTimer).count() > 57 | CombinationKeyDuration 58 | ) { 59 | for (size_t i = 0; i < ShortcutKeys.size(); ++i) { 60 | if (IfCombinationKey(ShortcutKeys[i].KeyCombination)) { 61 | LAST_HIT = (int32_t)i; 62 | ReturnCountID = (int32_t)i; 63 | continue; 64 | } 65 | } 66 | CombinationKeyFlag = false; 67 | CombinationKey.clear(); 68 | } 69 | return ReturnCountID; 70 | } 71 | 72 | void ShortcutKeyEditorWindow::DrawEditorWindow( 73 | uint32_t unqiue_id, 74 | const char* name, 75 | float interval, 76 | bool fixed_window, 77 | bool* p_open, 78 | ImGuiWindowFlags flags 79 | ) { 80 | ImGuiWindowFlags WindowFlags = ImGuiWindowFlags_None; 81 | if (fixed_window) 82 | WindowFlags = ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize; 83 | ImGui::PushID(unqiue_id); 84 | 85 | ImGui::PushStyleColor(ImGuiCol_ChildBg, IM_CONTROL_BASE::ColorBrightnesScale(EditorColorSystem, 0.62f)); 86 | 87 | ImGui::PushStyleColor(ImGuiCol_FrameBg, IM_CONTROL_BASE::ColorBrightnesScale(EditorColorSystem, 0.5f)); 88 | ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, IM_CONTROL_BASE::ColorBrightnesScale(EditorColorSystem, 0.5f)); 89 | ImGui::PushStyleColor(ImGuiCol_FrameBgActive, IM_CONTROL_BASE::ColorBrightnesScale(EditorColorSystem, 0.5f)); 90 | // button color. 91 | ImGui::PushStyleColor(ImGuiCol_Button, IM_CONTROL_BASE::ColorBrightnesScale(EditorColorSystem, 0.5f)); 92 | ImGui::PushStyleColor(ImGuiCol_ButtonHovered, IM_CONTROL_BASE::ColorBrightnesScale(EditorColorSystem, 0.2f)); 93 | ImGui::PushStyleColor(ImGuiCol_ButtonActive, EditorColorSystem); 94 | 95 | CombinationKeyDuration = int64_t(interval * 1000.0f); 96 | ImGui::Begin(name, p_open, WindowFlags | flags); 97 | { 98 | ImGui::BeginChild("@DEBUG_IFNO", ImVec2(ImGui::GetWindowSize().x - IMGUI_ITEM_SPAC * 2.0f, 76.0f)); 99 | 100 | ImGui::Spacing(); 101 | ImGui::Text(" RealTimeStatus: "); 102 | for (auto& Item : CombinationKey) { 103 | ImGui::SameLine(); 104 | std::string KeyName = ImGui::GetKeyName(Item); 105 | ImGui::SetNextItemWidth(ImGui::CalcTextSize(KeyName.c_str()).x + IMGUI_ITEM_SPAC); 106 | // dis input state. 107 | ImGui::BeginDisabled(true); 108 | ImGui::InputText("##DEBUGKEY", KeyName.data(), KeyName.size()); 109 | ImGui::EndDisabled(); 110 | } 111 | 112 | ImGui::SetCursorPosY(36.0f); 113 | ImGui::Separator(); 114 | ImGui::Spacing(); 115 | if (CombinationKeyFlag) ImGui::Text(" STATUS: INPUT"); 116 | else ImGui::Text(" STATUS: NULL "); 117 | ImGui::SameLine(); 118 | ImGui::Text("KeyTimer: %lld ms, Hit: %d ", CombinationKeyDuration, LAST_HIT); 119 | 120 | ImGui::SameLine(); 121 | if (ImGui::Button("Clear Last Hit", ImVec2(160.0f, 0.0f))) LAST_HIT = -1; 122 | ImGui::EndChild(); 123 | 124 | size_t IDCount = NULL; 125 | for (auto& Item : ShortcutKeys) { 126 | // hit debug background color. 127 | if (IDCount == LAST_HIT) 128 | ImGui::PushStyleColor(ImGuiCol_ChildBg, IM_CONTROL_BASE::ColorBrightnesScale(EditorColorSystem, 0.72f)); 129 | 130 | ImGui::BeginChild(std::to_string(IDCount).c_str(), ImVec2(ImGui::GetWindowSize().x - IMGUI_ITEM_SPAC * 2.0f, 72.0f), true); 131 | ImGui::Spacing(); 132 | std::string TextTemp = "Mode: "; 133 | 134 | ImGui::Text(" NAME:"); 135 | ImGui::SameLine(); 136 | ImGui::SetNextItemWidth(80.0f); 137 | ImGui::InputText("##NAME", Item.KeyShortcutName.data(), KeyNameLength); 138 | 139 | ImGui::SameLine(); ImGui::Text(" KEYS:"); 140 | size_t ButtonID = NULL; 141 | for (size_t i = 0; i < Item.KeyCombination.size(); ++i) { 142 | ImGui::SameLine(); 143 | std::string KeyTextTemp = ImGui::GetKeyName(Item.KeyCombination[i]); 144 | TextTemp += KeyTextTemp + " + "; 145 | 146 | ImGui::SetNextItemWidth(ImGui::CalcTextSize(KeyTextTemp.c_str()).x + IMGUI_ITEM_SPAC); 147 | // dis input state. 148 | ImGui::BeginDisabled(true); 149 | ImGui::InputText("##KEY", KeyTextTemp.data(), KeyTextTemp.size()); 150 | ImGui::EndDisabled(); 151 | 152 | ImGui::PushID((int)ButtonID); 153 | ImGui::SameLine(); 154 | if (i == 0) { 155 | ImGui::SetNextItemWidth( 156 | ImGui::CalcTextSize(ImGui::GetKeyName(MainKeysFlags[Item.MainKeyIndex])).x + IMGUI_ITEM_SPAC * 2.0f 157 | ); 158 | // main_key(header_key). 159 | ImGui::Combo("##MAINKEY", &Item.MainKeyIndex, MainKeys, IM_ARRAYSIZE(MainKeys)); 160 | Item.KeyCombination[i] = MainKeysFlags[Item.MainKeyIndex]; 161 | continue; 162 | } 163 | ImGui::Button("SET"); 164 | if (ImGui::IsItemActive()) { 165 | ImGuiKey FlagTemp = PressWhichKey(); 166 | if (FlagTemp != ImGuiKey_None) Item.KeyCombination[i] = FlagTemp; 167 | } 168 | } 169 | ImGui::PopID(); 170 | ++ButtonID; 171 | 172 | ImGui::SameLine(); 173 | if (ImGui::Button("+")) 174 | Item.KeyCombination.push_back(ImGuiKey_None); 175 | ImGui::SameLine(); 176 | if (ImGui::Button("-") && !Item.KeyCombination.empty()) 177 | Item.KeyCombination.pop_back(); 178 | 179 | TextTemp.pop_back(); TextTemp.pop_back(); 180 | ImGui::Text(" ID: %u, %s Number: %u", IDCount, TextTemp.c_str(), Item.KeyCombination.size()); 181 | 182 | ImGui::EndChild(); 183 | if (IDCount == LAST_HIT) ImGui::PopStyleColor(); 184 | ++IDCount; 185 | } 186 | 187 | if (ImGui::Button("ShortcutKey[+]", ImVec2(160.0f, 32.0f))) { 188 | ShortcutKeyInfo CreateShoryKey = {}; 189 | CreateShoryKey.KeyShortcutName.resize(KeyNameLength); 190 | ShortcutKeys.push_back(CreateShoryKey); 191 | } 192 | 193 | ImGui::SameLine(); 194 | if (ImGui::Button("ShortcutKey[-]", ImVec2(160.0f, 32.0f)) && !ShortcutKeys.empty()) 195 | ShortcutKeys.pop_back(); 196 | } 197 | ImGui::End(); 198 | ImGui::PopStyleColor(7); 199 | } 200 | } --------------------------------------------------------------------------------