1 // Copyright 2022 Garrett D'Amore
2 //
3 // Distributed under the Boost Software License, Version 1.0.
4 // (See accompanying file LICENSE or https://www.boost.org/LICENSE_1_0.txt)
5 
6 /**
7  * Colors (Dcell)
8  */
9 module color;
10 
11 import std.stdio;
12 import std.string;
13 import std.concurrency;
14 import std.random;
15 import std.range;
16 import dcell;
17 
18 class ColorBoxes
19 {
20 	import std.random;
21 
22 	int r;
23 	int g;
24 	int b;
25 	int ri;
26 	int gi;
27 	int bi;
28 	Random rng;
29 	enum inc = 8;
30 	int cnt;
31 
32 	bool flip()
33 	{
34 		return (rng.uniform!ubyte() & 0x1) != 0;
35 	}
36 
37 	this()
38 	{
39 		rng = rndGen();
40 		r = rng.uniform!ubyte();
41 		g = rng.uniform!ubyte();
42 		b = rng.uniform!ubyte();
43 		ri = inc;
44 		gi = inc / 4; // humans are very sensitive to green
45 		bi = inc;
46 	}
47 
48 	void makeBox(Screen s)
49 	{
50 		Coord wsz = s.size();
51 		dchar dc = ' ';
52 		Style style;
53 		cnt++;
54 
55 		if (s.colors() == 0)
56 		{
57 			dchar[] glyphs = ['@', '#', '&', '*', '=', '%', 'Z', 'A'];
58 			dc = choice(glyphs, rng);
59 			if (flip())
60 				style.attr |= Attr.reverse;
61 			else
62 				style.attr &= ~Attr.reverse;
63 		}
64 		else
65 		{
66 			r += ri;
67 			g += gi;
68 			b += bi;
69 			if (r >= 256 || r < 0)
70 			{
71 				ri = -ri;
72 				r += ri;
73 			}
74 			if (g >= 256 || g < 0)
75 			{
76 				gi = -gi;
77 				g += gi;
78 			}
79 			if (b >= 256 || b < 0)
80 			{
81 				bi = -bi;
82 				b += bi;
83 			}
84 			if (cnt % (256 / inc) == 0)
85 			{
86 				if (flip())
87 				{
88 					ri = -ri;
89 				}
90 
91 				if (flip())
92 				{
93 					gi = -gi;
94 				}
95 
96 				if (flip())
97 				{
98 					bi = -bi;
99 				}
100 			}
101 			style.bg = fromHex(
102 				int(r) << 15 | int(g) << 8 | int(b));
103 		}
104 
105 		// half the width and half the height
106 		Coord c1 = Coord(wsz.x / 4, wsz.y / 4);
107 		Coord c2 = Coord(c1.x + wsz.x / 2, c1.y + wsz.y / 2);
108 		Coord pos = c1;
109 		Cell cell = Cell(dc, style);
110 		for (pos.y = c1.y; pos.y <= c2.y; pos.y++)
111 		{
112 			for (pos.x = c1.x; pos.x <= c2.x; pos.x++)
113 			{
114 				s[pos] = cell;
115 			}
116 		}
117 		s.show();
118 	}
119 }
120 
121 void main()
122 {
123 	import std.stdio;
124 	import core.time;
125 	import core.stdc.stdlib;
126 
127 	auto s = newScreen();
128 	assert(s !is null);
129 	ColorBoxes cb = new ColorBoxes();
130 
131 	auto now = MonoTime.currTime();
132 
133 	s.start();
134 	bool done = false;
135 	while (!done)
136 	{
137 		cb.makeBox(s);
138 		auto ev = s.receiveEvent(msecs(50));
139 		switch (ev.type)
140 		{
141 		case EventType.key:
142 			switch (ev.key.key)
143 			{
144 			case Key.esc, Key.enter:
145 				done = true;
146 				break;
147 			case Key.ctrlL:
148 				s.resize();
149 				s.sync();
150 				break;
151 			default:
152 
153 			}
154 			break;
155 		case EventType.resize:
156 			s.resize();
157 			break;
158 		case EventType.closed:
159 			done = true;
160 			break;
161 		case EventType.error:
162 			assert(0, "errror received");
163 		default:
164 		}
165 	}
166 	auto end = MonoTime.currTime();
167 	s.stop();
168 	writefln("Drew %d boxes in %s.", cb.cnt, end - now);
169 	writefln("Average per box %s.", (end - now) / cb.cnt);
170 }