diff --git a/src/animation/animation.cpp b/src/animation/animation.cpp index 53a9b1d..061cf12 100644 --- a/src/animation/animation.cpp +++ b/src/animation/animation.cpp @@ -19,5 +19,34 @@ #include "animation.hpp" -void animation_base::animate(float dt) +animation_base::animation_base(): + position(0.0f), + start_callback(nullptr), + end_callback(nullptr), + loop_callback(nullptr) {} + +void animation_base::seek(double t) +{ + position = t; +} + +void animation_base::reset() +{ + seek(0.0); +} + +void animation_base::set_start_callback(std::function callback) +{ + start_callback = callback; +} + +void animation_base::set_end_callback(std::function callback) +{ + end_callback = callback; +} + +void animation_base::set_loop_callback(std::function callback) +{ + loop_callback = callback; +} diff --git a/src/animation/animation.hpp b/src/animation/animation.hpp index ff104a3..be522e3 100644 --- a/src/animation/animation.hpp +++ b/src/animation/animation.hpp @@ -21,44 +21,215 @@ #define ANTKEEPER_ANIMATION_HPP #include +#include +#include +#include -class animation_channel_base +/** + * Abstract base class for animations. + */ +class animation_base { +public: + animation_base(); + + /** + * Advances the animation position (t) by @p dt. + * + * @param dt Delta time by which the animation position will be advanced. + */ + virtual void advance(double dt) = 0; + + /** + * Sets the animation position to @p t. + * + * @param t Position in time to which the animation position will be set. + */ + void seek(double t); + + void reset(); + + /// Returns the current position in time of the animation. + double get_position() const; + + /// Sets the callback that's executed when the animation is started. + void set_start_callback(std::function callback); + /// Sets the callback that's executed when the animation ends. + void set_end_callback(std::function callback); + + /// Sets the callback that's executed when the animation loops. + void set_loop_callback(std::function callback); + +protected: + double position; + std::function start_callback; + std::function end_callback; + std::function loop_callback; }; +/** + * Templated keyframe animation class. + */ template -class animation_channel: public animation_channel_base +class animation: public animation_base { public: - void insert_keyframe(float position, const T& value); + /// Scheduled function consisting of a time and function object. + typedef std::tuple keyframe; + + /// Interpolator function type. + typedef typename std::decay>::type interpolator_type; + + /// Creates an animation + animation(); + + /// @copydoc animation_base::advance() + virtual void advance(double dt); + + /** + * Adds a keyframe to the animation. + * + * @param k Keyframe to add. + */ + void insert_keyframe(const keyframe& k); + + /** + * Removes all keyframes on `[start, end)`. + * + * @param start Starting position in time (inclusive). + * @param end Ending position in time (non-inclusive). + */ + void remove_keyframes(double start, double end); + + /** + * Returns all the keyframes on `[start, end)`. + * + * @param start Starting position in time (inclusive). + * @param end Ending position in time (non-inclusive). + * @return All keyframes on `[start, end)`. + */ + std::list get_keyframes(double start, double end) const; + + /// Removes all keyframes from the animation. + void clear(); + + /** + * Sets the frame interpolator function object. + * + * @param interpolator Frame interpolator function object. + */ + void set_interpolator(interpolator_type interpolator); + + /** + * Sets the callback that's executed on each frame of animation. + * + * @param callback Frame callback which receives the value of the interpolated frames. + */ + void set_frame_callback(std::function callback); + +private: + //static bool keyframe_compare(const keyframe& a, const keyframe & b); + + struct keyframe_compare + { + inline bool operator()(const keyframe& lhs, const keyframe& rhs) const + { + return std::get<0>(lhs) < std::get<0>(rhs); + } + }; + + interpolator_type interpolator; + std::function frame_callback; + std::set keyframes; }; -class animation_base +/* +template +bool animation::keyframe_compare(const keyframe& a, const keyframe & b) { -public: - void animate(float dt); -}; + return std::get<0>(a) < std::get<0>(b); +} +*/ template -class animation: public animation_base +animation::animation(): + interpolator(nullptr), + frame_callback(nullptr), + keyframes(keyframe_compare()) +{} + +template +void animation::advance(double dt) { -public: - void set_start_callback(std::function callback); - void set_end_callback(std::function callback); - void set_loop_callback(std::function callback); - void set_frame_callback(std::function callback); + position += dt; + + if (frame_callback != nullptr && interpolator != nullptr) + { + + auto upper_bound = keyframes.upper_bound({position, T()}); + auto lower_bound = upper_bound; + --lower_bound; + + if (lower_bound != keyframes.end() && upper_bound != keyframes.end()) + { + // Calculate interpolated frame + double t0 = std::get<0>(*lower_bound); + double t1 = std::get<0>(*upper_bound); + double alpha = (position - t0) / (t1 - t0); + T frame = interpolator(std::get<1>(*lower_bound), std::get<1>(*upper_bound), alpha); + + // Pass frame to frame callback + frame_callback(frame); + } + } +} -private: - std::function start_callback; - std::function end_callback; - std::function loop_callback; - std::function motion_callback; -}; +template +void animation::insert_keyframe(const keyframe& k) +{ + keyframes.emplace(k); +} -class skeletal_animation: public animation +template +void animation::remove_keyframes(double start, double end) { + auto lower_bound = keyframes.lower_bound({start, T()}); + auto upper_bound = keyframes.upper_bound({end, T()}); + keyframes.erase(lower_bound, upper_bound); +} -}; +template +std::list::keyframe> animation::get_keyframes(double start, double end) const +{ + std::list keyframe_list; + + auto lower_bound = keyframes.lower_bound({start, T()}); + auto upper_bound = keyframes.upper_bound({end, T()}); + for (auto iterator = lower_bound; iterator != upper_bound; ++iterator) + { + keyframe_list.push_back(*iterator); + } + + return keyframe_list; +} + +template +void animation::clear() +{ + keyframes.clear(); +} + +template +void animation::set_interpolator(interpolator_type interpolator) +{ + this->interpolator = interpolator; +} + +template +void animation::set_frame_callback(std::function callback) +{ + this->frame_callback = callback; +} #endif // ANTKEEPER_ANIMATION_HPP diff --git a/src/animation/animator.cpp b/src/animation/animator.cpp index b537368..eca8de3 100644 --- a/src/animation/animator.cpp +++ b/src/animation/animator.cpp @@ -18,9 +18,31 @@ */ #include "animator.hpp" +#include "animation/animation.hpp" -void animator::animate(float dt) +void animator::animate(double dt) { + for (animation_base* animation: animations) + { + animation->advance(dt); + } +} +void animator::add_animation(animation_base* animation) +{ + animations.emplace(animation); } +void animator::remove_animation(animation_base* animation) +{ + auto it = animations.find(animation); + if (it != animations.end()) + { + animations.erase(it); + } +} + +void animator::remove_animations() +{ + animations.clear(); +} diff --git a/src/animation/animator.hpp b/src/animation/animator.hpp index f93ff7c..f611a95 100644 --- a/src/animation/animator.hpp +++ b/src/animation/animator.hpp @@ -20,6 +20,10 @@ #ifndef ANTKEEPER_ANIMATOR_HPP #define ANTKEEPER_ANIMATOR_HPP +#include + +class animation_base; + class animator { public: @@ -28,8 +32,14 @@ public: * * @param dt Delta time by which the animations will be progressed. */ - void animate(float dt); + void animate(double dt); + + void add_animation(animation_base* animation); + void remove_animation(animation_base* animation); + void remove_animations(); + +private: + std::set animations; }; #endif // ANTKEEPER_ANIMATOR_HPP - diff --git a/src/animation/timeline.cpp b/src/animation/timeline.cpp index 4628f0f..96083a7 100644 --- a/src/animation/timeline.cpp +++ b/src/animation/timeline.cpp @@ -19,7 +19,7 @@ #include "timeline.hpp" -auto cue_compare = [](const cue& a, const cue& b) +auto cue_compare = [](const typename timeline::cue& a, const typename timeline::cue& b) { return std::get<0>(a) < std::get<0>(b); }; @@ -96,7 +96,7 @@ void timeline::set_autoremove(bool enabled) autoremove = enabled; } -sequence timeline::get_cues(float start, float end) +typename timeline::sequence timeline::get_cues(float start, float end) const { sequence s; diff --git a/src/animation/timeline.hpp b/src/animation/timeline.hpp index d48e3b4..97a6a3c 100644 --- a/src/animation/timeline.hpp +++ b/src/animation/timeline.hpp @@ -24,22 +24,18 @@ #include #include -/** - * Scheduled function consisting of a time and function object. - */ -typedef std::tuple> cue; - -/** - * List of cues. - */ -typedef std::list sequence; - /** * Timeline which executes cues (scheduled functions) when advanced over their respective positions in time. */ class timeline { public: + /// Scheduled function consisting of a time and function object. + typedef std::tuple> cue; + + /// List of cues. + typedef std::list sequence; + /** * Creates a timeline. */ @@ -119,7 +115,7 @@ public: * @param end Ending position in time (non-inclusive). * @return All cues on `[start, end)`. */ - sequence get_cues(float start, float end); + sequence get_cues(float start, float end) const; private: std::multiset> cues; diff --git a/src/animation/tween.hpp b/src/animation/tween.hpp index 319f558..f792ce8 100644 --- a/src/animation/tween.hpp +++ b/src/animation/tween.hpp @@ -33,21 +33,21 @@ * @return Interpolated value. */ template -T tween_default_lerp(const T& x, const T& y, float a); +T tween_default_interpolator(const T& x, const T& y, double a); /** * Container which stores two states along with an interpolator, for quick and easy tweening. * * @tparam T Value type. - * @tparam Interpolator Interpolator function or function object type. */ -template ::type(const T&, const T&, float)>> +template class tween { public: - typedef typename std::remove_pointer::type value_type; - typedef typename std::decay::type interpolator_type; - + //typedef typename std::remove_pointer::type value_type; + typedef T value_type; + typedef typename std::decay>::type interpolator_type; + /** * Creates a tween. * @@ -55,7 +55,7 @@ public: * @param state1 Initial value of state 1. * @param interpolator Function or function object that will be used to interpolate between states 0 and 1. */ - explicit tween(const T& state0, const T& state1, const interpolator_type& interpolator = tween_default_lerp); + explicit tween(const T& state0, const T& state1, const interpolator_type& interpolator = tween_default_interpolator); /** * Creates a tween. @@ -63,14 +63,14 @@ public: * @param value Initial value of states 0 and 1. * @param interpolator Function or function object that will be used to interpolate between states 0 and 1. */ - explicit tween(const T& value, const interpolator_type& interpolator = tween_default_lerp); + explicit tween(const T& value, const interpolator_type& interpolator = tween_default_interpolator); /** * Creates a tween. * * @param interpolator Function or function object that will be used to interpolate between states 0 and 1. */ - explicit tween(const interpolator_type& interpolator = tween_default_lerp); + explicit tween(const interpolator_type& interpolator = tween_default_interpolator); /** * Returns a reference to the specified tween state. @@ -89,7 +89,14 @@ public: * @param a Interpolation factor. Should be on `[0.0, 1.0]`. * @return Interpolated state. */ - value_type interpolate(float a) const; + value_type interpolate(double a) const; + + /** + * Sets the function object used to interpolate between states 0 and 1. + * + * @param interpolator Interpolator function object. + */ + void set_interpolator(const interpolator_type& interpolator); /** * Returns the function or function object that is used to interpolate between states 0 and 1. @@ -113,65 +120,77 @@ private: }; template -inline T tween_default_lerp(const T& x, const T& y, float a) +inline T tween_default_interpolator(const T& x, const T& y, double a) { - return x * (1.0f - a) + y * a; + //return x * (1.0 - a) + y * a; + return y; } -template -tween::tween(const T& value, const interpolator_type& interpolator): +template <> +inline float tween_default_interpolator(const float& x, const float& y, double a) +{ + return (y - x) * a + x; +} + +template +tween::tween(const T& value, const interpolator_type& interpolator): interpolator(interpolator), state0(value), state1(value) {} -template -tween::tween(const T& state0, const T& state1, const interpolator_type& interpolator): +template +tween::tween(const T& state0, const T& state1, const interpolator_type& interpolator): interpolator(interpolator), state0(state0), state1(state1) {} -template -tween::tween(const interpolator_type& interpolator): +template +tween::tween(const interpolator_type& interpolator): interpolator(interpolator) {} -template -inline const T& tween::operator[](int state) const +template +inline const T& tween::operator[](int state) const { return (state <= 0) ? state0 : state1; } -template -inline T& tween::operator[](int state) +template +inline T& tween::operator[](int state) { return (state <= 0) ? state0 : state1; } -template -inline typename tween::value_type tween::interpolate(float a) const +template +inline typename tween::value_type tween::interpolate(double a) const { return interpolator(state0, state1, a); } -template -inline const typename tween::interpolator_type& tween::get_interpolator() const +template +inline void tween::set_interpolator(const interpolator_type& interpolator) +{ + this->interpolator = interpolator; +} + +template +inline const typename tween::interpolator_type& tween::get_interpolator() const { return interpolator; } -template -inline void tween::update() +template +inline void tween::update() { state0 = state1; } -template -inline void tween::swap() +template +inline void tween::swap() { std::swap(state0, state1); } #endif // ANTKEEPER_TWEEN_HPP - diff --git a/src/application.cpp b/src/application.cpp index 8bfbf39..46507af 100644 --- a/src/application.cpp +++ b/src/application.cpp @@ -75,6 +75,7 @@ #include "renderer/material-property.hpp" // Animation +#include "animation/animation.hpp" #include "animation/animator.hpp" // Scene @@ -100,6 +101,24 @@ // Entity components #include "entity/components/cavity-component.hpp" +template +inline T ease_linear(const T& x, const T& y, double a) +{ + return (y - x) * a + x; +} + +template +T ease_in_quad(const T& x, const T& y, double a) +{ + return (y - x) * a * a + x; +} + +template +T ease_out_quad(const T& x, const T& y, double a) +{ + return -(y - x) * a * (a - 2.0f) + x; +} + using namespace vmq::operators; application::application(int argc, char** argv): @@ -156,6 +175,15 @@ application::application(int argc, char** argv): } } + // Register CLI commands + cli.register_command("echo", cc::echo); + cli.register_command("exit", std::function(std::bind(&cc::exit, this))); + cli.register_command("scrot", std::function(std::bind(&cc::scrot, this))); + cli.register_command("cue", std::function(std::bind(&cc::cue, this, std::placeholders::_1, std::placeholders::_2))); + //std::string cmd = "cue 20 exit"; + //logger.log(cmd + "\n"); + //logger.log(cli.interpret(cmd) + "\n"); + // Setup resource manager resource_manager = new ::resource_manager(); resource_manager->set_logger(&logger); @@ -229,9 +257,10 @@ application::application(int argc, char** argv): int window_height = 1080; fullscreen = true; - window_width = 1280; - window_height = 720; - fullscreen = false; + //window_width = 1280; + //window_height = 720; + //fullscreen = false; + viewport = {0.0f, 0.0f, static_cast(window_width), static_cast(window_height)}; int window_flags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIDDEN; @@ -446,8 +475,23 @@ application::application(int argc, char** argv): underworld_final_pass = new simple_render_pass(rasterizer, &rasterizer->get_default_framebuffer(), underworld_final_shader); underworld_final_pass->set_time_tween(&time); underground_transition_property = underworld_final_pass->get_material()->add_property("transition"); + underground_transition_property->set_value(0.0f); underground_color_texture_property = underworld_final_pass->get_material()->add_property("color_texture"); underground_color_texture_property->set_value(framebuffer_hdr_color); + underworld_final_pass->get_material()->update_tweens(); + + float radial_transition_time = 0.5f; + radial_transition_in = new animation(); + radial_transition_in->insert_keyframe({0.0f, 0.0f}); + radial_transition_in->insert_keyframe({radial_transition_time, 1.0f}); + radial_transition_in->set_frame_callback(std::bind(&material_property::set_val, underground_transition_property, std::placeholders::_1)); + radial_transition_in->set_interpolator(ease_in_quad); + + radial_transition_out = new animation(); + radial_transition_out->insert_keyframe({0.0f, 1.0f}); + radial_transition_out->insert_keyframe({radial_transition_time, 0.0f}); + radial_transition_out->set_frame_callback(std::bind(&material_property::set_val, underground_transition_property, std::placeholders::_1)); + radial_transition_out->set_interpolator(ease_out_quad); // Setup underworld compositor underworld_compositor.add_pass(underworld_clear_pass); @@ -497,7 +541,7 @@ application::application(int argc, char** argv): model_system = new ::model_system(ecs_registry, overworld_scene); // Setup systems - systems.push_back([this](double t, double dt){ this->overworld_scene.update_tweens(); this->underworld_scene.update_tweens(); this->ui_system->get_scene()->update_tweens(); focal_point_tween.update(); }); + systems.push_back([this](double t, double dt){ this->overworld_scene.update_tweens(); this->underworld_scene.update_tweens(); this->ui_system->get_scene()->update_tweens(); focal_point_tween.update(); this->underworld_final_pass->get_material()->update_tweens(); }); systems.push_back([this](double t, double dt){ this->translate_sdl_events(); }); systems.push_back([this](double t, double dt){ this->event_dispatcher.update(t); }); systems.push_back([this](double t, double dt){ this->timeline.advance(dt); }); @@ -627,13 +671,19 @@ application::application(int argc, char** argv): //this->overworld_camera.set_active(false); this->underworld_camera.set_active(true); this->active_scene = &this->underworld_scene; + this->animator->remove_animation(this->radial_transition_out); + this->animator->add_animation(this->radial_transition_in); + this->radial_transition_in->reset(); } else { // Switch to overworld - this->underworld_camera.set_active(false); + //this->underworld_camera.set_active(false); this->overworld_camera.set_active(true); this->active_scene = &this->overworld_scene; + this->animator->remove_animation(this->radial_transition_in); + this->animator->add_animation(this->radial_transition_out); + this->radial_transition_out->reset(); } }); @@ -801,14 +851,6 @@ application::application(int argc, char** argv): // Set overworld as active scene active_scene = &overworld_scene; - - // Setup debug CLI - cli.register_command("echo", cc::echo); - cli.register_command("exit", std::function(std::bind(&cc::exit, this))); - - std::string cmd = "echo abc 123"; - logger.log(cmd + "\n"); - logger.log(cli.interpret(cmd) + "\n"); } application::~application() @@ -830,7 +872,7 @@ void application::close(int status) int application::execute() { // Enter inital state - state_machine.change_state(splash_state); + state_machine.change_state(play_state); // Perform initial update update(0.0, 0.0); diff --git a/src/application.hpp b/src/application.hpp index 702fd16..7201cad 100644 --- a/src/application.hpp +++ b/src/application.hpp @@ -116,6 +116,9 @@ template class material_property; + + template + class animation; //} class application @@ -206,6 +209,8 @@ private: // Updatable systems timeline timeline; animator* animator; + animation* radial_transition_in; + animation* radial_transition_out; std::list> systems; int shadow_map_resolution; diff --git a/src/debug/console-commands.cpp b/src/debug/console-commands.cpp index 94f2081..cb7cc46 100644 --- a/src/debug/console-commands.cpp +++ b/src/debug/console-commands.cpp @@ -19,6 +19,8 @@ #include "console-commands.hpp" #include "application.hpp" +#include "animation/timeline.hpp" +#include "debug/cli.hpp" namespace cc { @@ -34,4 +36,20 @@ std::string exit(application* app) return std::string(); } +std::string scrot(application* app) +{ + app->take_screenshot(); + return std::string("screenshot saved"); +} + +std::string cue(application* app, float t, std::string command) +{ + ::timeline* timeline = app->get_timeline(); + ::cli* cli = app->get_cli(); + + timeline->add_cue({timeline->get_position() + t, std::function(std::bind(&::cli::interpret, cli, command))}); + + return std::string("command \"" + command + "\" will execute in " + std::to_string(t) + " seconds"); +} + } // namespace cc diff --git a/src/debug/console-commands.hpp b/src/debug/console-commands.hpp index 4c634c7..bc400be 100644 --- a/src/debug/console-commands.hpp +++ b/src/debug/console-commands.hpp @@ -31,6 +31,10 @@ std::string echo(std::string text); std::string exit(application* app); +std::string scrot(application* app); + +std::string cue(application* app, float t, std::string command); + } // namespace cc #endif // ANTKEEPER_CONSOLE_COMMANDS_HPP diff --git a/src/renderer/material-property.hpp b/src/renderer/material-property.hpp index 6fdefe7..4cf6eb4 100644 --- a/src/renderer/material-property.hpp +++ b/src/renderer/material-property.hpp @@ -20,6 +20,7 @@ #ifndef ANTKEEPER_MATERIAL_PROPERTY_HPP #define ANTKEEPER_MATERIAL_PROPERTY_HPP +#include "animation/tween.hpp" #include "rasterizer/shader-variable-type.hpp" #include "rasterizer/shader-input.hpp" #include @@ -50,13 +51,19 @@ public: * Disconnects the material property from its shader input. */ void disconnect(); + + /** + * Sets state 0 = state 1. + */ + virtual void update_tweens() = 0; /** * Uploads the material property to its shader program. * + * @param a Interpolation factor. Should be on `[0.0, 1.0]`. * @return `true` if the property was uploaded successfully, `false` otherwise. */ - virtual bool upload() const = 0; + virtual bool upload(double a) const = 0; /** * Returns the type of data which the property contains. @@ -107,9 +114,12 @@ public: material_property(const material_property&) = delete; material_property& operator=(const material_property&) = delete; + + /// @copydoc material_property_base::update_tweens() + virtual void update_tweens(); /// @copydoc material_property_base::upload() const - virtual bool upload() const; + virtual bool upload(double a) const; /** * Sets the value of this property. @@ -117,6 +127,7 @@ public: * @param value Value to set. */ void set_value(const T& value); + void set_val(const T& value); /** * Sets the value of a single element in this array property. @@ -143,7 +154,7 @@ public: private: std::size_t element_count; - T* values; + tween* values; }; template @@ -151,7 +162,7 @@ material_property::material_property(std::size_t element_count): element_count(element_count), values(nullptr) { - values = new T[element_count]; + values = new tween[element_count]; } template @@ -161,7 +172,16 @@ material_property::~material_property() } template -bool material_property::upload() const +void material_property::update_tweens() +{ + for (std::size_t i = 0; i < element_count; ++i) + { + values[i].update(); + } +} + +template +bool material_property::upload(double a) const { if (!is_connected()) { @@ -170,24 +190,36 @@ bool material_property::upload() const if (element_count > 1) { - return input->upload(0, values, element_count); + for (std::size_t i = 0; i < element_count; ++i) + { + if (!input->upload(i, values[i].interpolate(a))) + return false; + } + + return true; } else { - return input->upload(values[0]); + return input->upload(values[0].interpolate(a)); } } template void material_property::set_value(const T& value) { - values[0] = value; + values[0][1] = value; +} + +template +void material_property::set_val(const T& value) +{ + values[0][1] = value; } template void material_property::set_value(std::size_t index, const T& value) { - values[index] = value; + values[index][1] = value; } template @@ -195,7 +227,7 @@ void material_property::set_values(std::size_t index, const T* values, std::s { for (std::size_t i = 0; i < count; ++i) { - this->values[index + i] = values[i]; + this->values[index + i][1] = values[i]; } } @@ -331,7 +363,8 @@ material_property_base* material_property::clone() const material_property* property = new material_property(element_count); for (std::size_t i = 0; i < element_count; ++i) { - property->values[i] = values[i]; + property->values[i][0] = values[i][0]; + property->values[i][1] = values[i][1]; } property->input = input; diff --git a/src/renderer/material.cpp b/src/renderer/material.cpp index a65aaa0..05c5a01 100644 --- a/src/renderer/material.cpp +++ b/src/renderer/material.cpp @@ -64,7 +64,15 @@ material& material::operator=(const material& other) return *this; } -std::size_t material::upload() const +void material::update_tweens() +{ + for (material_property_base* property: properties) + { + property->update_tweens(); + } +} + +std::size_t material::upload(double a) const { if (!program) { @@ -75,7 +83,7 @@ std::size_t material::upload() const for (material_property_base* property: properties) { - if (!property->upload()) + if (!property->upload(a)) { ++failed_upload_count; } diff --git a/src/renderer/material.hpp b/src/renderer/material.hpp index 6eaae30..de6c9d0 100644 --- a/src/renderer/material.hpp +++ b/src/renderer/material.hpp @@ -65,13 +65,19 @@ public: * @return Reference to this material. */ material& operator=(const material& other); + + /** + * Sets state 0 = state 1 for each material property tween. + */ + void update_tweens(); /** * Uploads each material property to the material's shader program. * + * @param a Interpolation factor. Should be on `[0.0, 1.0]`. * @return Number of material property uploads which failed. */ - std::size_t upload() const; + std::size_t upload(double a) const; /** * Sets the material's shader program and reconnects all shader properties to their corresponding shader inputs. diff --git a/src/renderer/passes/material-pass.cpp b/src/renderer/passes/material-pass.cpp index 6694db6..0dbd469 100644 --- a/src/renderer/passes/material-pass.cpp +++ b/src/renderer/passes/material-pass.cpp @@ -403,7 +403,7 @@ void material_pass::render(render_context* context) const } // Upload material properties to shader - active_material->upload(); + active_material->upload(context->alpha); } // Calculate operation-dependent parameters diff --git a/src/renderer/simple-render-pass.cpp b/src/renderer/simple-render-pass.cpp index 5768c75..1e8f97b 100644 --- a/src/renderer/simple-render-pass.cpp +++ b/src/renderer/simple-render-pass.cpp @@ -103,7 +103,7 @@ void simple_render_pass::render(render_context* context) const resolution_property->set_value({static_cast(std::get<0>(viewport)), static_cast(std::get<1>(viewport))}); // Upload material properties - material->upload(); + material->upload(context->alpha); // Draw quad rasterizer->draw_arrays(*quad_vao, drawing_mode::triangles, 0, 6); diff --git a/src/resources/resource-manager.cpp b/src/resources/resource-manager.cpp index 0cbd739..f0adb90 100644 --- a/src/resources/resource-manager.cpp +++ b/src/resources/resource-manager.cpp @@ -43,7 +43,17 @@ void resource_manager::unload(const std::string& path) // Free the resource if the resource handle is unreferenced if (it->second->reference_count <= 0) { + if (logger) + { + logger->push_task("Unloading resource \"" + path + "\""); + } + delete it->second; + + if (logger) + { + logger->pop_task(EXIT_SUCCESS); + } } // Remove resource from the cache diff --git a/src/resources/resource-manager.hpp b/src/resources/resource-manager.hpp index 755db7d..56b559e 100644 --- a/src/resources/resource-manager.hpp +++ b/src/resources/resource-manager.hpp @@ -98,6 +98,11 @@ T* resource_manager::load(const std::string& path) auto it = resource_cache.find(path); if (it != resource_cache.end()) { + if (logger) + { + logger->log("Fetched resource \"" + path + "\"\n"); + } + // Resource found resource_handle* resource = static_cast*>(it->second); diff --git a/src/scene/billboard.cpp b/src/scene/billboard.cpp index 5858335..5b8c59a 100644 --- a/src/scene/billboard.cpp +++ b/src/scene/billboard.cpp @@ -18,8 +18,8 @@ */ #include "scene/billboard.hpp" +#include "renderer/material.hpp" #include "configuration.hpp" -#include const aabb billboard::untransformed_bounds = {{-1, -1, -1}, {1, 1, 1}}; @@ -63,3 +63,12 @@ void billboard::transformed() { bounds = aabb::transform(untransformed_bounds, get_transform()); } + +void billboard::update_tweens() +{ + scene_object_base::update_tweens(); + if (material) + { + material->update_tweens(); + } +} diff --git a/src/scene/billboard.hpp b/src/scene/billboard.hpp index 8004d4b..54d9147 100644 --- a/src/scene/billboard.hpp +++ b/src/scene/billboard.hpp @@ -61,12 +61,15 @@ public: material* get_material() const; billboard_type get_billboard_type() const; const float3& get_alignment_axis() const; + + virtual void update_tweens(); private: static const aabb untransformed_bounds; virtual void transformed(); + aabb bounds; material* material; billboard_type type; diff --git a/src/scene/model-instance.cpp b/src/scene/model-instance.cpp index b6fcf96..7b3d010 100644 --- a/src/scene/model-instance.cpp +++ b/src/scene/model-instance.cpp @@ -19,7 +19,7 @@ #include "scene/model-instance.hpp" #include "renderer/model.hpp" -#include +#include "renderer/material.hpp" model_instance::model_instance(::model* model): model(nullptr), @@ -99,3 +99,30 @@ void model_instance::transformed() { update_bounds(); } + +void model_instance::update_tweens() +{ + scene_object_base::update_tweens(); + + // Update model material tweens + if (model) + { + for (model_group* group: *model->get_groups()) + { + material* material = group->get_material(); + if (material) + { + material->update_tweens(); + } + } + } + + // Update material override tweens + for (::material* material: materials) + { + if (material) + { + material->update_tweens(); + } + } +} diff --git a/src/scene/model-instance.hpp b/src/scene/model-instance.hpp index 136fcbe..45d7787 100644 --- a/src/scene/model-instance.hpp +++ b/src/scene/model-instance.hpp @@ -74,6 +74,8 @@ public: bool is_instanced() const; std::size_t get_instance_count() const; + virtual void update_tweens(); + private: void update_bounds(); virtual void transformed(); diff --git a/src/state/splash-state.cpp b/src/state/splash-state.cpp index 4f51ec3..7517b21 100644 --- a/src/state/splash-state.cpp +++ b/src/state/splash-state.cpp @@ -48,7 +48,7 @@ void enter_splash_state(application* app) // Create splash sequence float t = timeline->get_position(); - sequence splash_sequence = + timeline::sequence splash_sequence = { {t + 0.0f, fade_in}, {t + 3.0f, fade_out}, diff --git a/src/state/title-state.cpp b/src/state/title-state.cpp index bac03e3..341a009 100644 --- a/src/state/title-state.cpp +++ b/src/state/title-state.cpp @@ -30,7 +30,7 @@ void enter_title_state(application* app) // Create title sequence float t = timeline->get_position(); - sequence title_sequence = + timeline::sequence title_sequence = { {t + 0.0f, [logger](){ logger->log("cue sound fade-in\n"); }}, {t + 3.0f, [logger](){ logger->log("cue scene fade-in from black\n"); }}, diff --git a/src/timestamp.cpp b/src/timestamp.cpp index 2e0bfaa..7222dcc 100644 --- a/src/timestamp.cpp +++ b/src/timestamp.cpp @@ -25,6 +25,8 @@ std::string timestamp() { + const char* time_format = "%y%m%d-%H%M%S-"; + auto now = std::chrono::system_clock::now(); std::time_t tt = std::chrono::system_clock::to_time_t(now); std::size_t ms = (std::chrono::duration_cast(now.time_since_epoch()) % 1000).count(); @@ -33,12 +35,12 @@ std::string timestamp() struct std::tm timeinfo; localtime_s(&timeinfo, &tt); std::stringstream stream; - stream << std::put_time(&timeinfo, "%Y%m%d-%H%M%S-"); + stream << std::put_time(&timeinfo, time_format); stream << std::setfill('0') << std::setw(3) << ms; #else struct std::tm* timeinfo = localtime(&tt); std::stringstream stream; - stream << std::put_time(timeinfo, "%Y%m%d-%H%M%S-"); + stream << std::put_time(timeinfo, time_format); stream << std::setfill('0') << std::setw(3) << ms; #endif