feat: updated transforms
parent
5b690a2e8d
commit
b486f09939
|
@ -17,7 +17,8 @@ env = Environment(CCFLAGS=[
|
|||
'-fno-exceptions',
|
||||
'-Wall', '-Wpedantic', '-Wextra', '-Werror',
|
||||
'-O0', '-g3', '-Isrc',
|
||||
'-DPROJECTNAME=\\\"'+project+'\\\"'
|
||||
'-DPROJECTNAME=\\\"'+project+'\\\"',
|
||||
'-DDEBUG'
|
||||
],
|
||||
LINKFLAGS=[
|
||||
'-lSDL2', '-lSDL2_image', '-lm',
|
||||
|
|
|
@ -29,7 +29,8 @@ CanvasEngine::CanvasEngine() {
|
|||
SDL_Quit();
|
||||
return;
|
||||
}
|
||||
this->window = SDL_CreateWindow(PROJECTNAME, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1000, 800, SDL_WINDOW_FULLSCREEN | SDL_WINDOW_RESIZABLE); if(this->window == nullptr) {
|
||||
this->window = SDL_CreateWindow(PROJECTNAME, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1000, 800, SDL_WINDOW_RESIZABLE | SDL_WINDOW_FULLSCREEN_DESKTOP);
|
||||
if(this->window == nullptr) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Failed to create window, SDL error: %s", SDL_GetError());
|
||||
IMG_Quit();
|
||||
SDL_Quit();
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "transform.hpp"
|
||||
#include <cassert>
|
||||
|
||||
namespace ce {
|
||||
void Transform::translate_by(Vecf const &translation) {
|
||||
|
@ -22,17 +23,20 @@ Vecf Transform::up() const {
|
|||
}
|
||||
|
||||
Transform operator *(Transform const &lhs, Transform const &rhs) {
|
||||
return Transform {
|
||||
Transform t{
|
||||
.position = rhs.position + lhs.position.rotated(rhs.rotation),
|
||||
.rotation = rhs.rotation + lhs.rotation,
|
||||
.scale = lhs.scale.scaled(rhs.scale)
|
||||
};
|
||||
assert(t.scale.x != 0.f || t.scale.y != 0.f); // !!!
|
||||
return t;
|
||||
}
|
||||
|
||||
Transform &operator *=(Transform &lhs, Transform const &rhs) {
|
||||
lhs.position += rhs.position.rotated(lhs.rotation);
|
||||
lhs.position += lhs.position.rotated(rhs.rotation);
|
||||
lhs.rotation += rhs.rotation;
|
||||
lhs.scale.scale(rhs.scale);
|
||||
assert(lhs.scale.x != 0.f || lhs.scale.y != 0.f); // !!!
|
||||
return lhs;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,9 +5,9 @@
|
|||
|
||||
namespace ce {
|
||||
struct Transform {
|
||||
Vecf position;
|
||||
double rotation;
|
||||
Vecf scale;
|
||||
Vecf position{0.f, 0.f};
|
||||
double rotation{0.0};
|
||||
Vecf scale{1.f, 1.f};
|
||||
void translate_by(Vecf const &translation);
|
||||
void rotate_by(double rotation);
|
||||
void scale_by(Vecf const &factors);
|
||||
|
|
|
@ -5,6 +5,10 @@
|
|||
#include <vector>
|
||||
|
||||
namespace ce {
|
||||
Node::Node(std::string name) {
|
||||
this->name = name;
|
||||
}
|
||||
|
||||
Node::~Node() {
|
||||
this->destroyed.invoke();
|
||||
}
|
||||
|
@ -111,7 +115,6 @@ void Node::propagate_post_tick() {
|
|||
});
|
||||
for(std::pair<std::string const, Node::OwnedPtr> &pair : this->children)
|
||||
pair.second->propagate_post_tick();
|
||||
this->_update_transform();
|
||||
}
|
||||
|
||||
void Node::propagate_removed() {
|
||||
|
@ -121,6 +124,7 @@ void Node::propagate_removed() {
|
|||
}
|
||||
|
||||
void Node::propagate_draw(SDL_Renderer *render) {
|
||||
this->_update_transform();
|
||||
if(this->visible) {
|
||||
this->_draw(render);
|
||||
for(std::pair<std::string const, Node::OwnedPtr> &pair : this->children)
|
||||
|
|
|
@ -27,7 +27,7 @@ public:
|
|||
Signal<Node*> child_removed{}; //!< Signal invoked when a child is removed.
|
||||
Signal<Node*> child_added{}; //!< Signal invoked when a child is added.
|
||||
public:
|
||||
Node() = default;
|
||||
Node(std::string name);
|
||||
virtual ~Node();
|
||||
protected:
|
||||
virtual void _added(Node *parent [[maybe_unused]]) {} //!< called the moment after the object is added as a child to another node
|
||||
|
@ -38,6 +38,7 @@ protected:
|
|||
virtual void _update_transform() {}
|
||||
public:
|
||||
template <class TNode> TNode *get_child(std::string const &name); //!< get a non-owning pointer to a child
|
||||
template <class TNode, typename... Args> TNode *create_child(Args... cargs);
|
||||
void add_child(Node::OwnedPtr &child); //!< add a child, the caller must own the pointer
|
||||
void set_parent(Node *new_parent);
|
||||
Node *get_parent() const; //!< get the parent.
|
||||
|
@ -61,6 +62,12 @@ private:
|
|||
template <class TNode> TNode *Node::get_child(std::string const &name) {
|
||||
return children.contains(name) ? dynamic_cast<TNode*>(children.at(name).get()) : nullptr;
|
||||
}
|
||||
template <class TNode, typename... Args> TNode *Node::create_child(Args... cargs) {
|
||||
OwnedPtr owned{std::make_unique<TNode>(cargs...)};
|
||||
TNode *referenced{dynamic_cast<TNode*>(owned.get())};
|
||||
this->add_child(owned);
|
||||
return referenced;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // !CANVAS_NODE_HPP
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
#include "node2d.hpp"
|
||||
#include <cassert>
|
||||
|
||||
namespace ce {
|
||||
Node2D::Node2D(std::string name) : Node(name) {}
|
||||
|
||||
void Node2D::_added(Node *parent) {
|
||||
this->parent_node2d = dynamic_cast<Node2D*>(parent);
|
||||
}
|
||||
|
@ -8,14 +11,13 @@ void Node2D::_added(Node *parent) {
|
|||
void Node2D::_update_transform() {
|
||||
if(this->parent_node2d != nullptr)
|
||||
this->global_transform = this->transform * this->parent_node2d->get_global_transform();
|
||||
else
|
||||
this->global_transform = this->transform;
|
||||
}
|
||||
|
||||
void Node2D::set_transform(Transform const &transform) {
|
||||
this->transform = transform;
|
||||
}
|
||||
|
||||
Transform &Node2D::get_transform() {
|
||||
return this->transform;
|
||||
this->_update_transform();
|
||||
}
|
||||
|
||||
Transform const &Node2D::get_transform() const {
|
||||
|
@ -28,12 +30,13 @@ void Node2D::set_global_transform(Transform transform) {
|
|||
Transform parent = this->parent_node2d->get_global_transform();
|
||||
transform.position -= parent.position.rotated(-parent.rotation);
|
||||
transform.scale_by(parent.scale.reciprocal());
|
||||
assert(transform.scale.x != 0.f || transform.scale.y != 0.f); // !!!
|
||||
transform.rotation -= parent.rotation;
|
||||
}
|
||||
this->transform = transform;
|
||||
}
|
||||
|
||||
Transform Node2D::get_global_transform() const {
|
||||
Transform const &Node2D::get_global_transform() const {
|
||||
return this->global_transform;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,14 +10,14 @@ class Node2D : public Node {
|
|||
Transform global_transform{};
|
||||
Node2D *parent_node2d{nullptr};
|
||||
public:
|
||||
Node2D(std::string name);
|
||||
virtual void _added(Node *parent) override;
|
||||
Node2D *get_parent_node2d() const;
|
||||
virtual void _update_transform() override;
|
||||
void set_transform(Transform const &transform);
|
||||
Transform &get_transform();
|
||||
Transform const &get_transform() const;
|
||||
void set_global_transform(Transform transform);
|
||||
Transform get_global_transform() const;
|
||||
Transform const &get_global_transform() const;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -5,23 +5,30 @@
|
|||
#include <cmath>
|
||||
|
||||
namespace ce {
|
||||
Sprite::Sprite(std::string const &texture)
|
||||
: Node2D() {
|
||||
Sprite::Sprite(std::string name, std::string texture)
|
||||
: Node2D(name) {
|
||||
std::optional<std::shared_ptr<Texture>> asset = CanvasEngine::get_singleton()->get_assets().get_asset<Texture>(texture);
|
||||
this->texture = asset.value();
|
||||
}
|
||||
|
||||
void Sprite::_draw(SDL_Renderer *render) {
|
||||
if(this->texture == nullptr)
|
||||
if(this->texture == nullptr) {
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "No texture assigned");
|
||||
this->set_visible(false);
|
||||
return;
|
||||
}
|
||||
int w, h;
|
||||
SDL_QueryTexture(this->texture->get(), NULL, NULL, &w, &h);
|
||||
Transform transform{this->get_transform()};
|
||||
Transform transform{this->get_global_transform()};
|
||||
assert(transform.scale.x != 0 && transform.scale.y != 0); // !!!
|
||||
float fw{w * transform.scale.x}, fh{h * transform.scale.y};
|
||||
assert(fw != 0.f && fh != 0.f);
|
||||
//float fw(w), fh(h);
|
||||
SDL_Rect src{0, 0, w, h};
|
||||
SDL_FRect dst{transform.position.x, transform.position.y, float(w), float(h)};
|
||||
SDL_FRect dst{transform.position.x - fw/2.f, transform.position.y - fh/2.f, fw, fh};
|
||||
SDL_RenderCopyExF(render, this->texture->get(),
|
||||
&src, &dst,
|
||||
transform.rotation,NULL,
|
||||
transform.rotation * 57.2958f,NULL,
|
||||
SDL_FLIP_NONE);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ namespace ce {
|
|||
class Sprite : public Node2D {
|
||||
std::shared_ptr<Texture> texture{nullptr};
|
||||
public:
|
||||
Sprite(std::string const &texture);
|
||||
Sprite(std::string name, std::string texture);
|
||||
virtual void _draw(SDL_Renderer *render) override;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
#include "level_1.hpp"
|
||||
#include "core/node.hpp"
|
||||
#include "core/sprite.hpp"
|
||||
#include "test_node.hpp"
|
||||
|
||||
void Level1::instantiate() {
|
||||
ce::Node::OwnedPtr &root_ptr{this->get_owned_root()};
|
||||
root_ptr.reset(new ce::Node());
|
||||
ce::Node::OwnedPtr sprite{std::make_unique<ce::Sprite>("neocat")};
|
||||
root->add_child(sprite);
|
||||
root_ptr.reset(new ce::Node("root"));
|
||||
ce::Node::OwnedPtr node{std::make_unique<TestNode>()};
|
||||
root->add_child(node);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
#include "test_node.hpp"
|
||||
#include "core/math/transform.hpp"
|
||||
#include <SDL2/SDL_render.h>
|
||||
#include <SDL2/SDL_timer.h>
|
||||
#include <cmath>
|
||||
|
||||
TestNode::TestNode()
|
||||
: ce::Node2D("TestNode") {
|
||||
this->sprite = this->create_child<ce::Sprite>("neocat", "neocat");
|
||||
}
|
||||
|
||||
void TestNode::_first_tick() {
|
||||
ce::Transform st{this->sprite->get_global_transform()};
|
||||
st.position.x += 200;
|
||||
this->sprite->set_global_transform(st);
|
||||
}
|
||||
|
||||
void TestNode::_tick(double const &delta) {
|
||||
ce::Node2D::_tick(delta);
|
||||
ce::Transform trans{this->get_transform()};
|
||||
trans.position.x = 500 + std::sin(SDL_GetTicks64() * 0.001) * 100.f;
|
||||
trans.position.y = 500 + std::cos(SDL_GetTicks64() * 0.001) * 100.f;
|
||||
trans.rotate_by(delta * 10.f);
|
||||
this->set_transform(trans);
|
||||
}
|
||||
|
||||
void TestNode::_draw(SDL_Renderer *render) {
|
||||
ce::Node2D::_draw(render);
|
||||
ce::Transform trans{this->get_global_transform()};
|
||||
SDL_SetRenderDrawColor(render, 255, 255, 255, 255);
|
||||
SDL_FRect rect{trans.position.x-101.f, trans.position.y-101.f, 202.f, 202.f};
|
||||
SDL_RenderDrawRectF(render, &rect);
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
#ifndef TEST_NODE_HPP
|
||||
#define TEST_NODE_HPP
|
||||
|
||||
#include "core/node2d.hpp"
|
||||
#include "core/sprite.hpp"
|
||||
|
||||
class TestNode : public ce::Node2D {
|
||||
private:
|
||||
ce::Sprite *sprite{nullptr};
|
||||
public:
|
||||
TestNode();
|
||||
virtual void _first_tick() override;
|
||||
virtual void _tick(double const &delta) override;
|
||||
virtual void _draw(SDL_Renderer *render) override;
|
||||
};
|
||||
|
||||
#endif // !TEST_NODE_HPP
|
Loading…
Reference in New Issue