Allow passing data_path from QML
authorunc0rr
Sat, 12 Nov 2022 21:12:14 +0100
changeset 15891 d52f5d8e75e6
parent 15890 8a6a2d931bae
child 15892 b3295f94e5e9
Allow passing data_path from QML
qmlfrontend/Page1.qml
qmlfrontend/engine_instance.cpp
qmlfrontend/engine_instance.h
qmlfrontend/engine_interface.h
qmlfrontend/hwengine.cpp
qmlfrontend/hwengine.h
qmlfrontend/net_session.cpp
qmlfrontend/players_model.cpp
rust/lib-hedgewars-engine/Cargo.toml
rust/lib-hedgewars-engine/src/instance.rs
rust/lib-hedgewars-engine/src/lib.rs
rust/lib-hedgewars-engine/src/world.rs
--- a/qmlfrontend/Page1.qml	Sat Nov 12 15:40:20 2022 +0100
+++ b/qmlfrontend/Page1.qml	Sat Nov 12 21:12:14 2022 +0100
@@ -2,66 +2,67 @@
 import Hedgewars.Engine 1.0
 
 Page1Form {
-  focus: true
+    focus: true
 
-  property HWEngine hwEngine
-  property NetSession netSession
+    property HWEngine hwEngine
+    property NetSession netSession
+
+    Component {
+        id: hwEngineComponent
 
-  Component {
-    id: hwEngineComponent
-
-    HWEngine {
-      engineLibrary: "./libhedgewars_engine.so"
-      previewAcceptor: PreviewAcceptor
-      onPreviewImageChanged: previewImage.source = "image://preview/image"
-      onPreviewIsRendering: previewImage.source = "qrc:/res/iconTime.png"
+        HWEngine {
+            engineLibrary: "../rust/lib-hedgewars-engine/target/debug/libhedgewars_engine.so"
+            dataPath: "../share/hedgewars/Data"
+            previewAcceptor: PreviewAcceptor
+            onPreviewImageChanged: previewImage.source = "image://preview/image"
+            onPreviewIsRendering: previewImage.source = "qrc:/res/iconTime.png"
+        }
     }
-  }
 
-  Component {
-    id: netSessionComponent
+    Component {
+        id: netSessionComponent
 
-    NetSession {
-      nickname: "test0272"
-      url: "hwnet://gameserver.hedgewars.org:46632"
+        NetSession {
+            nickname: "test0272"
+            url: "hwnet://gameserver.hedgewars.org:46632"
+        }
     }
-  }
 
-  Component.onCompleted: {
-    hwEngine = hwEngineComponent.createObject()
-  }
+    Component.onCompleted: {
+        hwEngine = hwEngineComponent.createObject()
+    }
 
-  tickButton {
-    onClicked: {
-      tickButton.visible = false
-      gameView.tick(100)
+    tickButton {
+        onClicked: {
+            tickButton.visible = false
+            gameView.tick(100)
+        }
     }
-  }
-  gameButton {
-    visible: !gameView.engineInstance
-    onClicked: {
-      var engineInstance = hwEngine.runQuickGame()
-      gameView.engineInstance = engineInstance
+    gameButton {
+        visible: !gameView.engineInstance
+        onClicked: {
+            const engineInstance = hwEngine.runQuickGame()
+            gameView.engineInstance = engineInstance
+        }
     }
-  }
-  button1 {
-    visible: !gameView.engineInstance
-    onClicked: {
-      hwEngine.getPreview()
+    button1 {
+        visible: !gameView.engineInstance
+        onClicked: {
+            hwEngine.getPreview()
+        }
+    }
+    netButton.onClicked: {
+        netSession = netSessionComponent.createObject()
+        netSession.open()
     }
-  }
-  netButton.onClicked: {
-    netSession = netSessionComponent.createObject()
-    netSession.open()
-  }
+
+    Keys.onPressed: {
+        if (event.key === Qt.Key_Enter)
+            gameView.engineInstance.longEvent(Engine.Attack, Engine.Set)
+    }
 
-  Keys.onPressed: {
-    if (event.key === Qt.Key_Enter)
-      gameView.engineInstance.longEvent(Engine.Attack, Engine.Set)
-  }
-
-  Keys.onReleased: {
-    if (event.key === Qt.Key_Enter)
-      gameView.engineInstance.longEvent(Engine.Attack, Engine.Unset)
-  }
+    Keys.onReleased: {
+        if (event.key === Qt.Key_Enter)
+            gameView.engineInstance.longEvent(Engine.Attack, Engine.Unset)
+    }
 }
--- a/qmlfrontend/engine_instance.cpp	Sat Nov 12 15:40:20 2022 +0100
+++ b/qmlfrontend/engine_instance.cpp	Sat Nov 12 21:12:14 2022 +0100
@@ -13,8 +13,8 @@
     return currentOpenglContext->getProcAddress(fn);
 }
 
-EngineInstance::EngineInstance(const QString& libraryPath, QObject* parent)
-    : QObject(parent) {
+EngineInstance::EngineInstance(const QString& libraryPath, const QString&dataPath, QObject* parent)
+    : QObject(parent), m_instance{nullptr, nullptr} {
   QLibrary hwlib(libraryPath);
 
   if (!hwlib.load())
@@ -62,52 +62,50 @@
     qDebug() << "Loaded engine library with protocol version"
              << hedgewars_engine_protocol_version();
 
-    m_instance = start_engine();
+    m_instance = std::unique_ptr<Engine::EngineInstance, Engine::cleanup_t*>(start_engine(dataPath.toUtf8().data()), cleanup);
   } else {
     qDebug("Engine library load failed");
   }
 }
 
-EngineInstance::~EngineInstance() {
-  if (m_isValid) cleanup(m_instance);
-}
+EngineInstance::~EngineInstance() = default;
 
 void EngineInstance::sendConfig(const GameConfig& config) {
   for (auto b : config.config()) {
-    send_ipc(m_instance, reinterpret_cast<uint8_t*>(b.data()),
+    send_ipc(m_instance.get(), reinterpret_cast<uint8_t*>(b.data()),
              static_cast<size_t>(b.size()));
   }
 }
 
 void EngineInstance::advance(quint32 ticks) {
-  advance_simulation(m_instance, ticks);
+  advance_simulation(m_instance.get(), ticks);
 }
 
 void EngineInstance::moveCamera(const QPoint& delta) {
-  move_camera(m_instance, delta.x(), delta.y());
+  move_camera(m_instance.get(), delta.x(), delta.y());
 }
 
 void EngineInstance::simpleEvent(Engine::SimpleEventType event_type) {
-  simple_event(m_instance, event_type);
+  simple_event(m_instance.get(), event_type);
 }
 
 void EngineInstance::longEvent(Engine::LongEventType event_type,
                                Engine::LongEventState state) {
-  long_event(m_instance, event_type, state);
+  long_event(m_instance.get(), event_type, state);
 }
 
 void EngineInstance::positionedEvent(Engine::PositionedEventType event_type,
                                      qint32 x, qint32 y) {
-  positioned_event(m_instance, event_type, x, y);
+  positioned_event(m_instance.get(), event_type, x, y);
 }
 
-void EngineInstance::renderFrame() { render_frame(m_instance); }
+void EngineInstance::renderFrame() { render_frame(m_instance.get()); }
 
 void EngineInstance::setOpenGLContext(QOpenGLContext* context) {
   currentOpenglContext = context;
 
   auto size = context->surface()->size();
-  setup_current_gl_context(m_instance, static_cast<quint16>(size.width()),
+  setup_current_gl_context(m_instance.get(), static_cast<quint16>(size.width()),
                            static_cast<quint16>(size.height()),
                            &getProcAddress);
 }
@@ -115,7 +113,7 @@
 QImage EngineInstance::generatePreview() {
   Engine::PreviewInfo pinfo;
 
-  generate_preview(m_instance, &pinfo);
+  generate_preview(m_instance.get(), &pinfo);
 
   QVector<QRgb> colorTable;
   colorTable.resize(256);
@@ -126,7 +124,7 @@
   previewImage.setColorTable(colorTable);
 
   // Cannot use it here, since QImage refers to original bytes
-  // dispose_preview(m_instance);
+  // dispose_preview(m_instance.get());
 
   return previewImage;
 }
--- a/qmlfrontend/engine_instance.h	Sat Nov 12 15:40:20 2022 +0100
+++ b/qmlfrontend/engine_instance.h	Sat Nov 12 21:12:14 2022 +0100
@@ -12,7 +12,7 @@
   Q_OBJECT
 
  public:
-  explicit EngineInstance(const QString& libraryPath,
+  explicit EngineInstance(const QString& libraryPath,const QString& dataPath,
                           QObject* parent = nullptr);
   ~EngineInstance();
 
@@ -38,7 +38,7 @@
                        qint32 y);
 
  private:
-  Engine::EngineInstance* m_instance;
+  std::unique_ptr<Engine::EngineInstance, Engine::cleanup_t*> m_instance;
 
   Engine::hedgewars_engine_protocol_version_t*
       hedgewars_engine_protocol_version;
--- a/qmlfrontend/engine_interface.h	Sat Nov 12 15:40:20 2022 +0100
+++ b/qmlfrontend/engine_interface.h	Sat Nov 12 21:12:14 2022 +0100
@@ -35,7 +35,7 @@
 } PreviewInfo;
 
 typedef uint32_t hedgewars_engine_protocol_version_t();
-typedef EngineInstance* start_engine_t();
+typedef EngineInstance* start_engine_t(const char* data_path);
 typedef void generate_preview_t(EngineInstance* engine_state,
                                 PreviewInfo* preview);
 typedef void dispose_preview_t(EngineInstance* engine_state);
--- a/qmlfrontend/hwengine.cpp	Sat Nov 12 15:40:20 2022 +0100
+++ b/qmlfrontend/hwengine.cpp	Sat Nov 12 21:12:14 2022 +0100
@@ -9,7 +9,7 @@
 #include "game_view.h"
 #include "preview_acceptor.h"
 
-HWEngine::HWEngine(QObject* parent) : QObject(parent) {}
+HWEngine::HWEngine(QObject* parent) : QObject(parent), m_dataPath{QStringLiteral("Data")} {}
 
 HWEngine::~HWEngine() {}
 
@@ -19,7 +19,7 @@
   m_gameConfig = GameConfig();
   m_gameConfig.cmdSeed(QUuid::createUuid().toByteArray());
 
-  EngineInstance engine(m_engineLibrary);
+  EngineInstance engine(m_engineLibrary, m_dataPath);
   if (!engine.isValid())  // TODO: error notification
     return;
 
@@ -43,7 +43,8 @@
   m_gameConfig.cmdTeam(team1);
   m_gameConfig.cmdTeam(team2);
 
-  EngineInstance* engine = new EngineInstance(m_engineLibrary, this);
+  EngineInstance* engine = new EngineInstance(m_engineLibrary, m_dataPath, this);
+  engine->sendConfig(m_gameConfig);
 
   return engine;
   // m_runQueue->queue(m_gameConfig);
@@ -68,3 +69,16 @@
   m_engineLibrary = engineLibrary;
   emit engineLibraryChanged(m_engineLibrary);
 }
+
+const QString &HWEngine::dataPath() const
+{
+  return m_dataPath;
+}
+
+void HWEngine::setDataPath(const QString &newDataPath)
+{
+  if (m_dataPath == newDataPath)
+    return;
+  m_dataPath = newDataPath;
+  emit dataPathChanged();
+}
--- a/qmlfrontend/hwengine.h	Sat Nov 12 15:40:20 2022 +0100
+++ b/qmlfrontend/hwengine.h	Sat Nov 12 21:12:14 2022 +0100
@@ -20,6 +20,7 @@
                  setPreviewAcceptor NOTIFY previewAcceptorChanged)
   Q_PROPERTY(QString engineLibrary READ engineLibrary WRITE setEngineLibrary
                  NOTIFY engineLibraryChanged)
+  Q_PROPERTY(QString dataPath READ dataPath WRITE setDataPath NOTIFY dataPathChanged)
 
  public:
   explicit HWEngine(QObject* parent = nullptr);
@@ -32,7 +33,10 @@
   PreviewAcceptor* previewAcceptor() const;
   QString engineLibrary() const;
 
- public slots:
+  const QString &dataPath() const;
+  void setDataPath(const QString &newDataPath);
+
+public slots:
   void setPreviewAcceptor(PreviewAcceptor* previewAcceptor);
   void setEngineLibrary(const QString& engineLibrary);
 
@@ -45,12 +49,15 @@
   void previewAcceptorChanged(PreviewAcceptor* previewAcceptor);
   void engineLibraryChanged(const QString& engineLibrary);
 
- private:
+  void dataPathChanged();
+
+private:
   QQmlEngine* m_engine;
   GameConfig m_gameConfig;
   int m_previewHedgehogsCount;
   PreviewAcceptor* m_previewAcceptor;
   QString m_engineLibrary;
+  QString m_dataPath;
 };
 
 #endif  // HWENGINE_H
--- a/qmlfrontend/net_session.cpp	Sat Nov 12 15:40:20 2022 +0100
+++ b/qmlfrontend/net_session.cpp	Sat Nov 12 21:12:14 2022 +0100
@@ -340,7 +340,7 @@
   QString hash =
       QCryptographicHash::hash(m_clientSalt.toLatin1()
                                    .append(m_serverSalt.toLatin1())
-                                   .append(m_passwordHash)
+                                   .append(m_passwordHash.toLatin1())
                                    .append(QByteArray::number(cProtocolVersion))
                                    .append("!hedgewars"),
                                QCryptographicHash::Sha1)
@@ -349,7 +349,7 @@
   m_serverHash =
       QCryptographicHash::hash(m_serverSalt.toLatin1()
                                    .append(m_clientSalt.toLatin1())
-                                   .append(m_passwordHash)
+                                   .append(m_passwordHash.toLatin1())
                                    .append(QByteArray::number(cProtocolVersion))
                                    .append("!hedgewars"),
                                QCryptographicHash::Sha1)
--- a/qmlfrontend/players_model.cpp	Sat Nov 12 15:40:20 2022 +0100
+++ b/qmlfrontend/players_model.cpp	Sat Nov 12 21:12:14 2022 +0100
@@ -355,10 +355,10 @@
 
   stream << "; this list is used by Hedgewars - do not edit it unless you know "
             "what you're doing!"
-         << endl;
+         << Qt::endl;
 
   foreach (const QString &nick, set.values())
-    stream << nick << endl;
+    stream << nick << Qt::endl;
 
   txt.close();
 }
--- a/rust/lib-hedgewars-engine/Cargo.toml	Sat Nov 12 15:40:20 2022 +0100
+++ b/rust/lib-hedgewars-engine/Cargo.toml	Sat Nov 12 21:12:14 2022 +0100
@@ -7,7 +7,7 @@
 [dependencies]
 gl = "0.11"
 netbuf = "0.4"
-itertools = "0.8"
+itertools = "0.10"
 png = "0.13"
 
 fpnum = { path = "../fpnum" }
--- a/rust/lib-hedgewars-engine/src/instance.rs	Sat Nov 12 15:40:20 2022 +0100
+++ b/rust/lib-hedgewars-engine/src/instance.rs	Sat Nov 12 21:12:14 2022 +0100
@@ -7,6 +7,8 @@
 use integral_geometry::{Point, Rect, Size};
 use landgen::outline_template::OutlineTemplate;
 
+use std::path::Path;
+
 use super::{ipc::*, world::World};
 
 pub struct EngineInstance {
@@ -16,8 +18,8 @@
 }
 
 impl EngineInstance {
-    pub fn new() -> Self {
-        let mut world = World::new();
+    pub fn new(data_path: &Path) -> Self {
+        let mut world = World::new(data_path);
 
         fn template() -> OutlineTemplate {
             let mut template = OutlineTemplate::new(Size::new(4096 * 1, 2048 * 1));
--- a/rust/lib-hedgewars-engine/src/lib.rs	Sat Nov 12 15:40:20 2022 +0100
+++ b/rust/lib-hedgewars-engine/src/lib.rs	Sat Nov 12 21:12:14 2022 +0100
@@ -5,10 +5,11 @@
 mod world;
 
 use std::{
-    ffi::CString,
+    ffi::{CString, CStr},
     io::{Read, Write},
     mem::replace,
     os::raw::{c_char, c_void},
+    path::Path,
 };
 
 use integral_geometry::Point;
@@ -87,8 +88,10 @@
 }
 
 #[no_mangle]
-pub extern "C" fn start_engine() -> *mut EngineInstance {
-    let engine_state = Box::new(EngineInstance::new());
+pub extern "C" fn start_engine(data_path: *const i8) -> *mut EngineInstance {
+    let data_path: &str = unsafe { CStr::from_ptr(data_path) }.to_str().unwrap();
+
+    let engine_state = Box::new(EngineInstance::new(Path::new(&data_path)));
 
     Box::leak(engine_state)
 }
--- a/rust/lib-hedgewars-engine/src/world.rs	Sat Nov 12 15:40:20 2022 +0100
+++ b/rust/lib-hedgewars-engine/src/world.rs	Sat Nov 12 21:12:14 2022 +0100
@@ -39,7 +39,7 @@
 }
 
 impl World {
-    pub fn new() -> Self {
+    pub fn new(data_path: &Path) -> Self {
         Self {
             random_numbers_gen: LaggedFibonacciPRNG::new(&[]),
             feature_size: 5,
@@ -49,7 +49,7 @@
             gear_renderer: None,
             camera: Camera::new(),
             gear_entries: vec![],
-            data_path: PathBuf::from("../../share/hedgewars/Data"),
+            data_path: data_path.to_owned(),
         }
     }