2018-12-18 06:24:28 -05:00
|
|
|
#include "animationsystem.h"
|
|
|
|
|
|
|
|
#include <fstream>
|
|
|
|
#include <sstream>
|
|
|
|
#include <json.hpp>
|
|
|
|
|
|
|
|
#include "mesh.h"
|
|
|
|
#include "stringutils.h"
|
|
|
|
#include "worldmanager.h"
|
|
|
|
#include "world.h"
|
|
|
|
#include "assetmanager.h"
|
2018-12-19 12:19:52 -05:00
|
|
|
#include "entityparser.h"
|
2018-12-18 06:24:28 -05:00
|
|
|
|
|
|
|
Cinematic* AnimationSystem::loadCinematic(const std::string& path) {
|
|
|
|
std::ifstream file("data/" + path);
|
|
|
|
if(!file)
|
|
|
|
return nullptr;
|
2018-12-19 12:19:52 -05:00
|
|
|
|
2018-12-18 06:24:28 -05:00
|
|
|
nlohmann::json json;
|
|
|
|
file >> json;
|
2018-12-19 12:19:52 -05:00
|
|
|
|
2018-12-18 06:24:28 -05:00
|
|
|
auto cinematic = new Cinematic();
|
|
|
|
for(auto shotObject : json["shots"]) {
|
|
|
|
Shot* shot = new Shot();
|
|
|
|
shot->start = shotObject["start"];
|
|
|
|
shot->end = shotObject["end"];
|
|
|
|
shot->world = shotObject["world"];
|
2018-12-19 12:19:52 -05:00
|
|
|
|
|
|
|
for(auto entityObject : shotObject["entities"]) {
|
|
|
|
CinematicEntity entity;
|
|
|
|
entity.data = entityObject;
|
|
|
|
|
|
|
|
shot->entities.push_back(entity);
|
2018-12-18 06:24:28 -05:00
|
|
|
}
|
2018-12-19 12:19:52 -05:00
|
|
|
|
2018-12-18 06:24:28 -05:00
|
|
|
for(auto animationObject : shotObject["animations"]) {
|
|
|
|
auto animation = new Animation();
|
|
|
|
animation->targetName = animationObject["target"];
|
2018-12-19 12:19:52 -05:00
|
|
|
animation->targetComponent = animationObject["targetComponent"];
|
|
|
|
|
2018-12-18 06:24:28 -05:00
|
|
|
const auto property = animationObject["property"];
|
|
|
|
if(property == "position")
|
|
|
|
animation->property = AnimationProperty::Position;
|
|
|
|
else if(property == "target")
|
|
|
|
animation->property = AnimationProperty::Target;
|
|
|
|
else if(property == "fov")
|
|
|
|
animation->property = AnimationProperty::FoV;
|
2018-12-19 12:19:52 -05:00
|
|
|
|
2018-12-18 06:24:28 -05:00
|
|
|
for(auto keyframeObject : animationObject["keyframes"]) {
|
|
|
|
Keyframe keyframe;
|
|
|
|
keyframe.time = keyframeObject["time"];
|
2018-12-19 12:19:52 -05:00
|
|
|
|
2018-12-18 06:24:28 -05:00
|
|
|
if(animation->property == AnimationProperty::Position || animation->property == AnimationProperty::Target) {
|
|
|
|
auto tokens = tokenize(keyframeObject["value"]);
|
2018-12-19 12:19:52 -05:00
|
|
|
|
2018-12-18 06:24:28 -05:00
|
|
|
keyframe.valueVec3[0] = atof(tokens[0].c_str());
|
|
|
|
keyframe.valueVec3[1] = atof(tokens[1].c_str());
|
|
|
|
keyframe.valueVec3[2] = atof(tokens[2].c_str());
|
2018-12-19 12:19:52 -05:00
|
|
|
|
2018-12-18 06:24:28 -05:00
|
|
|
animation->keyframes.push_back(keyframe);
|
|
|
|
} else if(animation->property == AnimationProperty::FoV) {
|
|
|
|
keyframe.valueInt = keyframeObject["value"];
|
2018-12-19 12:19:52 -05:00
|
|
|
|
2018-12-18 06:24:28 -05:00
|
|
|
animation->keyframes.push_back(keyframe);
|
|
|
|
}
|
|
|
|
}
|
2018-12-19 12:19:52 -05:00
|
|
|
|
2018-12-18 06:24:28 -05:00
|
|
|
shot->animations.push_back(animation);
|
|
|
|
}
|
2018-12-19 12:19:52 -05:00
|
|
|
|
2018-12-18 06:24:28 -05:00
|
|
|
cinematic->shots.push_back(shot);
|
|
|
|
}
|
2018-12-19 12:19:52 -05:00
|
|
|
|
2018-12-18 06:24:28 -05:00
|
|
|
preloadShot(cinematic->shots[0]);
|
|
|
|
loadShot(cinematic->shots[0]);
|
2018-12-19 12:19:52 -05:00
|
|
|
|
2018-12-18 06:24:28 -05:00
|
|
|
return cinematic;
|
|
|
|
}
|
|
|
|
|
|
|
|
void AnimationSystem::update(Cinematic* cinematic, float deltaTime) {
|
|
|
|
float endTime = 0.0f;
|
|
|
|
for(uint32_t i = 0; i < cinematic->shots.size(); i++) {
|
|
|
|
// load the shot before it happens
|
|
|
|
if((i + 1) <= cinematic->shots.size() && i == (currentShot + 1) && !cinematic->shots[currentShot + 1]->loaded) {
|
|
|
|
preloadShot(cinematic->shots[currentShot + 1]);
|
|
|
|
cinematic->shots[currentShot + 1]->loaded = true;
|
|
|
|
}
|
2018-12-19 12:19:52 -05:00
|
|
|
|
2018-12-18 06:24:28 -05:00
|
|
|
if(i > currentShot && animationTime > cinematic->shots[i]->start) {
|
|
|
|
unloadShot(cinematic->shots[currentShot]);
|
|
|
|
currentShot = i;
|
|
|
|
loadShot(cinematic->shots[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for(auto animation : cinematic->shots[currentShot]->animations) {
|
|
|
|
unsigned int frameIndex = 0;
|
|
|
|
for(size_t i = 0; i < animation->keyframes.size(); i++) {
|
|
|
|
if(animationTime < animation->keyframes[i + 1].time) {
|
|
|
|
frameIndex = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2018-12-19 12:19:52 -05:00
|
|
|
|
2018-12-18 06:24:28 -05:00
|
|
|
const auto currentFrame = animation->keyframes[frameIndex];
|
|
|
|
const auto nextFrame = animation->keyframes[(frameIndex + 1) % animation->keyframes.size()];
|
2018-12-19 12:19:52 -05:00
|
|
|
|
2018-12-18 06:24:28 -05:00
|
|
|
const float delta = (animationTime - currentFrame.time) / (nextFrame.time - currentFrame.time);
|
2018-12-19 12:19:52 -05:00
|
|
|
|
2018-12-18 06:24:28 -05:00
|
|
|
switch(animation->property) {
|
|
|
|
case AnimationProperty::Position:
|
|
|
|
{
|
|
|
|
auto pos = currentFrame.valueVec3 + delta * (nextFrame.valueVec3 - currentFrame.valueVec3);
|
2018-12-19 12:19:52 -05:00
|
|
|
|
|
|
|
if(animation->targetComponent == "Transform") {
|
|
|
|
TransformComponent* transform = ECS::getComponent<TransformComponent>(animation->target);
|
|
|
|
transform->position = pos;
|
2018-12-18 06:24:28 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case AnimationProperty::Target:
|
|
|
|
{
|
|
|
|
auto pos = currentFrame.valueVec3 + delta * (nextFrame.valueVec3 - currentFrame.valueVec3);
|
2018-12-19 12:19:52 -05:00
|
|
|
|
|
|
|
if(animation->targetComponent == "Camera") {
|
|
|
|
CameraComponent* camera = ECS::getComponent<CameraComponent>(animation->target);
|
|
|
|
camera->target = pos;
|
|
|
|
}
|
2018-12-18 06:24:28 -05:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case AnimationProperty::FoV:
|
|
|
|
{
|
|
|
|
auto pos = currentFrame.valueInt + delta * (nextFrame.valueInt - currentFrame.valueInt);
|
2018-12-19 12:19:52 -05:00
|
|
|
|
|
|
|
if(animation->targetComponent == "Camera") {
|
|
|
|
CameraComponent* camera = ECS::getComponent<CameraComponent>(animation->target);
|
|
|
|
camera->fov = pos;
|
|
|
|
}
|
2018-12-18 06:24:28 -05:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2018-12-19 12:19:52 -05:00
|
|
|
|
2018-12-18 06:24:28 -05:00
|
|
|
animationTime += deltaTime;
|
|
|
|
}
|
|
|
|
|
|
|
|
void AnimationSystem::preloadShot(Shot* shot) {
|
|
|
|
worldManager.loadWorld(shot->world);
|
2018-12-19 12:19:52 -05:00
|
|
|
|
|
|
|
for(auto cimEntity : shot->entities) {
|
|
|
|
EntityID entity = parseEntity(cimEntity.data, worldManager.getWorld(shot->world));
|
|
|
|
|
2018-12-18 06:24:28 -05:00
|
|
|
for(auto animation : shot->animations) {
|
2018-12-19 12:19:52 -05:00
|
|
|
if(animation->targetName == ECS::getComponent<InfoComponent>(entity)->name)
|
|
|
|
animation->target = entity;
|
2018-12-18 06:24:28 -05:00
|
|
|
}
|
2018-12-19 12:19:52 -05:00
|
|
|
|
|
|
|
shot->loadedEntities.push_back(entity);
|
2018-12-18 06:24:28 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void AnimationSystem::loadShot(Shot* shot) {
|
|
|
|
worldManager.switchWorld(shot->world);
|
|
|
|
}
|
|
|
|
|
|
|
|
void AnimationSystem::unloadShot(Shot* shot) {
|
|
|
|
World* world = worldManager.getCurrentWorld();
|
2018-12-19 12:19:52 -05:00
|
|
|
|
|
|
|
for(auto entity : shot->loadedEntities)
|
|
|
|
ECS::destroyEntity(entity);
|
2018-12-18 06:24:28 -05:00
|
|
|
}
|