Ein
Member
I have been working on a prop over the last few weeks with a working screen - specifically one of the 2.4" ILI9341s without touch. I have been using the ILI9341_t3 library thusfar and been very happy with things. Teensy 3.2 has been the perfect little brain for this device, and I've spent a bit of time figuring out how I want the layout of a few 'pages' of information on the device to display.
I'm going to use the 'start' screen on the device as an example:
The screen starts as the dark blue background color, then these graphics are drawn overtop sequentially. I draw the main outer 'border', the glow at the left and right edges, and the scan lines running across the image. Then I redraw certain areas with the background color again, to overwrite the scanlines, and add my flash memory bitmaps and other data overtop. I use a structure called 'graphic' just to help me draw the necessary background fields with padding and other things I found useful.
This is the meat of the drawing bits for that visual:
All of this works fine. When I advance to the next screen, I have been simply doing a fillScreen(); and re-drawing the background color onto the display, then drawing the next visual elements I need accordingly.
I'm now at the point where, rather than simply flip between the pages, I want to add a bit more of an elaborate visual transition. I am... not feeling particularly smart here.
Here's an example of what I would like to try for this start screen:
And here is where I start running into problems. My first thought was "just use two fill rectangles, one on the top half, one on the bottom... then redraw the image, and draw the fill rectangles again, sequentially moving them up to the top and bottom edge respectively." This is obviously not a workable solution, because the end result is something that flashes and strobes the whole screen with the full graphic and then the over-written one.
It is at this point my digging through the internet starts to suggest maybe I'm looking for some kind of frame buffer, so I can draw everything virtually and only update the changes. I have no idea how to go about doing this, and would really appreciate guidance. I looked through the "DemoSauce" example, which seemed to include screen wipes and other transitional animations, but it is a magnitude beyond what I can understand at my level of coding and there's not much in the way of commenting for me to follow to try and slog through it.
The other approach, which I'm still trying to figure out, would probably be to dim the backlight all the way off, draw the visuals onto the screen, then use the readRect() function to try and capture the screen data into single-pixel-height, full-screen-width arrays, then fillScreen() my background color back on, turn the backlight on, and use the writeRect() function to sequentially draw the graphics back onto the screen from the middle out. This feels like it would be enormously inefficient, assuming I can get it working right? And having to dim the backlight to hide it doesn't seem effective for every page transition I'd want to do.
Is there a better/simpler/smarter way to approach this that doesn't involve me totally rebuilding the UI drawing functions I've already come up with? It kinda feels like I'm looking for a way to have the 'end goal' screen data in memory work my way towards it, which sounds like the buffering approach, but I don't know how to implement that.
I'm going to use the 'start' screen on the device as an example:
The screen starts as the dark blue background color, then these graphics are drawn overtop sequentially. I draw the main outer 'border', the glow at the left and right edges, and the scan lines running across the image. Then I redraw certain areas with the background color again, to overwrite the scanlines, and add my flash memory bitmaps and other data overtop. I use a structure called 'graphic' just to help me draw the necessary background fields with padding and other things I found useful.
Code:
struct graphic{int x; int y; int w; int h; int pad;};
This is the meat of the drawing bits for that visual:
Code:
void UI::drawLAPDStartGraphics(){
// We've set up the general UI, now to draw the extras.
graphic LAPD = {0,100,184,58,7}; // Didn't set initial X position; will calculate that based on graphic width.
LAPD.x = (screenWidth-LAPD.w)/2;
graphic bgRect = {(screenWidth-LAPD.w)/2-LAPD.pad, LAPD.y-LAPD.pad, LAPD.w+LAPD.pad*2, LAPD.h+LAPD.pad*2, 0};
graphic subText = {0, bgRect.y+bgRect.h, 24, 11, 7}; // Didn't set initial X position; will calculate that based on graphic width.
subText.x = screenWidth/2-subText.w/2;
graphic vkLogo = {0,277,160,16,6}; // Didn't set initial X position; will calculate that based on graphic width.
vkLogo.x = screenWidth/2-vkLogo.w/2;
graphic vkRect = {vkLogo.x-vkLogo.pad, vkLogo.y-vkLogo.pad/2, vkLogo.w+vkLogo.pad*2, vkLogo.h+vkLogo.pad, 0};
// Draw background colors to cover scan line effect in certain areas.
tft->fillRect(bgRect.x, bgRect.y, bgRect.w, bgRect.h, BACKGROUND);
tft->fillRect(subText.x-subText.pad, subText.y-subText.pad/2, subText.w+subText.pad*2, subText.h+subText.pad, BACKGROUND); // vertical padding on this will only be half the horizontal, for aesthetics.
tft->fillRect(vkRect.x, vkRect.y, vkRect.w, vkRect.h, BACKGROUND); // vertical padding on this will only be half the horizontal, for aesthetics.
// Draw grid lines behind LAPD
drawVGridLines(bgRect.x, bgRect.y, bgRect.w, bgRect.h, 20, DARKBLUEUI);
drawHGridLines(bgRect.x, bgRect.y, bgRect.w, bgRect.h, 8, DARKBLUEUI);
// Draw grid lines behind VK Logo
drawVGridLines(vkRect.x, vkRect.y, vkRect.w, vkRect.h, 18, DARKBLUEUI);
drawHGridLines(vkRect.x, vkRect.y, vkRect.w, vkRect.h, 2, DARKBLUEUI);
// Draw all necessary images - LAPD logo, Chinese subtext, VK logo at footer
tft->drawBitmap(subText.x, subText.y+1, iconLAPDChinese, subText.w, subText.h, LIGHTBLUEUI);
tft->drawBitmap(vkLogo.x, vkLogo.y, vk_logo, vkLogo.w, vkLogo.h, LIGHTBLUEUI);
tft->drawBitmap((screenWidth-LAPD.w)/2,LAPD.y, lapdLogo, LAPD.w, LAPD.h, LIGHTBLUEUI);
}
All of this works fine. When I advance to the next screen, I have been simply doing a fillScreen(); and re-drawing the background color onto the display, then drawing the next visual elements I need accordingly.
I'm now at the point where, rather than simply flip between the pages, I want to add a bit more of an elaborate visual transition. I am... not feeling particularly smart here.
Here's an example of what I would like to try for this start screen:
And here is where I start running into problems. My first thought was "just use two fill rectangles, one on the top half, one on the bottom... then redraw the image, and draw the fill rectangles again, sequentially moving them up to the top and bottom edge respectively." This is obviously not a workable solution, because the end result is something that flashes and strobes the whole screen with the full graphic and then the over-written one.
It is at this point my digging through the internet starts to suggest maybe I'm looking for some kind of frame buffer, so I can draw everything virtually and only update the changes. I have no idea how to go about doing this, and would really appreciate guidance. I looked through the "DemoSauce" example, which seemed to include screen wipes and other transitional animations, but it is a magnitude beyond what I can understand at my level of coding and there's not much in the way of commenting for me to follow to try and slog through it.
The other approach, which I'm still trying to figure out, would probably be to dim the backlight all the way off, draw the visuals onto the screen, then use the readRect() function to try and capture the screen data into single-pixel-height, full-screen-width arrays, then fillScreen() my background color back on, turn the backlight on, and use the writeRect() function to sequentially draw the graphics back onto the screen from the middle out. This feels like it would be enormously inefficient, assuming I can get it working right? And having to dim the backlight to hide it doesn't seem effective for every page transition I'd want to do.
Is there a better/simpler/smarter way to approach this that doesn't involve me totally rebuilding the UI drawing functions I've already come up with? It kinda feels like I'm looking for a way to have the 'end goal' screen data in memory work my way towards it, which sounds like the buffering approach, but I don't know how to implement that.