Archived
1
Fork 0
This repository has been archived on 2025-04-12. You can view files and clone it, but cannot push or open issues or pull requests.
graph/src/animationsystem.cpp

172 lines
5.8 KiB
C++
Raw Normal View History

#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"
Cinematic* AnimationSystem::loadCinematic(const std::string& path) {
std::ifstream file("data/" + path);
if(!file)
return nullptr;
2018-12-19 12:19:52 -05:00
nlohmann::json json;
file >> json;
2018-12-19 12:19:52 -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-19 12:19:52 -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"];
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
for(auto keyframeObject : animationObject["keyframes"]) {
Keyframe keyframe;
keyframe.time = keyframeObject["time"];
2018-12-19 12:19:52 -05:00
if(animation->property == AnimationProperty::Position || animation->property == AnimationProperty::Target) {
auto tokens = tokenize(keyframeObject["value"]);
2018-12-19 12:19:52 -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
animation->keyframes.push_back(keyframe);
} else if(animation->property == AnimationProperty::FoV) {
keyframe.valueInt = keyframeObject["value"];
2018-12-19 12:19:52 -05:00
animation->keyframes.push_back(keyframe);
}
}
2018-12-19 12:19:52 -05:00
shot->animations.push_back(animation);
}
2018-12-19 12:19:52 -05:00
cinematic->shots.push_back(shot);
}
2018-12-19 12:19:52 -05:00
preloadShot(cinematic->shots[0]);
loadShot(cinematic->shots[0]);
2018-12-19 12:19:52 -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
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
const auto currentFrame = animation->keyframes[frameIndex];
const auto nextFrame = animation->keyframes[(frameIndex + 1) % animation->keyframes.size()];
2018-12-19 12:19:52 -05:00
const float delta = (animationTime - currentFrame.time) / (nextFrame.time - currentFrame.time);
2018-12-19 12:19:52 -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;
}
}
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;
}
}
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;
}
}
break;
}
}
2018-12-19 12:19:52 -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));
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-19 12:19:52 -05:00
shot->loadedEntities.push_back(entity);
}
}
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);
}