Example character level animations.

This commit is contained in:
2023-01-18 23:53:39 -08:00
parent 821074dfc4
commit 985218b9bc
29 changed files with 388 additions and 44 deletions

View File

@ -15,12 +15,27 @@ namespace Dawn {
template<typename T>
struct SimpleAnimation : public Animation {
protected:
/**
* Function for subclasses to be "notified" when the value has been
* modified.
*/
virtual void onValueModified() {
}
public:
easefunction_t *easing = &easeLinear;
T *modifies;
std::vector<struct SimpleKeyframe<T>> keyframes;
/**
* Constructs a new Simple Animation instance.
*
* @param modifies Pointer to the value that will be modified.
*/
SimpleAnimation(T *modifies) {
assertNotNull(modifies);
this->modifies = modifies;
}
@ -31,6 +46,8 @@ namespace Dawn {
* @param value Value at this given time.
*/
void addKeyframe(float_t time, T value) {
assertTrue(time >= 0);
struct SimpleKeyframe<T> keyframe;
keyframe.time = time;
keyframe.value = value;
@ -83,6 +100,17 @@ namespace Dawn {
this->addSequentialKeyframes(0, frameTime, start, end, 1);
}
/**
* Immediately sets the value, bypassing keyframes and ticks. Useful for
* setting an initial value.
*
* @param value Value to set.
*/
void setValue(T value) {
*modifies = value;
this->onValueModified();
}
void tick(float_t delta) override {
if(this->finished) return;
@ -106,6 +134,7 @@ namespace Dawn {
if(keyframeCurrent != nullptr && keyframeNext == nullptr) {
// "End of animation"
*this->modifies = keyframeCurrent->value;
this->onValueModified();
} else if(keyframeNext != nullptr) {
T oldValue;
float_t oldTime;
@ -127,6 +156,13 @@ namespace Dawn {
*this->modifies = oldValue + (
(keyframeNext->value - oldValue) * keyframeDelta
);
this->onValueModified();
}
// First possible frame? I think this can be done cleaner
if(this->time == 0 && keyframeCurrent->time == 0) {
*this->modifies = keyframeCurrent->value;
this->onValueModified();
}
// Update time.

View File

@ -0,0 +1,51 @@
// Copyright (c) 2023 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#pragma once
#include "SimpleAnimation.hpp"
namespace Dawn {
template<typename T, class I>
struct SimpleCallbackAnimation : public SimpleAnimation<T> {
protected:
I *instance;
void (I::*callback)(T arg);
T value;
/**
* Internally invoke the function that this animation is owning.
*/
void invoke() {
assertNotNull(this->instance);
((*this->instance).*(this->callback))(this->value);
}
void onValueModified() override {
SimpleAnimation::onValueModified();
this->invoke();
}
public:
/**
* Construct a new Simple Function Animation object
*/
SimpleCallbackAnimation() :
SimpleAnimation(&value)
{
}
/**
* Sets the callback for the animation to use.
*
* @param instance Instance of the object that has the callback.
* @param callback Callback method to be invoked.
*/
void setCallback(I *instance, void (I::*callback)(T arg)) {
assertNotNull(instance);
this->instance = instance;
this->callback = callback;
}
};
}

View File

@ -15,9 +15,17 @@ AnimationController::AnimationController(SceneItem *item) :
}
void AnimationController::addAnimation(Animation *animation) {
assertNotNull(animation);
this->animations.push_back(animation);
}
void AnimationController::onSceneUpdate() {
if(this->animation == nullptr) return;
this->animation->tick(this->getGame()->timeManager.delta);
auto it = this->animations.begin();
while(it != this->animations.end()) {
(*it)->tick(this->getGame()->timeManager.delta);
++it;
}
}
void AnimationController::onStart() {

View File

@ -10,13 +10,14 @@
namespace Dawn {
class AnimationController : public SceneItemComponent {
private:
std::vector<Animation*> animations;
void onSceneUpdate();
public:
Animation *animation = nullptr;
AnimationController(SceneItem *item);
void addAnimation(Animation *animation);
void onStart() override;
void onDispose() override;
};

View File

@ -10,5 +10,19 @@ using namespace Dawn;
VisualNovelCharacter::VisualNovelCharacter(SceneItem *item) :
SceneItemComponent(item)
{
}
void VisualNovelCharacter::setOpacity(float_t opacity) {
auto interface = this->item->getComponent<SimpleTexturedShaderInterface>();
assertNotNull(interface);
auto color = interface->getColor();
color.a = opacity;
interface->setColor(color);
}
float_t VisualNovelCharacter::getOpacity() {
auto interface = this->item->getComponent<SimpleTexturedShaderInterface>();
assertNotNull(interface);
auto color = interface->getColor();
return color.a;
}

View File

@ -5,10 +5,12 @@
#pragma once
#include "scene/SceneItemComponent.hpp"
#include "scene/components/display/shader/SimpleTexturedShaderInterface.hpp"
namespace Dawn {
class VisualNovelCharacter : public SceneItemComponent {
protected:
SimpleTexturedShaderInterface *shaderInterface = nullptr;
public:
std::string nameKey = "character.unknown";
@ -20,5 +22,11 @@ namespace Dawn {
* @param item Item that this component belongs to.
*/
VisualNovelCharacter(SceneItem *item);
SimpleTexturedShaderInterface * getShaderInterface();
void setOpacity(float_t opacity);
float_t getOpacity();
};
}

View File

@ -6,9 +6,12 @@
# Sources
target_sources(${DAWN_TARGET_NAME}
PRIVATE
VisualNovelAnimationEvent.cpp
VisualNovelFadeEvent.cpp
VisualNovelPauseEvent.cpp
VisualNovelTextboxEvent.cpp
VisualNovelChangeSimpleBackgroundEvent.cpp
)
)
# Subdirs
add_subdirectory(animation)
add_subdirectory(characters)
add_subdirectory(timing)

View File

@ -19,7 +19,7 @@ VisualNovelFadeEvent::VisualNovelFadeEvent(
this->duration = duration;
this->simpleAnimation.easing = ease;
}
void VisualNovelFadeEvent::onStart(IVisualNovelEvent *previous) {
VisualNovelSimpleAnimationEvent::onStart(previous);

View File

@ -4,7 +4,7 @@
// https://opensource.org/licenses/MIT
#pragma once
#include "VisualNovelSimpleAnimationEvent.hpp"
#include "visualnovel/events/animation/VisualNovelSimpleAnimationEvent.hpp"
namespace Dawn {
class VisualNovelFadeEvent : public VisualNovelSimpleAnimationEvent<float_t> {

View File

@ -0,0 +1,10 @@
# Copyright (c) 2022 Dominic Masters
#
# This software is released under the MIT License.
# https://opensource.org/licenses/MIT
# Sources
target_sources(${DAWN_TARGET_NAME}
PRIVATE
VisualNovelAnimationEvent.cpp
)

View File

@ -0,0 +1,24 @@
// Copyright (c) 2023 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#pragma once
#include "VisualNovelAnimationEvent.hpp"
#include "display/animation/SimpleCallbackAnimation.hpp"
namespace Dawn {
template<typename T, class I>
class VisualNovelSimpleCallbackAnimationEvent :
public VisualNovelAnimationEvent
{
public:
struct SimpleCallbackAnimation<T, I> callbackAnimation;
VisualNovelSimpleCallbackAnimationEvent(VisualNovelManager *man) :
VisualNovelAnimationEvent(man)
{
this->animation = &callbackAnimation;
}
};
}

View File

@ -0,0 +1,10 @@
# Copyright (c) 2022 Dominic Masters
#
# This software is released under the MIT License.
# https://opensource.org/licenses/MIT
# Sources
target_sources(${DAWN_TARGET_NAME}
PRIVATE
VisualNovelFadeCharacterEvent.cpp
)

View File

@ -0,0 +1,29 @@
// Copyright (c) 2023 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#include "VisualNovelFadeCharacterEvent.hpp"
using namespace Dawn;
VisualNovelFadeCharacterEvent::VisualNovelFadeCharacterEvent(
VisualNovelManager *man,
VisualNovelCharacter *character,
bool_t fadeIn,
easefunction_t *ease,
float_t duration
) : VisualNovelSimpleCallbackAnimationEvent<float_t, VisualNovelCharacter>(man)
{
this->callbackAnimation.easing = ease;
this->callbackAnimation.setCallback(
character, &VisualNovelCharacter::setOpacity
);
if(fadeIn) {
this->callbackAnimation.addKeyframe(0.0f, 0.0f);
this->callbackAnimation.addKeyframe(duration, 1.0f);
} else {
this->callbackAnimation.addKeyframe(0.0f, 1.0f);
this->callbackAnimation.addKeyframe(duration, 0.0f);
}
}

View File

@ -0,0 +1,24 @@
// Copyright (c) 2023 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#pragma once
#include "visualnovel/events/animation/VisualNovelSimpleCallbackAnimationEvent.hpp"
#include "visualnovel/components/VisualNovelCharacter.hpp"
#include "scene/components/display/Material.hpp"
namespace Dawn {
class VisualNovelFadeCharacterEvent :
public VisualNovelSimpleCallbackAnimationEvent<float_t,VisualNovelCharacter>
{
public:
VisualNovelFadeCharacterEvent(
VisualNovelManager *man,
VisualNovelCharacter *character,
bool_t fadeIn,
easefunction_t *ease,
float_t duration
);
};
}

View File

@ -0,0 +1,11 @@
# Copyright (c) 2022 Dominic Masters
#
# This software is released under the MIT License.
# https://opensource.org/licenses/MIT
# Sources
target_sources(${DAWN_TARGET_NAME}
PRIVATE
VisualNovelBatchEvent.cpp
VisualNovelPauseEvent.cpp
)

View File

@ -0,0 +1,66 @@
// Copyright (c) 2023 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#include "VisualNovelBatchEvent.hpp"
using namespace Dawn;
VisualNovelBatchEvent::VisualNovelBatchEvent(
VisualNovelManager *man,
std::vector<IVisualNovelEvent*> events
) : IVisualNovelEvent(man) {
this->activeEvents = events;
}
void VisualNovelBatchEvent::onStart(IVisualNovelEvent *previous) {
auto it = this->activeEvents.begin();
while(it != this->activeEvents.end()) {
auto evt = *it;
evt->start(previous);
++it;
}
}
bool_t VisualNovelBatchEvent::onUpdate() {
bool_t result;
auto it = this->activeEvents.begin();
while(it != this->activeEvents.end()) {
auto evt = *it;
result = evt->update();
if(result) {
++it;
continue;
}
auto subNext = evt->end();
// In future I may remove this and instead immediately queue the next thing.
assertNull(subNext);
it = this->activeEvents.erase(it);
this->inactiveEvents.push_back(evt);
}
return this->activeEvents.size() > 0;
}
void VisualNovelBatchEvent::onEnd() {
}
VisualNovelBatchEvent::~VisualNovelBatchEvent() {
auto itActive = this->activeEvents.begin();
while(itActive != this->activeEvents.end()) {
auto evt = *itActive;
delete evt;
++itActive;
}
auto itInactive = this->inactiveEvents.begin();
while(itInactive != this->inactiveEvents.end()) {
auto evt = *itInactive;
delete evt;
++itInactive;
}
}

View File

@ -0,0 +1,27 @@
// Copyright (c) 2023 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#pragma once
#include "visualnovel/VisualNovelManager.hpp"
namespace Dawn {
class VisualNovelBatchEvent : public IVisualNovelEvent {
protected:
std::vector<IVisualNovelEvent*> activeEvents;
std::vector<IVisualNovelEvent*> inactiveEvents;
void onStart(IVisualNovelEvent *previous) override;
bool_t onUpdate() override;
void onEnd() override;
public:
VisualNovelBatchEvent(
VisualNovelManager *man,
std::vector<IVisualNovelEvent*> events
);
~VisualNovelBatchEvent();
};
}

View File

@ -11,7 +11,7 @@
#include "scene/components/audio/AudioListener.hpp"
#include "visualnovel/VisualNovelManager.hpp"
#include "visualnovel/events/VisualNovelTextboxEvent.hpp"
#include "visualnovel/events/VisualNovelPauseEvent.hpp"
#include "visualnovel/events/timing/VisualNovelPauseEvent.hpp"
#include "visualnovel/events/VisualNovelFadeEvent.hpp"
#include "visualnovel/events/VisualNovelCAllbackEvent.hpp"
#include "visualnovel/events/VisualNovelChangeSimpleBackgroundEvent.hpp"