M
Da ich mittlerweile einen Großteil der Layout Engine fertig habe, kann ich ja mal ein Beispiel mit selbiger bringen:
Nutzung der Layout-Engine als DOM mit SDL2:
#include <map>
#include <stdio.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <solid/layout/widget.hpp>
#include <solid/layout/layoutmarkup.hpp>
using namespace solid;
using namespace solid::markup;
using namespace solid::layout;
SDL_Window *window;
SDL_Renderer *renderer;
// Texture caching and loading
std::map<std::string, std::shared_ptr<SDL_Texture>> cache;
std::shared_ptr<SDL_Texture> texture(const std::string &fileName)
{
if(::cache.count(fileName) == 0) {
SDL_Texture *tex = IMG_LoadTexture(::renderer, fileName.c_str());
std::shared_ptr<SDL_Texture> ptr(tex, [](SDL_Texture*texture) {
SDL_DestroyTexture(texture);
});
::cache.insert({fileName,ptr});
}
return ::cache.at(fileName);
}
void exit_sdl(int error = 1)
{
printf("SDL_GetError() => '%s'\n", SDL_GetError());
exit(error);
}
// Recursive draw routine
void paint(Widget *widget)
{
if(widget == nullptr) {
return;
}
SDL_Rect target;
target.x = widget->position().x;
target.y = widget->position().y;
target.w = widget->size().x;
target.h = widget->size().y;
// Paint all widgets with images.
if(widget->hasAttribute("image")) {
SDL_RenderCopy(::renderer, texture(widget->attribute("image").value()).get(), nullptr, &target);
}
for(Widget *w : widget->children<Widget>())
{
::paint(w);
}
}
int main(int, char*[])
{
if(SDL_Init(SDL_INIT_EVERYTHING) < 0) {
exit_sdl();
}
atexit(SDL_Quit);
if(IMG_Init(IMG_INIT_PNG | IMG_INIT_JPG) == 0) {
exit_sdl();
}
atexit(IMG_Quit);
if(SDL_CreateWindowAndRenderer(1280, 720, SDL_WINDOW_SHOWN, &::window, &::renderer) < 0) {
exit_sdl();
}
// Register classes and load markup
LayoutMarkup markup;
markup.registerWidgetClass<Widget>("Widget");
std::unique_ptr<Layout> layout = markup.load("demo.sll");
while(true)
{
SDL_Event e;
if(SDL_PollEvent(&e))
{
switch(e.type)
{
case SDL_QUIT:
goto quit;
case SDL_KEYDOWN:
{
switch(e.key.keysym.sym)
{
case SDLK_ESCAPE:
goto quit;
}
break;
}
}
}
// Layout UI
{
Size size;
SDL_GetWindowSize(::window, &size.x, &size.y);
layout->layout(size);
}
// Render UI
{
SDL_RenderClear(::renderer);
::paint(&layout->root<Widget>());
SDL_RenderPresent(::renderer);
}
SDL_Delay(16);
}
quit:
return 0;
}
Widget(image="fractale-06-scenery-antenna.jpg")
{
Widget(image="crosshair.png",verticalAlignment=center,horizontalAlignment=center,size="96;96");
Widget(image="minimap.png",verticalAlignment=top,horizontalAlignment=right,size="200;200");
StackLayout(size="auto;auto",verticalAlignment=bottom,horizontalAlignment=left,orientation=vertical)
{
Widget(image="endurance.png", size="200;64");
Widget(image="healthbar.png", size="200;64");
}
}
Das Ergebnis:
http://i.imgur.com/Lc0cif9.jpg (Gibt es keine Image-Tags?)
Mit dem Script von oben lassen sich beliebige Layouts erschaffen, wenn man jetzt noch eine eigene Widget-Klasse erstellt, welche das Image-Attribute bereitstellt, kann man sogar die Größen direkt aus dem Bild übernehmen, wenn als Wert "auto" geliefert wird.
Grüße
Felix