Make Qt editor work with the SDL engine

Viewport rendering doesn't quite work yet, though.
qteditor
Lukas Werling 2016-03-20 20:43:37 +01:00
parent e1eb62a552
commit 75f62e52f2
13 changed files with 219 additions and 23 deletions

View File

@ -919,6 +919,27 @@ elseif(USE_SDL_MAINLOOP)
src/platform/C4AppSDL.cpp
src/platform/C4WindowSDL.cpp
)
# TODO: Remove duplication
if(WITH_QT_EDITOR)
qt5_add_resources(qt_editor_resources "src/editor/resource.qrc")
list(APPEND OC_GUI_SOURCES
src/editor/C4ConsoleQt.cpp
src/editor/C4ConsoleQt.h
src/editor/C4ConsoleQtState.cpp
src/editor/C4ConsoleQtState.h
src/editor/C4ConsoleQtPropListViewer.cpp
src/editor/C4ConsoleQtPropListViewer.h
src/editor/C4ConsoleQtObjectListViewer.cpp
src/editor/C4ConsoleQtObjectListViewer.h
src/editor/C4ConsoleQtDefinitionListViewer.cpp
src/editor/C4ConsoleQtDefinitionListViewer.h
src/editor/C4ConsoleQtViewport.cpp
src/editor/C4ConsoleQtViewport.h
src/editor/C4ConsoleQtMainWindow.ui
src/editor/resource.qrc
${qt_editor_resources}
)
endif()
elseif(USE_WIN32_WINDOWS)
if(WITH_QT_EDITOR)
qt5_add_resources(qt_editor_resources "src/editor/resource.qrc")

View File

@ -561,7 +561,7 @@ void C4Console::RegisterRecentInput(const char *input, RecentScriptInputLists se
mru.erase(mru.begin());
}
#if !(defined(USE_WIN32_WINDOWS) || defined(USE_COCOA) || defined(USE_GTK))
#if !(defined(USE_WIN32_WINDOWS) || defined(USE_COCOA) || defined(USE_GTK) || defined(WITH_QT_EDITOR))
class C4ConsoleGUI::State: public C4ConsoleGUI::InternalState<class C4ConsoleGUI>
{
public: State(C4ConsoleGUI *console): Super(console) {}

View File

@ -95,7 +95,7 @@ C4Window* C4ConsoleGUI::CreateConsoleWindow(C4AbstractApp *application)
hWindow = reinterpret_cast<HWND>(state->window->winId());
renderwnd = hWindow;
#else
TODO
// nothing to do
#endif
Active = true;
EnableControls(fGameOpen);

View File

@ -391,6 +391,22 @@ bool C4ConsoleGUIState::CreateConsoleWindow(C4AbstractApp *app)
{
// No Qt main loop execution during console creation
ExecRecursionCheck no_qt_recursion;
// Initialize OpenGL.
QSurfaceFormat format;
format.setMajorVersion(/*REQUESTED_GL_CTX_MAJOR*/ 3);
format.setMinorVersion(/*REQUESTED_GL_CTX_MINOR*/ 2);
format.setRedBufferSize(8);
format.setGreenBufferSize(8);
format.setBlueBufferSize(8);
format.setDepthBufferSize(8);
format.setProfile(QSurfaceFormat::CoreProfile);
if (Config.Graphics.DebugOpenGL)
format.setOption(QSurfaceFormat::DebugContext);
QSurfaceFormat::setDefaultFormat(format);
QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
// Basic Qt+Main window setup from .ui file
int fake_argc = 0;
application.reset(new QApplication(fake_argc, NULL));

View File

@ -28,21 +28,23 @@
/* Console viewports */
C4ConsoleQtViewportView::C4ConsoleQtViewportView(class C4ConsoleQtViewportDockWidget *dock)
: QWidget(dock), dock(dock), cvp(dock->cvp ? dock->cvp->cvp : NULL)
: QOpenGLWidget(dock), dock(dock), cvp(dock->cvp ? dock->cvp->cvp : NULL)
{
setAutoFillBackground(false);
setAttribute(Qt::WA_NoSystemBackground, true);
setAttribute(Qt::WA_PaintOnScreen, true);
#ifdef USE_WIN32_WINDOWS
setAttribute(Qt::WA_NativeWindow, true);
#endif
setAttribute(Qt::WA_ShowWithoutActivating, true);
setWindowFlags(Qt::FramelessWindowHint);
setFocusPolicy(Qt::WheelFocus);
setMouseTracking(true);
// Register for viewport
C4ViewportWindow *window = dock->cvp;
#ifdef USE_WIN32_WINDOWS
dock->cvp->hWindow = reinterpret_cast<HWND>(this->winId());
window->hWindow = reinterpret_cast<HWND>(this->winId());
#else
TODO
window->glwidget = this;
#endif
}
@ -52,12 +54,6 @@ bool C4ConsoleQtViewportView::IsPlayViewport() const
&& (::Console.EditCursor.GetMode() == C4CNS_ModePlay));
}
void C4ConsoleQtViewportView::resizeEvent(QResizeEvent *resize_event)
{
QWidget::resizeEvent(resize_event);
if (cvp) dock->cvp->cvp->UpdateOutputSize(resize_event->size().width(), resize_event->size().height());
}
bool C4ConsoleQtViewportView::nativeEvent(const QByteArray &eventType, void *message, long *result)
{
// Handle native Windows messages
@ -234,7 +230,7 @@ static C4KeyCode QtKeyToUnixScancode(const QKeyEvent &event)
case Qt::Key_Down: return K_DOWN;
case Qt::Key_Left: return K_LEFT;
case Qt::Key_Right: return K_RIGHT;
case Qt::Key_Clear: return K_CENTER;
/* case Qt::Key_Clear: return K_CENTER; */
case Qt::Key_Insert: return K_INSERT;
case Qt::Key_Delete: return K_DELETE;
case Qt::Key_Menu: return K_MENU;
@ -311,6 +307,19 @@ void C4ConsoleQtViewportView::leaveEvent(QEvent *)
::Console.EditCursor.SetMouseHover(false);
}
void C4ConsoleQtViewportView::initializeGL() { }
void C4ConsoleQtViewportView::resizeGL(int w, int h)
{
cvp->UpdateOutputSize(w, h);
}
void C4ConsoleQtViewportView::paintGL()
{
// Painting is done regularily elsewhere anyways.
/* cvp->Execute(); */
}
C4ConsoleQtViewportLabel::C4ConsoleQtViewportLabel(const QString &title, C4ConsoleQtViewportDockWidget *dock)
: QLabel(dock), dock(dock)

View File

@ -24,7 +24,7 @@
#include <C4ConsoleGUI.h> // for glew.h
#include <C4ConsoleQt.h>
class C4ConsoleQtViewportView : public QWidget
class C4ConsoleQtViewportView : public QOpenGLWidget
{
Q_OBJECT
@ -37,7 +37,6 @@ private:
protected:
void focusInEvent(QFocusEvent * event) override;
void focusOutEvent(QFocusEvent * event) override;
void resizeEvent(QResizeEvent *resize_event) override;
bool nativeEvent(const QByteArray &eventType, void *message, long *result) override;
void mouseMoveEvent(QMouseEvent *eventMove) override;
void mousePressEvent(QMouseEvent *eventPress) override;
@ -51,6 +50,11 @@ protected:
public:
C4ConsoleQtViewportView(class C4ConsoleQtViewportDockWidget *dock);
// QOpenGLWidget functions
void initializeGL() override;
void resizeGL(int w, int h) override;
void paintGL() override;
};
class C4ConsoleQtViewportLabel : public QLabel

View File

@ -162,6 +162,12 @@ bool C4Viewport::ViewPositionByScrollBars()
#endif // USE_GTK
#if (defined(USE_SDL_MAINLOOP) && defined(WITH_QT_EDITOR))
// TODO
bool C4Viewport::ScrollBarsByViewPosition() {return 0;}
bool C4Viewport::TogglePlayerLock() {return 0;}
#endif
void C4ViewportWindow::PerformUpdate()
{
if (cvp)

View File

@ -66,6 +66,9 @@ bool C4Viewport::UpdateOutputSize(int32_t new_width, int32_t new_height)
rect.y = allocation.y;
rect.Wdt = allocation.width;
rect.Hgt = allocation.height;
#elif defined(WITH_QT_EDITOR)
// Never query the window - size is always passed from Qt.
return false;
#else
if (!pWindow->GetSize(&rect)) return false;
#endif

View File

@ -24,7 +24,7 @@
#include <C4FoWRegion.h>
#include "C4Rect.h"
#include "C4Config.h"
#include <C4App.h>
#include <C4Application.h>
#ifndef USE_CONSOLE
@ -288,7 +288,14 @@ CStdGLCtx *CStdGL::CreateContext(C4Window * pWindow, C4AbstractApp *pApp)
if (!pWindow) return NULL;
// create it
CStdGLCtx *pCtx = new CStdGLCtx();
CStdGLCtx *pCtx;
#ifdef WITH_QT_EDITOR
auto app = dynamic_cast<C4Application*>(pApp);
if (app->isEditor)
pCtx = new CStdGLCtxQt();
else
#endif
pCtx = new CStdGLCtx();
bool first_ctx = !pMainCtx;
if (first_ctx)
{

View File

@ -105,19 +105,19 @@ class CStdGLCtx
{
public:
CStdGLCtx(); // ctor
~CStdGLCtx() { Clear(); } // dtor
virtual ~CStdGLCtx() { Clear(); } // dtor
void Clear(bool multisample_change = false); // clear objects
virtual void Clear(bool multisample_change = false); // clear objects
#ifdef USE_WGL
std::vector<int> EnumerateMultiSamples() const;
#endif
bool Init(C4Window * pWindow, C4AbstractApp *pApp);
virtual bool Init(C4Window * pWindow, C4AbstractApp *pApp);
bool Select(bool verbose = false); // select this context
void Deselect(); // select this context
virtual bool Select(bool verbose = false); // select this context
virtual void Deselect(); // select this context
bool PageFlip(); // present scene
virtual bool PageFlip(); // present scene
protected:
void SelectCommon();
@ -144,6 +144,26 @@ protected:
friend class C4Surface;
};
#ifdef WITH_QT_EDITOR
// OpenGL context with Qt as backend. Implemented as subclass to allow co-existance with a different backend for fullscreen.
class CStdGLCtxQt : public CStdGLCtx
{
public:
CStdGLCtxQt();
//~CStdGLCtxQt();
void Clear(bool multisample_change = false) override; // clear objects
bool Init(C4Window * pWindow, C4AbstractApp *pApp) override;
bool Select(bool verbose = false) override; // select this context
void Deselect() override; // select this context
bool PageFlip() override; // present scene
private:
class QOpenGLContext *context = nullptr;
class QOffscreenSurface *surface = nullptr;
};
#endif
// OpenGL encapsulation
class CStdGL : public C4Draw
{
@ -272,6 +292,9 @@ protected:
friend class C4Window;
friend class C4ShaderCall;
friend class C4FoWRegion;
#ifdef WITH_QT_EDITOR
friend class CStdGLCtxQt;
#endif
};
// Global access pointer

View File

@ -653,4 +653,98 @@ bool CStdGLCtx::PageFlip()
#endif //USE_GTK/USE_SDL_MAINLOOP
#ifdef WITH_QT_EDITOR
#undef LineFeed // conflicts with Qt
#include <QOpenGLWidget>
#include <QOpenGLContext>
#include <QOffscreenSurface>
CStdGLCtxQt::CStdGLCtxQt() { }
void CStdGLCtxQt::Clear(bool multisample_change)
{
pWindow = nullptr;
if (context)
{
delete context;
delete surface;
}
}
bool CStdGLCtxQt::Init(C4Window *window, C4AbstractApp *app)
{
if (!pGL) return false;
pWindow = window;
if (!pWindow->glwidget)
{
surface = new QOffscreenSurface();
surface->create();
context = new QOpenGLContext();
if (!context->create())
return false;
}
if (!Select(true)) return false;
// init extensions
glewExperimental = GL_TRUE;
GLenum err = glewInit();
if (GLEW_OK != err)
{
// Problem: glewInit failed, something is seriously wrong.
return pGL->Error(reinterpret_cast<const char*>(glewGetErrorString(err)));
}
this_context = contexts.insert(contexts.end(), this);
return true;
}
bool CStdGLCtxQt::Select(bool verbose)
{
if (context)
{
if (!context->makeCurrent(surface))
return false;
}
else
pWindow->glwidget->makeCurrent();
SelectCommon();
// update clipper - might have been done by UpdateSize
// however, the wrong size might have been assumed
if (!pGL->UpdateClipper())
{
if (verbose) pGL->Error(" gl: UpdateClipper failed");
return false;
}
// success
return true;
}
void CStdGLCtxQt::Deselect()
{
if (context)
context->doneCurrent();
else
pWindow->glwidget->doneCurrent();
if (pGL && pGL->pCurrCtx == this)
{
pGL->pCurrCtx = 0;
pGL->RenderTarget = 0;
}
}
bool CStdGLCtxQt::PageFlip()
{
// flush GL buffer
glFlush();
if (!pWindow) return false;
if (context)
return false;
pWindow->glwidget->update();
return true;
}
#endif
#endif // USE_CONSOLE

View File

@ -403,6 +403,9 @@ public:
#elif defined(USE_GTK)
unsigned long renderwnd;
#endif
#ifdef WITH_QT_EDITOR
class QOpenGLWidget *glwidget;
#endif
protected:
#if defined(USE_GTK)
bool FindFBConfig(int samples, GLXFBConfig *info);

View File

@ -20,7 +20,9 @@
#include <C4Window.h>
#include <C4Application.h>
#include <C4Console.h>
#include <C4DrawGL.h>
#include <C4ViewportWindow.h>
#include <StdFile.h>
#include <StdBuf.h>
@ -42,6 +44,14 @@ C4Window::~C4Window ()
C4Window * C4Window::Init(WindowKind windowKind, C4AbstractApp * pApp, const char * Title, const C4Rect * size)
{
#ifdef WITH_QT_EDITOR
if (windowKind == W_Viewport)
{
// embed into editor: Viewport widget creation handled by C4ConsoleQt
::Console.AddViewport(static_cast<C4ViewportWindow *>(this));
return this;
}
#endif
/* SDL_GL_MULTISAMPLEBUFFERS,
SDL_GL_MULTISAMPLESAMPLES,*/
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);