Comments (12)
Hi, thanks for the report!
Interesting, looks like things changed significantly since I last checked on Arch. I got stuck already at CMake not being able to find wxgtk3
, I had to convince it by supplying an extra name for wx-config (fix commited in d8f6221). For the assertion, it seems the following patch fixes it (instead of moving SetCurrent()
to OnPaint()
):
diff --git a/src/MyApplication.cpp b/src/MyApplication.cpp
index 21d1672..05756d3 100644
--- a/src/MyApplication.cpp
+++ b/src/MyApplication.cpp
@@ -61,6 +61,7 @@ MainFrame::MainFrame(int argc, char** argv): wxFrame{nullptr, wxID_ANY, "Magnum
#endif
_wxGlContext = new wxGLContext{_wxGlCanvas};
+ Show();
_wxGlCanvas->SetCurrent(*_wxGlContext);
_glContext.create();
The GL::Context: unsupported OpenGL version (0, 0)
was just a consequence of the SetCurrent()
being moved -- _glContext
needs an active OpenGL context in order to query version and setup Magnum's GL wrapper and if it doesn't have it, it usually ends up getting all zeros for everything it queries.
However, I have zero idea what I'm doing here (not a wxWidgets user at all), so I didn't commit the above. Can you confirm that Show()
is allowed to be called in the constructor? Or do I need to attach to some wxEVT_SHOW
event and do the GL context and Magnum GLContext setup in there instead? @williamjcm, you were the original author of this code, can you advise? Thanks :)
from magnum-bootstrap.
@mosra Thanks for the fix. Calling Show
in the constructor as you did fixed it for me.
CMake couldn't find wxWidgets for me too. I fixed it by creating a symlink /usr/bin/wx-config pointing to /usr/bin/wx-config-gtk3 instead of your CMakeLists solution. wxgtk3
package only installs /usr/bin/wx-config-gtk3. I think there should be a wx-config executable on the system because there might be other projects using it.
I am an absolute beginner in wxWidgets and I chose it because it is said to provide native look. I will develop a cross platform app for Windows and Linux. I have used .Net WPF before. I didn't like Qt because it seemed too tied to the Qt Creator. Do you use any GUI framework? I appreciate it if you have any suggestion.
from magnum-bootstrap.
I think there should be a wx-config executable on the system
By looking at the FindwxWidgets
module, there's about 15 of them already, so I suppose this was only one case that wasn't added there yet. I'd rather have that patched up by the buildsystem than requiring users to create symlinks. Ideally the CMake module would be updated to recognize this name as well, but I'm too busy to open a PR on the cmake repository...
I didn't like Qt because it seemed too tied to the Qt Creator.
I was happily using Qt without QtCreator for several years in the Qt4 days, and didn't really miss any of its features for Qt development. Though I have to admit it "jumped the shark" after that, and version 5 (and now 6) seems rather bloated. (OTOH I'm a happy KDE user and wouldn't trade it for a GTK-based environment ever, the difference in overall polish and flexibility is just too huge between the two.)
Qt is bloated, GTK lacks critical features like fractional DPI scaling, .NET is, well, C#... I don't have a suggestion, sorry, it's all various levels of bad nowadays :( Depending on what you'll be doing, using ImGui might be just fine and flexible enough (and Magnum has integration for it). That one is very feature-rich although I don't personally like the default look, and the only major downside is that it's not suited for "idle" apps because it requires constant redraw in order to function properly.
from magnum-bootstrap.
Sorry for the late answer! I don't check GitHub as often as I used to. ๐
Show()
is allowed to be called in the constructor? [...] @williamjcm, you were the original author of this code, can you advise? Thanks :)
Yes, it can. In fact, in my wxWidgets/Magnum project, I do all of the context setup in the constructor for the window.
Here's what I have in that project:
_wxGlContext.emplace(_glCanvas, nullptr, &context_attributes);
#ifdef __WXGTK__
Show();
#endif
_wxGlContext->SetCurrent(*_glCanvas);
#ifdef __WXGTK__
Hide();
#endif
Since I only target Windows and Linux, I use #ifdef __WXGTK__
, but if it happens on other targets, those lines should be replaced with #ifndef __WXMSW__
.
If there are any further questions, I'll try to answer them ASAP.
from magnum-bootstrap.
Oh, so you're saying it's backend-dependent? Interesting. Are there any "good practice" docs explaining this in more detail? Like if it's a GTK quirk or something one should expect in general.
from magnum-bootstrap.
Oh, so you're saying it's backend-dependent?
In a way, yeah.
On Windows, wxWidgets will assert in the same way as on GTK when calling wxGLCanvas::SetCurrent()
when the window is hidden, but, for some reason, it doesn't when calling wxGLContext::SetCurrent()
.
Are there any "good practice" docs explaining this in more detail? Like if it's a GTK quirk or something one should expect in general.
The "good practice" on all platforms would be to only set a context as current when the canvas is shown, as the docs for wxGLCanvas::SetCurrent()
say.
While the docs also say to not call it in the constructor of the window, it worked fine during my testing of the bootstrap project. And in my main project, I do the initialisation of the context in another class that inherits from the window's class, so the window itself is technically ready by that point.
It's... a bit of a mess, I admit.
from magnum-bootstrap.
Hi, I just try the base-wxwidgets project under Code::Blocks (I'm using msys2's prebuild magnum library, and msys2's wx 3.1.5 library)
The pure base-wxwidgets works OK without any issue. See the image show below:
But if I try to add some member variables in the MainFrame class, I got crashed.
Here is the code:
#include <Magnum/GL/DefaultFramebuffer.h>
#include <Magnum/Platform/GLContext.h>
#include <Magnum/GL/Buffer.h>
#include <Magnum/GL/DefaultFramebuffer.h>
#include <Magnum/GL/Mesh.h>
#include <Magnum/Math/Color.h>
#include <Magnum/Shaders/VertexColor.h>
#include <wx/app.h>
#include <wx/frame.h>
#include <wx/glcanvas.h>
#include <wx/sizer.h>
#include <wx/version.h>
using namespace Magnum;
class MyApplication: public wxApp {
public:
bool OnInit();
};
class MainFrame: public wxFrame {
public:
explicit MainFrame(int argc, char** argv);
~MainFrame();
private:
void OnPaint(wxPaintEvent& event);
wxGLCanvas* _wxGlCanvas;
wxGLContext* _wxGlContext;
Platform::GLContext _glContext;
#if 1
//GL::Mesh _mesh;
//Shaders::VertexColor2D _shader;
#endif // 0
};
wxIMPLEMENT_APP(MyApplication);
bool MyApplication::OnInit() {
MainFrame *frame = new MainFrame{argc, argv};
frame->Show(true);
return true;
}
MainFrame::MainFrame(int argc, char** argv)
: wxFrame{nullptr, wxID_ANY, "Magnum wxWidgets Application"},
_glContext{NoCreate, argc, argv}
{
wxBoxSizer* bSizer;
bSizer = new wxBoxSizer{wxVERTICAL};
#if (wxMAJOR_VERSION == 3) && (wxMINOR_VERSION >= 1)
wxGLAttributes attributes;
attributes.PlatformDefaults()
.BufferSize(24)
.MinRGBA(8, 8, 8, 0)
.Depth(24)
.Stencil(0)
.DoubleBuffer()
.EndList();
_wxGlCanvas = new wxGLCanvas{this, attributes, wxID_ANY, wxDefaultPosition, wxSize{800, 600}};
#elif (wxMAJOR_VERSION == 3) && (wxMINOR_VERSION == 0)
int attributes[] = { WX_GL_RGBA,
WX_GL_DOUBLEBUFFER,
WX_GL_DEPTH_SIZE, 24,
WX_GL_STENCIL_SIZE, 0,
0 };
_wxGlCanvas = new wxGLCanvas{this, wxID_ANY, &attributes[0], wxDefaultPosition, wxSize{800, 600}};
#else
#error You need wxWidgets version 3.0 or later.
#endif
_wxGlContext = new wxGLContext{_wxGlCanvas};
_wxGlCanvas->SetCurrent(*_wxGlContext);
_glContext.create();
bSizer->Add(_wxGlCanvas, 1, wxALL|wxEXPAND, 5);
SetSizer(bSizer);
Layout();
bSizer->Fit(this);
Centre(wxBOTH);
_wxGlCanvas->Connect(wxEVT_PAINT, wxPaintEventHandler(MainFrame::OnPaint), nullptr, this);
/* TODO: Add your initialization code here */
#if 0
// https://doc.magnum.graphics/magnum/triangle_2TriangleExample_8cpp-example.html
using namespace Math::Literals;
struct TriangleVertex {
Vector2 position;
Color3 color;
};
const TriangleVertex data[]{
{{-0.5f, -0.5f}, 0xff0000_rgbf}, /* Left vertex, red color */
{{ 0.5f, -0.5f}, 0x00ff00_rgbf}, /* Right vertex, green color */
{{ 0.0f, 0.5f}, 0x0000ff_rgbf} /* Top vertex, blue color */
};
GL::Buffer buffer;
buffer.setData(data);
_mesh.setCount(3)
.addVertexBuffer(std::move(buffer), 0,
Shaders::VertexColor2D::Position{},
Shaders::VertexColor2D::Color3{});
#endif // 0
}
MainFrame::~MainFrame() {
_wxGlCanvas->Disconnect(wxEVT_PAINT, wxPaintEventHandler(MainFrame::OnPaint), nullptr, this);
}
void MainFrame::OnPaint(wxPaintEvent& event) {
GL::defaultFramebuffer.clear(GL::FramebufferClear::Color);
/* TODO: Add your drawing code here */
#if 0
_shader.draw(_mesh);
#endif // 0
_wxGlCanvas->SwapBuffers();
}
Note that there are two member variables
GL::Mesh _mesh;
Shaders::VertexColor2D _shader;
If you umcomment either one of them, or all of them, I got crash on the construction of the MainFrame.
The crash just open a message below:
Note that I'm using the msys2's prebuild version, which is: mingw64/mingw-w64-x86_64-magnum 2020.06-1
and mingw64/mingw-w64-x86_64-wxmsw3.1 3.1.5-3
Any ideas how to solve this issue? Thanks.
from magnum-bootstrap.
Some extra information, if I enable the console window, I see when it crashed, some message was shown in the console, see below image show:
GL::Context::current(): no current context
So, when the member variable get initialized, they need an active context?
from magnum-bootstrap.
By searching the error message, I got this:
Context::current(): no current context ยท Issue #167 ยท mosra/magnum
As the internal context is created by the NoCreate
parameter.
_glContext{NoCreate, argc, argv}
How can we create a mesh and shader object if the _glContext
is not created yet?
from magnum-bootstrap.
I solved this issue by a hack that I just create a function to initialize the _glContext
member variable before the other shader and mesh members, see the full code below and screen shot.
#include <Magnum/GL/DefaultFramebuffer.h>
#include <Magnum/Platform/GLContext.h>
#include <Magnum/GL/Buffer.h>
#include <Magnum/GL/DefaultFramebuffer.h>
#include <Magnum/GL/Mesh.h>
#include <Magnum/Math/Color.h>
#include <Magnum/Shaders/VertexColor.h>
#include <wx/app.h>
#include <wx/frame.h>
#include <wx/glcanvas.h>
#include <wx/sizer.h>
#include <wx/version.h>
using namespace Magnum;
class MyApplication: public wxApp {
public:
bool OnInit();
};
class MainFrame: public wxFrame {
public:
explicit MainFrame(int argc, char** argv);
~MainFrame();
private:
void OnPaint(wxPaintEvent& event);
void InitContext();
wxGLCanvas* _wxGlCanvas;
wxGLContext* _wxGlContext;
Platform::GLContext _glContext;
int m_a;
#if 1
GL::Mesh _mesh;
Shaders::VertexColor2D _shader;
#endif // 0
};
wxIMPLEMENT_APP(MyApplication);
void CreateConsole()
{
if (!AllocConsole()) {
// Add some error handling here.
// You can call GetLastError() to get more info about the error.
return;
}
// std::cout, std::clog, std::cerr, std::cin
FILE* fDummy;
freopen_s(&fDummy, "CONOUT$", "w", stdout);
freopen_s(&fDummy, "CONOUT$", "w", stderr);
freopen_s(&fDummy, "CONIN$", "r", stdin);
std::cout.clear();
std::clog.clear();
std::cerr.clear();
std::cin.clear();
// std::wcout, std::wclog, std::wcerr, std::wcin
HANDLE hConOut = CreateFile(_T("CONOUT$"), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
HANDLE hConIn = CreateFile(_T("CONIN$"), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
SetStdHandle(STD_OUTPUT_HANDLE, hConOut);
SetStdHandle(STD_ERROR_HANDLE, hConOut);
SetStdHandle(STD_INPUT_HANDLE, hConIn);
std::wcout.clear();
std::wclog.clear();
std::wcerr.clear();
std::wcin.clear();
}
bool MyApplication::OnInit() {
CreateConsole();
MainFrame *frame = new MainFrame{argc, argv};
frame->Show(true);
return true;
}
MainFrame::MainFrame(int argc, char** argv)
: wxFrame{nullptr, wxID_ANY, "Magnum wxWidgets Application"},
_glContext{NoCreate, argc, argv},
m_a{(InitContext(),0)}
{
wxBoxSizer* bSizer;
bSizer = new wxBoxSizer{wxVERTICAL};
bSizer->Add(_wxGlCanvas, 1, wxALL|wxEXPAND, 5);
SetSizer(bSizer);
Layout();
bSizer->Fit(this);
Centre(wxBOTH);
_wxGlCanvas->Connect(wxEVT_PAINT, wxPaintEventHandler(MainFrame::OnPaint), nullptr, this);
/* TODO: Add your initialization code here */
#if 1
// https://doc.magnum.graphics/magnum/triangle_2TriangleExample_8cpp-example.html
using namespace Math::Literals;
struct TriangleVertex {
Vector2 position;
Color3 color;
};
const TriangleVertex data[]{
{{-0.5f, -0.5f}, 0xff0000_rgbf}, /* Left vertex, red color */
{{ 0.5f, -0.5f}, 0x00ff00_rgbf}, /* Right vertex, green color */
{{ 0.0f, 0.5f}, 0x0000ff_rgbf} /* Top vertex, blue color */
};
GL::Buffer buffer;
buffer.setData(data);
_mesh.setCount(3)
.addVertexBuffer(std::move(buffer), 0,
Shaders::VertexColor2D::Position{},
Shaders::VertexColor2D::Color3{});
#endif // 0
}
void MainFrame::InitContext()
{
#if (wxMAJOR_VERSION == 3) && (wxMINOR_VERSION >= 1)
wxGLAttributes attributes;
attributes.PlatformDefaults()
.BufferSize(24)
.MinRGBA(8, 8, 8, 0)
.Depth(24)
.Stencil(0)
.DoubleBuffer()
.EndList();
_wxGlCanvas = new wxGLCanvas{this, attributes, wxID_ANY, wxDefaultPosition, wxSize{800, 600}};
#elif (wxMAJOR_VERSION == 3) && (wxMINOR_VERSION == 0)
int attributes[] = { WX_GL_RGBA,
WX_GL_DOUBLEBUFFER,
WX_GL_DEPTH_SIZE, 24,
WX_GL_STENCIL_SIZE, 0,
0 };
_wxGlCanvas = new wxGLCanvas{this, wxID_ANY, &attributes[0], wxDefaultPosition, wxSize{800, 600}};
#else
#error You need wxWidgets version 3.0 or later.
#endif
_wxGlContext = new wxGLContext{_wxGlCanvas};
_wxGlCanvas->SetCurrent(*_wxGlContext);
_glContext.create();
}
MainFrame::~MainFrame() {
_wxGlCanvas->Disconnect(wxEVT_PAINT, wxPaintEventHandler(MainFrame::OnPaint), nullptr, this);
}
void MainFrame::OnPaint(wxPaintEvent& event) {
GL::defaultFramebuffer.clear(GL::FramebufferClear::Color);
/* TODO: Add your drawing code here */
#if 1
_shader.draw(_mesh);
#endif // 0
_wxGlCanvas->SwapBuffers();
}
It is dirty, because I have to use the method mentioned here:
constructor - C++ - Run a function before initializing a class member - Stack Overflow
Now, the next step is I just try to see if I can add the mouse event handling, so I can tweak the camera (to rotate, scale the scene)
from magnum-bootstrap.
@asmwarrior delayed context creation is a rather common workflow, the solution is using the NoCreate
constructors for GL objects as well:
GL::Mesh _mesh{NoCreate};
Shaders::VertexColor2D _shader{NoCreate};
and then, once you have the context created, populating them with proper live instances:
_glContext.create();
// Now it's safe to call into GL
_mesh = GL::Mesh{};
_shader = Shaders::VertexColor2D{};
I realized the documentation for this workflow was rather nonexistent (sorry about that), so I mentioned this in the OpenGL wrapper overview and a few other places (mosra/magnum@2bd933d).
from magnum-bootstrap.
Hi, @mosra , many thanks!
The document: in the OpenGL wrapper overview is so nice, especially for the beginners.
from magnum-bootstrap.
Related Issues (20)
- Linker Error (SDL2) HOT 1
- Not installing `.wasm` HOT 1
- Build Output Directories HOT 3
- Building woes HOT 23
- vcpkg doesn't play well with FindXYZ modules HOT 4
- FrameBuffer::clearColor not working HOT 6
- Unable to build on VS2019 HOT 4
- Help understanding bootstrap emscripten js error HOT 6
- Android Gradle build HOT 7
- base-Qt reports wrong OpenGL Version HOT 9
- ANDROID_SDK variable has wrong path on Windows. HOT 2
- magnum + wxWidgets sample projects, mouse drag can rotate the camera, but not as expected HOT 1
- Building Issue - The fully qualified file name must be less than 260 characters HOT 1
- Add bootstrap example using FLTK HOT 2
- Linking issue with scenegraph3D bootstrap project HOT 1
- Separate declarations from implementations HOT 1
- Cross platform bootstrap? HOT 18
- Getting started tutorial issue - can't find SDL2 HOT 3
- Segment fault using Getting Started Guide on Ubuntu 16.06 HOT 4
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. ๐๐๐
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google โค๏ธ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from magnum-bootstrap.