Break engine completely and make it render in frontend window (no actual rendering yet, just white screen) qmlfrontend
authorunc0rr
Tue, 02 Jan 2018 23:45:18 +0100
branchqmlfrontend
changeset 12881 b544bbbd0696
parent 12868 fe16fa088b69
child 12882 c9418f57fcbc
Break engine completely and make it render in frontend window (no actual rendering yet, just white screen)
hedgewars/hwLibrary.pas
hedgewars/hwengine.pas
hedgewars/uDebug.pas
hedgewars/uStore.pas
qmlfrontend/CMakeLists.txt
qmlfrontend/Page1.qml
qmlfrontend/Page1Form.ui.qml
qmlfrontend/flib.h
qmlfrontend/gameview.cpp
qmlfrontend/gameview.h
qmlfrontend/hwengine.cpp
qmlfrontend/hwengine.h
--- a/hedgewars/hwLibrary.pas	Wed Dec 27 00:59:26 2017 +0100
+++ b/hedgewars/hwLibrary.pas	Tue Jan 02 23:45:18 2018 +0100
@@ -62,7 +62,8 @@
     ipcToEngineRaw,
     ipcSetEngineBarrier,
     ipcRemoveBarrierFromEngineQueue,
-    RunEngine
+    RunEngine,
+    GameTick
     ;
 
 begin
--- a/hedgewars/hwengine.pas	Wed Dec 27 00:59:26 2017 +0100
+++ b/hedgewars/hwengine.pas	Tue Jan 02 23:45:18 2018 +0100
@@ -36,6 +36,8 @@
      ;
 
 function  RunEngine(argc: LongInt; argv: PPChar): Longint; cdecl; export;
+function GameTick(delta: Longword): boolean; cdecl; export;
+
 procedure preInitEverything();
 procedure initEverything(complete:boolean);
 procedure freeEverything(complete:boolean);
@@ -361,7 +363,7 @@
 
     if not allOK then exit;
     //SDL_StartTextInput();
-    SDL_ShowCursor(0);
+    //SDL_ShowCursor(0);
 
 
 {$IFDEF USE_VIDEO_RECORDING}
@@ -439,7 +441,7 @@
     end;
 {$ENDIF}
 
-    MainLoop;
+    //MainLoop;
 end;
 
 procedure Game;
@@ -589,6 +591,8 @@
     EngineThread:= 0
 end;
 
+type TRunState = (rsVoid, rsInit, rsRun);
+var runState: TRunState;
 
 function RunEngine(argc: LongInt; argv: PPChar): Longint; cdecl; export;
 var t: PSDL_Thread;
@@ -596,6 +600,8 @@
     operatingsystem_parameter_argc:= argc;
     operatingsystem_parameter_argv:= argv;
 
+    runState:= rsInit;
+
 {$IFDEF WIN32}
     ShcoreLibHandle := LoadLibrary('Shcore.dll');
     if (ShcoreLibHandle <> 0) then
@@ -618,10 +624,34 @@
         RunEngine:= HaltUsageError
     else
     begin
-        t:= SDL_CreateThread(@EngineThread, 'engine', nil);
-        SDL_DetachThread(t);
+        //t:= SDL_CreateThread(@EngineThread, 'engine', nil);
+        //SDL_DetachThread(t);
         RunEngine:= 0
     end
 end;
 
+function GameTick(delta: Longword): boolean; cdecl; export;
+begin
+    GameTick:= true;
+    case runState of
+        rsInit: begin
+                system.writeln('[[]] rsInit');
+        initEverything(true);
+        SendIPC('TG');
+        GameRoutine;
+        runState:= rsRun;
+            end;
+        rsRun: begin
+                system.writeln('[[]] rsRun');
+                if DoTimer(delta) then begin
+                    system.writeln('[[]] Cleaning up');
+                    // clean up all the memory allocated
+                    freeEverything(true);
+                    runState:= rsVoid;
+                    GameTick:= false
+                end;
+            end;
+    end;
+end;
+
 end.
--- a/hedgewars/uDebug.pas	Wed Dec 27 00:59:26 2017 +0100
+++ b/hedgewars/uDebug.pas	Tue Jan 02 23:45:18 2018 +0100
@@ -31,7 +31,7 @@
     allOK: boolean;
 
 implementation
-uses SDLh, uConsole, uCommands, uConsts;
+uses SDLh, uConsole, uCommands, uConsts, sysutils;
 
 procedure OutError(Msg: shortstring; isFatalError: boolean);
 begin
@@ -52,6 +52,7 @@
         OutError(Msg, false);
 
     allOK:= allOK and (Assert or (not isFatal));
+    if not allOk then raise Exception.create(msg);
     checkFails:= (not Assert) and isFatal
 end;
 
@@ -65,6 +66,7 @@
     end;
 
     allOK:= allOK and (Assert or (not isFatal));
+    if not allOk then raise Exception.create(msg);
     SDLCheck:= (not Assert) and isFatal
 end;
 
--- a/hedgewars/uStore.pas	Wed Dec 27 00:59:26 2017 +0100
+++ b/hedgewars/uStore.pas	Tue Jan 02 23:45:18 2018 +0100
@@ -779,10 +779,10 @@
     // un-comment below and add proper logic to support opengles2.0
     //SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
     //SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
-    if SDLGLcontext = nil then
+    {if SDLGLcontext = nil then
         SDLGLcontext:= SDL_GL_CreateContext(SDLwindow);
     if SDLCheck(SDLGLcontext <> nil, 'SDLGLcontext', true) then exit;
-    SDL_GL_SetSwapInterval(1);
+    SDL_GL_SetSwapInterval(1);}
 
     RendererSetup();
 
@@ -793,8 +793,8 @@
 procedure AddProgress;
 var r: TSDL_Rect;
     texsurf: PSDL_Surface;
-begin
-    if cOnlyStats then exit;
+begin 
+    if cOnlyStats then exit; (*
     if Step = 0 then
     begin
         WriteToConsole(msgLoading + 'progress sprite: ');
@@ -832,11 +832,11 @@
 
     SwapBuffers;
 
-    inc(Step);
+    inc(Step); *)
 end;
 
 procedure FinishProgress;
-begin
+begin (*
     {$IFNDEF PAS2C}
     with mobileRecord do
         if GameLoaded <> nil then
@@ -845,7 +845,7 @@
     WriteLnToConsole('Freeing progress textures... ');
     FreeAndNilTexture(ProgrTex);
     FreeAndNilTexture(LoadingText);
-    Step:= 0
+    Step:= 0 *)
 end;
 
 function RenderHelpWindow(caption, subcaption, description, extra: ansistring; extracolor: LongInt; iconsurf: PSDL_Surface; iconrect: PSDL_Rect): PTexture;
@@ -1084,7 +1084,7 @@
         cScreenWidth:= cWindowedWidth;
         cScreenHeight:= cWindowedHeight;
         end;
-
+{
     AddFileLog('Preparing to change video parameters...');
     if SDLwindow = nil then
         begin
@@ -1180,7 +1180,7 @@
         SDL_SetWindowIcon(SDLwindow, ico);
         SDL_FreeSurface(ico);
         end;
-    {$ENDIF}
+    {$ENDIF}}
     SetupOpenGL();
 
     if reinit then
--- a/qmlfrontend/CMakeLists.txt	Wed Dec 27 00:59:26 2017 +0100
+++ b/qmlfrontend/CMakeLists.txt	Tue Jan 02 23:45:18 2018 +0100
@@ -12,6 +12,7 @@
     "hwengine.cpp" "hwengine.h"
     "gameconfig.cpp" "gameconfig.h"
     "runqueue.cpp" "runqueue.h"
+    "gameview.cpp" "gameview.h"
     "team.cpp" "team.h"
     "previewimageprovider.cpp" "previewimageprovider.h"
     "flib.h")
--- a/qmlfrontend/Page1.qml	Wed Dec 27 00:59:26 2017 +0100
+++ b/qmlfrontend/Page1.qml	Tue Jan 02 23:45:18 2018 +0100
@@ -2,9 +2,12 @@
 import Hedgewars.Engine 1.0
 
 Page1Form {
+  tickButton.onClicked: {
+    item1.tick(100);
+}
   gameButton.onClicked: {
     HWEngine.runQuickGame()
-}
+  }
   button1.onClicked: {
     HWEngine.getPreview()
   }
@@ -15,11 +18,9 @@
           previewImage.source = "image://preview/image"
       }
       onPreviewIsRendering: {
-        console.log("==========")
           previewImage.source = "qrc:/res/iconTime.png"
       }
       onPreviewHogCountChanged: {
       }
   }
-
 }
--- a/qmlfrontend/Page1Form.ui.qml	Wed Dec 27 00:59:26 2017 +0100
+++ b/qmlfrontend/Page1Form.ui.qml	Tue Jan 02 23:45:18 2018 +0100
@@ -2,10 +2,16 @@
 import QtQuick.Controls 2.0
 import QtQuick.Layouts 1.3
 
+import Hedgewars.Engine 1.0
+
 Item {
-  property alias button1: button1
-  property alias previewImage: previewImage
-  property alias gameButton: gameButton
+    property alias button1: button1
+    property alias previewImage: previewImage
+    property alias gameButton: gameButton
+    width: 1024
+    height: 800
+    property alias tickButton: tickButton
+    property alias item1: item1
 
     RowLayout {
         anchors.horizontalCenter: parent.horizontalCenter
@@ -13,23 +19,36 @@
         anchors.top: parent.top
 
         Button {
-          id: button1
-          text: qsTr("Preview")
+            id: button1
+            text: qsTr("Preview")
         }
 
         Button {
             id: gameButton
             text: qsTr("Game")
         }
+
+        Button {
+            id: tickButton
+            text: qsTr("Tick")
+        }
     }
 
     Image {
         id: previewImage
-        x: 188
-        y: 176
+        x: 8
+        y: 20
         width: 256
         height: 128
         source: "qrc:/res/iconTime.png"
         cache: false
     }
+
+    GameView {
+        id: item1
+        x: 8
+        y: 154
+        width: 1008
+        height: 638
+    }
 }
--- a/qmlfrontend/flib.h	Wed Dec 27 00:59:26 2017 +0100
+++ b/qmlfrontend/flib.h	Tue Jan 02 23:45:18 2018 +0100
@@ -25,6 +25,7 @@
 } string255;
 
 typedef void RunEngine_t(int argc, const char** argv);
+typedef void GameTick_t(uint32_t time_delta);
 typedef void ipcToEngineRaw_t(const char* msg, uint32_t len);
 typedef void ipcSetEngineBarrier_t();
 typedef void ipcRemoveBarrierFromEngineQueue_t();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/qmlfrontend/gameview.cpp	Tue Jan 02 23:45:18 2018 +0100
@@ -0,0 +1,68 @@
+#include "gameview.h"
+
+#include <QtGui/QOpenGLContext>
+#include <QtGui/QOpenGLShaderProgram>
+#include <QtQuick/qquickwindow.h>
+
+#include "flib.h"
+
+extern "C" {
+extern GameTick_t* flibGameTick;
+}
+
+GameView::GameView()
+    : m_delta(0)
+    , m_renderer(0)
+{
+    connect(this, &QQuickItem::windowChanged, this, &GameView::handleWindowChanged);
+}
+
+void GameView::tick(quint32 delta)
+{
+    m_delta = delta;
+    if (window())
+        window()->update();
+}
+
+void GameView::handleWindowChanged(QQuickWindow* win)
+{
+    if (win) {
+        connect(win, &QQuickWindow::beforeSynchronizing, this, &GameView::sync, Qt::DirectConnection);
+        connect(win, &QQuickWindow::sceneGraphInvalidated, this, &GameView::cleanup, Qt::DirectConnection);
+
+        win->setClearBeforeRendering(false);
+    }
+}
+
+void GameView::cleanup()
+{
+    if (m_renderer) {
+        delete m_renderer;
+        m_renderer = 0;
+    }
+}
+
+GameViewRenderer::~GameViewRenderer()
+{
+}
+
+void GameView::sync()
+{
+    if (!m_renderer) {
+        m_renderer = new GameViewRenderer();
+        connect(window(), &QQuickWindow::beforeRendering, m_renderer, &GameViewRenderer::paint, Qt::DirectConnection);
+    }
+    m_renderer->setViewportSize(window()->size() * window()->devicePixelRatio());
+    m_renderer->tick(m_delta);
+    m_renderer->setWindow(window());
+}
+
+void GameViewRenderer::paint()
+{
+    if (m_delta == 0)
+        return;
+
+    flibGameTick(m_delta);
+
+    m_window->resetOpenGLState();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/qmlfrontend/gameview.h	Tue Jan 02 23:45:18 2018 +0100
@@ -0,0 +1,54 @@
+#ifndef GAMEVIEW_H
+#define GAMEVIEW_H
+
+#include <QQuickItem>
+
+#include <QtGui/QOpenGLFunctions>
+#include <QtGui/QOpenGLShaderProgram>
+
+class GameViewRenderer : public QObject, protected QOpenGLFunctions {
+    Q_OBJECT
+public:
+    GameViewRenderer()
+        : m_delta(0)
+    {
+    }
+    ~GameViewRenderer();
+
+    void tick(quint32 delta) { m_delta = delta; }
+    void setViewportSize(const QSize& size) { m_viewportSize = size; }
+    void setWindow(QQuickWindow* window) { m_window = window; }
+
+public slots:
+    void paint();
+
+private:
+    QSize m_viewportSize;
+    quint32 m_delta;
+    QQuickWindow* m_window;
+};
+
+class GameView : public QQuickItem {
+    Q_OBJECT
+
+public:
+    GameView();
+
+    Q_INVOKABLE void tick(quint32 delta);
+
+signals:
+    void tChanged();
+
+public slots:
+    void sync();
+    void cleanup();
+
+private slots:
+    void handleWindowChanged(QQuickWindow* win);
+
+private:
+    quint32 m_delta;
+    GameViewRenderer* m_renderer;
+};
+
+#endif // GAMEVIEW_H
--- a/qmlfrontend/hwengine.cpp	Wed Dec 27 00:59:26 2017 +0100
+++ b/qmlfrontend/hwengine.cpp	Tue Jan 02 23:45:18 2018 +0100
@@ -5,11 +5,13 @@
 #include <QQmlEngine>
 #include <QUuid>
 
+#include "gameview.h"
 #include "previewimageprovider.h"
 #include "runqueue.h"
 
 extern "C" {
 RunEngine_t* flibRunEngine;
+GameTick_t* flibGameTick;
 ipcToEngineRaw_t* flibIpcToEngineRaw;
 ipcSetEngineBarrier_t* flibIpcSetEngineBarrier;
 ipcRemoveBarrierFromEngineQueue_t* flibIpcRemoveBarrierFromEngineQueue;
@@ -37,6 +39,7 @@
         qWarning() << "Engine library not found" << hwlib.errorString();
 
     flibRunEngine = (RunEngine_t*)hwlib.resolve("RunEngine");
+    flibGameTick = (GameTick_t*)hwlib.resolve("GameTick");
     flibIpcToEngineRaw = (ipcToEngineRaw_t*)hwlib.resolve("ipcToEngineRaw");
     flibIpcSetEngineBarrier = (ipcSetEngineBarrier_t*)hwlib.resolve("ipcSetEngineBarrier");
     flibIpcRemoveBarrierFromEngineQueue = (ipcRemoveBarrierFromEngineQueue_t*)hwlib.resolve("ipcRemoveBarrierFromEngineQueue");
@@ -70,6 +73,7 @@
 {
     qDebug("HWEngine::exposeToQML");
     qmlRegisterSingletonType<HWEngine>("Hedgewars.Engine", 1, 0, "HWEngine", hwengine_singletontype_provider);
+    qmlRegisterType<GameView>("Hedgewars.Engine", 1, 0, "GameView");
 }
 
 void HWEngine::guiMessagesCallback(void* context, MessageType mt, const char* msg, uint32_t len)
@@ -110,7 +114,8 @@
 
 void HWEngine::getPreview()
 {
-    m_gameConfig.cmdSeed(QUuid::createUuid().toByteArray());
+    m_seed = QUuid::createUuid().toByteArray();
+    m_gameConfig.cmdSeed(m_seed);
     m_gameConfig.setPreview(true);
 
     m_runQueue->queue(m_gameConfig);
@@ -118,7 +123,8 @@
 
 void HWEngine::runQuickGame()
 {
-    m_gameConfig.cmdTheme("Bamboo");
+    m_gameConfig.cmdSeed(m_seed);
+    m_gameConfig.cmdTheme("Nature");
     Team team1;
     team1.name = "team1";
     Team team2;
--- a/qmlfrontend/hwengine.h	Wed Dec 27 00:59:26 2017 +0100
+++ b/qmlfrontend/hwengine.h	Tue Jan 02 23:45:18 2018 +0100
@@ -36,6 +36,7 @@
     PreviewImageProvider* m_previewProvider;
     RunQueue* m_runQueue;
     GameConfig m_gameConfig;
+    QByteArray m_seed;
 
     static void guiMessagesCallback(void* context, MessageType mt, const char* msg, uint32_t len);