#ifndef TRANSITION_HALFTONE_H__ #define TRANSITION_HALFTONE_H__ #include #include "ILI9341_t3.h" #include "MathUtil.h" #include "BaseTransition.h" const float HALFTONE_SPEED = 0.06f; const float HALFTONE_SLOPE = 0.5f; const int_fast8_t HALFTONE_CIRC_SIZE = 15; const uint_fast8_t HALFTONE_CIRC_SPACING = (uint_fast8_t)(HALFTONE_CIRC_SIZE * cos(M_PI/6.0f)) * 2 - 1; class TransitionHalftone : public BaseTransition { public: TransitionHalftone() : BaseTransition() {}; void init( ILI9341_t3 tft ); void restart( ILI9341_t3 tft, uint_fast16_t color ); void perFrame( ILI9341_t3 tft, FrameParams frameParams ); boolean isComplete(); private: float _phase = 0; uint_fast16_t _color; boolean _isComplete = false; }; void TransitionHalftone::init( ILI9341_t3 tft ) { } void TransitionHalftone::restart( ILI9341_t3 tft, uint_fast16_t inColor ) { //uint_fast16_t w = tft.width(); //uint_fast16_t h = tft.height(); _phase = 0; _color = inColor; _isComplete = false; } void TransitionHalftone::perFrame( ILI9341_t3 tft, FrameParams frameParams ) { uint_fast16_t w = (uint_fast16_t)tft.width(); uint_fast16_t h = (uint_fast16_t)tft.height(); uint_fast16_t w_2 = (w>>1); uint_fast16_t h_2 = (h>>1); float _prevPhase = _phase; _phase += frameParams.timeMult * HALFTONE_SPEED; boolean anySmallCircles = false; // Draw circes, offset so circles grow out from center int_fast8_t across = (w / (HALFTONE_CIRC_SPACING*cos(M_PI/6.0f))) + 1; int_fast8_t across_2 = (across>>1); int_fast8_t down = h / HALFTONE_CIRC_SPACING + 1; int_fast8_t down_2 = (down>>1)+1; for( int_fast8_t i=-across_2; i<=across_2; i++ ) { for( int_fast8_t j=-down_2; j<=down_2; j++ ) { float i_f = (float)(i); float j_f = (float)(j); if( i & 0x1 ) j_f -= 0.5f; // Stagger odd columns, so a triangular lattice is formed float distance = sqrtf( i_f*i_f + j_f*j_f ); int_fast8_t prevSize = HALFTONE_CIRC_SIZE * constrain( _prevPhase - distance*HALFTONE_SLOPE, 0.0f, 1.0f ); int_fast8_t size = HALFTONE_CIRC_SIZE * constrain( _phase - distance*HALFTONE_SLOPE, 0.0f, 1.0f ); if( size < HALFTONE_CIRC_SIZE ) anySmallCircles = true; // Only redraw circles that change size if( size > prevSize ) { int_fast16_t x = w_2 + i_f*HALFTONE_CIRC_SPACING; int_fast16_t y = h_2 + j_f*HALFTONE_CIRC_SPACING; tft.fillCircle( x, y, size, _color ); // Circle drawing issue: Circles at the top of the screen aren't filling correctly, // so just draw a box there :P if( j == -down_2 ) { tft.fillRect( max( x-size, 0 ), max( y-size, 0 ), size*2, size*2, _color ); } } } } // When all circles are full-size, the transition is done! _isComplete = !anySmallCircles; } boolean TransitionHalftone::isComplete() { return _isComplete; } #endif