I am trying to use Derelict and D to write a simple graphics test program.
When I try to do nearly anything with SDL it will seg-fault. Here is the code that is having issues:
import std.stdio;
import derelict.opengl3.gl3;
import derelict.sdl2.sdl;
import derelict.sdl2.image;
import derelict.sdl2.mixer;
import derelict.sdl2.ttf;
import derelict.sdl2.net;
void main()
{
SDL_Window* mainWindow;
SDL_GLContext mainGLContext;
try
{
DerelictGL3.load();
// Load the SDL 2 library.
DerelictSDL2.load();
.
DerelictSDL2Image.load();
DerelictSDL2Mixer.load();
DerelictSDL2ttf.load();
DerelictSDL2Net.load();
}
catch(Exception e){}
finally{}
// Initialise SDL
if( SDL_Init( SDL_INIT_EVERYTHING ) == -1 ) {
throw new Exception("SDL initialization failed");
}
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION,3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION,3);
Uint32 flags = SDL_WINDOW_SHOWN|SDL_WINDOW_OPENGL;
int width = 1024;
int height = 768;
mainWindow = SDL_CreateWindow("SDL2 OpenGL Example", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, flags);
mainGLContext = SDL_GL_CreateContext(mainWindow);
DerelictGL3.reload();
SDL_DestroyWindow(mainWindow);
SDL_Quit();
}
The issue will still occur even if everything below SDL_GL_SetAttribute() is commented out.
Additionally, derelict throws an exception when trying load SDL, but I think this is fairly common:
derelict.util.exception.SymbolLoadException#../../.dub/packages/derelict-util-2.0.4/source/derelict/util/exception.d(35): Failed to load symbol SDL_QueueAudio from shared library libSDL2.so
I am running Elementary OS and have used apt-get to ensure that SDL is up to date.
Thank you very much for your help.
This is almost certainly down to SDL versioning issues.
My recommendation is to build the whole thing from source.
It's not difficult by any means.
You can get SDL2 source here:
https://www.libsdl.org/download-2.0.php
Ensure you also get the extra projects too, i.e. sdl2 image, net, mixer and ttf.
Links for these are at:
https://www.libsdl.org/projects/
To install them, your usual
./configure
make
sudo make install
will do the trick. Do SDL2 first, then the rest in whatever order you like.
I had this problem on Debian/Fedora/Ubuntu too. It is finding SDL 1.2 instead of your SDL 2.X and failing to bind to that. You need to specify what SDL version to use. Derelict should work fine with any 2.X version of SDL. You should not have to build SDL on any big name Linux distro. Do this to fix it:
// Change this
DerelictSDL2.load();
// To this
DerelictSDL2.load(SharedLibVersion(2, 0, 2));
Related
I am new in imgui and just installed it with vcpkg and created an application in vs2022 and add these codes:
#include <imgui.h>
using namespace std;
void MySaveFunction()
{
}
int main()
{
ImGui::Text("Hello, world %d", 123);
if (ImGui::Button("Save"))
MySaveFunction();
}
but when I run this application I get this error:
What minimum code do I need to display a window with a button on it?
I searched on the IMGUI website but could not find any simple sample that works.
Dear ImGui provided some detailed examples on how to get started.
Don't be scared to read the code, which might be long and overwhelming if you are new to it.
You basically need to choose a backend, I personally prefer DirectX 11. Then you have to create a window and initialize DirectX. Then create the ImGuiContext - which throws the error for g is nullptr because the context wasn't created, and initialize the backend after that.
I'm using SDL2 in my programm.
The Gamepad is initialised using:
SDL_Joystick* Pad1 = NULL;
Pad1 = SDL_JoystickOpen( 0 );
In my Event-Handling function, i included this thing:
switch( event.type ){
//Button-Event, as an example:
case SDL_JOYBUTTONDOWN:
//printf("Button: %d", event.jbutton.button, " ");
if(event.jbutton.button==ControllP1.MoveLeftButton)
MoveLeft=true;
//lot of other cases
case SDL_JOYHATMOTION:
if(event.jhat.value==SDL_HAT_UP){MoveUp=true;MoveLeft=false; MoveRight=false; MoveDown=false;}
if(event.jhat.value==SDL_HAT_DOWN){MoveDown=true;MoveUp=false; MoveLeft=false; MoveRight=false;}
if(event.jhat.value==SDL_HAT_LEFT){MoveLeft=true; MoveDown=false; MoveUp=false; MoveRight=false;}
if(event.jhat.value==SDL_HAT_RIGHT){MoveRight=true;MoveDown=false; MoveUp=false; MoveLeft=false; }
if(event.jhat.value==SDL_HAT_CENTERED){MoveDown=false; MoveUp=false; MoveLeft=false; MoveRight=false;}
if(event.jhat.value==SDL_HAT_LEFTUP){MoveDown=false; MoveUp=true; MoveLeft=true; MoveRight=false;}
if(event.jhat.value==SDL_HAT_RIGHTUP){MoveDown=false; MoveUp=true; MoveLeft=false; MoveRight=true;}
if(event.jhat.value==SDL_HAT_RIGHTDOWN){MoveDown=true; MoveUp=false; MoveLeft=false; MoveRight=true;}
if(event.jhat.value==SDL_HAT_LEFTDOWN){MoveDown=true; MoveUp=false; MoveLeft=true; MoveRight=false;}
break;
Note that this code isn't targeting only the specified pad but should react to the input on any gamepad.
Within OpenSuse/Linux this is fine. As soon as I use the Hat on any Gamepad, it triggers the event. It however doesn't work for windows. The rest of the Code is running as intented (including the specified axis, button, etc. events) but using the Hat doesn't cause any reaction. What is the reason for this? Do i need to specifiy a gamepad when using SDL2 under Windows?
Thanks and greetings, mumbo
Edit1:
Surfing arround, I probably did find an explanation for my problem:
https://forums.libsdl.org/viewtopic.php?p=39991
I suppose that the DPAD isn't detected as an HAT but rather as an Analog-Stick under Windows when using the Joystick-API?
Edit2:
It was a bug in the SDL2.dll on the windows-machine i used for testing. Replacing the SDL2.dll with the fresh one solved the Problem, hats are responding as intended :)
Thanks for the help guys, good to know about the GameController-API.
I did update SDL2 on the target-windows-machine - and the whole thing is working as intented. Code is fine.
Thanks for the Help anyone, good to have learned about the GameController-API.
tl;dr: On windows you might be having driver problems if your device is a weird one, and you might want to use the gamecontroller API if you're targeting gamepads as it gives you a more consistent interface to use.
Mumbo: The hat got usually the form of a cross (or a circle with a cross-form ontop). You can usually find it on the left side of your gamepad
So you mean the DPAD.
First, the joystick API from SDL is a bit lower level, handling stuff like actual joysticks, steering wheels and (in your use case) gamepads indistinguishable of the device. This means the API might not be consistent across devices, for example two different gamepads might map a button to different indexes.
Although I think the joyhat might be always mapped to the DPAD in the more common devices, the other buttons might not, (triggers, x, y, a, b star, circle, etc). Come GamePadController to save the day which gives you a more consistent way to handle the controller (by giving you an Xbox 360 like gamepad and a database of mappings for several devices).
In the source tree of SDL there is a databse of controllers you can load (or is loaded by default, I didn't check), you can also check this link where I think there is another database of mappings for all kinds of controllers that you can load into your program by hand.
This example uses the GameController API instead of the JoyStick API and prints values when the DPAD is pressed. I did a test on linux only, might hop on windows later to try it out.
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <thread>
#define HEIGHT 600
#define WIDTH 800
using namespace std;
int main() {
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER);
SDL_Window *window = SDL_CreateWindow("Test", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, WIDTH, HEIGHT, SDL_WINDOW_SHOWN);
SDL_Event event;
SDL_GameController *controller = SDL_GameControllerOpen(0);
bool quit = false;
//SDL_Joystick *joy = SDL_GameControllerGetJoystick(controller);
while (!quit) {
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
quit = true;
}
if (event.type == SDL_CONTROLLERBUTTONDOWN || event.type == SDL_CONTROLLERBUTTONUP) {
SDL_ControllerButtonEvent ev = event.cbutton;
if (ev.button == SDL_CONTROLLER_BUTTON_DPAD_DOWN)
printf("SDL_DPAD_HAT_DOWN_UP\n");
if (ev.button == SDL_CONTROLLER_BUTTON_DPAD_UP)
printf("SDL_DPAD_HAT_UP_UP\n");
if (ev.button == SDL_CONTROLLER_BUTTON_DPAD_RIGHT)
printf("SDL_DPAD_HAT_RIGHT_UP\n");
if (ev.button == SDL_CONTROLLER_BUTTON_DPAD_LEFT)
printf("SDL_DPAD_HAT_LEFT_UP\n");
}
if (event.type == SDL_CONTROLLERBUTTONDOWN) { puts ("DPAD DOWN STATE"); }
}
std::this_thread::sleep_for(std::chrono::milliseconds{33});
}
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
On the other hand you might have DRIVER problems (not uncommon on windows with rando controllers) or be against a gamepad that isn't mapped yet. (I've tried on linux with a PS4 controller and it worked correctly but with a cheap knockoff of a PS2 controller it didn't).
I tried to build a program using glfw + glew on Fedora 25.
part of it is:
int main()
{
glfwInit();
glfwWindowHint(GLFW_OPENGL_PROFILE,GLFW_OPENGL_ANY_PROFILE);
//glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR,3);
//glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR,3);
mainWindow = glfwCreateWindow(1024,768,"NONE",nullptr,nullptr);
if(mainWindow == nullptr)
{
std::cout<<"Creating window ERROR.\n"<<std::endl;
glfwTerminate();
return 1;
}
.....
}
If I use glfwWindowHint(GLFW_OPENGL_PROFILE,GLFW_OPENGL_CORE_PROFILE); to get the version 3.3, it'll be unable to create window though.
My hardware supports openGL 4.1.
upd: got the answer....
Just uncomment glfwWindowHint(GLFW_CONTEXT_VERSION_*,*) there.
While using core profile with glfwWindowHint(GLFW_OPENGL_PROFILE,GLFW_OPENGL_CORE_PROFILE),
the explicit version needs to be requested.
Thanks to the comment of Dietrich Epp.
By the way, can anyone tell me how to get such information?
I am creating an application using SDL2 & OpenGL, and it worked fine on 3 different computers. But on another computer (an updated arch linux), it doesn't, and it crashes with this error:
OpenGL context already created
So my question is: How do I check if the OpenGL context has already been created? And then, if it is already created, how do I get a handle for it?
If I can't do this, how do I bypass this issue?
SDL2 does not in fact create an OpenGL context without you asking to make one. However, if you ask it to create an OpenGL context when OpenGL doesn't work at all, SDL2 likes to, erm, freestyle a bit. (The actual reason is that it does a bad job in error checking, so if X fails to create an OpenGL context, it assumes that it's because a context was already created)
So, to answer the third question ("how do I bypass this issue"), you have to fix OpenGL before attempting to use it. Figures, right?
To answer the first and second, well, no API call that I know of... but you can do it a slightly different way:
SDL_Window* window = NULL;
SDL_GLContext* context = NULL; // NOTE: This is a pointer!
...
int main(int argc, char** argv) {
// Stuff here, initialize 'window'
*context = SDL_GL_CreateContext(window);
// More stuff here
if (context) {
// context is initialized!! yay!
}
return 2; // Just to confuse people a bit =P
}
Im very new to gui programming in linux and Im stumbling at the 1st hurdle, Im using glade to design a form (i come from windows background) it looks completly different in Glade than it does when I run the compiled program.
heres a screen grab of them
see link as they wont let me post images
heres the c++
#include <gtk/gtk.h>
void close_app(GtkWidget* widget,gpointer user_data) {
gtk_main_quit();
}
int main (int argc, char **argv) {
GtkBuilder *gtkBuilder;
GtkWidget *mainwin;
gtk_set_locale();
gtk_init (&argc, &argv);
gtkBuilder= gtk_builder_new();
gtk_builder_add_from_file(gtkBuilder,"test2.glade",NULL);
gtk_builder_connect_signals ( gtkBuilder, NULL );
mainwin= GTK_WIDGET(gtk_builder_get_object(gtkBuilder,"window1"));
g_object_unref ( G_OBJECT(gtkBuilder) );
gtk_widget_show_all ( mainwin );
gtk_main ();
return 0;
}
im on debian squeeze and im using libgtk2.0-dev version 2.20 libgnome2.24 <- I dont even know if this mught be the problem?
any ideas?
Thanks
You have nothing in the empty spaces in your HBox and VBox. If there are no other widgets taking up the space, then your button will expand to fill all available space. Put some other widgets in your window if you don't want the button to fill it. Sizing and placement work differently in GTK than they do in other toolkits, the idea is to build a user interface that still looks good when the user resizes the window or when the UI strings change length because the user is using your application in another language.
See the relevant section of the GTK tutorial or this other tutorial.