1 module isodi.raylib.resources.side;
2 
3 import raylib;
4 
5 import std.string;
6 import std.random;
7 
8 import isodi.pack;
9 import isodi.raylib.cell;
10 import isodi.raylib.internal;
11 
12 
13 @safe:
14 
15 
16 /// A side resource.
17 struct Side {
18 
19     /// Owner object.
20     RaylibCell cell;
21 
22     /// Textures of each side.
23     Texture2D[4] textures;
24 
25     /// Display scale of the sides.
26     float[4] scale;
27 
28     /// Create the side and load resources.
29     this(RaylibCell cell, Pack.Resource!string[4] resources) {
30 
31         this.cell = cell;
32 
33         foreach (side, resource; resources) {
34 
35             // Load the texture
36             textures[side] = cell.display.loadTexture(resource.match);
37             scale[side] = cast(float) cell.display.cellSize / textures[side].width;
38 
39         }
40 
41     }
42 
43     /// Draw the side
44     void draw() @trusted {
45 
46         const cellSize = cell.display.cellSize;
47 
48         const leftSide  = cast(short) (360+180 - cell.display.camera.angle.x) / 90 % 4;
49         const rightSide = (leftSide + 1) % 4;
50 
51         // Draw each side
52         foreach (side; [leftSide, rightSide]) {
53 
54             // If there's a neighbor on this side
55             if (auto neighbor = cell.getVisualNeighbor(cast(ubyte) side)) {
56 
57                 auto thisHeight = cell.visualPosition.height;
58                 auto neighborHeight = neighbor.visualPosition.height;
59 
60                 // And it covers the the side of this cell, don't render
61                 if (neighborHeight.top >= thisHeight.top
62                     && neighborHeight.depth + neighborHeight.top >= thisHeight.depth) continue;
63 
64             }
65 
66             rlPushMatrix();
67             scope (exit) rlPopMatrix();
68 
69             // Transform
70             {
71 
72                 // Move to an appropriate position
73                 rlTranslatef(cell.visualPosition.toTuple3(cellSize).expand);
74 
75                 // Correct positions
76                 rlTranslatef(
77                     cellSize * (side == 1 || side == 2),
78                     0,
79                     cellSize * (side == 2 || side == 3)
80                 );
81 
82                 // Rotate appropriately
83                 rlRotatef(side * -90, 0, 1, 0);
84 
85                 // Scale to fit
86                 rlScalef(scale[side], scale[side], scale[side]);
87 
88                 // Final corrections
89                 rlTranslatef(0, 0, 1);
90 
91             }
92 
93             const texture = textures[side];
94             const targetDepth = cell.visualPosition.height.depth * texture.width;
95 
96             float drawn = 0;
97             size_t start = 0;
98 
99             // Draw the texture
100             while (drawn < targetDepth) {
101 
102                 /// Space on the image that can be drawn
103                 const drawAvailable = texture.height - start;
104 
105                 /// Space left to draw
106                 const drawLeft = targetDepth - drawn;
107 
108                 /// Get space to draw
109                 const drawSpace = drawLeft < drawAvailable
110                     ? drawLeft
111                     : drawAvailable;
112 
113                 rlPushMatrix();
114 
115                     // Push the texture down
116                     rlTranslatef(0, -drawSpace - drawn, 0);
117 
118                     // Draw the texture
119                     textures[side].DrawTextureRec(
120                         Rectangle(
121                             0,             start,
122                             texture.width, -drawSpace,
123                         ),
124                         Vector2(0, 0),
125                         cell.color,
126                     );
127 
128                 rlPopMatrix();
129 
130                 // Mark as drawn
131                 drawn += drawSpace;
132 
133                 // Texture is higher than wide
134                 if (!start && texture.height > texture.width) {
135 
136                     // Move start
137                     start = texture.height - texture.width;
138 
139                 }
140 
141             }
142 
143         }
144 
145     }
146 
147 }