module dgt.camera;

import dgt.geom;

///A set of projections used to manage windows and views
struct Camera
{
    const Transform project, unproject, opengl;

    ////Create a camera with a given window size and view of the world
    pure @nogc nothrow this(in Rectangle windowSize, in Rectangle world, in Transform cameraTransform = Transform())
    {
        unproject = cameraTransform
            * Transform.translate(-world.topLeft)
            * Transform.scale(Vector(world.width / windowSize.width, world.height / windowSize.height).inverse)
            * Transform.translate(windowSize.topLeft);
        project = unproject.inverse;
        opengl = cameraTransform
            * Transform.translate(-world.topLeft)
            * Transform.scale(world.size.inverse * 2)
            * Transform.translate(Vector(-1, -1))
            * Transform.scale(Vector(1, -1));
    }
}

unittest
{
    const cam = Camera(Rectangle(0, 0, 100, 100), Rectangle(0, 0, 50, 50));
    const screenBottom = Vector(0, 100);
    const worldBottom = Vector(0, 50);
    assert(cam.project * screenBottom == worldBottom);
    assert(cam.unproject * worldBottom == screenBottom);
    assert(cam.opengl * worldBottom == Vector(-1, -1));
}
unittest
{
    const cam = Camera(Rectangle(0, 0, 100, 100), Rectangle(50, 50, 50, 50));
    const worldTop = Vector(50, 50);
    assert(cam.opengl * worldTop == Vector(-1, 1));
}
unittest
{
    const cam = Camera(Rectangle(0, 0, 10, 10), Rectangle(0, 0, 10, 10),
            Transform.rotate(-90));
    const projected = cam.project * Vector(5, 0);
    assert(projected == Vector(0, 5));
}