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 }