Bert
Bert

Reputation: 153

SLD2: strange rendering error on OS X using SDL2_gfx and AntTweakBar

I am trying to render 3 things:

Each of those works fine by its own, but combining them somehow breaks the AntTweakBar, depending on the combination:

  1. Only AntTweakBar: renders everything fine works fine without circle and texture
  2. AntTweakBar + Texture: everything but the text disappeared in the TestBar. The mouse is in the same position as before, but 'width' is not highlighted and all "icons" are missing. Somehow, the 'Help & Shortcuts'-bars background survived. Removing the texture again won't change anything. Adding the circle will lead to case 3 but fuck this
  3. AntTweakBar + Circle (+Texture):everything but the text gets rendered and the text turned into boxes. Adding the texture or removing the circle again won't change anything, but removing the circle first and then adding the texture will lead to case 2. and that

Here is the (messy) source code for this test application. res_path.h and cleanup.h can be found here and here (but should not matter).

#include <iostream>
#include <SDL2/SDL.h>
#include "res_path.h"
#include "cleanup.h"
#include "SDL2/SDL2_gfxPrimitives.h"
#include <AntTweakBar.h>

const int SCREEN_WIDTH  = 640;
const int SCREEN_HEIGHT = 480;

bool quit = false;
bool tex = false;
bool circ = false;

//-----------------------------------------------------------------------

/**
 * Log an SDL error with some error message to the output stream of our choice
 * @param os The output stream to write the message to
 * @param msg The error message to write, format will be msg error: SDL_GetError()
 */
void logSDLError(std::ostream &os, const std::string &msg)
{
    os << msg << " error: " << SDL_GetError() << std::endl;
}

/**
 * Loads a BMP image into a texture on the rendering device
 * @param file The BMP image file to load
 * @param ren The renderer to load the texture onto
 * @return the loaded texture, or nullptr if something went wrong.
 */
SDL_Texture* loadTexture(const std::string &file, SDL_Renderer *ren)
{
    //Initialize to nullptr to avoid dangling pointer issues
    SDL_Texture *texture = nullptr;
    //Load the image
    SDL_Surface *loadedImage = SDL_LoadBMP(file.c_str());
    //If the loading went ok, convert to texture and return the texture
    if (loadedImage != nullptr){
        texture = SDL_CreateTextureFromSurface(ren, loadedImage);
        SDL_FreeSurface(loadedImage);
        //Make sure converting went ok too
        if (texture == nullptr){
            logSDLError(std::cout, "CreateTextureFromSurface");
        }
    }
    else {
        logSDLError(std::cout, "LoadBMP");
    }
    return texture;
}


/**
 * Draw an SDL_Texture to an SDL_Renderer at position x, y, preserving
 * the texture's width and height
 * @param tex The source texture we want to draw
 * @param ren The renderer we want to draw to
 * @param x The x coordinate to draw to
 * @param y The y coordinate to draw to
 */
void renderTexture(SDL_Texture *tex, SDL_Renderer *ren, int x, int y)
{
    //Setup the destination rectangle to be at the position we want
    SDL_Rect dst;
    dst.x = x;
    dst.y = y;
    //Query the texture to get its width and height to use
    SDL_QueryTexture(tex, NULL, NULL, &dst.w, &dst.h);
    SDL_RenderCopy(ren, tex, NULL, &dst);
}

void TW_CALL RunCA(void * /*clientData*/)
{
    std::cout << "button 1 clicked" << std::endl;
    tex = !tex;
}
void TW_CALL RunCB(void * /*clientData*/)
{
    std::cout << "button 2 clicked" << std::endl;
    circ = !circ;
}

//---------------------------------------

int main()
{

    int size=10;
    int alpha=100;

    std::cout << "Resource path is: " << getResourcePath() << std::endl;

    if (SDL_Init(SDL_INIT_EVERYTHING) != 0){
        logSDLError(std::cout, "SDL_Init");
        return 1;
    }

    SDL_Window *window = SDL_CreateWindow("Lesson 2", SDL_WINDOWPOS_CENTERED,
        SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH,SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
    if (window == nullptr){
        logSDLError(std::cout, "CreateWindow");
        SDL_Quit();
        return 1;
    }
    SDL_Renderer *renderer = SDL_CreateRenderer(window, -1,
            SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE);
    if (renderer == nullptr){
        logSDLError(std::cout, "CreateRenderer");
        cleanup(window);
        SDL_Quit();
        return 1;
    }


    const std::string resPath = getResourcePath();
    SDL_Texture *image = loadTexture(resPath + "image.bmp", renderer);
    if (image == nullptr){
        cleanup(image, renderer, window);
        SDL_Quit();
        return 1;
    }


    TwInit(TW_OPENGL, NULL);
    TwWindowSize(SCREEN_WIDTH, SCREEN_HEIGHT);

    TwBar *myBar;
    myBar = TwNewBar("TestBar");
    TwDefine(" GLOBAL help='example help' "); // Message added to the help bar.

    TwAddButton(myBar, "Switch Texture", RunCA, NULL, " label='texture' ");
    TwAddButton(myBar, "Switch Circle", RunCB, NULL, " label='circle' ");

    TwAddVarRW(myBar, "width", TW_TYPE_INT32, &size, " keyIncr=w, keyDecr=s ");
    TwAddVarRW(myBar, "alpha", TW_TYPE_INT32, &alpha, " ");
    // Add 'quit' to 'bar': this is a modifiable (RW) variable of type TW_TYPE_BOOL32
    // (a boolean stored in a 32 bits integer). Its shortcut is [ESC].
    TwAddVarRW(myBar, "Quit", TW_TYPE_BOOL32, &quit,
        " label='Quit?' true='+' false='-' key='ESC' help='Quit program.' ");

    // main loop
    while( !quit )
    {
        SDL_Event event;
        int handled=1;

        SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
        SDL_RenderClear(renderer);

        if(tex)
        renderTexture(image, renderer, 50, 50);

        if(circ)
        filledCircleRGBA(renderer,
                100, 100,
                size,
                0, 255, 0, alpha);


        TwDraw();  // draw the tweak bar(s)


        SDL_RenderPresent(renderer);

        while(SDL_PollEvent(&event))
        {
            handled = TwEventSDL(&event, SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
            if( !handled )
            {
                //If user closes the window
                if (event.type == SDL_QUIT){
                    std::cout << "window closed" << std::endl;
                    quit = true;
                }
                //If user presses any key
                if (event.type == SDL_KEYDOWN){
                    std::cout << "key down" << std::endl;
                }
                //If user clicks the mouse
                if (event.type == SDL_MOUSEBUTTONDOWN){
                    std::cout << "mouse clicked" << std::endl;
                }
            }    
        }

    //      SDL_Delay(10);


    } // end of main loop


//cleanup
cleanup(image, renderer, window);
// Terminate AntTweakBar
TwTerminate();
SDL_Quit();
return 0;
}

Does anybody know what is going on and how this could be fixed or avoided? If not, maybe somebody could recommend a different approach for rendering simple geometric shapes and a GUI (to configure some parameters) in SDL2/C++ without too much effort.

Upvotes: 0

Views: 313

Answers (1)

Bert
Bert

Reputation: 153

I got around it by changing my development environment from OSX (10.11.1) to Linux (Ubuntu 14.04-3). Of course this is no "REAL" solution, but maybe this information can still help somebody.

Upvotes: 0

Related Questions