1 /// 2 module isodi.object3d; 3 4 import std.stdio; 5 import std.string; 6 7 public { 8 9 import isodi.bind; 10 import isodi.display; 11 import isodi.position; 12 import isodi.resource; 13 14 } 15 16 17 @safe: 18 19 20 /// Represents an object that can be drawn on a 3D space. 21 abstract class Object3D { 22 23 /// Display this object is connected to. 24 Display display; 25 26 /// Get the current position of the object. 27 abstract const(Position) position() const; 28 29 /// Get the current visual position of the object. 30 abstract const(Position) visualPosition() const; 31 32 /// Params: 33 /// display = Display to connect to. 34 this(Display display) { 35 36 this.display = display; 37 38 } 39 40 /// Add a basic implementation for the position as a property, includes a setter. 41 mixin template Implement() { 42 43 @safe: 44 45 private Position _position; 46 47 /// Get the current position of the object. 48 /// 49 /// This returns a const value, use `positionRef` to get a reference. 50 override const(Position) position() const { return _position; } 51 52 /// Ditto 53 override const(Position) visualPosition() const { return position; } 54 55 /// Get a reference to the position value. 56 ref Position positionRef() { return _position; } 57 58 /// Set the new position. 59 Position position(Position value) { return _position = value; } 60 61 } 62 63 /// 64 static unittest { 65 66 class Example : Object3D { 67 68 mixin Object3D.Implement; 69 70 this() { 71 super(null); 72 } 73 74 } 75 76 auto ex = new Example; 77 assert(ex.position == .position(0, 0)); 78 79 ex.positionRef.x += 1; 80 assert(ex.position == .position(1, 0)); 81 82 ex.position = .position(2, 2); 83 assert(ex.position == .position(2, 2)); 84 85 } 86 87 /// Implement the position as a const property. `_position` and `_visualPosition` must be set in constructor. 88 mixin template ImplementConst() { 89 90 @safe: 91 92 private const Position _position; 93 override const(Position) position() const { return _position; } 94 95 private Position _visualPosition; 96 97 /// Get the position the cell is displayed on. 98 override const(Position) visualPosition() const { 99 100 return _visualPosition; 101 102 } 103 104 /// Set an offset for the visual position. 105 /// 106 /// $(B Note:) Mind that depth is initialized to 1 by default, which might cause unwanted effects. If you don't 107 /// want to offset it, use `positionOff`. 108 const(Position) offset(Position value) { 109 110 return _visualPosition = Position( 111 _position.x + value.x, 112 _position.y + value.y, 113 _position.layer + value.layer, 114 Height( 115 _position.height.top + value.height.top, 116 _position.height.depth + value.height.depth, 117 ) 118 ); 119 120 } 121 122 /// Reset the offset 123 void resetOffset() { 124 125 _visualPosition = _position; 126 127 } 128 129 } 130 131 }