Example character level animations.
This commit is contained in:
@ -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.
|
||||
|
51
src/dawn/display/animation/SimpleCallbackAnimation.hpp
Normal file
51
src/dawn/display/animation/SimpleCallbackAnimation.hpp
Normal 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;
|
||||
}
|
||||
};
|
||||
}
|
@ -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() {
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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;
|
||||
}
|
@ -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();
|
||||
};
|
||||
}
|
@ -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)
|
@ -19,7 +19,7 @@ VisualNovelFadeEvent::VisualNovelFadeEvent(
|
||||
this->duration = duration;
|
||||
this->simpleAnimation.easing = ease;
|
||||
}
|
||||
|
||||
|
||||
void VisualNovelFadeEvent::onStart(IVisualNovelEvent *previous) {
|
||||
VisualNovelSimpleAnimationEvent::onStart(previous);
|
||||
|
||||
|
@ -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> {
|
||||
|
10
src/dawn/visualnovel/events/animation/CMakeLists.txt
Normal file
10
src/dawn/visualnovel/events/animation/CMakeLists.txt
Normal 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
|
||||
)
|
@ -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;
|
||||
}
|
||||
};
|
||||
}
|
10
src/dawn/visualnovel/events/characters/CMakeLists.txt
Normal file
10
src/dawn/visualnovel/events/characters/CMakeLists.txt
Normal 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
|
||||
)
|
@ -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);
|
||||
}
|
||||
}
|
@ -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
|
||||
);
|
||||
};
|
||||
}
|
11
src/dawn/visualnovel/events/timing/CMakeLists.txt
Normal file
11
src/dawn/visualnovel/events/timing/CMakeLists.txt
Normal 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
|
||||
)
|
66
src/dawn/visualnovel/events/timing/VisualNovelBatchEvent.cpp
Normal file
66
src/dawn/visualnovel/events/timing/VisualNovelBatchEvent.cpp
Normal 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;
|
||||
}
|
||||
}
|
27
src/dawn/visualnovel/events/timing/VisualNovelBatchEvent.hpp
Normal file
27
src/dawn/visualnovel/events/timing/VisualNovelBatchEvent.hpp
Normal 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();
|
||||
};
|
||||
}
|
@ -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"
|
||||
|
Reference in New Issue
Block a user