/*
* InfiniPaint
* Copyright (C) 2025-2026 Yousef Khadadeh
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#pragma once
#include "SharedTypes.hpp"
#include
#include
#include
#ifndef IS_SERVER
#include "include/core/SkMatrix.h"
#include "include/core/SkCanvas.h"
#endif
class World;
struct DrawData;
WorldVec rotate_world_coord(const WorldVec& a, double rotationAngle);
class CoordSpaceHelper {
public:
template void save(Archive& a) const {
a(pos, inverseScale, rotation);
}
template void load(Archive& a) {
a(pos, inverseScale, rotation);
}
CoordSpaceHelper();
CoordSpaceHelper(const WorldVec& initPos, const WorldScalar& initInverseScale, double initRotation);
bool operator==(const CoordSpaceHelper& otherCoords) const;
bool operator!=(const CoordSpaceHelper& otherCoords) const;
Vector2f to_space(const WorldVec& coord) const;
WorldVec from_space(Vector2f coord) const;
WorldVec from_space_world(const WorldVec& coord) const;
WorldVec to_space_world(const WorldVec& coord) const;
WorldScalar scalar_from_space(float coord) const;
float scalar_to_space(const WorldScalar& coord) const;
WorldVec dir_from_space(Vector2f coord) const;
Vector2f dir_to_space(const WorldVec& coord) const;
Vector2f normalized_dir_to_space(const WorldVec& coord) const;
CoordSpaceHelper other_coord_space_to_this_space(const CoordSpaceHelper& other) const;
CoordSpaceHelper other_coord_space_from_this_space(const CoordSpaceHelper& other) const;
template S collider_to_world(const T& collider) const {
return collider.template transform(
[&coords = *this](const Vector2f& a) {
return coords.from_space(a);
},
[&coords = *this](const float& a) {
return coords.scalar_from_space(a);
});
}
template T collider_to_new_coords(const CoordSpaceHelper newCoords, const T& collider) const {
return collider.template transform(
[&coords = *this, &newCoords](const Vector2f& a) {
return newCoords.to_space(coords.from_space(a));
},
[&coords = *this, &newCoords](const float& a) {
return newCoords.scalar_to_space(coords.scalar_from_space(a));
});
}
template S world_collider_to_coords(const T& collider) const {
return collider.template transform(
[&coords = *this](const WorldVec& a) {
return coords.to_space(a);
},
[&coords = *this](const WorldScalar& a) {
return coords.scalar_to_space(a);
});
}
//float scalar_to_space(WorldScalar coord) const;
std::vector to_space(const std::vector& coord) const;
std::vector from_space(const std::vector& coord) const;
std::vector to_space_world(const std::vector& coord) const;
std::vector from_space_world(const std::vector& coord) const;
void translate(const WorldVec& translation);
void scale(const WorldScalar& scaleAmount);
void rotate_about(const WorldVec& rotatePos, double angle);
void scale_about(const WorldVec& scalePos, const WorldScalar& scaleAmount, bool flipScale);
void scale_about(const WorldVec& scalePos, const WorldMultiplier& scaleAmount);
void scale_about_double(const WorldVec& scalePos, double scaleAmount);
void set_rotation(double newRotation);
template std::array to_space(const std::array& coord) const {
std::array toRet;
for(size_t i = 0; i < coord.size(); i++)
toRet[i] = to_space(coord[i]);
return toRet;
}
template std::array from_space(const std::array& coord) const {
std::array toRet;
for(size_t i = 0; i < coord.size(); i++)
toRet[i] = from_space(coord[i]);
return toRet;
}
Vector2f get_mouse_pos(const World& w) const;
Vector2f from_cam_space_to_this(const World& w, const Vector2f& coord) const;
Vector2f from_this_to_cam_space(const World& w, const Vector2f& coord) const;
//SkMatrix get_sk_matrix_temp(const WorldTransform& tempTransform, const DrawData& drawData) const;
//SkMatrix get_sk_matrix(const DrawData& drawData) const;
void transform_sk_canvas(SkCanvas* canvas, const DrawData& drawData) const;
WorldVec pos{0, 0};
WorldScalar inverseScale{1};
double rotation = 0.0;
};