1 module caLib.renderers.OneDimBasicRenderer;
2 
3 import caLib_abstract.lattice : isBoundedLattice, isAnyBoundedLattice;
4 import caLib_abstract.palette : isColorPalette, isAnyColorPalette;
5 import std.traits : CommonType;
6 import caLib_util.image : Image;
7 import caLib_util.video : Video;
8 import caLib_util.structs : Rect, Color;
9 import caLib_util.graphics;
10 
11 public import caLib_util.graphics : Window;
12 
13 
14 
15 template create_OneDimBasicRenderer(Ct, Lt, Pt)
16 if(isBoundedLattice!(Lt, Ct, 1) && isColorPalette!(Pt, Ct))
17 {
18     OneDimBasicRenderer!(Ct, Lt, Pt)*
19     create_OneDimBasicRenderer(Lt* lattice, Pt* palette, Window window)
20     {
21         return new OneDimBasicRenderer!(Ct, Lt, Pt)(lattice, palette, window);
22     }
23 }
24 
25 
26 
27 
28 auto create_OneDimBasicRenderer(Lt, Pt)(Lt* lattice, Pt* palette, Window window)
29 if(isAnyBoundedLattice!Lt && isAnyColorPalette!Pt && Lt.Dimension == 1)
30 {
31     alias Ct = CommonType!(Lt.CellStateType, Pt.CellStateType);
32     static assert(!is(Ct == void));
33 
34     return new OneDimBasicRenderer!(Ct, Lt, Pt)(lattice, palette, window);
35 }
36 
37 
38 
39 struct OneDimBasicRenderer(Ct, Lt, Pt)
40 if(isColorPalette!(Pt, Ct) && isBoundedLattice!(Lt, Ct, 1))
41 {
42 
43 private:
44 
45     Lt* lattice;
46 
47     Pt* palette;
48 
49     Window window;
50     Texture texture;
51 
52     uint cellSize;
53     uint n;
54     SDL_Rect sRectBottom;
55     SDL_Rect dRectBottom;
56     SDL_Rect sRectTop;
57     SDL_Rect dRectTop;
58 
59 public:
60 
61     this(Lt* lattice, Pt* palette, Window window)
62     in
63     {
64         assert(window.getWidth() / lattice.getLatticeBounds()[0] > 0);
65     }
66     body
67     {
68         this.lattice = lattice;
69         this.palette = palette;
70 
71         this.window = window;
72 
73         cellSize = window.getWidth() / lattice.getLatticeBounds()[0];
74         n=0;
75 
76         texture = new Texture(window, lattice.getLatticeBounds()[0], window.getHeight() / cellSize);
77 
78         sRectBottom = SDL_Rect(0, 0, texture.getWidth(), n+1);
79 		dRectBottom = SDL_Rect(0, window.getHeight() - (n+1)*cellSize, window.getWidth(), (n+1)*cellSize);
80 		sRectTop = SDL_Rect(0, n+1, texture.getWidth(), texture.getHeight() - (n+1));
81 		dRectTop = SDL_Rect(0, 0, window.getWidth(), window.getHeight() - (n+1)*cellSize);
82     }
83 
84     void render()
85     {
86     	{
87     		uint* pixels = texture.lock();
88     		scope(exit) texture.unlock();
89 
90     		foreach(col; 0 .. texture.getWidth())
91     		{
92     			pixels[n * texture.getWidth() + col] = palette.getDisplayValue(lattice.get(col));
93     		}
94     	}
95 
96 		sRectBottom.h = n+1;
97 		dRectBottom.y = window.getHeight() - (n+1) * cellSize;
98 		dRectBottom.h = (n+1) * cellSize;
99 		SDL_RenderCopy(window.getRenderer(), texture.getTexture(), &sRectBottom, &dRectBottom);
100 
101 		sRectTop.y = n+1;
102 		sRectTop.h = texture.getHeight() - (n+1);
103 		dRectTop.h = window.getHeight() - (n+1) * cellSize;
104 		SDL_RenderCopy(window.getRenderer(), texture.getTexture(), &sRectTop, &dRectTop);
105 
106         SDL_RenderPresent(window.getRenderer());
107 
108         n ++;
109 
110         if(n >= texture.getHeight())
111         	n=0;
112     }
113 
114     void screenshot(string path)
115     in
116     { assert(path !is(null)); }
117     body
118     {
119     	uint* pixels = texture.lock();
120     	scope(exit) texture.unlock();
121 
122     	Image image = new Image(texture.getWidth(), texture.getHeight());
123     	foreach(row; 0 .. texture.getHeight())
124     	{
125     		foreach(col; 0 .. texture.getWidth())
126     		{
127     			image.setPixel(col, row, Color(pixels[(n + row) % texture.getHeight() * texture.getWidth() + col]));
128     		}
129     	}
130     	image.saveToFile(path);
131     }
132 
133     void startRecording(string path, uint framerate)
134     {
135         assert(0);
136     }
137     
138     void stopRecording()
139     {
140         assert(0);
141     }
142 }
143 
144 
145 
146 version(unittest)
147 {
148     import caLib_abstract.renderer : isRenderer;
149     import caLib_abstract.lattice : BoundedLattice;
150     import caLib_abstract.palette : Palette;
151 }
152 
153 
154 
155 unittest
156 {
157     alias Ct = string;
158     assert(isRenderer!(OneDimBasicRenderer!(Ct, BoundedLattice!(Ct, 1), Palette!(Ct, Color))));
159 }