Dynamically sized (9-slice) panels
This may be interesting to someone out there. In order to create the menu panels like the inventory display in the previous post, I have (out of laziness) been creating textures of the exact size of the panel.
I then use that panel as a backdrop to display text:
It's not a ton of work, but there are two issues. The first is that I need to create a texture for every panel I plan to display. A simple menu screen may have 5 or 6 panels on it, which is not only annoying but also a maintenance nightmare. If we decide to resize one panel, I need to edit the texture, then change the code to place it differently.
The second issue is that it prohibits me from creating panels that can grow in size depending on what I'm planning on putting inside of it. I need to know the size of every panel beforehand to create its texture. I ran into this issue when trying to design a pop up panel that would tell you what items you've collected in a particular scenario. It would be nice if that panel could be small if the number of items is small, but can grow larger for a lot of items.
I could, of course, simply take a template panel like this:
and stretch it as needed to create a larger panel, like this:
But that's really ugly. The borders are different thicknesses now, as it was stretched more vertically than it was horizontally. What I really want is to make it look like this:
In order to do that, you need to do something pretty interesting. To use the previous example, you have to slice the template panel into 9 different portions, like a tic-tac-toe board:
Those 9 slices (4 corners, 4 edges, and the center) can be recombined to create a seamless composite image. The trick is that you can scale the individual slices in the process, and each one can be scaled in a different way. Here's what I mean (enlarged for visibility):
It looks a little crazy, but there is logic behind it. The arrows show which direction that slice can be scaled/stretched while preserving the desired look.
The center slice can be stretched in any direction, because it lacks any details and is just a solid color. Stretching it does not affect the way it looks at all.
The corners, on the other hand, have the most detail. If you stretch one of the corners vertically, its horizontal lines will become too thick. If you stretch it horizontally, its vertical lines will become too thick. Therefore, you can not stretch the corner slices at all.
The remaining 4 slices (the edges between the corners) are a little more interesting. Take the top edge as an example. You cannot stretch this vertically, as those lines will become too thick, just as in the corners. However, if you stretch it horizontally, it really would not affect the detail at all. That is because the pattern is comprised entirely of horizontal lines. Stretching it just makes longer versions of the same lines. The same goes for vertically stretching the side edges.
Given all of this, with very careful coding, you could create a dynamically sized panel using just a template image and a desired size. With this info, the panel will then determine how to stretch its slices to create the size you need. I was able to implement this last night. The code is a little messy, but it works! The difference between these two images is a single line of code:
Interestingly, the template image can actually be much smaller than the one I described earlier. If you were to reduce it to the absolute bare minimum, this is all you technically need to recreate the above images:
The cool thing is that you can create a panel that looks very different simply by switching your template. Using this template:
the same code produces the following panel:
I thought I invented this technique, but with more investigation, I discovered it's been around for quite some time in things such as Flash, Photoshop, and the Android SDK. It is often called 9-slice or 9-patch. I think it's extremely cool, and I'm glad I took the time to implement it!