From 64c7b3d2ebf30f584778b2e4331e3887fd2127e5 Mon Sep 17 00:00:00 2001
From: Shaun Reed <shaunrd0@gmail.com>
Date: Thu, 13 Feb 2025 20:12:28 -0500
Subject: [PATCH] old WIP code

---
 src/app/CMakeLists.txt       |   4 +-
 src/app/debugconsole.cpp     |   3 +-
 src/app/debugconsole.h       |   3 +-
 src/app/logger.cpp           | 107 +++++++++++++++++++++++++++++++++++
 src/app/logger.h             |  37 ++++++++++++
 src/app/qtkwidget.cpp        |  92 ++++++------------------------
 src/app/qtkwidget.h          |   8 ++-
 src/qtk/CMakeLists.txt       |   4 ++
 src/qtk/camera3d.cpp         |  25 --------
 src/qtk/camera3d.h           |  25 +++-----
 src/qtk/qtkapi.h             |   4 +-
 src/qtk/qtkmessagelogger.cpp |  61 ++++++++++++++++++++
 src/qtk/qtkmessagelogger.h   |  96 +++++++++++++++++++++++++++++++
 src/qtk/transform3D.cpp      |  43 +-------------
 src/qtk/transform3D.h        |  13 ++---
 15 files changed, 349 insertions(+), 176 deletions(-)
 create mode 100644 src/app/logger.cpp
 create mode 100644 src/app/logger.h
 create mode 100644 src/qtk/qtkmessagelogger.cpp
 create mode 100644 src/qtk/qtkmessagelogger.h

diff --git a/src/app/CMakeLists.txt b/src/app/CMakeLists.txt
index 5f85378..fef4434 100644
--- a/src/app/CMakeLists.txt
+++ b/src/app/CMakeLists.txt
@@ -47,13 +47,13 @@ target_link_libraries(qtk_plugins PUBLIC qtk_plugin_library)
 ################################################################################
 # Final Qtk Application
 ################################################################################
-
+# Source files for the main window and core application
 set(
     QTK_GUI_SOURCES
     qtkscene.cpp qtkscene.h
+#    logger.cpp logger.h
     main.cpp
 )
-
 qt_add_executable(qtk_gui ${QTK_GUI_SOURCES})
 target_link_libraries(qtk_gui PRIVATE qtk_plugin_library)
 
diff --git a/src/app/debugconsole.cpp b/src/app/debugconsole.cpp
index 186c302..3314af1 100644
--- a/src/app/debugconsole.cpp
+++ b/src/app/debugconsole.cpp
@@ -28,6 +28,7 @@ DebugConsole::DebugConsole(
 
   auto qtkWidget = dynamic_cast<QtkWidget *>(owner);
   if(qtkWidget) {
-    connect(qtkWidget, &QtkWidget::sendLog, this, &DebugConsole::sendLog);
+    connect(
+        qtkWidget->getLogger(), &Logger::sendLog, this, &DebugConsole::sendLog);
   }
 }
diff --git a/src/app/debugconsole.h b/src/app/debugconsole.h
index a2fc69e..270cba3 100644
--- a/src/app/debugconsole.h
+++ b/src/app/debugconsole.h
@@ -61,7 +61,8 @@ namespace Qtk {
        * @param context The DebugContext to use for the message.
        *    Default value is Status.
        */
-      inline void sendLog(QString message, DebugContext context = Status) {
+      inline void sendLog(QString message, Qtk::DebugContext context = Status) {
+//        qDebug() << "[LOGGER]: " << qPrintable(message) << "; LOGGER";
         mConsole->setTextColor(logColor(context));
         mConsole->append(logPrefix(message, context));
       }
diff --git a/src/app/logger.cpp b/src/app/logger.cpp
new file mode 100644
index 0000000..7a7f5f7
--- /dev/null
+++ b/src/app/logger.cpp
@@ -0,0 +1,107 @@
+/*##############################################################################
+## Author: Shaun Reed                                                         ##
+## Legal: All Content (c) 2023 Shaun Reed, all rights reserved                ##
+## About: Logger for Qtk                                                      ##
+##                                                                            ##
+## Contact: shaunrd0@gmail.com  | URL: www.shaunreed.com | GitHub: shaunrd0   ##
+##############################################################################*/
+
+#include "logger.h"
+#include "qtkwidget.h"
+
+using namespace Qtk;
+
+Logger::Logger(Qtk::QtkWidget * parent) : QObject(parent) {
+  //  connect(
+  //      this, SIGNAL(sendLog(QString, Qtk::DebugContext)), this,
+  //      SLOT(log(QString, Qtk::DebugContext)));
+  if(parent != Q_NULLPTR) {
+    connect(
+        parent, SIGNAL(sendLog(QString, Qtk::DebugContext)), this,
+        SLOT(log(QString, Qtk::DebugContext)));
+  }
+}
+
+std::pair<QString, DebugContext> Logger::log(const QOpenGLDebugMessage & msg) {
+  QString error_msg;
+  DebugContext context;
+
+  // Format based on severity
+  switch(msg.severity()) {
+    case QOpenGLDebugMessage::NotificationSeverity:
+      error_msg += "--";
+      context = Status;
+      break;
+    case QOpenGLDebugMessage::HighSeverity:
+      error_msg += "!!";
+      context = Fatal;
+      break;
+    case QOpenGLDebugMessage::MediumSeverity:
+      error_msg += "!~";
+      context = Error;
+      break;
+    case QOpenGLDebugMessage::LowSeverity:
+      error_msg += "~~";
+      context = Warn;
+      break;
+    case QOpenGLDebugMessage::InvalidSeverity:
+      error_msg += "??";
+      context = Invalid;
+      break;
+    case QOpenGLDebugMessage::AnySeverity:
+      error_msg += "**";
+      context = Any;
+      break;
+  }
+
+  error_msg += " (";
+
+  // Format based on source
+#define CASE(c)                \
+  case QOpenGLDebugMessage::c: \
+    error_msg += #c;           \
+    break
+  switch(msg.source()) {
+    CASE(APISource);
+    CASE(WindowSystemSource);
+    CASE(ShaderCompilerSource);
+    CASE(ThirdPartySource);
+    CASE(ApplicationSource);
+    CASE(OtherSource);
+    CASE(InvalidSource);
+    CASE(AnySource);
+  }
+#undef CASE
+
+  error_msg += " : ";
+
+// Format based on type
+#define CASE(c)                \
+  case QOpenGLDebugMessage::c: \
+    error_msg += #c;           \
+    break
+  switch(msg.type()) {
+    CASE(InvalidType);
+    CASE(ErrorType);
+    CASE(DeprecatedBehaviorType);
+    CASE(UndefinedBehaviorType);
+    CASE(PortabilityType);
+    CASE(PerformanceType);
+    CASE(OtherType);
+    CASE(MarkerType);
+    CASE(GroupPushType);
+    CASE(GroupPopType);
+    CASE(AnyType);
+  }
+#undef CASE
+
+  error_msg += ")\n" + msg.message();
+  log(error_msg, context);
+  return {error_msg, context};
+}
+
+void Logger::log(const QString & message, DebugContext context) {
+  const QString log_msg = "[LOGGER]: " + message + "; LOGGER";
+  qDebug() << qPrintable(log_msg);
+  emit sendLog(log_msg, context);
+}
diff --git a/src/app/logger.h b/src/app/logger.h
new file mode 100644
index 0000000..5627abe
--- /dev/null
+++ b/src/app/logger.h
@@ -0,0 +1,37 @@
+/*##############################################################################
+## Author: Shaun Reed                                                         ##
+## Legal: All Content (c) 2023 Shaun Reed, all rights reserved                ##
+## About: Logger for Qtk                                                      ##
+##                                                                            ##
+## Contact: shaunrd0@gmail.com  | URL: www.shaunreed.com | GitHub: shaunrd0   ##
+##############################################################################*/
+
+#ifndef QTK_LOGGER_H
+#define QTK_LOGGER_H
+
+#include <QOpenGLDebugMessage>
+#include <QString>
+#include "qtk/qtkapi.h"
+namespace Qtk {
+  class QtkWidget;
+
+  class Logger : public QObject {
+      Q_OBJECT
+
+    public:
+      explicit Logger(Qtk::QtkWidget * parent = nullptr);
+
+    public slots:
+      std::pair<QString, DebugContext> log(
+          const QOpenGLDebugMessage & msg);
+
+      void log(
+          const QString & message,
+          Qtk::DebugContext context = Qtk::DebugContext::Status);
+
+    signals:
+      void sendLog(const QString & message, Qtk::DebugContext context);
+  };
+}  // namespace Qtk
+
+#endif  // QTK_LOGGER_H
diff --git a/src/app/qtkwidget.cpp b/src/app/qtkwidget.cpp
index d02c0ea..2b456b5 100644
--- a/src/app/qtkwidget.cpp
+++ b/src/app/qtkwidget.cpp
@@ -15,6 +15,7 @@
 #include <qtk/shape.h>
 
 #include "debugconsole.h"
+#include "qtk/qtkmessagelogger.h"
 #include "qtkmainwindow.h"
 #include "qtkwidget.h"
 
@@ -30,8 +31,9 @@ QtkWidget::QtkWidget(QWidget * parent, const QString & name) :
     QtkWidget(parent, name, Q_NULLPTR) {}
 
 QtkWidget::QtkWidget(QWidget * parent, const QString & name, Scene * scene) :
-    QOpenGLWidget(parent), mDebugLogger(Q_NULLPTR),
-    mConsole(new DebugConsole(this, name)), mScene(Q_NULLPTR) {
+    QOpenGLWidget(parent), mDebugLogger(new QOpenGLDebugLogger(this)),
+    mConsole(new DebugConsole(this, name)), mScene(Q_NULLPTR),
+    mLogger(new Qtk::Logger(this)) {
   setAcceptDrops(true);
   setScene(scene);
   setObjectName(name);
@@ -74,13 +76,20 @@ void QtkWidget::initializeGL() {
 
   toggleConsole();
   // Initialize OpenGL debug context
-  mDebugLogger = new QOpenGLDebugLogger(this);
   if(mDebugLogger->initialize()) {
-    qDebug() << "GL_DEBUG Debug Logger" << mDebugLogger << "\n";
     connect(
-        mDebugLogger, SIGNAL(messageLogged(QOpenGLDebugMessage)), this,
-        SLOT(messageLogged(QOpenGLDebugMessage)));
+        mDebugLogger, SIGNAL(messageLogged(QOpenGLDebugMessage)), mLogger,
+        SLOT(log(QOpenGLDebugMessage)));
+    //        connect(
+    //            Qtk::QtkMessageLogger::get(),
+    //            &Qtk::QtkMessageLogger::messageLogged, mLogger,
+    //            &Qtk::Logger::parseError);
     mDebugLogger->startLogging();
+    QString msg;
+    QTextStream stream(&msg);
+    stream << "Logging started on GL_DEBUG Debug Logger: " << mDebugLogger;
+    mDebugLogger->logMessage(QOpenGLDebugMessage::createApplicationMessage(
+        stream.string()->toStdString().c_str()));
   }
 
   printContextInformation();
@@ -205,74 +214,6 @@ void QtkWidget::update() {
   QWidget::update();
 }
 
-void QtkWidget::messageLogged(const QOpenGLDebugMessage & msg) {
-  QString error;
-
-  DebugContext context;
-  // Format based on severity
-  switch(msg.severity()) {
-    case QOpenGLDebugMessage::NotificationSeverity:
-      error += "--";
-      context = Status;
-      break;
-    case QOpenGLDebugMessage::HighSeverity:
-      error += "!!";
-      context = Fatal;
-      break;
-    case QOpenGLDebugMessage::MediumSeverity:
-      error += "!~";
-      context = Error;
-      break;
-    case QOpenGLDebugMessage::LowSeverity:
-      error += "~~";
-      context = Warn;
-      break;
-  }
-
-  error += " (";
-
-  // Format based on source
-#define CASE(c)                \
-  case QOpenGLDebugMessage::c: \
-    error += #c;               \
-    break
-  switch(msg.source()) {
-    CASE(APISource);
-    CASE(WindowSystemSource);
-    CASE(ShaderCompilerSource);
-    CASE(ThirdPartySource);
-    CASE(ApplicationSource);
-    CASE(OtherSource);
-    CASE(InvalidSource);
-  }
-#undef CASE
-
-  error += " : ";
-
-// Format based on type
-#define CASE(c)                \
-  case QOpenGLDebugMessage::c: \
-    error += #c;               \
-    break
-  switch(msg.type()) {
-    CASE(InvalidType);
-    CASE(ErrorType);
-    CASE(DeprecatedBehaviorType);
-    CASE(UndefinedBehaviorType);
-    CASE(PortabilityType);
-    CASE(PerformanceType);
-    CASE(OtherType);
-    CASE(MarkerType);
-    CASE(GroupPushType);
-    CASE(GroupPopType);
-  }
-#undef CASE
-
-  error += ")\n" + msg.message() + "\n";
-  qDebug() << qPrintable(error);
-  sendLog("(OpenGL) " + error.replace("\n", "\n(OpenGL) "), context);
-}
-
 /*******************************************************************************
  * Private Methods
  ******************************************************************************/
@@ -347,6 +288,5 @@ void QtkWidget::printContextInformation() {
   auto message = QString(glType) + glVersion + "(" + glProfile + ")"
                  + "\nOpenGL Vendor: " + glVendor
                  + "\nRendering Device: " + glRenderer;
-  qDebug() << qPrintable(message);
-  sendLog("(OpenGL) " + message.replace("\n", "\n(OpenGL) "), Status);
+  emit sendLog("(OpenGL) " + message.replace("\n", "\n(OpenGL) "), Status);
 }
diff --git a/src/app/qtkwidget.h b/src/app/qtkwidget.h
index a028700..9e01dce 100644
--- a/src/app/qtkwidget.h
+++ b/src/app/qtkwidget.h
@@ -19,6 +19,7 @@
 
 #include <qtk/qtkapi.h>
 #include <qtk/scene.h>
+#include "logger.h"
 
 namespace Qtk {
   class DebugConsole;
@@ -107,6 +108,8 @@ namespace Qtk {
         return mDebugLogger;
       }
 
+      inline Logger * getLogger() { return mLogger; }
+
       /*************************************************************************
        * Setters
        ************************************************************************/
@@ -129,7 +132,7 @@ namespace Qtk {
        * @param message The message to log.
        * @param context The context of the log message.
        */
-      void sendLog(const QString & message, DebugContext context = Status);
+      void sendLog(const QString & message, Qtk::DebugContext context = Status);
 
       // TODO: Use this signal in treeview and toolbox to update object
       // properties
@@ -178,7 +181,7 @@ namespace Qtk {
        *
        * @param msg The message logged.
        */
-      void messageLogged(const QOpenGLDebugMessage & msg);
+//      void messageLogged(const QOpenGLDebugMessage & msg);
 
     private:
       /*************************************************************************
@@ -204,6 +207,7 @@ namespace Qtk {
        * Private Members
        ************************************************************************/
 
+      Qtk::Logger * mLogger;
       QOpenGLDebugLogger * mDebugLogger;
       Qtk::Scene * mScene;
       Qtk::DebugConsole * mConsole;
diff --git a/src/qtk/CMakeLists.txt b/src/qtk/CMakeLists.txt
index 4eca544..48c8f2d 100644
--- a/src/qtk/CMakeLists.txt
+++ b/src/qtk/CMakeLists.txt
@@ -24,6 +24,8 @@ set(
     skybox.h
     texture.h
     transform3D.h
+    qtkmessagelogger.h
+    ../app/logger.h
 )
 
 set(
@@ -41,6 +43,8 @@ set(
     skybox.cpp
     texture.cpp
     transform3D.cpp
+    qtkmessagelogger.cpp
+    ../app/logger.cpp
 )
 
 qt6_add_big_resources(QTK_LIBRARY_SOURCES "${QTK_RESOURCES}/resources.qrc")
diff --git a/src/qtk/camera3d.cpp b/src/qtk/camera3d.cpp
index 1a2689d..cbaf7a2 100644
--- a/src/qtk/camera3d.cpp
+++ b/src/qtk/camera3d.cpp
@@ -29,28 +29,3 @@ const QMatrix4x4 & Camera3D::toMatrix() {
   mWorld.translate(-mTransform.getTranslation());
   return mWorld;
 }
-
-/*******************************************************************************
- * Qt Streams
- ******************************************************************************/
-
-QDataStream & operator<<(QDataStream & out, Camera3D & transform) {
-  out << transform.getTransform();
-  return out;
-}
-
-QDataStream & operator>>(QDataStream & in, Camera3D & transform) {
-  in >> transform.getTransform();
-  return in;
-}
-
-QDebug operator<<(QDebug dbg, const Camera3D & transform) {
-  dbg << "Camera3D\n{\n";
-  dbg << "Position: <" << transform.getTranslation().x() << ", "
-      << transform.getTranslation().y() << ", "
-      << transform.getTranslation().z() << ">\n";
-  dbg << "Rotation: <" << transform.getRotation().x() << ", "
-      << transform.getRotation().y() << ", " << transform.getRotation().z()
-      << " | " << transform.getRotation().scalar() << ">\n}";
-  return dbg;
-}
diff --git a/src/qtk/camera3d.h b/src/qtk/camera3d.h
index 24cc2b9..4280fd0 100644
--- a/src/qtk/camera3d.h
+++ b/src/qtk/camera3d.h
@@ -142,32 +142,23 @@ namespace Qtk {
       }
 
     private:
-      /*************************************************************************
-       * Private Methods
-       ************************************************************************/
-
-#ifndef QT_NO_DATASTREAM
-      friend QDataStream & operator<<(QDataStream & out, Camera3D & transform);
-      friend QDataStream & operator>>(QDataStream & in, Camera3D & transform);
-#endif
-
       /*************************************************************************
        * Private Members
        ************************************************************************/
 
       Transform3D mTransform;
       QMatrix4x4 mWorld;
-  };
 
-// Qt Streams
+      /*************************************************************************
+       * Qt Streams
+       ************************************************************************/
+
 #ifndef QT_NO_DATASTREAM
-  QDataStream & operator<<(QDataStream & out, const Camera3D & transform);
-  QDataStream & operator>>(QDataStream & in, Camera3D & transform);
-#endif
-
-#ifndef QT_NO_DEBUG_STREAM
-  QDebug operator<<(QDebug dbg, const Camera3D & transform);
+      friend QDataStream & operator<<(
+          QDataStream & out, const Camera3D & camera);
+      friend QDataStream & operator>>(QDataStream & in, Camera3D & camera);
 #endif
+  };
 }  // namespace Qtk
 
 Q_DECLARE_TYPEINFO(Qtk::Camera3D, Q_MOVABLE_TYPE);
diff --git a/src/qtk/qtkapi.h b/src/qtk/qtkapi.h
index 15a74c3..ff46b51 100644
--- a/src/qtk/qtkapi.h
+++ b/src/qtk/qtkapi.h
@@ -22,6 +22,8 @@
 #define QTKAPI
 #endif
 
+#include "qtk/qtkmessagelogger.h"
+
 /**
  * Initialize Qt resources required by the Qtk library.
  * This cannot be defined within any namespace, but can be called by ctors.
@@ -35,7 +37,7 @@ namespace Qtk {
   /**
    * Flag to set context for debug messages.
    */
-  enum DebugContext { Status, Debug, Warn, Error, Fatal };
+  enum DebugContext { Status, Debug, Warn, Error, Fatal, Invalid, Any };
 
   /**
    * Find top level parent for a widget.
diff --git a/src/qtk/qtkmessagelogger.cpp b/src/qtk/qtkmessagelogger.cpp
new file mode 100644
index 0000000..ac4ec84
--- /dev/null
+++ b/src/qtk/qtkmessagelogger.cpp
@@ -0,0 +1,61 @@
+
+#include "qtkmessagelogger.h"
+#include "camera3d.h"
+#include "transform3D.h"
+
+
+Qtk::QtkDebug Qtk::QtkDebug::operator<<(const Qtk::Transform3D & transform) {}
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug Qtk::operator<<(QDebug dbg, const Qtk::Transform3D & transform) {
+  dbg << "Transform3D\n{\n";
+  dbg << "Position: <" << transform.getTranslation().x() << ", "
+      << transform.getTranslation().y() << ", "
+      << transform.getTranslation().z() << ">\n";
+  dbg << "Scale: <" << transform.getScale().x() << ", "
+      << transform.getScale().y() << ", " << transform.getScale().z() << ">\n";
+  dbg << "Rotation: <" << transform.getRotation().x() << ", "
+      << transform.getRotation().y() << ", " << transform.getRotation().z()
+      << " | " << transform.getRotation().scalar() << ">\n}";
+  return dbg;
+}
+
+QDebug Qtk::operator<<(QDebug dbg, const Qtk::Camera3D & transform) {
+  dbg << "Camera3D\n{\n";
+  dbg << "Position: <" << transform.getTranslation().x() << ", "
+      << transform.getTranslation().y() << ", "
+      << transform.getTranslation().z() << ">\n";
+  dbg << "Rotation: <" << transform.getRotation().x() << ", "
+      << transform.getRotation().y() << ", " << transform.getRotation().z()
+      << " | " << transform.getRotation().scalar() << ">\n}";
+  return dbg;
+}
+#endif
+
+#ifndef QT_NO_DATASTREAM
+QDataStream & Qtk::operator<<(
+    QDataStream & out, const Qtk::Transform3D & transform) {
+  out << transform.mTranslation;
+  out << transform.mScale;
+  out << transform.mRotation;
+  return out;
+}
+
+QDataStream & Qtk::operator>>(QDataStream & in, Qtk::Transform3D & transform) {
+  in >> transform.mTranslation;
+  in >> transform.mScale;
+  in >> transform.mRotation;
+  transform.m_dirty = true;
+  return in;
+}
+
+QDataStream & Qtk::operator<<(QDataStream & out, const Qtk::Camera3D & camera) {
+  out << camera.getTransform();
+  return out;
+}
+
+QDataStream & Qtk::operator>>(QDataStream & in, Qtk::Camera3D & camera) {
+  in >> camera.mTransform;
+  return in;
+}
+#endif
\ No newline at end of file
diff --git a/src/qtk/qtkmessagelogger.h b/src/qtk/qtkmessagelogger.h
new file mode 100644
index 0000000..5d2ba9f
--- /dev/null
+++ b/src/qtk/qtkmessagelogger.h
@@ -0,0 +1,96 @@
+
+#ifndef QTK_QTKMESSAGELOGGER_H
+#define QTK_QTKMESSAGELOGGER_H
+
+#include "qtkapi.h"
+
+#include <QDebug>
+#include <QMessageLogger>
+#include <Qt>
+
+// #define qtkDebug    Qtk::QtkMessageLogger::get().debug
+// #define qtkInfo     Qtk::QtkMessageLogger::get().info
+// #define qtkWarning  Qtk::QtkMessageLogger::get().warning
+// #define qtkCritical Qtk::QtkMessageLogger::get().critical
+// #define qtkFatal    Qtk::QtkMessageLogger::get().fatal
+
+#define qtkDebug                                                  \
+  Qtk::QtkMessageLogger(                                          \
+      QT_MESSAGELOG_FILE, QT_MESSAGELOG_LINE, QT_MESSAGELOG_FUNC) \
+      .logger()                                                   \
+      .debug
+#define qtkInfo                                                   \
+  Qtk::QtkMessageLogger(                                          \
+      QT_MESSAGELOG_FILE, QT_MESSAGELOG_LINE, QT_MESSAGELOG_FUNC) \
+      .logger()                                                   \
+      .info
+#define qtkWarning                                                \
+  Qtk::QtkMessageLogger(                                          \
+      QT_MESSAGELOG_FILE, QT_MESSAGELOG_LINE, QT_MESSAGELOG_FUNC) \
+      .logger()                                                   \
+      .warning
+#define qtkCritical                                               \
+  Qtk::QtkMessageLogger(                                          \
+      QT_MESSAGELOG_FILE, QT_MESSAGELOG_LINE, QT_MESSAGELOG_FUNC) \
+      .logger()                                                   \
+      .critical
+#define qtkFatal                                                  \
+  Qtk::QtkMessageLogger(                                          \
+      QT_MESSAGELOG_FILE, QT_MESSAGELOG_LINE, QT_MESSAGELOG_FUNC) \
+      .logger()                                                   \
+      .fatal
+
+namespace Qtk {
+  class Transform3D;
+  class Camera3D;
+
+  class QTKAPI QtkDebug : public QDebug {
+    public:
+      QtkDebug operator<<(const Transform3D & transform);
+  };
+
+#ifndef QT_NO_DEBUG_STREAM
+  QDebug operator<<(QDebug dbg, const Transform3D & transform);
+
+  QDebug operator<<(QDebug dbg, const Camera3D & camera);
+#endif
+
+#ifndef QT_NO_DATASTREAM
+  QDataStream & operator<<(QDataStream & out, const Transform3D & transform);
+  QDataStream & operator>>(QDataStream & in, Transform3D & transform);
+
+  QDataStream & operator<<(QDataStream & out, const Camera3D & camera);
+  QDataStream & operator>>(QDataStream & in, Camera3D & camera);
+#endif
+
+  class QTKAPI QtkMessageLogger {
+    public:
+      QtkMessageLogger(const char * file, int line, const char * function) :
+          mQMessageLogger(file, line, function) {
+        qDebug();
+      }
+
+      //      static QtkMessageLogger * get() {
+      //        if(mQtkMessageLogger == Q_NULLPTR) {
+      //          mQtkMessageLogger = new QtkMessageLogger();
+      //        }
+      //        return mQtkMessageLogger;
+      //      }
+
+      //      QtkDebug debug() const {}
+
+      [[nodiscard]] inline const QMessageLogger & logger() const {
+        return mQMessageLogger;
+      }
+
+      inline QtkDebug debug() const { return {}; };
+
+
+      static QtkMessageLogger * mQtkMessageLogger;
+      QMessageLogger mQMessageLogger;
+  };
+
+
+}  // namespace Qtk
+
+#endif  // QTK_QTKMESSAGELOGGER_H
diff --git a/src/qtk/transform3D.cpp b/src/qtk/transform3D.cpp
index 3013890..75e5f34 100644
--- a/src/qtk/transform3D.cpp
+++ b/src/qtk/transform3D.cpp
@@ -42,6 +42,7 @@ void Transform3D::rotate(const QQuaternion & dr) {
 
 void Transform3D::setTranslation(const QVector3D & t) {
   m_dirty = true;
+  qtkDebug() << "Setting translation to " << t;
   mTranslation = t;
 }
 
@@ -77,45 +78,3 @@ QVector3D Transform3D::getUp() const {
 QVector3D Transform3D::getRight() const {
   return mRotation.rotatedVector(LocalRight);
 }
-
-/*******************************************************************************
- * Private Methods
- ******************************************************************************/
-
-namespace Qtk {
-#ifndef QT_NO_DEBUG_STREAM
-
-  QDebug operator<<(QDebug dbg, const Transform3D & transform) {
-    dbg << "Transform3D\n{\n";
-    dbg << "Position: <" << transform.getTranslation().x() << ", "
-        << transform.getTranslation().y() << ", "
-        << transform.getTranslation().z() << ">\n";
-    dbg << "Scale: <" << transform.getScale().x() << ", "
-        << transform.getScale().y() << ", " << transform.getScale().z()
-        << ">\n";
-    dbg << "Rotation: <" << transform.getRotation().x() << ", "
-        << transform.getRotation().y() << ", " << transform.getRotation().z()
-        << " | " << transform.getRotation().scalar() << ">\n}";
-    return dbg;
-  }
-
-#endif
-
-#ifndef QT_NO_DATASTREAM
-  QDataStream & operator<<(QDataStream & out, const Transform3D & transform) {
-    out << transform.mTranslation;
-    out << transform.mScale;
-    out << transform.mRotation;
-    return out;
-  }
-
-  QDataStream & operator>>(QDataStream & in, Transform3D & transform) {
-    in >> transform.mTranslation;
-    in >> transform.mScale;
-    in >> transform.mRotation;
-    transform.m_dirty = true;
-    return in;
-  }
-
-#endif
-}  // namespace Qtk
diff --git a/src/qtk/transform3D.h b/src/qtk/transform3D.h
index 8981835..d76b1cb 100644
--- a/src/qtk/transform3D.h
+++ b/src/qtk/transform3D.h
@@ -249,6 +249,10 @@ namespace Qtk {
 
       bool m_dirty;
 
+      /*************************************************************************
+       * Qt Streams
+       ************************************************************************/
+
 #ifndef QT_NO_DATASTREAM
       friend QDataStream & operator<<(
           QDataStream & out, const Transform3D & transform);
@@ -256,15 +260,6 @@ namespace Qtk {
           QDataStream & in, Transform3D & transform);
 #endif
   };
-
-#ifndef QT_NO_DEBUG_STREAM
-  QDebug operator<<(QDebug dbg, const Transform3D & transform);
-#endif
-
-#ifndef QT_NO_DATASTREAM
-  QDataStream & operator<<(QDataStream & out, const Transform3D & transform);
-  QDataStream & operator>>(QDataStream & in, Transform3D & transform);
-#endif
 }  // namespace Qtk
 
 Q_DECLARE_TYPEINFO(Qtk::Transform3D, Q_MOVABLE_TYPE);