Compare commits
6 Commits
main
...
SP3-17-ani
Author | SHA1 | Date |
---|---|---|
Kah Wei | 26f84fb8d6 | |
Kah Wei | 52913562e7 | |
Kah Wei | 3b5d1ef6d5 | |
Kah Wei | 1044d79243 | |
Kah Wei | 1c56864ccb | |
Kah Wei | b93dfe3ba4 |
|
@ -60,6 +60,7 @@ namespace SHADE
|
||||||
/// Constructs an SHAnimation Clip from a specified SHAnimAsset.
|
/// Constructs an SHAnimation Clip from a specified SHAnimAsset.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="asset">Animation asset to load.</param>
|
/// <param name="asset">Animation asset to load.</param>
|
||||||
|
SHAnimationClip() = default;
|
||||||
explicit SHAnimationClip(const SHAnimAsset& asset);
|
explicit SHAnimationClip(const SHAnimAsset& asset);
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
@ -68,14 +69,16 @@ namespace SHADE
|
||||||
const std::vector<Channel>& GetChannels() const noexcept { return channels; }
|
const std::vector<Channel>& GetChannels() const noexcept { return channels; }
|
||||||
int GetTicksPerSecond() const noexcept { return ticksPerSecond; }
|
int GetTicksPerSecond() const noexcept { return ticksPerSecond; }
|
||||||
float GetTotalTime() const noexcept { return totalTime; }
|
float GetTotalTime() const noexcept { return totalTime; }
|
||||||
|
int GetTotalFrames() const noexcept { return totalFrames; }
|
||||||
|
|
||||||
private:
|
//private:
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Data Members */
|
/* Data Members */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
std::vector<Channel> channels;
|
std::vector<Channel> channels;
|
||||||
int ticksPerSecond;
|
int ticksPerSecond;
|
||||||
float totalTime;
|
float totalTime;
|
||||||
|
int totalFrames;
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Helper Functions */
|
/* Helper Functions */
|
||||||
|
|
|
@ -0,0 +1,194 @@
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\file SHAnimationClip.cpp
|
||||||
|
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||||
|
\par email: kahwei.tng\@digipen.edu
|
||||||
|
\date Nov 20, 2022
|
||||||
|
\brief Contains the function definitions of the SHAnimationClip class.
|
||||||
|
|
||||||
|
Copyright (C) 2022 DigiPen Institute of Technology.
|
||||||
|
Reproduction or disclosure of this file or its contents without the prior written consent
|
||||||
|
of DigiPen Institute of Technology is prohibited.
|
||||||
|
*//*************************************************************************************/
|
||||||
|
// Pre-compiled Header
|
||||||
|
#include "SHpch.h"
|
||||||
|
// Primary Header
|
||||||
|
#include "SHAnimationEditor.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Constructors */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
SHAnimationEditor::SHAnimationEditor()
|
||||||
|
: SHEditorWindow(ICON_MD_ANIMATION" Animation Editor", ImGuiWindowFlags_MenuBar)
|
||||||
|
{
|
||||||
|
// Construct a simple test clip
|
||||||
|
clip.channels.emplace_back
|
||||||
|
(
|
||||||
|
SHAnimationClip::Channel
|
||||||
|
{
|
||||||
|
.Name = "Child 1",
|
||||||
|
.PositionKeyFrames =
|
||||||
|
{
|
||||||
|
SHAnimationKeyFrame<SHVec3>
|
||||||
|
{
|
||||||
|
.FrameIndex = 0,
|
||||||
|
.Data = SHVec3 { 1.0f, 0.0f, 0.0f }
|
||||||
|
},
|
||||||
|
SHAnimationKeyFrame<SHVec3>
|
||||||
|
{
|
||||||
|
.FrameIndex = 30,
|
||||||
|
.Data = SHVec3 { 0.0f, 0.0f, 0.0f }
|
||||||
|
},
|
||||||
|
SHAnimationKeyFrame<SHVec3>
|
||||||
|
{
|
||||||
|
.FrameIndex = 60,
|
||||||
|
.Data = SHVec3 { 1.0f, 0.0f, 0.0f }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
clip.channels.emplace_back
|
||||||
|
(
|
||||||
|
SHAnimationClip::Channel
|
||||||
|
{
|
||||||
|
.Name = "Child 2",
|
||||||
|
.PositionKeyFrames =
|
||||||
|
{
|
||||||
|
SHAnimationKeyFrame<SHVec3>
|
||||||
|
{
|
||||||
|
.FrameIndex = 0,
|
||||||
|
.Data = SHVec3 { 1.0f, 0.0f, 0.0f }
|
||||||
|
},
|
||||||
|
SHAnimationKeyFrame<SHVec3>
|
||||||
|
{
|
||||||
|
.FrameIndex = 30,
|
||||||
|
.Data = SHVec3 { 0.0f, 0.0f, 0.0f }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
clip.channels.emplace_back
|
||||||
|
(
|
||||||
|
SHAnimationClip::Channel
|
||||||
|
{
|
||||||
|
.Name = "Child 3",
|
||||||
|
.PositionKeyFrames =
|
||||||
|
{
|
||||||
|
SHAnimationKeyFrame<SHVec3>
|
||||||
|
{
|
||||||
|
.FrameIndex = 15,
|
||||||
|
.Data = SHVec3 { 1.0f, 0.0f, 0.0f }
|
||||||
|
},
|
||||||
|
SHAnimationKeyFrame<SHVec3>
|
||||||
|
{
|
||||||
|
.FrameIndex = 30,
|
||||||
|
.Data = SHVec3 { 0.0f, 0.0f, 0.0f }
|
||||||
|
},
|
||||||
|
SHAnimationKeyFrame<SHVec3>
|
||||||
|
{
|
||||||
|
.FrameIndex = 45,
|
||||||
|
.Data = SHVec3 { 1.0f, 0.0f, 0.0f }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
clip.totalFrames = 60;
|
||||||
|
clip.totalTime = static_cast<float>(clip.totalFrames) / clip.GetTicksPerSecond();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Editor Lifecycle */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
void SHAnimationEditor::Init()
|
||||||
|
{
|
||||||
|
SHEditorWindow::Init();
|
||||||
|
}
|
||||||
|
void SHAnimationEditor::Update()
|
||||||
|
{
|
||||||
|
SHEditorWindow::Update();
|
||||||
|
|
||||||
|
// Constants
|
||||||
|
static constexpr float CHANNELS_COL_WIDTH = 150.0f;
|
||||||
|
static constexpr float TMP_TABLE_PADDING = 50.0f;
|
||||||
|
|
||||||
|
// Render the window
|
||||||
|
if (Begin())
|
||||||
|
{
|
||||||
|
// Construct 2-column table of the channels on the left
|
||||||
|
if (ImGui::BeginTable("animWindowTable", 2, ImGuiTableFlags_None))
|
||||||
|
{
|
||||||
|
// Set up Columns
|
||||||
|
ImGui::TableSetupColumn("Channels", ImGuiTableColumnFlags_WidthFixed, CHANNELS_COL_WIDTH);
|
||||||
|
ImGui::TableSetupColumn("");
|
||||||
|
|
||||||
|
// Compute dimensions for the clip
|
||||||
|
const float COL_WIDTH = windowSize.x - CHANNELS_COL_WIDTH - TMP_TABLE_PADDING;
|
||||||
|
const float DIST_PER_FRAME = 18.0f;//COL_WIDTH / static_cast<float>(clip.GetTotalFrames()); // Hardcoded distance based on the keyframe icon size
|
||||||
|
|
||||||
|
// Get Resources
|
||||||
|
const auto WINDOW_POS = ImGui::GetWindowPos();
|
||||||
|
auto drawList = ImGui::GetForegroundDrawList();
|
||||||
|
|
||||||
|
// Render Header
|
||||||
|
ImGui::TableHeadersRow();
|
||||||
|
ImGui::SameLine();
|
||||||
|
const auto TIMELINE_HEADER_START_POS = ImGui::GetCursorPos();
|
||||||
|
static constexpr int STEP = 10;
|
||||||
|
for (int frame = 0; frame <= clip.GetTotalFrames(); frame += STEP)
|
||||||
|
{
|
||||||
|
const float X_OFFSET = TIMELINE_HEADER_START_POS.x + frame * DIST_PER_FRAME;
|
||||||
|
// Draw Text
|
||||||
|
ImGui::SetCursorPos(ImVec2(X_OFFSET, TIMELINE_HEADER_START_POS.y));
|
||||||
|
SHEditorUI::Text(std::to_string(frame));
|
||||||
|
|
||||||
|
// Draw line
|
||||||
|
ImVec2 startPoint { WINDOW_POS.x + X_OFFSET, WINDOW_POS.y + TIMELINE_HEADER_START_POS.y };
|
||||||
|
drawList->AddLine(startPoint, ImVec2(startPoint.x, startPoint.y + beginContentRegionAvailable.y), ImGui::GetColorU32(ImVec4(1.0f, 1.0f, 1.0f, 1.0f)));
|
||||||
|
|
||||||
|
// Draw smaller lines
|
||||||
|
for (int innerFrames = frame + 1; innerFrames < std::min(frame + STEP, clip.GetTotalFrames()); ++innerFrames)
|
||||||
|
{
|
||||||
|
ImVec2 innerStartPoint{ WINDOW_POS.x + TIMELINE_HEADER_START_POS.x + innerFrames * DIST_PER_FRAME, WINDOW_POS.y + TIMELINE_HEADER_START_POS.y };
|
||||||
|
drawList->AddLine(innerStartPoint, ImVec2(innerStartPoint.x, innerStartPoint.y + beginContentRegionAvailable.y), ImGui::GetColorU32(ImVec4(0.2f, 0.2f, 0.2f, 1.0f)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::SetCursorPos(TIMELINE_HEADER_START_POS);
|
||||||
|
|
||||||
|
// Render all channels
|
||||||
|
for (const auto& channel : clip.channels)
|
||||||
|
{
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
const bool SHOW_ALL = ImGui::CollapsingHeader(channel.Name.c_str(), ImGuiTreeNodeFlags_DefaultOpen);
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
|
||||||
|
if (SHOW_ALL)
|
||||||
|
{
|
||||||
|
drawChannelKeyFrames("Position", channel.PositionKeyFrames);
|
||||||
|
drawChannelKeyFrames("Rotation", channel.RotationKeyFrames);
|
||||||
|
drawChannelKeyFrames("Scale", channel.ScaleKeyFrames);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// TODO: Show flattened view
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::EndTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
ImGui::End();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Usage Functions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Helper Functions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\file SHAnimationEditor.h
|
||||||
|
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||||
|
\par email: kahwei.tng\@digipen.edu
|
||||||
|
\date Jan 8, 2023
|
||||||
|
\brief Contains the definition of the SHAnimationEditor class and related types.
|
||||||
|
|
||||||
|
Copyright (C) 2023 DigiPen Institute of Technology.
|
||||||
|
Reproduction or disclosure of this file or its contents without the prior written consent
|
||||||
|
of DigiPen Institute of Technology is prohibited.
|
||||||
|
*//*************************************************************************************/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// Project Includes
|
||||||
|
#include "Editor/EditorWindow/SHEditorWindow.h"
|
||||||
|
#include "Animation/SHAnimationClip.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// ImGui window that contains the SHAnimationEditor
|
||||||
|
/// </summary>
|
||||||
|
class SHAnimationEditor final : public SHEditorWindow
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Constructor/Destructors */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
SHAnimationEditor();
|
||||||
|
virtual ~SHAnimationEditor() = default;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Editor Lifecycle */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
void Init() override;
|
||||||
|
void Update() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Static Constants */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
static constexpr float DIST_PER_FRAME = 18.0f;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Data Members */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
SHAnimationClip clip;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Helper Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
template<typename T>
|
||||||
|
void drawChannelKeyFrames(const std::string& name, const std::vector<SHAnimationKeyFrame<T>>& keyframes);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "SHAnimationEditor.hpp"
|
|
@ -0,0 +1,47 @@
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\file SHAnimationEditor.hpp
|
||||||
|
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||||
|
\par email: kahwei.tng\@digipen.edu
|
||||||
|
\date Jan 16, 2023
|
||||||
|
\brief Contains the definition of the SHAnimationEditor function templates.
|
||||||
|
|
||||||
|
Copyright (C) 2023 DigiPen Institute of Technology.
|
||||||
|
Reproduction or disclosure of this file or its contents without the prior written consent
|
||||||
|
of DigiPen Institute of Technology is prohibited.
|
||||||
|
*//*************************************************************************************/
|
||||||
|
#pragma once
|
||||||
|
// Primary Include
|
||||||
|
#include "SHAnimationEditor.h"
|
||||||
|
// Project Include
|
||||||
|
#include "Editor/SHEditorUI.h"
|
||||||
|
// External Dependencies
|
||||||
|
#include <imgui.h>
|
||||||
|
#include "Editor/IconsMaterialDesign.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
template<typename T>
|
||||||
|
void SHAnimationEditor::drawChannelKeyFrames(const std::string& name, const std::vector<SHAnimationKeyFrame<T>>& keyframes)
|
||||||
|
{
|
||||||
|
// Ignore if keyframes list is empty
|
||||||
|
if (keyframes.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Title
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::Indent();
|
||||||
|
ImGui::Text(name.c_str());
|
||||||
|
ImGui::Unindent();
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
|
||||||
|
// Draw all the keyframes
|
||||||
|
const auto START_POS = ImGui::GetCursorPos();
|
||||||
|
for (const auto& keyframe : keyframes)
|
||||||
|
{
|
||||||
|
ImGui::SetCursorPos(ImVec2(START_POS.x + keyframe.FrameIndex * DIST_PER_FRAME, START_POS.y));
|
||||||
|
SHEditorUI::OffsetText(ICON_MD_RADIO_BUTTON_CHECKED, 6.0f); // Hardcoded offset to align icon since ImGui can't calculate icon with properly
|
||||||
|
}
|
||||||
|
ImGui::SetCursorPos(START_POS);
|
||||||
|
}
|
||||||
|
}
|
|
@ -31,6 +31,7 @@
|
||||||
//#==============================================================#
|
//#==============================================================#
|
||||||
#include "EditorWindow/SHEditorWindowManager.h"
|
#include "EditorWindow/SHEditorWindowManager.h"
|
||||||
#include "EditorWindow/SHEditorWindowIncludes.h"
|
#include "EditorWindow/SHEditorWindowIncludes.h"
|
||||||
|
#include "EditorWindow/AnimationEditor/SHAnimationEditor.h"
|
||||||
|
|
||||||
//#==============================================================#
|
//#==============================================================#
|
||||||
//|| Library Includes ||
|
//|| Library Includes ||
|
||||||
|
@ -104,6 +105,7 @@ namespace SHADE
|
||||||
SHEditorWindowManager::CreateEditorWindow<SHAssetBrowser>();
|
SHEditorWindowManager::CreateEditorWindow<SHAssetBrowser>();
|
||||||
SHEditorWindowManager::CreateEditorWindow<SHMaterialInspector>();
|
SHEditorWindowManager::CreateEditorWindow<SHMaterialInspector>();
|
||||||
SHEditorWindowManager::CreateEditorWindow<SHColliderTagPanel>();
|
SHEditorWindowManager::CreateEditorWindow<SHColliderTagPanel>();
|
||||||
|
SHEditorWindowManager::CreateEditorWindow<SHAnimationEditor>();
|
||||||
|
|
||||||
SHEditorWindowManager::CreateEditorWindow<SHEditorViewport>();
|
SHEditorWindowManager::CreateEditorWindow<SHEditorViewport>();
|
||||||
|
|
||||||
|
|
|
@ -137,6 +137,18 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
ImGui::Text(title.c_str());
|
ImGui::Text(title.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SHEditorUI::CenteredText(const std::string& title)
|
||||||
|
{
|
||||||
|
OffsetText(title, -ImGui::CalcTextSize(title.c_str()).x * 1.5f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHEditorUI::OffsetText(const std::string& title, float offset)
|
||||||
|
{
|
||||||
|
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + offset);
|
||||||
|
ImGui::Text(title.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
bool SHEditorUI::SmallButton(const std::string& title)
|
bool SHEditorUI::SmallButton(const std::string& title)
|
||||||
{
|
{
|
||||||
return ImGui::SmallButton(title.c_str());
|
return ImGui::SmallButton(title.c_str());
|
||||||
|
|
|
@ -150,6 +150,19 @@ namespace SHADE
|
||||||
/// <param name="title">Text to display.</param>
|
/// <param name="title">Text to display.</param>
|
||||||
static void Text(const std::string& title);
|
static void Text(const std::string& title);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// Creates a visual text widget that is visually centered about the current
|
||||||
|
/// cursor point.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="title">Text to display.</param>
|
||||||
|
static void CenteredText(const std::string& title);
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a visual text widget that is visually offset from the current cursor
|
||||||
|
/// point.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="title">Text to display.</param>
|
||||||
|
/// <param name="offset">Distance to offset. Positive is to the right.</param>
|
||||||
|
static void OffsetText(const std::string& title, float offset);
|
||||||
|
/// <summary>
|
||||||
/// Creates a small inline button widget.
|
/// Creates a small inline button widget.
|
||||||
/// <br/>
|
/// <br/>
|
||||||
/// Wraps up ImGui::SmallButton().
|
/// Wraps up ImGui::SmallButton().
|
||||||
|
@ -341,7 +354,6 @@ namespace SHADE
|
||||||
/// <returns>Whether the value was modified.</returns>
|
/// <returns>Whether the value was modified.</returns>
|
||||||
static bool InputEnumCombo(const std::string& label, int& v, const std::vector<std::string>& enumNames, bool* isHovered = nullptr);
|
static bool InputEnumCombo(const std::string& label, int& v, const std::vector<std::string>& enumNames, bool* isHovered = nullptr);
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Prevent instantiation of this static class
|
// Prevent instantiation of this static class
|
||||||
SHEditorUI() = delete;
|
SHEditorUI() = delete;
|
||||||
|
|
Loading…
Reference in New Issue