1 ///
2 module isodi.position;
3 
4 import std.meta;
5 import std.typecons;
6 import std.algorithm;
7 
8 /// Represents the height of a cell
9 struct Height {
10 
11     /// Position of the cell's top side.
12     float top = 0;
13 
14     /// Depth of the cell; how much space does the cell occupy in this column.
15     float depth = 1;
16 
17 }
18 
19 /// Unique values for locating an object in the 3D space.
20 alias UniquePosition = Tuple!(
21     int, "x",
22     int, "y",
23     int, "layer",
24 );
25 
26 /// Denotes an object's position.
27 alias Position = Tuple!(
28     int, "x",
29     int, "y",
30     int, "layer",
31     Height, "height",
32 );
33 
34 /// Arguments to pass to `multiSort` to sort Object3Ds by `position`.
35 private alias positionSortArgs = AliasSeq!(
36     `a.position.layer < b.position.layer`,
37     `a.position.y < b.position.y`,
38     `a.position.x < b.position.x`,
39 );
40 
41 /// Sort Object3Ds by `position`.
42 alias positionSort = multiSort!positionSortArgs;
43 
44 
45 @safe:
46 
47 
48 /// Create a position tuple.
49 Position position(int x, int y, int layer = 0, Height height = Height.init) {
50 
51     return Position(x, y, layer, height);
52 
53 }
54 
55 /// Create a position tuple.
56 Position position(int x, int y, Height height, int layer = 0) {
57 
58     return Position(x, y, layer, height);
59 
60 }
61 
62 /// Create an offset tuple.
63 ///
64 /// Unlike the other position constructors, this will subtract 1 from depth.
65 Position positionOff(int x, int y, Height height = Height.init) {
66 
67     height.depth -= 1;
68 
69     return Position(x, y, 0, height);
70 
71 }
72 
73 /// Get the unique position from a Position tuple.
74 inout(UniquePosition) toUnique(inout Position position) {
75 
76     return UniquePosition(position.x, position.y, position.layer);
77 
78 }
79 
80 Position sum(Position a, Position b) {
81 
82     return Position(
83         a.x + b.x,
84         a.y + b.y,
85         a.layer + b.layer,
86         Height(
87             a.height.top + b.height.top,
88             a.height.depth + b.height.depth,
89         )
90     );
91 
92 }