mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-07-16 15:52:55 +03:00
Better views and viewport in ratio instead of pixels.
--HG-- branch : dev-2.1
This commit is contained in:
64
include/eepp/math/transform.hpp
Normal file
64
include/eepp/math/transform.hpp
Normal file
@@ -0,0 +1,64 @@
|
||||
#ifndef SFML_TRANSFORM_HPP
|
||||
#define SFML_TRANSFORM_HPP
|
||||
|
||||
#include <eepp/config.hpp>
|
||||
#include <eepp/math/rect.hpp>
|
||||
#include <eepp/math/vector2.hpp>
|
||||
|
||||
namespace EE { namespace Math {
|
||||
|
||||
class EE_API Transform {
|
||||
public:
|
||||
Transform();
|
||||
|
||||
Transform(float a00, float a01, float a02, float a10, float a11, float a12, float a20, float a21, float a22 );
|
||||
|
||||
const float* getMatrix() const;
|
||||
|
||||
Transform getInverse() const;
|
||||
|
||||
Vector2f transformPoint(float x, float y) const;
|
||||
|
||||
Vector2f transformPoint(const Vector2f& point) const;
|
||||
|
||||
Rectf transformRect(const Rectf& rectangle) const;
|
||||
|
||||
Transform& combine(const Transform& transform);
|
||||
|
||||
Transform& translate(float x, float y);
|
||||
|
||||
Transform& translate(const Vector2f& offset);
|
||||
|
||||
Transform& rotate(float angle);
|
||||
|
||||
Transform& rotate(float angle, float centerX, float centerY);
|
||||
|
||||
Transform& rotate(float angle, const Vector2f& center);
|
||||
|
||||
Transform& scale(float scaleX, float scaleY);
|
||||
|
||||
Transform& scale(float scaleX, float scaleY, float centerX, float centerY);
|
||||
|
||||
Transform& scale(const Vector2f& factors);
|
||||
|
||||
Transform& scale(const Vector2f& factors, const Vector2f& center);
|
||||
|
||||
static const Transform Identity;
|
||||
private:
|
||||
|
||||
float mMatrix[16];
|
||||
};
|
||||
|
||||
EE_API Transform operator *(const Transform& left, const Transform& right);
|
||||
|
||||
EE_API Transform& operator *=(Transform& left, const Transform& right);
|
||||
|
||||
EE_API Vector2f operator *(const Transform& left, const Vector2f& right);
|
||||
|
||||
EE_API bool operator ==(const Transform& left, const Transform& right);
|
||||
|
||||
EE_API bool operator !=(const Transform& left, const Transform& right);
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
@@ -116,7 +116,7 @@ class EE_API Input {
|
||||
void setMousePos( const Vector2i& Pos );
|
||||
|
||||
/** @return The mouse position over the current view */
|
||||
Vector2i getMousePosFromView( const View& View );
|
||||
Vector2f getMousePosFromView( const View& View );
|
||||
|
||||
/** Set the mouse speed ( only affects grabed windows ) */
|
||||
void setMouseSpeed( const Float& Speed );
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
#ifndef EE_WINDOWCVIEW_H
|
||||
#define EE_WINDOWCVIEW_H
|
||||
|
||||
#include <eepp/window/base.hpp>
|
||||
#include <eepp/math/size.hpp>
|
||||
#include <eepp/math/transform.hpp>
|
||||
using namespace EE::Math;
|
||||
|
||||
namespace EE { namespace Window {
|
||||
|
||||
@@ -10,51 +12,54 @@ class EE_API View {
|
||||
public:
|
||||
View();
|
||||
|
||||
View( const int& X, const int& Y, const int& Width, const int& Height );
|
||||
explicit View(const Rectf& rectangle);
|
||||
|
||||
View( const Rect& View );
|
||||
View(const Vector2f& center, const Vector2f& size);
|
||||
|
||||
~View();
|
||||
void setCenter(float x, float y);
|
||||
|
||||
/** Offset the position */
|
||||
void move( const int& OffsetX, const int& OffsetY );
|
||||
void setCenter(const Vector2f& center);
|
||||
|
||||
/** Offset the position */
|
||||
void move( const Vector2i& Offset );
|
||||
void setSize(float width, float height);
|
||||
|
||||
/** Scale the current view (from center) */
|
||||
void scale( const Float& Factor );
|
||||
void setSize(const Sizef& size);
|
||||
|
||||
/** Scale the current view (from center) */
|
||||
void scale( const Vector2f& Factor );
|
||||
void setRotation(float angle);
|
||||
|
||||
/** @return The center position of the view */
|
||||
Vector2i getCenter() const;
|
||||
void setViewport(const Rectf& viewport);
|
||||
|
||||
/** Set the center position of the view ( will move it if is needed ) */
|
||||
void setCenter( const Vector2i& center );
|
||||
void reset(const Rectf& rectangle);
|
||||
|
||||
/** @return The current view ( Left = X, Right = Width, Top = Y, Bottom = Height ) */
|
||||
Rect getView() const { return mView; }
|
||||
const Vector2f& getCenter() const;
|
||||
|
||||
/** Set a new position to the view */
|
||||
void setPosition( const int& X, const int& Y );
|
||||
const Sizef & getSize() const;
|
||||
|
||||
/** Set a new size to the view */
|
||||
void setSize( const int& Width, const int& Height );
|
||||
float getRotation() const;
|
||||
|
||||
/** Creates a new view */
|
||||
void setView( const int& X, const int& Y, const int& Width, const int& Height );
|
||||
const Rectf& getViewport() const;
|
||||
|
||||
void move(float offsetX, float offsetY);
|
||||
|
||||
void move(const Vector2f& offset);
|
||||
|
||||
void rotate(float angle);
|
||||
|
||||
void zoom(float factor);
|
||||
|
||||
const Transform& getTransform() const;
|
||||
|
||||
const Transform& getInverseTransform() const;
|
||||
private:
|
||||
friend class Window;
|
||||
|
||||
bool mNeedUpdate;
|
||||
Rect mView;
|
||||
Vector2f mCenter;
|
||||
|
||||
void calcCenter();
|
||||
|
||||
bool needUpdate() const;
|
||||
Vector2f mCenter; ///< Center of the view, in scene coordinates
|
||||
Sizef mSize; ///< Size of the view, in scene coordinates
|
||||
float mRotation; ///< Angle of rotation of the view rectangle, in degrees
|
||||
Rectf mViewport; ///< Viewport rectangle, expressed as a factor of the render-target's size
|
||||
mutable Transform mTransform; ///< Precomputed projection transform corresponding to the view
|
||||
mutable Transform mInverseTransform; ///< Precomputed inverse projection transform corresponding to the view
|
||||
mutable bool mTransformUpdated; ///< Internal state telling if the transform needs to be updated
|
||||
mutable bool mInvTransformUpdated; ///< Internal state telling if the inverse transform needs to be updated
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
@@ -295,9 +295,15 @@ class EE_API Window {
|
||||
/** Set a new 2D projection matrix */
|
||||
void set2DProjection( const Uint32& Width, const Uint32& Height );
|
||||
|
||||
/** Set a new projection matrix */
|
||||
void setProjection( const Transform& transform );
|
||||
|
||||
/** Set the current Viewport ( and creates a new ortho proyection if needed ) */
|
||||
void setViewport( const Int32& x, const Int32& y, const Uint32& Width, const Uint32& Height );
|
||||
|
||||
/** @return The viewport in pixels of the view */
|
||||
Rect getViewport(const View& view);
|
||||
|
||||
/** Set the window background color */
|
||||
void setClearColor( const RGB& Color );
|
||||
|
||||
@@ -407,6 +413,14 @@ class EE_API Window {
|
||||
** @param func The main loop function
|
||||
** @param fps The desired FPS ( 0 = infinite ) */
|
||||
void runMainLoop( void (*func)(), int fps = 0 );
|
||||
|
||||
Vector2f mapPixelToCoords(const Vector2i & point);
|
||||
|
||||
Vector2f mapPixelToCoords(const Vector2i & point, const View & view);
|
||||
|
||||
Vector2i mapCoordsToPixel(const Vector2f & point);
|
||||
|
||||
Vector2i mapCoordsToPixel(const Vector2f & point, const View & view);
|
||||
protected:
|
||||
friend class Engine;
|
||||
friend class Input;
|
||||
@@ -474,8 +488,6 @@ class EE_API Window {
|
||||
|
||||
void getElapsedTime();
|
||||
|
||||
void viewCheckUpdate();
|
||||
|
||||
void logSuccessfulInit( const std::string& BackendName );
|
||||
|
||||
void logFailureInit( const std::string& ClassName, const std::string& BackendName );
|
||||
|
||||
@@ -65,7 +65,7 @@ void FrameBuffer::setBufferView() {
|
||||
GLi->getCurrentMatrix( GL_PROJECTION_MATRIX, mProjMat );
|
||||
GLi->getCurrentMatrix( GL_MODELVIEW_MATRIX, mModelViewMat );
|
||||
|
||||
mView.setSize( mSize.getWidth(), mSize.getHeight() );
|
||||
mView.reset( Rectf( 0, 0, mSize.getWidth(), mSize.getHeight() ) );
|
||||
sFBOActiveViews.push_back(&mView);
|
||||
|
||||
GLi->viewport( 0, 0, mSize.getWidth(), mSize.getHeight() );
|
||||
@@ -85,7 +85,7 @@ void FrameBuffer::recoverView() {
|
||||
mWindow->setView( mWindow->getView() );
|
||||
} else {
|
||||
const View* view = sFBOActiveViews.back();
|
||||
GLi->viewport( 0, 0, view->getView().getWidth(), view->getView().getHeight() );
|
||||
GLi->viewport( 0, 0, view->getSize().getWidth(), view->getSize().getHeight() );
|
||||
}
|
||||
|
||||
// Recover the user projection and modelview matrix
|
||||
|
||||
190
src/eepp/math/transform.cpp
Normal file
190
src/eepp/math/transform.cpp
Normal file
@@ -0,0 +1,190 @@
|
||||
#include <eepp/math/transform.hpp>
|
||||
#include <cmath>
|
||||
|
||||
namespace EE { namespace Math {
|
||||
|
||||
const Transform Transform::Identity;
|
||||
|
||||
Transform::Transform() {
|
||||
// Identity matrix
|
||||
mMatrix[0] = 1.f; mMatrix[4] = 0.f; mMatrix[8] = 0.f; mMatrix[12] = 0.f;
|
||||
mMatrix[1] = 0.f; mMatrix[5] = 1.f; mMatrix[9] = 0.f; mMatrix[13] = 0.f;
|
||||
mMatrix[2] = 0.f; mMatrix[6] = 0.f; mMatrix[10] = 1.f; mMatrix[14] = 0.f;
|
||||
mMatrix[3] = 0.f; mMatrix[7] = 0.f; mMatrix[11] = 0.f; mMatrix[15] = 1.f;
|
||||
}
|
||||
|
||||
Transform::Transform( float a00, float a01, float a02, float a10, float a11, float a12, float a20, float a21, float a22 ) {
|
||||
mMatrix[0] = a00; mMatrix[4] = a01; mMatrix[8] = 0.f; mMatrix[12] = a02;
|
||||
mMatrix[1] = a10; mMatrix[5] = a11; mMatrix[9] = 0.f; mMatrix[13] = a12;
|
||||
mMatrix[2] = 0.f; mMatrix[6] = 0.f; mMatrix[10] = 1.f; mMatrix[14] = 0.f;
|
||||
mMatrix[3] = a20; mMatrix[7] = a21; mMatrix[11] = 0.f; mMatrix[15] = a22;
|
||||
}
|
||||
|
||||
const float* Transform::getMatrix() const {
|
||||
return mMatrix;
|
||||
}
|
||||
|
||||
Transform Transform::getInverse() const {
|
||||
// Compute the determinant
|
||||
float det = mMatrix[0] * (mMatrix[15] * mMatrix[5] - mMatrix[7] * mMatrix[13]) -
|
||||
mMatrix[1] * (mMatrix[15] * mMatrix[4] - mMatrix[7] * mMatrix[12]) +
|
||||
mMatrix[3] * (mMatrix[13] * mMatrix[4] - mMatrix[5] * mMatrix[12]);
|
||||
|
||||
// Compute the inverse if the determinant is not zero
|
||||
// (don't use an epsilon because the determinant may *really* be tiny)
|
||||
if (det != 0.f) {
|
||||
return Transform( (mMatrix[15] * mMatrix[5] - mMatrix[7] * mMatrix[13]) / det,
|
||||
-(mMatrix[15] * mMatrix[4] - mMatrix[7] * mMatrix[12]) / det,
|
||||
(mMatrix[13] * mMatrix[4] - mMatrix[5] * mMatrix[12]) / det,
|
||||
-(mMatrix[15] * mMatrix[1] - mMatrix[3] * mMatrix[13]) / det,
|
||||
(mMatrix[15] * mMatrix[0] - mMatrix[3] * mMatrix[12]) / det,
|
||||
-(mMatrix[13] * mMatrix[0] - mMatrix[1] * mMatrix[12]) / det,
|
||||
(mMatrix[7] * mMatrix[1] - mMatrix[3] * mMatrix[5]) / det,
|
||||
-(mMatrix[7] * mMatrix[0] - mMatrix[3] * mMatrix[4]) / det,
|
||||
(mMatrix[5] * mMatrix[0] - mMatrix[1] * mMatrix[4]) / det);
|
||||
} else {
|
||||
return Identity;
|
||||
}
|
||||
}
|
||||
|
||||
Vector2f Transform::transformPoint(float x, float y) const {
|
||||
return Vector2f(mMatrix[0] * x + mMatrix[4] * y + mMatrix[12],
|
||||
mMatrix[1] * x + mMatrix[5] * y + mMatrix[13]);
|
||||
}
|
||||
|
||||
Vector2f Transform::transformPoint(const Vector2f& point) const {
|
||||
return transformPoint(point.x, point.y);
|
||||
}
|
||||
|
||||
Rectf Transform::transformRect(const Rectf& rectangle) const {
|
||||
// Transform the 4 corners of the rectangle
|
||||
const Vector2f points[] =
|
||||
{
|
||||
transformPoint(rectangle.Left, rectangle.Top),
|
||||
transformPoint(rectangle.Left, rectangle.Top + rectangle.Bottom),
|
||||
transformPoint(rectangle.Left + rectangle.Right, rectangle.Top),
|
||||
transformPoint(rectangle.Left + rectangle.Right, rectangle.Top + rectangle.Bottom)
|
||||
};
|
||||
|
||||
// Compute the bounding rectangle of the transformed points
|
||||
float left = points[0].x;
|
||||
float top = points[0].y;
|
||||
float right = points[0].x;
|
||||
float bottom = points[0].y;
|
||||
for (int i = 1; i < 4; ++i) {
|
||||
if (points[i].x < left) left = points[i].x;
|
||||
else if (points[i].x > right) right = points[i].x;
|
||||
if (points[i].y < top) top = points[i].y;
|
||||
else if (points[i].y > bottom) bottom = points[i].y;
|
||||
}
|
||||
|
||||
return Rectf(left, top, right - left, bottom - top);
|
||||
}
|
||||
|
||||
Transform& Transform::combine(const Transform& transform) {
|
||||
const float* a = mMatrix;
|
||||
const float* b = transform.mMatrix;
|
||||
|
||||
*this = Transform(a[0] * b[0] + a[4] * b[1] + a[12] * b[3],
|
||||
a[0] * b[4] + a[4] * b[5] + a[12] * b[7],
|
||||
a[0] * b[12] + a[4] * b[13] + a[12] * b[15],
|
||||
a[1] * b[0] + a[5] * b[1] + a[13] * b[3],
|
||||
a[1] * b[4] + a[5] * b[5] + a[13] * b[7],
|
||||
a[1] * b[12] + a[5] * b[13] + a[13] * b[15],
|
||||
a[3] * b[0] + a[7] * b[1] + a[15] * b[3],
|
||||
a[3] * b[4] + a[7] * b[5] + a[15] * b[7],
|
||||
a[3] * b[12] + a[7] * b[13] + a[15] * b[15]);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Transform& Transform::translate(float x, float y) {
|
||||
Transform translation(1, 0, x,
|
||||
0, 1, y,
|
||||
0, 0, 1);
|
||||
|
||||
return combine(translation);
|
||||
}
|
||||
|
||||
Transform& Transform::translate(const Vector2f& offset) {
|
||||
return translate(offset.x, offset.y);
|
||||
}
|
||||
|
||||
Transform& Transform::rotate(float angle) {
|
||||
float rad = angle * 3.141592654f / 180.f;
|
||||
float cos = std::cos(rad);
|
||||
float sin = std::sin(rad);
|
||||
|
||||
Transform rotation(cos, -sin, 0,
|
||||
sin, cos, 0,
|
||||
0, 0, 1);
|
||||
|
||||
return combine(rotation);
|
||||
}
|
||||
|
||||
Transform& Transform::rotate(float angle, float centerX, float centerY) {
|
||||
float rad = angle * 3.141592654f / 180.f;
|
||||
float cos = std::cos(rad);
|
||||
float sin = std::sin(rad);
|
||||
|
||||
Transform rotation(cos, -sin, centerX * (1 - cos) + centerY * sin,
|
||||
sin, cos, centerY * (1 - cos) - centerX * sin,
|
||||
0, 0, 1);
|
||||
|
||||
return combine(rotation);
|
||||
}
|
||||
|
||||
Transform& Transform::rotate(float angle, const Vector2f& center) {
|
||||
return rotate(angle, center.x, center.y);
|
||||
}
|
||||
|
||||
Transform& Transform::scale(float scaleX, float scaleY) {
|
||||
Transform scaling(scaleX, 0, 0,
|
||||
0, scaleY, 0,
|
||||
0, 0, 1);
|
||||
|
||||
return combine(scaling);
|
||||
}
|
||||
|
||||
Transform& Transform::scale(float scaleX, float scaleY, float centerX, float centerY) {
|
||||
Transform scaling(scaleX, 0, centerX * (1 - scaleX),
|
||||
0, scaleY, centerY * (1 - scaleY),
|
||||
0, 0, 1);
|
||||
|
||||
return combine(scaling);
|
||||
}
|
||||
|
||||
Transform& Transform::scale(const Vector2f& factors) {
|
||||
return scale(factors.x, factors.y);
|
||||
}
|
||||
|
||||
Transform& Transform::scale(const Vector2f& factors, const Vector2f& center) {
|
||||
return scale(factors.x, factors.y, center.x, center.y);
|
||||
}
|
||||
|
||||
Transform operator *(const Transform& left, const Transform& right) {
|
||||
return Transform(left).combine(right);
|
||||
}
|
||||
|
||||
Transform& operator *=(Transform& left, const Transform& right) {
|
||||
return left.combine(right);
|
||||
}
|
||||
|
||||
Vector2f operator *(const Transform& left, const Vector2f& right) {
|
||||
return left.transformPoint(right);
|
||||
}
|
||||
|
||||
bool operator ==(const Transform& left, const Transform& right) {
|
||||
const float* a = left.getMatrix();
|
||||
const float* b = right.getMatrix();
|
||||
|
||||
return ((a[0] == b[0]) && (a[1] == b[1]) && (a[3] == b[3]) &&
|
||||
(a[4] == b[4]) && (a[5] == b[5]) && (a[7] == b[7]) &&
|
||||
(a[12] == b[12]) && (a[13] == b[13]) && (a[15] == b[15]));
|
||||
}
|
||||
|
||||
bool operator !=(const Transform& left, const Transform& right) {
|
||||
return !(left == right);
|
||||
}
|
||||
|
||||
}}
|
||||
@@ -214,7 +214,7 @@ bool WindowSDL::create( WindowSettings Settings, ContextSettings Context ) {
|
||||
|
||||
createView();
|
||||
|
||||
setup2D();
|
||||
setup2D( false );
|
||||
|
||||
mWindow.Created = true;
|
||||
|
||||
@@ -349,9 +349,9 @@ void WindowSDL::onWindowResize( Uint32 Width, Uint32 Height ) {
|
||||
mWindow.WindowConfig.Height = Height;
|
||||
mWindow.WindowSize = Sizei( Width, Height );
|
||||
|
||||
mDefaultView.setView( 0, 0, Width, Height );
|
||||
mDefaultView.reset( Rectf( 0, 0, Width, Height ) );
|
||||
|
||||
setup2D();
|
||||
setup2D( false );
|
||||
|
||||
SDL_PumpEvents();
|
||||
|
||||
@@ -407,9 +407,7 @@ void WindowSDL::setSize( Uint32 Width, Uint32 Height, bool Windowed ) {
|
||||
|
||||
BitOp::setBitFlagValue( &mWindow.WindowConfig.Style, WindowStyle::Fullscreen, !Windowed );
|
||||
|
||||
mDefaultView.setView( 0, 0, Width, Height );
|
||||
|
||||
setup2D();
|
||||
setup2D( false );
|
||||
|
||||
SDL_PumpEvents();
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@ bool WindowSFML::create( WindowSettings Settings, ContextSettings Context ) {
|
||||
|
||||
createView();
|
||||
|
||||
setup2D();
|
||||
setup2D( false );
|
||||
|
||||
mWindow.Created = true;
|
||||
mVisible = true;
|
||||
@@ -183,9 +183,9 @@ void WindowSFML::videoResize( Uint32 Width, Uint32 Height ) {
|
||||
mWindow.WindowConfig.Width = Width;
|
||||
mWindow.WindowConfig.Height = Height;
|
||||
|
||||
mDefaultView.setView( 0, 0, Width, Height );
|
||||
mDefaultView.reset( Rectf( 0, 0, Width, Height ) );
|
||||
|
||||
setup2D();
|
||||
setup2D( false );
|
||||
|
||||
mCursorManager->reload();
|
||||
|
||||
|
||||
@@ -286,10 +286,8 @@ Vector2f Input::getMousePosf() {
|
||||
return Vector2f( (Float)mMousePos.x, (Float)mMousePos.y );
|
||||
}
|
||||
|
||||
Vector2i Input::getMousePosFromView( const View& View ) {
|
||||
Vector2i RealMousePos = getMousePos();
|
||||
Rect RView = View.getView();
|
||||
return Vector2i( RealMousePos.x - RView.Left, RealMousePos.y - RView.Top );
|
||||
Vector2f Input::getMousePosFromView( const View& View ) {
|
||||
return mWindow->mapPixelToCoords( getMousePos(), View );
|
||||
}
|
||||
|
||||
Uint32 Input::pushCallback( const InputCallback& cb ) {
|
||||
|
||||
@@ -2,106 +2,151 @@
|
||||
|
||||
namespace EE { namespace Window {
|
||||
|
||||
View::View() : mNeedUpdate(true) {
|
||||
mView.Left = 0;
|
||||
mView.Right = 0;
|
||||
mView.Top = 0;
|
||||
mView.Bottom = 0;
|
||||
|
||||
calcCenter();
|
||||
View::View() :
|
||||
mCenter (),
|
||||
mSize (),
|
||||
mRotation (0),
|
||||
mViewport (0, 0, 1, 1),
|
||||
mTransformUpdated (false),
|
||||
mInvTransformUpdated(false)
|
||||
{
|
||||
reset(Rectf(0, 0, 1000, 1000));
|
||||
}
|
||||
|
||||
View::View( const int& X, const int& Y, const int& Width, const int& Height ) : mNeedUpdate(true) {
|
||||
setView( X, Y, Width, Height );
|
||||
View::View(const Rectf& rectangle) :
|
||||
mCenter (),
|
||||
mSize (),
|
||||
mRotation (0),
|
||||
mViewport (0, 0, 1, 1),
|
||||
mTransformUpdated (false),
|
||||
mInvTransformUpdated(false)
|
||||
{
|
||||
reset(rectangle);
|
||||
}
|
||||
|
||||
View::View( const Rect& View ) : mNeedUpdate(true) {
|
||||
mView = View;
|
||||
View::View(const Vector2f& center, const Vector2f& size) :
|
||||
mCenter (center),
|
||||
mSize (size),
|
||||
mRotation (0),
|
||||
mViewport (0, 0, 1, 1),
|
||||
mTransformUpdated (false),
|
||||
mInvTransformUpdated(false)
|
||||
{}
|
||||
|
||||
calcCenter();
|
||||
void View::setCenter(float x, float y) {
|
||||
mCenter.x = x;
|
||||
mCenter.y = y;
|
||||
|
||||
mTransformUpdated = false;
|
||||
mInvTransformUpdated = false;
|
||||
}
|
||||
|
||||
View::~View() {
|
||||
void View::setCenter(const Vector2f& center) {
|
||||
setCenter(center.x, center.y);
|
||||
}
|
||||
|
||||
void View::setView( const int& X, const int& Y, const int& Width, const int& Height ) {
|
||||
mView.Left = X;
|
||||
mView.Top = Y;
|
||||
mView.Right = Width;
|
||||
mView.Bottom = Height;
|
||||
calcCenter();
|
||||
mNeedUpdate = true;
|
||||
void View::setSize(float width, float height) {
|
||||
mSize.x = width;
|
||||
mSize.y = height;
|
||||
|
||||
mTransformUpdated = false;
|
||||
mInvTransformUpdated = false;
|
||||
}
|
||||
|
||||
void View::calcCenter() {
|
||||
mCenter.x = ( ( mView.Left + mView.Right ) - mView.Left ) * 0.5f;
|
||||
mCenter.y = ( ( mView.Top + mView.Bottom ) - mView.Top ) * 0.5f;
|
||||
void View::setSize(const Sizef & size) {
|
||||
setSize(size.x, size.y);
|
||||
}
|
||||
|
||||
Vector2i View::getCenter() const {
|
||||
return Vector2i( (int)mCenter.x, (Int32)mCenter.y );
|
||||
void View::setRotation(float angle) {
|
||||
mRotation = static_cast<float>(fmod(angle, 360));
|
||||
if (mRotation < 0)
|
||||
mRotation += 360.f;
|
||||
|
||||
mTransformUpdated = false;
|
||||
mInvTransformUpdated = false;
|
||||
}
|
||||
|
||||
void View::setCenter( const Vector2i& Center ) {
|
||||
mCenter.x = (Float)Center.x;
|
||||
mCenter.y = (Float)Center.y;
|
||||
mView.Left = static_cast<int> ( mCenter.x - (Float)mView.Right * 0.5f );
|
||||
mView.Top = static_cast<int> ( mCenter.y - (Float)mView.Bottom * 0.5f );
|
||||
|
||||
mNeedUpdate = true;
|
||||
void View::setViewport(const Rectf& viewport) {
|
||||
mViewport = viewport;
|
||||
}
|
||||
|
||||
void View::move( const int& OffsetX, const int& OffsetY ) {
|
||||
mView.Left += OffsetX;
|
||||
mView.Top += OffsetY;
|
||||
void View::reset(const Rectf& rectangle) {
|
||||
mCenter.x = rectangle.Left + rectangle.Right / 2.f;
|
||||
mCenter.y = rectangle.Top + rectangle.Bottom / 2.f;
|
||||
mSize.x = rectangle.Right;
|
||||
mSize.y = rectangle.Bottom;
|
||||
mRotation = 0;
|
||||
|
||||
calcCenter();
|
||||
mNeedUpdate = true;
|
||||
mTransformUpdated = false;
|
||||
mInvTransformUpdated = false;
|
||||
}
|
||||
|
||||
void View::move( const Vector2i& Offset ) {
|
||||
move( Offset.x, Offset.y );
|
||||
const Vector2f& View::getCenter() const {
|
||||
return mCenter;
|
||||
}
|
||||
|
||||
void View::scale( const Vector2f& Factor ) {
|
||||
Vector2f v( mView.Right * 0.5f, mView.Bottom * 0.5f );
|
||||
|
||||
mView.Left = mView.Left + static_cast<int> ( v.x - v.x * Factor.x );
|
||||
mView.Top = mView.Top + static_cast<int> ( v.y - v.y * Factor.y );
|
||||
mView.Right = static_cast<Int32>( (Float)mView.Right * Factor.x );
|
||||
mView.Bottom = static_cast<Int32>( (Float)mView.Bottom * Factor.y );
|
||||
|
||||
calcCenter();
|
||||
mNeedUpdate = true;
|
||||
const Sizef& View::getSize() const {
|
||||
return mSize;
|
||||
}
|
||||
|
||||
void View::scale( const Float& Factor ) {
|
||||
scale( Vector2f( Factor, Factor ) );
|
||||
float View::getRotation() const {
|
||||
return mRotation;
|
||||
}
|
||||
|
||||
void View::setPosition( const int& X, const int& Y ) {
|
||||
mView.Left = X;
|
||||
mView.Top = Y;
|
||||
|
||||
calcCenter();
|
||||
mNeedUpdate = true;
|
||||
const Rectf& View::getViewport() const {
|
||||
return mViewport;
|
||||
}
|
||||
|
||||
void View::setSize( const int& Width, const int& Height ) {
|
||||
mView.Right = Width;
|
||||
mView.Bottom = Height;
|
||||
|
||||
calcCenter();
|
||||
mNeedUpdate = true;
|
||||
void View::move(float offsetX, float offsetY) {
|
||||
setCenter(mCenter.x + offsetX, mCenter.y + offsetY);
|
||||
}
|
||||
|
||||
bool View::needUpdate() const {
|
||||
bool Need = mNeedUpdate;
|
||||
void View::move(const Vector2f& offset) {
|
||||
setCenter(mCenter + offset);
|
||||
}
|
||||
|
||||
if ( Need )
|
||||
const_cast<View*>(this)->mNeedUpdate = false;
|
||||
void View::rotate(float angle) {
|
||||
setRotation(mRotation + angle);
|
||||
}
|
||||
|
||||
return Need;
|
||||
void View::zoom(float factor) {
|
||||
setSize(mSize.x * factor, mSize.y * factor);
|
||||
}
|
||||
|
||||
const Transform& View::getTransform() const {
|
||||
// Recompute the matrix if needed
|
||||
if (!mTransformUpdated) {
|
||||
// Rotation components
|
||||
float angle = mRotation * 3.141592654f / 180.f;
|
||||
float cosine = static_cast<float>(std::cos(angle));
|
||||
float sine = static_cast<float>(std::sin(angle));
|
||||
float tx = -mCenter.x * cosine - mCenter.y * sine + mCenter.x;
|
||||
float ty = mCenter.x * sine - mCenter.y * cosine + mCenter.y;
|
||||
|
||||
// Projection components
|
||||
float a = 2.f / mSize.x;
|
||||
float b = -2.f / mSize.y;
|
||||
float c = -a * mCenter.x;
|
||||
float d = -b * mCenter.y;
|
||||
|
||||
// Rebuild the projection matrix
|
||||
mTransform = Transform( a * cosine, a * sine, a * tx + c,
|
||||
-b * sine, b * cosine, b * ty + d,
|
||||
0.f, 0.f, 1.f);
|
||||
mTransformUpdated = true;
|
||||
}
|
||||
|
||||
return mTransform;
|
||||
}
|
||||
|
||||
const Transform& View::getInverseTransform() const {
|
||||
// Recompute the matrix if needed
|
||||
if (!mInvTransformUpdated) {
|
||||
mInverseTransform = getTransform().getInverse();
|
||||
mInvTransformUpdated = true;
|
||||
}
|
||||
|
||||
return mInverseTransform;
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
@@ -104,18 +104,69 @@ void Window::set2DProjection( const Uint32& Width, const Uint32& Height ) {
|
||||
GLi->loadIdentity();
|
||||
}
|
||||
|
||||
void Window::setViewport(const Int32& x, const Int32& y, const Uint32& Width, const Uint32& Height ) {
|
||||
void Window::setProjection(const Transform & transform) {
|
||||
GLi->matrixMode( GL_PROJECTION );
|
||||
GLi->loadMatrixf( transform.getMatrix() );
|
||||
|
||||
GLi->matrixMode( GL_MODELVIEW );
|
||||
GLi->loadIdentity();
|
||||
}
|
||||
|
||||
Vector2f Window::mapPixelToCoords(const Vector2i& point) {
|
||||
return mapPixelToCoords(point, getView());
|
||||
}
|
||||
|
||||
Vector2f Window::mapPixelToCoords(const Vector2i& point, const View& view) {
|
||||
// First, convert from viewport coordinates to homogeneous coordinates
|
||||
Vector2f normalized;
|
||||
Rect viewport = getViewport(view);
|
||||
normalized.x = -1.f + 2.f * (point.x - viewport.Left) / viewport.Right;
|
||||
normalized.y = 1.f - 2.f * (point.y - viewport.Top) / viewport.Bottom;
|
||||
|
||||
// Then transform by the inverse of the view matrix
|
||||
return view.getInverseTransform().transformPoint(normalized);
|
||||
}
|
||||
|
||||
Vector2i Window::mapCoordsToPixel(const Vector2f& point) {
|
||||
return mapCoordsToPixel(point, getView());
|
||||
}
|
||||
|
||||
Vector2i Window::mapCoordsToPixel(const Vector2f& point, const View& view) {
|
||||
// First, transform the point by the view matrix
|
||||
Vector2f normalized = view.getTransform().transformPoint(point);
|
||||
|
||||
// Then convert to viewport coordinates
|
||||
Vector2i pixel;
|
||||
Rect viewport = getViewport(view);
|
||||
pixel.x = static_cast<int>(( normalized.x + 1.f) / 2.f * viewport.Right + viewport.Left);
|
||||
pixel.y = static_cast<int>((-normalized.y + 1.f) / 2.f * viewport.Bottom + viewport.Top);
|
||||
|
||||
return pixel;
|
||||
}
|
||||
|
||||
void Window::setViewport( const Int32& x, const Int32& y, const Uint32& Width, const Uint32& Height ) {
|
||||
GLi->viewport( x, getHeight() - ( y + Height ), Width, Height );
|
||||
}
|
||||
|
||||
Rect Window::getViewport( const View& view ) {
|
||||
float width = static_cast<float>(getSize().getWidth());
|
||||
float height = static_cast<float>(getSize().getHeight());
|
||||
const Rectf& viewport = view.getViewport();
|
||||
|
||||
return Rect( static_cast<int>(0.5f + width * viewport.Left),
|
||||
static_cast<int>(0.5f + height * viewport.Top),
|
||||
static_cast<int>(0.5f + width * viewport.Right),
|
||||
static_cast<int>(0.5f + height * viewport.Bottom));
|
||||
}
|
||||
|
||||
void Window::setView( const View& View ) {
|
||||
mCurrentView = &View;
|
||||
|
||||
Rect RView = mCurrentView->getView();
|
||||
Rect viewport = getViewport( *mCurrentView );
|
||||
|
||||
setViewport( RView.Left, RView.Top, RView.Right, RView.Bottom );
|
||||
setViewport( viewport.Left, viewport.Top, viewport.Right, viewport.Bottom );
|
||||
|
||||
set2DProjection( RView.Right, RView.Bottom );
|
||||
setProjection( View.getTransform() );
|
||||
}
|
||||
|
||||
const View& Window::getDefaultView() const {
|
||||
@@ -127,7 +178,7 @@ const View& Window::getView() const {
|
||||
}
|
||||
|
||||
void Window::createView() {
|
||||
mDefaultView.setView( 0, 0, mWindow.WindowConfig.Width, mWindow.WindowConfig.Height );
|
||||
mDefaultView.reset( Rectf( 0, 0, mWindow.WindowConfig.Width, mWindow.WindowConfig.Height ) );
|
||||
mCurrentView = &mDefaultView;
|
||||
}
|
||||
|
||||
@@ -148,8 +199,6 @@ void Window::setup2D( const bool& KeepView ) {
|
||||
|
||||
if ( !KeepView ) {
|
||||
setView( mDefaultView );
|
||||
|
||||
mCurrentView->needUpdate();
|
||||
}
|
||||
|
||||
BlendMode::setMode( BlendAlpha, true );
|
||||
@@ -298,12 +347,6 @@ void Window::limitFps() {
|
||||
}
|
||||
}
|
||||
|
||||
void Window::viewCheckUpdate() {
|
||||
if ( mCurrentView->needUpdate() ) {
|
||||
setView( *mCurrentView );
|
||||
}
|
||||
}
|
||||
|
||||
void Window::clear() {
|
||||
GLi->clear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
|
||||
}
|
||||
@@ -311,9 +354,6 @@ void Window::clear() {
|
||||
void Window::display( bool clear ) {
|
||||
GlobalBatchRenderer::instance()->draw();
|
||||
|
||||
if ( mCurrentView->needUpdate() )
|
||||
setView( *mCurrentView );
|
||||
|
||||
swapBuffers();
|
||||
|
||||
#if EE_PLATFORM != EE_PLATFORM_EMSCRIPTEN
|
||||
|
||||
@@ -1642,19 +1642,22 @@ void EETest::render() {
|
||||
if ( !MultiViewportMode ) {
|
||||
Scenes[ Screen ]();
|
||||
} else {
|
||||
Views[0].setView( 0, 0, mWindow->getWidth(), static_cast<Uint32>( HHeight ) );
|
||||
Views[1].setView( 0, static_cast<Int32> ( HHeight ), mWindow->getWidth(), static_cast<Uint32>( HHeight ) );
|
||||
|
||||
mWindow->setView( Views[1] );
|
||||
Mouse = KM->getMousePosFromView( Views[1] );
|
||||
Mousef = Vector2f( (Float)Mouse.x, (Float)Mouse.y );
|
||||
screen2();
|
||||
Views[0].reset( Rectf( 0, 0, mWindow->getWidth(), HHeight ) );
|
||||
Views[0].setViewport( Rectf( 0, 0, 1, 0.5f ) );
|
||||
|
||||
mWindow->setView( Views[0] );
|
||||
Mouse = KM->getMousePosFromView( Views[0] );
|
||||
Mousef = Vector2f( (Float)Mouse.x, (Float)Mouse.y );
|
||||
Mousef = KM->getMousePosFromView( Views[0] );
|
||||
Mouse = Vector2i( Mousef.x, Mousef.y );
|
||||
screen1();
|
||||
|
||||
Views[1].reset( Rectf( 0, 0, mWindow->getWidth(), HHeight ) );
|
||||
Views[1].setViewport( Rectf( 0, 0.5f, 1, 0.5f ) );
|
||||
|
||||
mWindow->setView( Views[1] );
|
||||
Mousef = KM->getMousePosFromView( Views[1] );
|
||||
Mouse = Vector2i( Mousef.x, Mousef.y );
|
||||
screen2();
|
||||
|
||||
mWindow->setView( mWindow->getDefaultView() );
|
||||
GLi->getClippingMask()->clipEnable( (Int32)HWidth - 320, (Int32)HHeight - 240, 640, 480 );
|
||||
screen3();
|
||||
|
||||
Reference in New Issue
Block a user