├── font.ttf ├── Resource.rc ├── FractalClock.zip ├── README.md ├── resource.h ├── HSV.h ├── LICENSE ├── FractalClock.vcxproj.filters ├── FractalClock.vcxproj └── Main.cpp /font.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HackerPoet/FractalClock/HEAD/font.ttf -------------------------------------------------------------------------------- /Resource.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HackerPoet/FractalClock/HEAD/Resource.rc -------------------------------------------------------------------------------- /FractalClock.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HackerPoet/FractalClock/HEAD/FractalClock.zip -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FractalClock 2 | A simple, relaxing fractal clock demo 3 | 4 | **Video:** https://youtu.be/4SH_-YhN15A 5 | -------------------------------------------------------------------------------- /resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by Resource.rc 4 | // 5 | #define IDR_FONT 101 6 | 7 | // Next default values for new objects 8 | // 9 | #ifdef APSTUDIO_INVOKED 10 | #ifndef APSTUDIO_READONLY_SYMBOLS 11 | #define _APS_NEXT_RESOURCE_VALUE 101 12 | #define _APS_NEXT_COMMAND_VALUE 40001 13 | #define _APS_NEXT_CONTROL_VALUE 1001 14 | #define _APS_NEXT_SYMED_VALUE 101 15 | #endif 16 | #endif 17 | -------------------------------------------------------------------------------- /HSV.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | inline sf::Color FromHSV(float h, float s, float v) { 5 | //All input ranges expected to be 0-1 6 | const int i = int(h * 6); 7 | const float f = h * 6 - i; 8 | const float p = v * (1 - s); 9 | const float q = v * (1 - f * s); 10 | const float t = v * (1 - (1 - f) * s); 11 | 12 | //Special cases 13 | float r, g, b; 14 | switch (i % 6) { 15 | case 0: r = v, g = t, b = p; break; 16 | case 1: r = q, g = v, b = p; break; 17 | case 2: r = p, g = v, b = t; break; 18 | case 3: r = p, g = q, b = v; break; 19 | case 4: r = t, g = p, b = v; break; 20 | case 5: r = v, g = p, b = q; break; 21 | } 22 | 23 | //Convert color range from 0-1 to 0-255 24 | return sf::Color(uint8_t(r * 255), uint8_t(g * 255), uint8_t(b * 255)); 25 | } 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 HackerPoet 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /FractalClock.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | 23 | 24 | Header Files 25 | 26 | 27 | Header Files 28 | 29 | 30 | 31 | 32 | Resource Files 33 | 34 | 35 | -------------------------------------------------------------------------------- /FractalClock.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {A638F934-E1C3-4E21-ACDC-96DF63A0DE7C} 23 | FractalClock 24 | 8.1 25 | 26 | 27 | 28 | Application 29 | true 30 | v140 31 | MultiByte 32 | 33 | 34 | Application 35 | false 36 | v140 37 | true 38 | MultiByte 39 | 40 | 41 | Application 42 | true 43 | v140 44 | MultiByte 45 | 46 | 47 | Application 48 | false 49 | v140 50 | true 51 | MultiByte 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | Level3 75 | Disabled 76 | true 77 | 78 | 79 | 80 | 81 | Level3 82 | Disabled 83 | true 84 | C:\Program Files\SFML\include 85 | SFML_STATIC;%(PreprocessorDefinitions) 86 | MultiThreadedDebug 87 | 88 | 89 | C:\Program Files\SFML\lib 90 | sfml-graphics-s-d.lib;sfml-system-s-d.lib;sfml-window-s-d.lib;opengl32.lib;winmm.lib;gdi32.lib;glu32.lib;freetype.lib;%(AdditionalDependencies) 91 | 92 | 93 | 94 | 95 | Level3 96 | MaxSpeed 97 | true 98 | true 99 | true 100 | 101 | 102 | true 103 | true 104 | 105 | 106 | 107 | 108 | Level3 109 | MaxSpeed 110 | true 111 | true 112 | true 113 | C:\Program Files\SFML\include 114 | SFML_STATIC;%(PreprocessorDefinitions) 115 | MultiThreaded 116 | 117 | 118 | true 119 | true 120 | C:\Program Files\SFML\lib 121 | sfml-graphics-s.lib;sfml-system-s.lib;sfml-window-s.lib;opengl32.lib;winmm.lib;gdi32.lib;glu32.lib;freetype.lib;%(AdditionalDependencies) 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | -------------------------------------------------------------------------------- /Main.cpp: -------------------------------------------------------------------------------- 1 | #define _CRT_SECURE_NO_WARNINGS 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "HSV.h" 7 | #include "resource.h" 8 | 9 | static const float PI = 3.14159265359f; 10 | static const int max_iters = 16; 11 | static const int window_w_init = 700; 12 | static const int window_h_init = 700; 13 | static const sf::Color clock_face_color(255, 255, 255, 192); 14 | static const sf::Color bgnd_color(16, 16, 16); 15 | enum ClockType { 16 | MS, HMS, HM, NUM 17 | }; 18 | static const char* clock_type_name[] = { 19 | "[M] Minutes, Seconds", 20 | "[M] Hours, Minutes, Seconds", 21 | "[M] Hours, Minutes", 22 | }; 23 | static const char* realtime_name[] = { 24 | "[R] Timer", 25 | "[R] Real-time", 26 | }; 27 | static const char* tick_name[] = { 28 | "[T] Smooth Time", 29 | "[T] Tick Time", 30 | }; 31 | static const char* draw_branches_name[] = { 32 | "[B] Hide Branches", 33 | "[B] Draw Branches", 34 | }; 35 | static const char* draw_clock_name[] = { 36 | "[C] Hide Clock", 37 | "[C] Draw Clock", 38 | }; 39 | 40 | static std::vector line_array; 41 | static std::vector point_array; 42 | static std::vector clock_face_array1; 43 | static std::vector clock_face_array2; 44 | static sf::Vector2f rotH, rotM, rotS; 45 | static float ratioH = 0.5f; 46 | static float ratioM = std::sqrt(1.0f / 2.0f); 47 | static float ratioS = std::sqrt(1.0f / 2.0f); 48 | static sf::Color color_scheme[max_iters]; 49 | static bool toggle_fullscreen = false; 50 | 51 | static ClockType clock_type = ClockType::HMS; 52 | static bool use_realtime = true; 53 | static bool use_tick = false; 54 | static bool draw_branches = true; 55 | static bool draw_clock = true; 56 | static bool is_fullscreen = false; 57 | 58 | struct Res { 59 | Res(int id) { 60 | HRSRC src = ::FindResource(NULL, MAKEINTRESOURCE(id), RT_RCDATA); 61 | ptr = ::LockResource(::LoadResource(NULL, src)); 62 | size = (size_t)::SizeofResource(NULL, src); 63 | } 64 | void* ptr; 65 | size_t size; 66 | }; 67 | 68 | void FractalIterMS(sf::Vector2f pt, sf::Vector2f dir, int depth) { 69 | const sf::Color& col = color_scheme[depth]; 70 | if (depth == 0) { 71 | point_array.emplace_back(pt, col); 72 | } else { 73 | const sf::Vector2f dirS((dir.x*rotS.x - dir.y*rotS.y)*ratioS, (dir.y*rotS.x + dir.x*rotS.y)*ratioS); 74 | const sf::Vector2f dirM((dir.x*rotM.x - dir.y*rotM.y)*ratioM, (dir.y*rotM.x + dir.x*rotM.y)*ratioM); 75 | FractalIterMS(pt + dirS, dirS, depth - 1); 76 | FractalIterMS(pt + dirM, dirM, depth - 1); 77 | line_array.emplace_back(pt, col); 78 | line_array.emplace_back(pt + dirS, col); 79 | line_array.emplace_back(pt, col); 80 | line_array.emplace_back(pt + dirM, col); 81 | } 82 | } 83 | 84 | void FractalIterHMS(sf::Vector2f pt, sf::Vector2f dir, int depth) { 85 | const sf::Color& col = color_scheme[depth]; 86 | if (depth == 0) { 87 | point_array.emplace_back(pt, col); 88 | } else { 89 | const sf::Vector2f dirS((dir.x*rotS.x - dir.y*rotS.y)*ratioS, (dir.y*rotS.x + dir.x*rotS.y)*ratioS); 90 | const sf::Vector2f dirM((dir.x*rotM.x - dir.y*rotM.y)*ratioM, (dir.y*rotM.x + dir.x*rotM.y)*ratioM); 91 | const sf::Vector2f dirH((dir.x*rotH.x - dir.y*rotH.y)*ratioH, (dir.y*rotH.x + dir.x*rotH.y)*ratioH); 92 | FractalIterHMS(pt + dirS, dirS, depth - 1); 93 | FractalIterHMS(pt + dirM, dirM, depth - 1); 94 | FractalIterHMS(pt + dirH, dirH, depth - 1); 95 | line_array.emplace_back(pt, col); 96 | line_array.emplace_back(pt + dirS, col); 97 | line_array.emplace_back(pt, col); 98 | line_array.emplace_back(pt + dirM, col); 99 | line_array.emplace_back(pt, col); 100 | line_array.emplace_back(pt + dirH, col); 101 | } 102 | } 103 | 104 | void FractalIterHM(sf::Vector2f pt, sf::Vector2f dir, int depth) { 105 | const sf::Color& col = color_scheme[depth]; 106 | if (depth == 0) { 107 | point_array.emplace_back(pt, col); 108 | } else { 109 | const sf::Vector2f dirM((dir.x*rotM.x - dir.y*rotM.y)*ratioM, (dir.y*rotM.x + dir.x*rotM.y)*ratioM); 110 | const sf::Vector2f dirH((dir.x*rotH.x - dir.y*rotH.y)*ratioH, (dir.y*rotH.x + dir.x*rotH.y)*ratioH); 111 | FractalIterHM(pt + dirM, dirM, depth - 1); 112 | FractalIterHM(pt + dirH, dirH, depth - 1); 113 | line_array.emplace_back(pt, col); 114 | line_array.emplace_back(pt + dirM, col); 115 | line_array.emplace_back(pt, col); 116 | line_array.emplace_back(pt + dirH, col); 117 | } 118 | } 119 | 120 | int main(int argc, char *argv[]) { 121 | //GL settings 122 | sf::ContextSettings settings; 123 | settings.depthBits = 24; 124 | settings.stencilBits = 8; 125 | settings.antialiasingLevel = 4; 126 | settings.majorVersion = 3; 127 | settings.minorVersion = 0; 128 | 129 | //Load the font 130 | sf::Font font; 131 | Res font_res(IDR_FONT); 132 | font.loadFromMemory(font_res.ptr, font_res.size); 133 | 134 | //Setup UI elements 135 | sf::Text clock_num; 136 | clock_num.setFont(font); 137 | clock_num.setFillColor(clock_face_color); 138 | sf::Text clock_type_text; 139 | clock_type_text.setFont(font); 140 | clock_type_text.setFillColor(clock_face_color); 141 | clock_type_text.setCharacterSize(24); 142 | clock_type_text.setPosition(10, 10); 143 | sf::Text realtime_text; 144 | realtime_text.setFont(font); 145 | realtime_text.setFillColor(clock_face_color); 146 | realtime_text.setCharacterSize(24); 147 | realtime_text.setPosition(10, 40); 148 | sf::Text tick_text; 149 | tick_text.setFont(font); 150 | tick_text.setFillColor(clock_face_color); 151 | tick_text.setCharacterSize(24); 152 | tick_text.setPosition(10, 70); 153 | sf::Text draw_branches_text; 154 | draw_branches_text.setFont(font); 155 | draw_branches_text.setFillColor(clock_face_color); 156 | draw_branches_text.setCharacterSize(24); 157 | draw_branches_text.setPosition(10, 100); 158 | sf::Text draw_clock_text; 159 | draw_clock_text.setFont(font); 160 | draw_clock_text.setFillColor(clock_face_color); 161 | draw_clock_text.setCharacterSize(24); 162 | draw_clock_text.setPosition(10, 130); 163 | 164 | //Create the window 165 | sf::VideoMode screenSize = sf::VideoMode(window_w_init, window_h_init, 24); 166 | sf::RenderWindow window(screenSize, "Fractal Clock", sf::Style::Resize | sf::Style::Close, settings); 167 | window.setFramerateLimit(60); 168 | window.setActive(true); 169 | window.requestFocus(); 170 | sf::Clock clock; 171 | 172 | //Main Loop 173 | clock.restart(); 174 | while (window.isOpen()) { 175 | sf::Event event; 176 | while (window.pollEvent(event)) { 177 | if (event.type == sf::Event::Closed) { 178 | window.close(); 179 | break; 180 | } else if (event.type == sf::Event::KeyPressed) { 181 | const sf::Keyboard::Key keycode = event.key.code; 182 | if (keycode == sf::Keyboard::Escape) { 183 | window.close(); 184 | break; 185 | } else if (keycode == sf::Keyboard::M) { 186 | clock_type = ClockType((clock_type + 1) % ClockType::NUM); 187 | } else if (keycode == sf::Keyboard::R) { 188 | use_realtime = !use_realtime; 189 | clock.restart(); 190 | } else if (keycode == sf::Keyboard::T) { 191 | use_tick = !use_tick; 192 | } else if (keycode == sf::Keyboard::B) { 193 | draw_branches = !draw_branches; 194 | } else if (keycode == sf::Keyboard::C) { 195 | draw_clock = !draw_clock; 196 | } else if (keycode == sf::Keyboard::F11) { 197 | toggle_fullscreen = true; 198 | } 199 | } else if (event.type == sf::Event::Resized) { 200 | screenSize.width = event.size.width; 201 | screenSize.height = event.size.height; 202 | window.setView(sf::View(sf::FloatRect(0.0f, 0.0f, (float)screenSize.width, (float)screenSize.height))); 203 | } 204 | } 205 | 206 | //Calculate maximum iterations 207 | int iters = max_iters; 208 | if (clock_type == ClockType::HMS) { 209 | iters = max_iters - 3; 210 | } 211 | 212 | //Get the time 213 | float cur_time = 0.0f; 214 | if (use_realtime) { 215 | FILETIME fileTime; 216 | SYSTEMTIME systemTime; 217 | SYSTEMTIME localTime; 218 | GetSystemTimeAsFileTime(&fileTime); 219 | FileTimeToSystemTime(&fileTime, &systemTime); 220 | SystemTimeToTzSpecificLocalTime(NULL, &systemTime, &localTime); 221 | cur_time = float(localTime.wMilliseconds) / 1000.0f; 222 | cur_time += float(localTime.wSecond); 223 | cur_time += float(localTime.wMinute) * 60.0f; 224 | cur_time += float(localTime.wHour) * 3600.0f; 225 | } else { 226 | cur_time = clock.getElapsedTime().asSeconds(); 227 | } 228 | if (use_tick) { 229 | static const float a = 30.0f; 230 | static const float b = 14.0f; 231 | const float x = std::fmodf(cur_time, 1.0f); 232 | const float y = 1.0f - std::cos(a*x)*std::exp(-b*x); 233 | cur_time = cur_time - x + y; 234 | } 235 | 236 | const float seconds = std::fmodf(cur_time, 60.0f) * 2.0f * PI / 60.0f; 237 | const float minutes = std::fmodf(cur_time, 3600.0f) * 2.0f * PI / 3600.0f; 238 | const float hours = std::fmodf(cur_time, 43200.0f) * 2.0f * PI / 43200.0f; 239 | 240 | //Update the clock 241 | const float ratio = std::max(std::max(ratioH, ratioM), ratioS); 242 | const float start_mag = std::min(screenSize.width, screenSize.height) * 0.5f * (1.0f - ratio) / ratio; 243 | 244 | rotH = sf::Vector2f(std::cos(hours), std::sin(hours)); 245 | rotM = sf::Vector2f(std::cos(minutes), std::sin(minutes)); 246 | rotS = sf::Vector2f(std::cos(seconds), std::sin(seconds)); 247 | const sf::Vector2f pt(float(screenSize.width)*0.5f, float(screenSize.height)*0.5f); 248 | const sf::Vector2f dir(0.0f, -start_mag); 249 | 250 | //Update the clock face 251 | clock_face_array1.clear(); 252 | clock_face_array2.clear(); 253 | for (int i = 0; i < 60; ++i) { 254 | const float ang = float(i) * 2.0f * PI / 60.0f; 255 | const sf::Vector2f v(std::cos(ang), std::sin(ang)); 256 | const bool is_hour = (i % 5 == 0); 257 | std::vector& clock_face_array = (is_hour ? clock_face_array1 : clock_face_array2); 258 | const float inner_rad = (is_hour ? 0.9f : 0.95f); 259 | clock_face_array.emplace_back(pt + v * start_mag * inner_rad, clock_face_color); 260 | clock_face_array.emplace_back(pt + v * start_mag * 1.0f, clock_face_color); 261 | } 262 | 263 | //Update the colors 264 | const float r1 = std::sin(cur_time * 0.017f)*0.5f + 0.5f; 265 | const float r2 = std::sin(cur_time * 0.011f)*0.5f + 0.5f; 266 | const float r3 = std::sin(cur_time * 0.003f)*0.5f + 0.5f; 267 | for (int i = 0; i < iters; ++i) { 268 | const float a = float(i) / float(iters - 1); 269 | const float h = std::fmodf(r2 + 0.5f*a, 1.0f); 270 | const float s = 0.5f + 0.5f * r3 - 0.5f*(1.0f - a); 271 | const float v = 0.3f + 0.5f * r1; 272 | if (i == 0) { 273 | color_scheme[i] = FromHSV(h, 1.0f, 1.0f); 274 | color_scheme[i].a = 128; 275 | } else if (i == iters - 1 && draw_clock) { 276 | color_scheme[i] = clock_face_color; 277 | } else { 278 | color_scheme[i] = FromHSV(h, s, v); 279 | color_scheme[i].a = 255; //128; 280 | } 281 | } 282 | 283 | //Update the fractal 284 | line_array.clear(); 285 | point_array.clear(); 286 | if (clock_type == ClockType::HM) { 287 | FractalIterHM(pt, dir, iters - 1); 288 | } else if (clock_type == ClockType::HMS) { 289 | FractalIterHMS(pt, dir, iters - 1); 290 | } else if (clock_type == ClockType::MS) { 291 | FractalIterMS(pt, dir, iters - 1); 292 | } 293 | 294 | //Clear the screen 295 | window.clear(bgnd_color); 296 | 297 | //Draw the fractal branches 298 | if (draw_branches) { 299 | glEnable(GL_LINE_SMOOTH); 300 | glLineWidth(2.0f); 301 | if (!draw_clock) { 302 | window.draw(line_array.data(), line_array.size(), sf::PrimitiveType::Lines); 303 | } else if (clock_type == ClockType::HMS) { 304 | window.draw(line_array.data(), line_array.size() - 6, sf::PrimitiveType::Lines); 305 | } else { 306 | window.draw(line_array.data(), line_array.size() - 4, sf::PrimitiveType::Lines); 307 | } 308 | } 309 | 310 | //Draw the final fractal in a brighter color 311 | glEnable(GL_POINT_SMOOTH); 312 | glPointSize(1.0f); 313 | window.draw(point_array.data(), point_array.size(), sf::PrimitiveType::Points); 314 | 315 | //Draw the clock 316 | if (draw_clock) { 317 | //Draw the clock face lines 318 | glEnable(GL_LINE_SMOOTH); 319 | glLineWidth(4.0f); 320 | window.draw(clock_face_array1.data(), clock_face_array1.size(), sf::PrimitiveType::Lines); 321 | glLineWidth(2.0f); 322 | window.draw(clock_face_array2.data(), clock_face_array2.size(), sf::PrimitiveType::Lines); 323 | 324 | //Draw the clock face numbers 325 | for (int i = 0; i < 12; ++i) { 326 | const float ang = float(i) * 2.0f * PI / 12.0f; 327 | const sf::Vector2f v(std::sin(ang), -std::cos(ang)); 328 | const std::string num_str = std::to_string(i == 0 ? 12 : i); 329 | clock_num.setString(num_str); 330 | clock_num.setCharacterSize(uint32_t(start_mag * 0.18f)); 331 | 332 | const sf::FloatRect bounds = clock_num.getLocalBounds(); 333 | clock_num.setOrigin(bounds.width * 0.5f, bounds.height * 0.85f); 334 | clock_num.setPosition(pt + v * start_mag * 0.8f); 335 | window.draw(clock_num); 336 | } 337 | 338 | //Draw the clock hands 339 | if (clock_type == ClockType::HM) { 340 | glLineWidth(4.0f); 341 | window.draw(line_array.data() + line_array.size() - 4, 2, sf::PrimitiveType::Lines); 342 | glLineWidth(5.0f); 343 | window.draw(line_array.data() + line_array.size() - 2, 2, sf::PrimitiveType::Lines); 344 | } else if (clock_type == ClockType::HMS) { 345 | glLineWidth(2.0f); 346 | window.draw(line_array.data() + line_array.size() - 6, 2, sf::PrimitiveType::Lines); 347 | glLineWidth(4.0f); 348 | window.draw(line_array.data() + line_array.size() - 4, 2, sf::PrimitiveType::Lines); 349 | glLineWidth(5.0f); 350 | window.draw(line_array.data() + line_array.size() - 2, 2, sf::PrimitiveType::Lines); 351 | } else if (clock_type == ClockType::MS) { 352 | glLineWidth(2.0f); 353 | window.draw(line_array.data() + line_array.size() - 4, 2, sf::PrimitiveType::Lines); 354 | glLineWidth(4.0f); 355 | window.draw(line_array.data() + line_array.size() - 2, 2, sf::PrimitiveType::Lines); 356 | } 357 | } 358 | 359 | //Draw UI elements 360 | clock_type_text.setString(clock_type_name[clock_type]); 361 | window.draw(clock_type_text); 362 | realtime_text.setString(realtime_name[use_realtime ? 1 : 0]); 363 | window.draw(realtime_text); 364 | tick_text.setString(tick_name[use_tick ? 1 : 0]); 365 | window.draw(tick_text); 366 | draw_branches_text.setString(draw_branches_name[draw_branches ? 1 : 0]); 367 | window.draw(draw_branches_text); 368 | draw_clock_text.setString(draw_clock_name[draw_clock ? 1 : 0]); 369 | window.draw(draw_clock_text); 370 | 371 | //Flip the screen buffer 372 | window.display(); 373 | 374 | //Toggle full-screen if needed 375 | if (toggle_fullscreen) { 376 | toggle_fullscreen = false; 377 | is_fullscreen = !is_fullscreen; 378 | if (is_fullscreen) { 379 | window.close(); 380 | screenSize = sf::VideoMode::getDesktopMode(); 381 | window.create(screenSize, "Fractal Clock", sf::Style::Fullscreen, settings); 382 | } else { 383 | window.close(); 384 | screenSize = sf::VideoMode(window_w_init, window_h_init, 24); 385 | window.create(screenSize, "Fractal Clock", sf::Style::Resize | sf::Style::Close, settings); 386 | } 387 | } 388 | } 389 | 390 | return 0; 391 | } 392 | --------------------------------------------------------------------------------