1 /* 2 ******************************************************************************************* 3 * Dgame (a D game framework) - Copyright (c) Randy Schütt 4 * 5 * This software is provided 'as-is', without any express or implied warranty. 6 * In no event will the authors be held liable for any damages arising from 7 * the use of this software. 8 * 9 * Permission is granted to anyone to use this software for any purpose, 10 * including commercial applications, and to alter it and redistribute it 11 * freely, subject to the following restrictions: 12 * 13 * 1. The origin of this software must not be misrepresented; you must not claim 14 * that you wrote the original software. If you use this software in a product, 15 * an acknowledgment in the product documentation would be appreciated but is 16 * not required. 17 * 18 * 2. Altered source versions must be plainly marked as such, and must not be 19 * misrepresented as being the original software. 20 * 21 * 3. This notice may not be removed or altered from any source distribution. 22 ******************************************************************************************* 23 */ 24 module Dgame.Graphics.Transformable; 25 26 private { 27 import std.math : isNaN; 28 29 import derelict.opengl3.gl; 30 31 import Dgame.Math.Vector2; 32 import Dgame.Graphics.Moveable; 33 } 34 35 /** 36 * Basic implementation for transformable objects. 37 * 38 * Author: rschuett 39 */ 40 abstract class Transformable : Moveable { 41 private: 42 short _rotAngle; 43 float _zoom = 1f; 44 Vector2s _rotCenter; 45 46 protected: 47 /** 48 * Apply translation to the object. 49 */ 50 override void _applyTranslation() const { 51 super._applyTranslation(); 52 53 if (this._rotAngle != 0) { 54 if (!this._rotCenter.isEmpty()) 55 glTranslatef(this._rotCenter.x, this._rotCenter.y, 0f); 56 57 glRotatef(this._rotAngle, 0f, 0f, 1f); 58 59 if (!this._rotCenter.isEmpty()) 60 glTranslatef(-this._rotCenter.x, -this._rotCenter.y, 0f); 61 } 62 63 if (!isNaN(this._zoom) && this._zoom != 1f) 64 glScalef(this._zoom, this._zoom, 0f); 65 } 66 67 public: 68 /** 69 * Calculate, store and return the center point. 70 */ 71 abstract ref const(Vector2s) calculateCenter() pure nothrow; 72 73 /** 74 * Reset the translation. 75 */ 76 override void resetTranslation() { 77 super.resetTranslation(); 78 79 this.setRotation(0); 80 this.setScale(1); 81 } 82 83 final: 84 /** 85 * Set the rotation center. 86 */ 87 void setCenter(ref const Vector2s center) { 88 this._rotCenter = center; 89 } 90 91 /** 92 * Set the rotation center. 93 */ 94 void setCenter(short x, short y) pure nothrow { 95 this._rotCenter.set(x, y); 96 } 97 98 /** 99 * Returns the rotation center. 100 */ 101 ref const(Vector2s) getCenter() const pure nothrow { 102 return this._rotCenter; 103 } 104 105 /** 106 * Set a (new) rotation. 107 */ 108 void setRotation(short rotAngle) pure nothrow { 109 this._rotAngle = rotAngle; 110 111 if (this._rotAngle > 360 || this._rotAngle < -360) 112 this._rotAngle = 0; 113 } 114 115 /** 116 * Increase/Decrease the rotation. 117 */ 118 void rotate(short rotAngle) pure nothrow { 119 this._rotAngle += rotAngle; 120 } 121 122 /** 123 * Returns the current rotation. 124 */ 125 short getRotation() const pure nothrow { 126 return this._rotAngle; 127 } 128 129 /** 130 * Set a new scale. 131 */ 132 void setScale(float zoom) pure nothrow { 133 this._zoom = zoom; 134 } 135 136 /** 137 * Increase/Decrease the scale/zoom. 138 */ 139 void scale(float zoom) pure nothrow { 140 if (isNaN(this._zoom)) 141 return this.setScale(zoom); 142 143 this._zoom += zoom; 144 } 145 146 /** 147 * Returns the current scale/zoom. 148 */ 149 float getScale() const pure nothrow { 150 return this._zoom; 151 } 152 }