关于ImGui动画系统 如何使用ImGui做动画!!

1 篇文章 0 订阅
1 篇文章 0 订阅
本文详细介绍了如何在ImGui中使用HImGuiAnimation库创建和管理动画,包括Play函数、updata更新、回调机制、动画序列和过渡效果的实现。通过实例展示了如何在用户界面中实现动画控制和参数调整。
摘要由CSDN通过智能技术生成

GitHub 链接


GitHub封面

废话

动画管理器对于创建交互性和吸引人的用户界面效果非常重要。它可以帮助你实现一些酷炫的动画效果,提高用户体验。

在给ImGui使用的动画管理器中,我实现了以下功能:

  1. 动画创建和管理:你可以在管理器中创建和管理多个动画对象。每个动画对象可以有不同的参数,如开始和结束值、持续时间 等。

  2. 动画播放控制:你可以控制动画的播放状态,如播放、暂停、停止等。这可以通过在ImGui界面中添加按钮或滑动条来实现。

  3. 动画过渡效果:你可以使用动画管理器实现平滑的过渡效果。例如,你可以使用动画管理器在两个界面之间实现平滑的渐变效果,而不是突然切换。

  4. 动画事件和回调:你可以在动画管理器中实现事件和回调函数。在动画播放过程中调用回调函数。

  5. 动画参数编辑:你可以在ImGui界面中添加参数编辑器,以便用户可以调整动画的参数,如FPS限制、播放速度 等。

  6. 动画序列和组合:你可以将多个动画对象组合在一起,形成一个动画序列或组合效果。例如,你可以创建一个淡入动画和一个移动动画,然后将它们组合在一起,实现一个对象的同时淡入和移动效果。

总之,制作一个给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::AnimationSequenceHAnimationSystem::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();
	}
}
  • 9
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值