├── 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 | }
--------------------------------------------------------------------------------