#include "camera.hpp" #include #include "animation.hpp" #include #include "components.hpp" #include "config.hpp" #include namespace cinematic { using components::Animation, std::string, std::min, std::clamp; struct CameraManager { std::unordered_map animations; }; static CameraManager MGR; static bool initialized = false; void init() { if(!initialized) { auto cameras = settings::get("cameras"); for(auto &[name, data] : cameras.json().items()) { auto anim = components::convert(data); MGR.animations.try_emplace(name, anim); } initialized = true; } } Camera::Camera(sf::Vector2f size) : anim(MGR.animations.at("pan")), size(size), base_size(size), aimed_at{size.x/2, size.y/2}, going_to{size.x/2, size.y/2}, camera_bounds{{0,0}, size}, view{aimed_at, size} { } void Camera::update_camera_bounds(sf::Vector2f size) { // camera bounds now constrains the x/y so that the mid-point // of the size won't go too far outside of the frame camera_bounds = { {size.x / 2.0f, size.y / 2.0f}, {base_size.x - size.x / 2.0f, base_size.y - size.y / 2.0f} }; } void Camera::scale(float ratio) { size.x = base_size.x * ratio; size.y = base_size.y * ratio; update_camera_bounds(size); } void Camera::resize(float width) { dbc::check(width <= base_size.x, "invalid width for camera"); size.x = width; size.y = base_size.y * (width / base_size.x); update_camera_bounds(size); } void Camera::style(const std::string &name) { anim = MGR.animations.at(name); } void Camera::position(float x, float y) { aimed_at.x = clamp(x, camera_bounds.position.x, camera_bounds.size.x); aimed_at.y = clamp(y, camera_bounds.position.y, camera_bounds.size.y); } void Camera::move(float x, float y) { going_to.x = clamp(x, camera_bounds.position.x, camera_bounds.size.x); going_to.y = clamp(y, camera_bounds.position.y, camera_bounds.size.y); // BUG: annoying special case if(anim.motion == ease::SLIDE) { anim.min_x = aimed_at.x; anim.min_y = aimed_at.y; anim.max_x = going_to.x; anim.max_y = going_to.y; } } void Camera::reset(sf::RenderTexture& target) { size = {base_size.x, base_size.y}; aimed_at = {base_size.x/2, base_size.y/2}; going_to = {base_size.x/2, base_size.y/2}; view = {aimed_at, size}; camera_bounds = {{0,0}, base_size}; // BUG: is getDefaultView different from view? target.setView(target.getDefaultView()); } void Camera::render(sf::RenderTexture& target) { if(anim.playing) { anim.apply(view, going_to, size); target.setView(view); } } bool Camera::playing() { return anim.playing; } void Camera::play() { anim.play(); } }