I posted the following on the Card Kingdom development blog.
Another new feature for the engine this go-around is an enhanced UI. Our previous UI was built using objects and custom components for each type of widget. Buttons, text labels, sliders, and other such controls could be placed in the game interface with a few custom animations, such as sliding in and out of the frame and rollover/highlight states. These controls functioned well and were pretty simple to use and extend, but it took a lot of initial work developing the widgets that could have been used in other areas of the engine.
To replace the old UI, we looked at Scaleform; a popular game UI system that basically wraps a Flash SWF and allows it render to the screen and communicate with the game engine. Scaleform also adds some common UI widgets that can be customized and skinned to match the art style of the game. Flash itself supports a wide variety of widgets, as well as animations, font rendering and text input. Developing the UI in Flash speeds up the interface development time, since many of the features of the UI can be tested directly in Flash and animations, roll overs, etc. can be easily created. Scaleform are a great solution, but we were unable to find a student or free version for download, so we decided to make our own.
After searching around the Internet for a while, we came across a somewhat nonchalant tutorial about rendering Flash in DirectX 9. After looking over the code, it was rather straight forward they way it’s done: basically, a wrapper class around the system’s Flash and Shockwave COM Objects is made; user inputs can be somewhat simulated and sent into the wrapper to handle mouse movement and keyboard strokes; rendering is done by getting the HDC of a DirectX 9 Surface and rendering directly to that, then taking that surface and rendering it to a texture or the screen.
This tutorial was a great starting point for our system. One of the biggest initial challenges was converting the DirectX 9 rendering code to work with DirectX 11. This took quite some time and many, many Google searches. It turns out there is no easy, or at least no well documented way of getting a HDC from anything in DirectX 11. The basic way you have to do it is like this:
// creating the Texture2D Descriptor requires some specific flags and formats D3D11_TEXTURE2D_DESC textureDesc; textureDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; textureDesc.MiscFlags = D3D11_RESOURCE_MISC_GDI_COMPATIBLE;
// grabbing the HDC from a ID3D11Texture2D is as follows IDXGISurface1* pRenderSurface = NULL; HDC hDC = NULL; m_pRenderTexture->QueryInterface( __uuidof(IDXGISurface1), (void**)&pRenderSurface ); pRenderSurface->GetDC( false, &hDC ); ... // render pRenderSurface->ReleaseDC( NULL ); pRenderSurface->Release();
As of now, we can successfully render a Flash SWF to a texture and render that texture to the screen… basically. There are some alpha blending issues that need to be worked out before it will be 100%. Here is the closest render we could get to something that looks almost correct:
As you can see, Flash solves many problems with making a UI programmatically. Different non-system, non-monospaced fonts can be rendered quite easily. Text boxes, where users can enter text (the text in the center of the screen is actually one of these), can be put in the UI just by dragging it onto the Flash scene. Buttons (the control in the upper left) are just as simple to add as the circle shape in the center, which has a gradient transparency.
Once the alpha blending issues have been solved, this solution for our UI will be robust, flexible and highly customizable, reducing HUD development time to almost nothing.