qmlfrontend/engine_instance.cpp
branchui-scaling
changeset 15288 c4fd2813b127
parent 15222 b32c52c76977
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/qmlfrontend/engine_instance.cpp	Wed Jul 31 23:14:27 2019 +0200
@@ -0,0 +1,134 @@
+#include "engine_instance.h"
+
+#include <QDebug>
+#include <QLibrary>
+#include <QOpenGLFunctions>
+#include <QSurface>
+
+static QOpenGLContext* currentOpenglContext = nullptr;
+extern "C" void (*getProcAddress(const char* fn))() {
+  if (!currentOpenglContext)
+    return nullptr;
+  else
+    return currentOpenglContext->getProcAddress(fn);
+}
+
+EngineInstance::EngineInstance(const QString& libraryPath, QObject* parent)
+    : QObject(parent) {
+  QLibrary hwlib(libraryPath);
+
+  if (!hwlib.load())
+    qWarning() << "Engine library not found" << hwlib.errorString();
+
+  hedgewars_engine_protocol_version =
+      reinterpret_cast<Engine::hedgewars_engine_protocol_version_t*>(
+          hwlib.resolve("hedgewars_engine_protocol_version"));
+  start_engine =
+      reinterpret_cast<Engine::start_engine_t*>(hwlib.resolve("start_engine"));
+  generate_preview = reinterpret_cast<Engine::generate_preview_t*>(
+      hwlib.resolve("generate_preview"));
+  dispose_preview = reinterpret_cast<Engine::dispose_preview_t*>(
+      hwlib.resolve("dispose_preview"));
+  cleanup = reinterpret_cast<Engine::cleanup_t*>(hwlib.resolve("cleanup"));
+
+  send_ipc = reinterpret_cast<Engine::send_ipc_t*>(hwlib.resolve("send_ipc"));
+  read_ipc = reinterpret_cast<Engine::read_ipc_t*>(hwlib.resolve("read_ipc"));
+
+  setup_current_gl_context =
+      reinterpret_cast<Engine::setup_current_gl_context_t*>(
+          hwlib.resolve("setup_current_gl_context"));
+  render_frame =
+      reinterpret_cast<Engine::render_frame_t*>(hwlib.resolve("render_frame"));
+  advance_simulation = reinterpret_cast<Engine::advance_simulation_t*>(
+      hwlib.resolve("advance_simulation"));
+  move_camera =
+      reinterpret_cast<Engine::move_camera_t*>(hwlib.resolve("move_camera"));
+  simple_event =
+      reinterpret_cast<Engine::simple_event_t*>(hwlib.resolve("simple_event"));
+  long_event =
+      reinterpret_cast<Engine::long_event_t*>(hwlib.resolve("long_event"));
+  positioned_event = reinterpret_cast<Engine::positioned_event_t*>(
+      hwlib.resolve("positioned_event"));
+
+  m_isValid = hedgewars_engine_protocol_version && start_engine &&
+              generate_preview && dispose_preview && cleanup && send_ipc &&
+              read_ipc && setup_current_gl_context && render_frame &&
+              advance_simulation && move_camera && simple_event && long_event &&
+              positioned_event;
+
+  emit isValidChanged(m_isValid);
+
+  if (isValid()) {
+    qDebug() << "Loaded engine library with protocol version"
+             << hedgewars_engine_protocol_version();
+
+    m_instance = start_engine();
+  } else {
+    qDebug("Engine library load failed");
+  }
+}
+
+EngineInstance::~EngineInstance() {
+  if (m_isValid) cleanup(m_instance);
+}
+
+void EngineInstance::sendConfig(const GameConfig& config) {
+  for (auto b : config.config()) {
+    send_ipc(m_instance, reinterpret_cast<uint8_t*>(b.data()),
+             static_cast<size_t>(b.size()));
+  }
+}
+
+void EngineInstance::advance(quint32 ticks) {
+  advance_simulation(m_instance, ticks);
+}
+
+void EngineInstance::moveCamera(const QPoint& delta) {
+  move_camera(m_instance, delta.x(), delta.y());
+}
+
+void EngineInstance::simpleEvent(Engine::SimpleEventType event_type) {
+  simple_event(m_instance, event_type);
+}
+
+void EngineInstance::longEvent(Engine::LongEventType event_type,
+                               Engine::LongEventState state) {
+  long_event(m_instance, event_type, state);
+}
+
+void EngineInstance::positionedEvent(Engine::PositionedEventType event_type,
+                                     qint32 x, qint32 y) {
+  positioned_event(m_instance, event_type, x, y);
+}
+
+void EngineInstance::renderFrame() { render_frame(m_instance); }
+
+void EngineInstance::setOpenGLContext(QOpenGLContext* context) {
+  currentOpenglContext = context;
+
+  auto size = context->surface()->size();
+  setup_current_gl_context(m_instance, static_cast<quint16>(size.width()),
+                           static_cast<quint16>(size.height()),
+                           &getProcAddress);
+}
+
+QImage EngineInstance::generatePreview() {
+  Engine::PreviewInfo pinfo;
+
+  generate_preview(m_instance, &pinfo);
+
+  QVector<QRgb> colorTable;
+  colorTable.resize(256);
+  for (int i = 0; i < 256; ++i) colorTable[i] = qRgba(255, 255, 0, i);
+
+  QImage previewImage(pinfo.land, static_cast<int>(pinfo.width),
+                      static_cast<int>(pinfo.height), QImage::Format_Indexed8);
+  previewImage.setColorTable(colorTable);
+
+  // Cannot use it here, since QImage refers to original bytes
+  // dispose_preview(m_instance);
+
+  return previewImage;
+}
+
+bool EngineInstance::isValid() const { return m_isValid; }