get good, get zeus, for ever
-
Автор темы
- #1
Анимированный 3Д куб, сделан в стилистике загрузочного спинера прогресс бара нету просто кубик крутится + анимация цвета


source code:
#include <array>
#include <cmath>
struct ImVec3 {
float x, y, z;
ImVec3(float _x, float _y, float _z) : x(_x), y(_y), z(_z) {}
};
ImVec3 RotateX(const ImVec3& v, float angle) {
float rad = angle * (3.14159f / 180.0f);
float cosA = cos(rad);
float sinA = sin(rad);
return ImVec3(v.x, v.y * cosA - v.z * sinA, v.y * sinA + v.z * cosA);
}
ImVec3 RotateY(const ImVec3& v, float angle) {
float rad = angle * (3.14159f / 180.0f);
float cosA = cos(rad);
float sinA = sin(rad);
return ImVec3(v.x * cosA + v.z * sinA, v.y, -v.x * sinA + v.z * cosA);
}
void Add3DCube(ImVec2 center, float size, float perspective, float rotationX, float rotationY, float distance)
{
std::array<ImVec3, 8> cube_vertices{ {
ImVec3(-1, -1, -1), ImVec3(1, -1, -1),
ImVec3(1, 1, -1), ImVec3(-1, 1, -1),
ImVec3(-1, -1, 1), ImVec3(1, -1, 1),
ImVec3(1, 1, 1), ImVec3(-1, 1, 1)
} };
std::array<ImVec2, 8> projected_vertices;
for (size_t i = 0; i < cube_vertices.size(); i++)
{
ImVec3 rotated = RotateX(cube_vertices[i], rotationX);
rotated = RotateY(rotated, rotationY);
rotated.x *= distance;
rotated.y *= distance;
rotated.z *= distance;
float z = rotated.z * perspective + 3.0f;
projected_vertices[i] = ImVec2(
center.x + rotated.x * size / z,
center.y + rotated.y * size / z
);
//ImGui::GetWindowDrawList()->AddCircle(
// projected_vertices[i], 3.5f, ImColor(255, 255, 0, 255), 24, 2.0f
//);
}
std::array<std::pair<int, int>, 12> edges = { {
{0, 1}, {1, 2}, {2, 3}, {3, 0},
{4, 5}, {5, 6}, {6, 7}, {7, 4},
{0, 4}, {1, 5}, {2, 6}, {3, 7}
} };
for (const auto& edge : edges)
{
ImGui::GetWindowDrawList()->AddLine(
projected_vertices[edge.first],
projected_vertices[edge.second],
IM_COL32(255, 255, 255, 255), 2.0f
);
}
}
struct AnimationState {
bool state;
float target_speed;
float speed_multiplier;
float rotation_x;
float rotation_y;
};
void AddLoadingCube(const char* label)
{
ImGuiWindow* window = ImGui::GetCurrentWindow();
ImGuiID id = window->GetID(label);
if (window->SkipItems)
return;
ImGui::PushID(id);
auto& g = *GImGui;
auto center = ImGui::GetWindowPos() + ImVec2(ImGui::GetWindowWidth(), ImGui::GetWindowHeight()) / 2;
auto delta_time = ImGui::GetIO().DeltaTime;
ImVec2 text_size = ImGui::CalcTextSize(label);
static float spacing = 25.f;
static float cube_size = 50.f;
const ImVec2 extra_bb = ImVec2(cube_size + spacing, cube_size + spacing);
const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + extra_bb);
ImGui::ItemSize(extra_bb);
ImGui::ItemAdd(bb, 0);
/[I]ImGui::GetWindowDrawList()->AddRect(bb.Min, bb.Max, ImColor(255, 255, 0, 255), 0.0f, ImDrawFlags_None, 2.0f);[/I]/
static std::map<ImGuiID, AnimationState> animations;
if (animations.find(id) == animations.end()) {
animations[id] = AnimationState{ true, 68.0f, 0.0f, 0.0f, 0.0f };
}
AnimationState& anim_state = animations[id];
float lerp_factor = delta_time * 3.0f;
if (anim_state.state) {
anim_state.speed_multiplier = ImLerp(anim_state.speed_multiplier, anim_state.target_speed, lerp_factor);
if (anim_state.speed_multiplier >= anim_state.target_speed * 0.95f)
anim_state.state = false;
}
else {
anim_state.speed_multiplier = ImLerp(anim_state.speed_multiplier, 2.0f, lerp_factor);
if (anim_state.speed_multiplier <= 2.4f)
anim_state.state = true;
}
anim_state.rotation_x += delta_time * (8.5f * anim_state.speed_multiplier);
anim_state.rotation_y -= delta_time * (8.0f * anim_state.speed_multiplier);
float scale_factor = 1.0f + (anim_state.speed_multiplier * 0.0012f);
Add3DCube(bb.Min + ImVec2(cube_size / 2.f + spacing / 2, cube_size / 2.f + spacing / 4.f), cube_size, 0.f, anim_state.rotation_x, anim_state.rotation_y, scale_factor);
ImGui::PushFont(ImGui::GetIO().Fonts->Fonts[8]);
static std::map<ImGuiID, float> values;
auto value = values.find(id);
if (value == values.end()) {
values.insert({ id, 0.f });
value = values.find(id);
}
value->second = ImLerp(value->second, 200.f, g.IO.DeltaTime * 10.f);
ImVec2 text_pos = ImVec2(bb.Min.x + (bb.GetWidth() - text_size.x) / 2.0f, bb.Min.y + (bb.GetHeight() - text_size.y) / 1.0f);
ImGui::GetWindowDrawList()->AddText(text_pos, ImColor(255, 255, 255, int((anim_state.speed_multiplier * 2) + 135)), label);
ImGui::PopFont();
ImGui::PopID();
}
Последнее редактирование: