Skip to content

Commit

Permalink
Merge pull request #9 from FlareCoding/development
Browse files Browse the repository at this point in the history
Minor UI performance improvements and introduced a brand new animation system.
  • Loading branch information
FlareCoding authored Sep 1, 2020
2 parents 6a46c16 + 93de9e4 commit 2285b6c
Show file tree
Hide file tree
Showing 27 changed files with 722 additions and 18 deletions.
2 changes: 2 additions & 0 deletions src/Monochrome.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@
#include "window/UIWindow.h"
#include "ui/UIElements.h"
#include "ui/UIFileDialogue.h"
#include "ui/UITimer.h"
#include "ui/animations/Animations.h"
#include "events/Events.h"
6 changes: 6 additions & 0 deletions src/ui/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
cmake_minimum_required(VERSION 3.0)

add_subdirectory(elements)
add_subdirectory(animations)

set(
MC_UI_HEADERS

${MC_UIELEMENTS_HEADERS}
${MC_ANIMATIONS_HEADERS}

src/ui/IDrawable.h
src/ui/Layer.h
src/ui/UIElements.h
src/ui/UIView.h
src/ui/UIFileDialogue.h
src/ui/UICursor.h
src/ui/UITimer.h

PARENT_SCOPE
)
Expand All @@ -21,9 +24,12 @@ set(
MC_UI_SOURCES

${MC_UIELEMENTS_SOURCES}
${MC_ANIMATIONS_SOURCES}

src/ui/UIView.cpp
src/ui/UIFileDialogue.cpp
src/ui/UICursor.cpp
src/ui/UITimer.cpp

PARENT_SCOPE
)
45 changes: 45 additions & 0 deletions src/ui/UITimer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#include "UITimer.h"

namespace mc
{
UITimer::UITimer(OnTickCallback_t fn)
: m_OnTickCallback(fn)
{
}

void UITimer::Start(uint32_t intervals)
{
std::thread timer_thread([this, intervals]() {
m_Running = true;
uint32_t tick = 0;
while (m_Running)
{
std::this_thread::sleep_for(std::chrono::milliseconds(intervals));
tick++;

if (m_OnTickCallback)
m_OnTickCallback(tick, this);
}
});
timer_thread.detach();
}

void UITimer::Schedule(uint32_t wait_time, uint32_t intervals)
{
std::thread scheduler_thread([this, wait_time, intervals]() {
std::this_thread::sleep_for(std::chrono::milliseconds(wait_time));
Start(intervals);
});
scheduler_thread.detach();
}

void UITimer::Stop()
{
m_Running = false;
}

void UITimer::SetOnTickFunction(OnTickCallback_t fn)
{
m_OnTickCallback = fn;
}
}
37 changes: 37 additions & 0 deletions src/ui/UITimer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#pragma once
#include <core/Core.h>
#include <functional>

namespace mc
{
class UITimer
{
public:
using OnTickCallback_t = std::function<void(uint32_t tick, UITimer* timer)>;

public:
UITimer() = default;
UITimer(OnTickCallback_t fn);
~UITimer() = default;

/// Starts the timer that will call its on-tick callback once per specified interval.
/// All time parameters are measured in miliseconds.
void Start(uint32_t intervals);

/// Waits for the specified wait_time and starts the timer.
/// All time parameters are measured in miliseconds.
void Schedule(uint32_t wait_time, uint32_t intervals);

/// Stops the timer's loop and exits out of its thread.
/// All time parameters are measured in miliseconds.
void Stop();

/// Specified the callback function to call on every tick.
/// All time parameters are measured in miliseconds.
void SetOnTickFunction(OnTickCallback_t fn);

private:
bool m_Running = false;
OnTickCallback_t m_OnTickCallback = nullptr;
};
}
69 changes: 69 additions & 0 deletions src/ui/animations/Animation.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#include "Animation.h"
#include "Animations.h"

#include <vector>
#include <mutex>

namespace mc
{
std::vector<Ref<Animation>> s_RunningAnimations;
std::mutex s_AnimationManagementMutex;

void Animation::DestroyAnimation(Animation* animation)
{
s_AnimationManagementMutex.lock();

for (auto it = s_RunningAnimations.begin(); it != s_RunningAnimations.end(); it++)
{
if (it->get() == animation)
{
s_RunningAnimations.erase(it);
break;
}
}

s_AnimationManagementMutex.unlock();
}

Ref<Animation> Animation::Create(AnimationType type, UIView* target)
{
Ref<Animation> instance = nullptr;
switch (type)
{
case AnimationType::FadeOut:
{
instance = MakeRef<FadeOutAnimation>();
break;
}
case AnimationType::FadeIn:
{
instance = MakeRef<FadeInAnimation>();
break;
}
case AnimationType::Translation:
{
instance = MakeRef<TranslationAnimation>();
break;
}
case AnimationType::Scale:
{
instance = MakeRef<ScaleAnimation>();
break;
}
case AnimationType::Custom:
{
instance = MakeRef<CustomAnimation>();
break;
}
default: break;
}

if (instance)
{
instance->Target = target;
s_RunningAnimations.push_back(instance);
}

return instance;
}
}
64 changes: 64 additions & 0 deletions src/ui/animations/Animation.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#pragma once
#include <ui/UITimer.h>
#include <ui/UIView.h>

namespace mc
{
/// Specifies the type of animation.
enum class AnimationType
{
/// Reduces the alpha value of the color of the view until it reaches 0.
FadeOut,

/// Increases the alpha value of the color of the view until it reaches 1.
FadeIn,

/// Translates the view by a certain amount in pixels.
Translation,

/// Resizes the view by a specifies amount in pixels.
Scale,

/// Performs a user specified callback over a duration.
Custom
};

/// Sets the OnTick member function to be the tick callback for the timer.
#define ANIMATION_INSTANCE_CONSTRUCTOR \
m_Timer.SetOnTickFunction([this](uint32_t tick, UITimer* timer) { OnTick(tick, timer); });

/// Performs a dynamic pointer cast
#define AnimCast(type, anim) std::dynamic_pointer_cast<type>(anim)

/// Base class for all framework animations.
class Animation
{
public:
/// Creates an instance of an appropriate animation class depending on the specified type.
/// @param type Specifies the type of the animation to be created.
/// @param target Specifies the target UIView on which specified animation will perform.
/// @note If the animation type is Custom, target parameter can be left blank.
/// @returns Ref to the base animation class that can be casted to an appropriate
/// subclass using AnimCast macro.
static Ref<Animation> Create(AnimationType type, UIView* target);

virtual ~Animation() = default;

/// Starts the animation that will be performed in a separate background thread.
/// @param duration Time in miliseconds the animation is going to run for.
/// @param completion_handler Optional user-defined function that will run
/// upon completion of the animation.
virtual void Animate(
uint32_t duration,
std::function<void()> completion_handler = nullptr
) = 0;

protected:
UITimer m_Timer;
virtual void OnTick(uint32_t tick, UITimer* timer) = 0;

protected:
UIView* Target = nullptr;
void DestroyAnimation(Animation* animation);
};
}
6 changes: 6 additions & 0 deletions src/ui/animations/Animations.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#pragma once
#include "FadeOutAnimation.h"
#include "FadeInAnimation.h"
#include "TranslationAnimation.h"
#include "ScaleAnimation.h"
#include "CustomAnimation.h"
28 changes: 28 additions & 0 deletions src/ui/animations/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
cmake_minimum_required(VERSION 3.0)

set(
MC_ANIMATIONS_HEADERS

src/ui/animations/Animations.h
src/ui/animations/Animation.h
src/ui/animations/FadeOutAnimation.h
src/ui/animations/FadeInAnimation.h
src/ui/animations/TranslationAnimation.h
src/ui/animations/ScaleAnimation.h
src/ui/animations/CustomAnimation.h

PARENT_SCOPE
)

set(
MC_ANIMATIONS_SOURCES

src/ui/animations/Animation.cpp
src/ui/animations/FadeOutAnimation.cpp
src/ui/animations/FadeInAnimation.cpp
src/ui/animations/TranslationAnimation.cpp
src/ui/animations/ScaleAnimation.cpp
src/ui/animations/CustomAnimation.cpp

PARENT_SCOPE
)
39 changes: 39 additions & 0 deletions src/ui/animations/CustomAnimation.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#include "CustomAnimation.h"

namespace mc
{
CustomAnimation::CustomAnimation()
{
ANIMATION_INSTANCE_CONSTRUCTOR
}

void CustomAnimation::Animate(
uint32_t duration,
std::function<void()> completion_handler
)
{
if (m_Started) return;
m_Started = true;

m_CompletionHandler = completion_handler;
m_Duration = duration;
m_Timer.Start(1);
}

void CustomAnimation::OnTick(uint32_t tick, UITimer* timer)
{
if (m_UserOnTick)
m_UserOnTick(tick);

if (tick >= m_Duration)
{
m_Timer.Stop();
if (m_CompletionHandler)
m_CompletionHandler();

DestroyAnimation(this);
}
}
}


37 changes: 37 additions & 0 deletions src/ui/animations/CustomAnimation.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#pragma once
#include "Animation.h"

namespace mc
{
/// CustomAnimation is an animation class that allows the user to define their own animation logic.
/// Before starting the animation, SetAnimationFunction() must be called
/// to set the user defined function that controls the animation logic.
class CustomAnimation : public Animation
{
public:
CustomAnimation();

/// Sets the user defined callback that gets executed
/// on every tick (every milisecond) during the animation.
void SetAnimationFunction(std::function<void(uint32_t)> fn) { m_UserOnTick = fn; }

/// Starts the animation that will be performed in a separate background thread.
/// @param duration Time in miliseconds the animation is going to run for.
/// @param completion_handler Optional user-defined function that will run
/// upon completion of the animation.
void Animate(
uint32_t duration,
std::function<void()> completion_handler = nullptr
) override;

private:
std::function<void()> m_CompletionHandler = nullptr;

bool m_Started = false;
void OnTick(uint32_t tick, UITimer* timer) override;

private:
uint32_t m_Duration = 0;
std::function<void(uint32_t)> m_UserOnTick;
};
}
Loading

0 comments on commit 2285b6c

Please sign in to comment.