GitHub 链接
关于ImGui动画系统 如何使用ImGui做动画!!
- [GitHub 链接](https://github.com/Half-People/HImGuiAnimation)
- 废话完结了 (太好了)
- 1.` HAnimationSystem::Play` 播放动画函数
- 2. `HAnimationSystem::updata` 管理器更新
- 3.`HAnimationSystem::PlayerCallBack::AnimationPlayerCallBack` 回調函数
- 4.`HAnimationSystem::AnimationSequence` 在`HAnimationSystem::Play`当中返回的動畫序列
- 5. `HAnimationSystem::HValue_Get` 轉換HValue變數方便在callback当中读取`HValue`
- 6.`HAnimationSystem::PlayerCallBack::GetInterpolationInfoFromKeys` 获取当前Fram的值用于过渡效果噢
- 7. 过渡效果
- 示例代码
废话
动画管理器对于创建交互性和吸引人的用户界面效果非常重要。它可以帮助你实现一些酷炫的动画效果,提高用户体验。
在给ImGui使用的动画管理器中,我实现了以下功能:
-
动画创建和管理:你可以在管理器中创建和管理多个动画对象。每个动画对象可以有不同的参数,如开始和结束值、持续时间 等。
-
动画播放控制:你可以控制动画的播放状态,如播放、暂停、停止等。这可以通过在ImGui界面中添加按钮或滑动条来实现。
-
动画过渡效果:你可以使用动画管理器实现平滑的过渡效果。例如,你可以使用动画管理器在两个界面之间实现平滑的渐变效果,而不是突然切换。
-
动画事件和回调:你可以在动画管理器中实现事件和回调函数。在动画播放过程中调用回调函数。
-
动画参数编辑:你可以在ImGui界面中添加参数编辑器,以便用户可以调整动画的参数,如FPS限制、播放速度 等。
-
动画序列和组合:你可以将多个动画对象组合在一起,形成一个动画序列或组合效果。例如,你可以创建一个淡入动画和一个移动动画,然后将它们组合在一起,实现一个对象的同时淡入和移动效果。
总之,制作一个给ImGui使用的动画管理器是一个很有挑战性和有趣的项目。它可以帮助你提高用户界面的交互性和吸引力,为用户提供更好的体验。
废话完结了 (太好了)
首先就上链接先啊! GitHub/Half-People/HImGuiAnimation 给个⭐谢谢 : )
其实可以使用他来过渡窗口大小 Button大小 位置什么的 这里只是说给你看到过渡和Key的定义 可以出来的过渡效果 这个不是只能做这种效果的意思噢
我是制作了Wiki不过我想了想其实因为我是用的英文写的 其实也没有那么清晰 那么下面我就翻译一下我哪Wiki当中写了一些什么吧
總的來說,你需要專注於編寫的只是回調函數:) 因为其他东西我底层都帮你控制好咯
一下是里面所有可以用到的函数
此庫中只需要使用兩個主要函數 HAnimationSystem::Play
HAnimationSystem::updata
1. HAnimationSystem::Play
播放动画函数
此功能已與底層通信,會自動為您調度佇列(重複觸發會在播放未完成時忽略您的觸發器。當然,如果需要,可以手動停止播放)
- callback (動畫過度處理。有關詳細資訊,請參閱 AnimationPlayerCallBack 註釋)
- MaxFrame (動畫中最大的幀 或者可以说是Key)
- value (傳輸到回調的值 其实就是方便你在 回調函数里面使用不同的值输入和输出)
- out (動畫序列返回 里面有其他功能噢 这个东西完成播放时会删除的)
- speed (播放速度)
- FPS (最大 FPS : 解除限制 尽量不要这样做(-1) )
- IsLoop (持續迴圈)
HAnimationSystem::Play(PlayerCallBack::AnimationPlayerCallBack callback, size_t MaxFrame, HValue value = nullptr, HAnimationSystem::AnimationSequence** out = 0, float speed = 5, int FPS = 60, bool IsLoop = false)
2. HAnimationSystem::updata
管理器更新
只要用一个就行不用多加
- delta_time(請使用
ImGui::GetIO().DeltaTime
)
//動畫管理器更新(在主迴圈中使用)
void updata(float delta_time);
使用上面那个比较好噢
//動畫管理器更新(在主迴圈中使用)(管理器 FPS 限制,動畫序列將被禁用 FPS 限制)
void updata(float delta_time, int MaxFPS);
3.HAnimationSystem::PlayerCallBack::AnimationPlayerCallBack
回調函数
這是 HAnimationSystem::Play
的函數回調
//示例:函數回調
void Sequencer(int32_t Frame, HAnimationSystem::HValue value)
{
const std::vector<int> keys = { 0 , 30 , 64 };//關鍵針位置 Key
const std::vector<float> values = { 80,200,80 };//關鍵針數值 value
HAnimationSystem::PlayerCallBack::HInterpolationInfo info = HAnimationSystem::PlayerCallBack::GetInterpolationInfoFromKeys(keys, Frame);
HAnimationSystem::HValue_Get<float>(value) = HAnimationSystem::PlayerCallBack::LinearInterpolation(values[info.PreviousKey], values[info.LastOneKey], info.alpha);//There are many plug-in tools in `HAnimationSystem::PlayerCallBack`. Of course, you can write your own
}
...
static float value;
static HAnimationSystem::AnimationSequence* Sequence; //Introduction to waiting array
HAnimationSystem::Play(Sequencer,64/*因为Key里面最大的是64嘛*/ ,&value,&Sequence);
//示例:lambda
HAnimationSystem::Play([](int32_t Frame, HAnimationSystem::HValue value)
{
const std::vector<int> keys = { 0 , 30 , 64 };
const std::vector<float> values = { 80,200,80 };
HAnimationSystem::PlayerCallBack::HInterpolationInfo info = HAnimationSystem::PlayerCallBack::GetInterpolationInfoFromKeys(keys, Frame);
HAnimationSystem::HValue_Get<float>(value) = HAnimationSystem::PlayerCallBack::LinearInterpolation(values[info.PreviousKey], values[info.LastOneKey], info.alpha);//There are many plug-in tools in `HAnimationSystem::PlayerCallBack`. Of course, you can write your own
}, ...);
4.HAnimationSystem::AnimationSequence
在HAnimationSystem::Play
当中返回的動畫序列
HAnimationSystem::AnimationSequence::information
用於保存基礎變數的結構
您可以使用函數
HAnimationSystem::AnimationSequence::getinfo()
進行讀取和寫入
HAnimationSystem::AnimationSequence::Stop
退出動畫播放HAnimationSystem::AnimationSequence::Pause
暫停動畫HAnimationSystem::AnimationSequence::Play
恢復暫停的動畫HAnimationSystem::AnimationSequence::IsPlaying
動畫是否正在播放HAnimationSystem::AnimationSequence::getinfo
取得底層資訊(所有資訊皆可動態調整Speed,IsLoop…)(!請勿使用此調整MaxFPS,data,MaxFrame,pos,callback!)HAnimationSystem::AnimationSequence::updata_MaxFPS
請用它動態調整MaxFPS
5. HAnimationSystem::HValue_Get
轉換HValue變數方便在callback当中读取HValue
本質上程式碼只是
T& HValue_Get(HValue value)
{
return *static_cast<T*>(value);
}
6.HAnimationSystem::PlayerCallBack::GetInterpolationInfoFromKeys
获取当前Fram的值用于过渡效果噢
//可以参考3当中的代码理解噢
HInterpolationInfo GetInterpolationInfoFromKeys(const std::vector<int> keys, int32_t Frame);
7. 过渡效果
HAnimationSystem::PlayerCallBack::LinearInterpolation
平滑过渡HAnimationSystem::PlayerCallBack::SimpleBezierInterpolation
简单的貝塞爾平滑过渡HAnimationSystem::PlayerCallBack::CubicBezierInterpolation
标准貝塞爾平滑过渡HAnimationSystem::PlayerCallBack::StringInterpolation
文本过渡
欢迎在 我的GitHub讨论区 添加自己的过渡效果噢
示例代码
void Sequencer(int32_t Frame/*當前幀*/, HAnimationSystem::HValue value) //定義CallBack函數(value部分是可轉換的 什么类型都可以输入)
{
const std::vector<int> keys = { 0 , 30 , 64 };
const std::vector<float> values = { 80,200,80 };
HAnimationSystem::PlayerCallBack::HInterpolationInfo info = HAnimationSystem::PlayerCallBack::GetInterpolationInfoFromKeys(keys, Frame); //Get interpolation information
HAnimationSystem::HValue_Get<float>(value) = HAnimationSystem::PlayerCallBack::LinearInterpolation(values[info.PreviousKey], values[info.LastOneKey], info.alpha); //Interpolation and return value
}
...//各种Init
while (...) //<<-----这个是绘制的Loop噢
{
... //各种ImGui的操作
static float value;
if (ImGui::Button("play"))
HAnimationSystem::Play(Sequencer, 64, &value, &curr, speed, fps, loop); //播放動畫(無需填寫太多資料即可使用)
ImGui::SliderFloat("Test", &value, 80, 200) //應用測試
...//ImGui和窗口完结
HAnimationSystem::updata(ImGui::GetIO().DeltaTime); // updata animation manager
}
下面是完整代码 其实就是刚才看到图片的那个项目噢
GUI.h
进行UI的绘制 就分离出来方便使用一点嘛
#pragma once
#include "Imgui.h"
#include "HImGuiAnimation.h"
std::string test;
ImVec4 rgb;
inline ImVec4 ImVec4Interpolation(ImVec4 a, ImVec4 b, float af)
{
ImVec4 buff(1, 1, 1, 1);
buff.x = HAnimationSystem::PlayerCallBack::SimpleBezierInterpolation(a.x, b.x, af);
buff.y = HAnimationSystem::PlayerCallBack::SimpleBezierInterpolation(a.y, b.y, af);
buff.z = HAnimationSystem::PlayerCallBack::SimpleBezierInterpolation(a.z, b.z, af);
return buff;
}
void Sequencer(int32_t Frame, HAnimationSystem::HValue value)
{
const std::vector<int> keys = { 0 , 30 , 64 };
const std::vector<float> values = { 80,200,80 };
const std::vector<ImVec4> rgbvalues = { ImVec4(1,0,0,1),ImVec4(0,1,0,1),ImVec4(0,0,1,1) };
HAnimationSystem::PlayerCallBack::HInterpolationInfo info = HAnimationSystem::PlayerCallBack::GetInterpolationInfoFromKeys(keys, Frame);
HAnimationSystem::HValue_Get<float>(value) = HAnimationSystem::PlayerCallBack::LinearInterpolation(values[info.PreviousKey], values[info.LastOneKey], info.alpha);
test = HAnimationSystem::PlayerCallBack::StringInterpolation("hello world aaaaaaaaa vvvvvvv oooooooooo dawdad :/", info.alpha);
rgb = ImVec4Interpolation(rgbvalues[info.PreviousKey], rgbvalues[info.LastOneKey], info.alpha);
}
float speed = 1;
int fps = 60;
bool loop = false;
HAnimationSystem::AnimationSequence* curr;
float value;
void DrawGUI()
{
ImGui::Begin(u8"×÷˜IÓÃ");
if (ImGui::Button("play"))
HAnimationSystem::Play(Sequencer, 64, &value, &curr, speed, fps, loop);
if (curr)
{
ImGui::SameLine();
if (ImGui::Button("Stop"))
{
curr->Stop();
}
ImGui::SameLine();
if (ImGui::Button("pause"))
{
curr->Pause();
}
ImGui::SameLine();
if (ImGui::Button("KeepPlay"))
{
curr->Play();
}
ImGui::SameLine();
ImGui::Text("IsPlaying : %s", (curr->IsPlaying() ? "true" : "false"));
}
if (ImGui::BeginChild("init", ImVec2(270, 125), true, ImGuiWindowFlags_AlwaysAutoResize))
{
ImGui::Text("StartPlaySetting :");
ImGui::SetNextItemWidth(200);
ImGui::DragFloat("speed", &speed, 0.1, 1);
ImGui::SetNextItemWidth(200);
ImGui::DragInt("FPS", &fps, 0.1, 1);
ImGui::SetNextItemWidth(200);
ImGui::Checkbox("loop", &loop);
}
ImGui::EndChild();
if (curr)
{
ImGui::SameLine();
if (ImGui::BeginChild("initrnt", ImVec2(270, 125), true, ImGuiWindowFlags_AlwaysAutoResize))
{
ImGui::Text("RuningTimePlayerSetting :");
ImGui::SetNextItemWidth(200);
ImGui::DragFloat("speed", &curr->getinfo().speed, 0.1, 1);
ImGui::SetNextItemWidth(200);
static int fpsbuff = 1000 / curr->getinfo().FPS_delta_time;
if (ImGui::DragInt("FPS", &fpsbuff, 0.1, 1))
curr->getinfo().FPS_delta_time = 1 / fpsbuff;
ImGui::SetNextItemWidth(200);
ImGui::Checkbox("loop", &curr->getinfo().IsLoop);
}
ImGui::EndChild();
}
if (ImGui::SliderFloat("Test", &value, 80, 200))
{
}
ImGui::ColorEdit4("ColorTest", (float*)&rgb);
ImGui::Text(test.c_str());
ImGui::End();
HAnimationSystem::updata(ImGui::GetIO().DeltaTime);
}
main.cpp
其实我觉得应该不用放这个也可以吧
#define GLEW_STATIC
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#pragma comment(lib,"../API/GLFW/glfw3.lib")
#pragma comment(lib,"../API/GLEW/glew32s.lib")
#pragma comment(lib,"Opengl32.lib")
#include <iostream>
#include <string>
#include "imgui.h"
#include "imgui_impl_glfw.h"
#include "imgui_impl_opengl3.h"
#include "GUI.h"
GLFWwindow* Windows;
int main()
{
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
Windows = glfwCreateWindow(900, 800, "HalfPeople-Imgui", NULL, NULL);
glfwMakeContextCurrent(Windows);
glfwSwapInterval(0);
IMGUI_CHECKVERSION();
ImGui::CreateContext(NULL);
ImGuiIO& io = ImGui::GetIO(); (void)io;
io.Fonts->AddFontFromFileTTF("kaiu.ttf", 18, NULL, io.Fonts->GetGlyphRangesChineseFull());
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
io.ConfigFlags |= ImGuiViewportFlags_NoDecoration;
io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;
io.ConfigFlags |= ImGuiCol_DockingEmptyBg;
ImGui::StyleColorsDark();
ImGuiStyle& style = ImGui::GetStyle();
ImGui_ImplGlfw_InitForOpenGL(Windows, true);
ImGui_ImplOpenGL3_Init("#version 330");
while (!glfwWindowShouldClose(Windows))
{
glClear(GL_COLOR_BUFFER_BIT);
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
ImGui::DockSpaceOverViewport();
DrawGUI();
ImGui::ShowDemoWindow();
ImGui::Render();
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
{
GLFWwindow* backup_current_context = glfwGetCurrentContext();
ImGui::UpdatePlatformWindows();
ImGui::RenderPlatformWindowsDefault();
glfwMakeContextCurrent(backup_current_context);
}
glfwSwapBuffers(Windows);
glfwPollEvents();
}
}