diff --git a/qteditor/QtEditor/ui_logwidget.h b/qteditor/QtEditor/ui_logwidget.h new file mode 100644 index 000000000..9d6aaf6c1 --- /dev/null +++ b/qteditor/QtEditor/ui_logwidget.h @@ -0,0 +1,87 @@ +/******************************************************************************** +** Form generated from reading UI file 'logwidget.ui' +** +** Created by: Qt User Interface Compiler version 5.2.1 +** +** WARNING! All changes made in this file will be lost when recompiling UI file! +********************************************************************************/ + +#ifndef UI_LOGWIDGET_H +#define UI_LOGWIDGET_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class Ui_LogWidget +{ +public: + QWidget *dockWidgetContents; + QHBoxLayout *horizontalLayout; + QTableWidget *tableWidget; + QPushButton *clearButton; + + void setupUi(QDockWidget *LogWidget) + { + if (LogWidget->objectName().isEmpty()) + LogWidget->setObjectName(QStringLiteral("LogWidget")); + LogWidget->resize(783, 360); + dockWidgetContents = new QWidget(); + dockWidgetContents->setObjectName(QStringLiteral("dockWidgetContents")); + horizontalLayout = new QHBoxLayout(dockWidgetContents); + horizontalLayout->setObjectName(QStringLiteral("horizontalLayout")); + tableWidget = new QTableWidget(dockWidgetContents); + if (tableWidget->columnCount() < 2) + tableWidget->setColumnCount(2); + QTableWidgetItem *__qtablewidgetitem = new QTableWidgetItem(); + tableWidget->setHorizontalHeaderItem(0, __qtablewidgetitem); + QTableWidgetItem *__qtablewidgetitem1 = new QTableWidgetItem(); + tableWidget->setHorizontalHeaderItem(1, __qtablewidgetitem1); + tableWidget->setObjectName(QStringLiteral("tableWidget")); + tableWidget->setColumnCount(2); + tableWidget->horizontalHeader()->setDefaultSectionSize(200); + tableWidget->horizontalHeader()->setStretchLastSection(true); + tableWidget->verticalHeader()->setVisible(false); + + horizontalLayout->addWidget(tableWidget); + + clearButton = new QPushButton(dockWidgetContents); + clearButton->setObjectName(QStringLiteral("clearButton")); + + horizontalLayout->addWidget(clearButton); + + LogWidget->setWidget(dockWidgetContents); + + retranslateUi(LogWidget); + + QMetaObject::connectSlotsByName(LogWidget); + } // setupUi + + void retranslateUi(QDockWidget *LogWidget) + { + LogWidget->setWindowTitle(QApplication::translate("LogWidget", "Log", 0)); + QTableWidgetItem *___qtablewidgetitem = tableWidget->horizontalHeaderItem(0); + ___qtablewidgetitem->setText(QApplication::translate("LogWidget", "System", 0)); + QTableWidgetItem *___qtablewidgetitem1 = tableWidget->horizontalHeaderItem(1); + ___qtablewidgetitem1->setText(QApplication::translate("LogWidget", "Message", 0)); + clearButton->setText(QApplication::translate("LogWidget", "Clear", 0)); + } // retranslateUi + +}; + +namespace Ui { + class LogWidget: public Ui_LogWidget {}; +} // namespace Ui + +QT_END_NAMESPACE + +#endif // UI_LOGWIDGET_H diff --git a/qteditor/QtEditor/ui_mainwindow.h b/qteditor/QtEditor/ui_mainwindow.h new file mode 100644 index 000000000..7d31745f4 --- /dev/null +++ b/qteditor/QtEditor/ui_mainwindow.h @@ -0,0 +1,155 @@ +/******************************************************************************** +** Form generated from reading UI file 'mainwindow.ui' +** +** Created by: Qt User Interface Compiler version 5.2.1 +** +** WARNING! All changes made in this file will be lost when recompiling UI file! +********************************************************************************/ + +#ifndef UI_MAINWINDOW_H +#define UI_MAINWINDOW_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "sceneview.h" + +QT_BEGIN_NAMESPACE + +class Ui_MainWindow +{ +public: + QAction *actionLog; + QAction *actionNew; + QAction *actionOpen; + QAction *actionSave; + QAction *actionE_xit; + QAction *actionSave_As; + QAction *actionGame_mode; + QAction *actionCompile_scripts; + QAction *actionCreate; + QAction *actionProperties; + QWidget *centralWidget; + QGridLayout *gridLayout; + SceneView *widget; + QMenuBar *menuBar; + QMenu *menuView; + QMenu *menuFile; + QMenu *menuTools; + QMenu *menuEntity; + QToolBar *mainToolBar; + QStatusBar *statusBar; + + void setupUi(QMainWindow *MainWindow) + { + if (MainWindow->objectName().isEmpty()) + MainWindow->setObjectName(QStringLiteral("MainWindow")); + MainWindow->resize(892, 658); + actionLog = new QAction(MainWindow); + actionLog->setObjectName(QStringLiteral("actionLog")); + actionNew = new QAction(MainWindow); + actionNew->setObjectName(QStringLiteral("actionNew")); + actionOpen = new QAction(MainWindow); + actionOpen->setObjectName(QStringLiteral("actionOpen")); + actionSave = new QAction(MainWindow); + actionSave->setObjectName(QStringLiteral("actionSave")); + actionE_xit = new QAction(MainWindow); + actionE_xit->setObjectName(QStringLiteral("actionE_xit")); + actionSave_As = new QAction(MainWindow); + actionSave_As->setObjectName(QStringLiteral("actionSave_As")); + actionGame_mode = new QAction(MainWindow); + actionGame_mode->setObjectName(QStringLiteral("actionGame_mode")); + actionCompile_scripts = new QAction(MainWindow); + actionCompile_scripts->setObjectName(QStringLiteral("actionCompile_scripts")); + actionCreate = new QAction(MainWindow); + actionCreate->setObjectName(QStringLiteral("actionCreate")); + actionProperties = new QAction(MainWindow); + actionProperties->setObjectName(QStringLiteral("actionProperties")); + centralWidget = new QWidget(MainWindow); + centralWidget->setObjectName(QStringLiteral("centralWidget")); + gridLayout = new QGridLayout(centralWidget); + gridLayout->setSpacing(6); + gridLayout->setContentsMargins(11, 11, 11, 11); + gridLayout->setObjectName(QStringLiteral("gridLayout")); + widget = new SceneView(centralWidget); + widget->setObjectName(QStringLiteral("widget")); + + gridLayout->addWidget(widget, 0, 0, 1, 1); + + MainWindow->setCentralWidget(centralWidget); + menuBar = new QMenuBar(MainWindow); + menuBar->setObjectName(QStringLiteral("menuBar")); + menuBar->setGeometry(QRect(0, 0, 892, 21)); + menuView = new QMenu(menuBar); + menuView->setObjectName(QStringLiteral("menuView")); + menuFile = new QMenu(menuBar); + menuFile->setObjectName(QStringLiteral("menuFile")); + menuTools = new QMenu(menuBar); + menuTools->setObjectName(QStringLiteral("menuTools")); + menuEntity = new QMenu(menuBar); + menuEntity->setObjectName(QStringLiteral("menuEntity")); + MainWindow->setMenuBar(menuBar); + mainToolBar = new QToolBar(MainWindow); + mainToolBar->setObjectName(QStringLiteral("mainToolBar")); + MainWindow->addToolBar(Qt::TopToolBarArea, mainToolBar); + statusBar = new QStatusBar(MainWindow); + statusBar->setObjectName(QStringLiteral("statusBar")); + MainWindow->setStatusBar(statusBar); + + menuBar->addAction(menuFile->menuAction()); + menuBar->addAction(menuView->menuAction()); + menuBar->addAction(menuTools->menuAction()); + menuBar->addAction(menuEntity->menuAction()); + menuView->addAction(actionLog); + menuView->addAction(actionProperties); + menuFile->addAction(actionNew); + menuFile->addAction(actionOpen); + menuFile->addAction(actionSave); + menuFile->addAction(actionSave_As); + menuFile->addAction(actionE_xit); + menuTools->addAction(actionGame_mode); + menuTools->addAction(actionCompile_scripts); + menuEntity->addAction(actionCreate); + + retranslateUi(MainWindow); + + QMetaObject::connectSlotsByName(MainWindow); + } // setupUi + + void retranslateUi(QMainWindow *MainWindow) + { + MainWindow->setWindowTitle(QApplication::translate("MainWindow", "MainWindow", 0)); + actionLog->setText(QApplication::translate("MainWindow", "Log", 0)); + actionNew->setText(QApplication::translate("MainWindow", "&New", 0)); + actionOpen->setText(QApplication::translate("MainWindow", "&Open", 0)); + actionSave->setText(QApplication::translate("MainWindow", "&Save", 0)); + actionE_xit->setText(QApplication::translate("MainWindow", "E&xit", 0)); + actionSave_As->setText(QApplication::translate("MainWindow", "Save As", 0)); + actionGame_mode->setText(QApplication::translate("MainWindow", "Game mode", 0)); + actionCompile_scripts->setText(QApplication::translate("MainWindow", "Compile scripts", 0)); + actionCreate->setText(QApplication::translate("MainWindow", "Create", 0)); + actionProperties->setText(QApplication::translate("MainWindow", "Properties", 0)); + menuView->setTitle(QApplication::translate("MainWindow", "View", 0)); + menuFile->setTitle(QApplication::translate("MainWindow", "File", 0)); + menuTools->setTitle(QApplication::translate("MainWindow", "Tools", 0)); + menuEntity->setTitle(QApplication::translate("MainWindow", "Entity", 0)); + } // retranslateUi + +}; + +namespace Ui { + class MainWindow: public Ui_MainWindow {}; +} // namespace Ui + +QT_END_NAMESPACE + +#endif // UI_MAINWINDOW_H diff --git a/qteditor/QtEditor/ui_property_view.h b/qteditor/QtEditor/ui_property_view.h new file mode 100644 index 000000000..50764c746 --- /dev/null +++ b/qteditor/QtEditor/ui_property_view.h @@ -0,0 +1,123 @@ +/******************************************************************************** +** Form generated from reading UI file 'property_view.ui' +** +** Created by: Qt User Interface Compiler version 5.2.1 +** +** WARNING! All changes made in this file will be lost when recompiling UI file! +********************************************************************************/ + +#ifndef UI_PROPERTY_VIEW_H +#define UI_PROPERTY_VIEW_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class Ui_PropertyView +{ +public: + QWidget *dockWidgetContents; + QVBoxLayout *verticalLayout; + QToolBox *components; + QWidget *componentA; + QWidget *componentB; + QWidget *widget; + QHBoxLayout *horizontalLayout; + QComboBox *componentTypeCombo; + QPushButton *addComponentButton; + + void setupUi(QDockWidget *PropertyView) + { + if (PropertyView->objectName().isEmpty()) + PropertyView->setObjectName(QStringLiteral("PropertyView")); + PropertyView->resize(251, 446); + dockWidgetContents = new QWidget(); + dockWidgetContents->setObjectName(QStringLiteral("dockWidgetContents")); + verticalLayout = new QVBoxLayout(dockWidgetContents); + verticalLayout->setObjectName(QStringLiteral("verticalLayout")); + components = new QToolBox(dockWidgetContents); + components->setObjectName(QStringLiteral("components")); + componentA = new QWidget(); + componentA->setObjectName(QStringLiteral("componentA")); + componentA->setGeometry(QRect(0, 0, 98, 28)); + components->addItem(componentA, QStringLiteral("Page 1")); + componentB = new QWidget(); + componentB->setObjectName(QStringLiteral("componentB")); + componentB->setGeometry(QRect(0, 0, 233, 315)); + components->addItem(componentB, QStringLiteral("Page 2")); + + verticalLayout->addWidget(components); + + widget = new QWidget(dockWidgetContents); + widget->setObjectName(QStringLiteral("widget")); + horizontalLayout = new QHBoxLayout(widget); + horizontalLayout->setObjectName(QStringLiteral("horizontalLayout")); + componentTypeCombo = new QComboBox(widget); + componentTypeCombo->setObjectName(QStringLiteral("componentTypeCombo")); + QSizePolicy sizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); + sizePolicy.setHorizontalStretch(2); + sizePolicy.setVerticalStretch(2); + sizePolicy.setHeightForWidth(componentTypeCombo->sizePolicy().hasHeightForWidth()); + componentTypeCombo->setSizePolicy(sizePolicy); + + horizontalLayout->addWidget(componentTypeCombo); + + addComponentButton = new QPushButton(widget); + addComponentButton->setObjectName(QStringLiteral("addComponentButton")); + QSizePolicy sizePolicy1(QSizePolicy::Minimum, QSizePolicy::Fixed); + sizePolicy1.setHorizontalStretch(1); + sizePolicy1.setVerticalStretch(1); + sizePolicy1.setHeightForWidth(addComponentButton->sizePolicy().hasHeightForWidth()); + addComponentButton->setSizePolicy(sizePolicy1); + + horizontalLayout->addWidget(addComponentButton); + + + verticalLayout->addWidget(widget); + + PropertyView->setWidget(dockWidgetContents); + + retranslateUi(PropertyView); + + components->setCurrentIndex(1); + components->layout()->setSpacing(1); + + + QMetaObject::connectSlotsByName(PropertyView); + } // setupUi + + void retranslateUi(QDockWidget *PropertyView) + { + PropertyView->setWindowTitle(QApplication::translate("PropertyView", "Properties", 0)); + components->setItemText(components->indexOf(componentA), QApplication::translate("PropertyView", "Page 1", 0)); + components->setItemText(components->indexOf(componentB), QApplication::translate("PropertyView", "Page 2", 0)); + componentTypeCombo->clear(); + componentTypeCombo->insertItems(0, QStringList() + << QApplication::translate("PropertyView", "Renderable", 0) + << QApplication::translate("PropertyView", "Animable", 0) + << QApplication::translate("PropertyView", "Point Light", 0) + << QApplication::translate("PropertyView", "Script", 0) + ); + addComponentButton->setText(QApplication::translate("PropertyView", "Add", 0)); + } // retranslateUi + +}; + +namespace Ui { + class PropertyView: public Ui_PropertyView {}; +} // namespace Ui + +QT_END_NAMESPACE + +#endif // UI_PROPERTY_VIEW_H diff --git a/qteditor/QtEditor/ui_property_widget_base.h b/qteditor/QtEditor/ui_property_widget_base.h new file mode 100644 index 000000000..3f9ba9f96 --- /dev/null +++ b/qteditor/QtEditor/ui_property_widget_base.h @@ -0,0 +1,51 @@ +/******************************************************************************** +** Form generated from reading UI file 'property_widget_base.ui' +** +** Created by: Qt User Interface Compiler version 5.2.1 +** +** WARNING! All changes made in this file will be lost when recompiling UI file! +********************************************************************************/ + +#ifndef UI_PROPERTY_WIDGET_BASE_H +#define UI_PROPERTY_WIDGET_BASE_H + +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class Ui_PropertyWidgetBase +{ +public: + + void setupUi(QFrame *PropertyWidgetBase) + { + if (PropertyWidgetBase->objectName().isEmpty()) + PropertyWidgetBase->setObjectName(QStringLiteral("PropertyWidgetBase")); + PropertyWidgetBase->resize(245, 324); + PropertyWidgetBase->setFrameShape(QFrame::StyledPanel); + PropertyWidgetBase->setFrameShadow(QFrame::Raised); + + retranslateUi(PropertyWidgetBase); + + QMetaObject::connectSlotsByName(PropertyWidgetBase); + } // setupUi + + void retranslateUi(QFrame *PropertyWidgetBase) + { + PropertyWidgetBase->setWindowTitle(QApplication::translate("PropertyWidgetBase", "Frame", 0)); + } // retranslateUi + +}; + +namespace Ui { + class PropertyWidgetBase: public Ui_PropertyWidgetBase {}; +} // namespace Ui + +QT_END_NAMESPACE + +#endif // UI_PROPERTY_WIDGET_BASE_H diff --git a/qteditor/QtEditor/ui_renderable_widget.h b/qteditor/QtEditor/ui_renderable_widget.h new file mode 100644 index 000000000..2e6304976 --- /dev/null +++ b/qteditor/QtEditor/ui_renderable_widget.h @@ -0,0 +1,90 @@ +/******************************************************************************** +** Form generated from reading UI file 'renderable_widget.ui' +** +** Created by: Qt User Interface Compiler version 5.2.1 +** +** WARNING! All changes made in this file will be lost when recompiling UI file! +********************************************************************************/ + +#ifndef UI_RENDERABLE_WIDGET_H +#define UI_RENDERABLE_WIDGET_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class Ui_RenderableWidget +{ +public: + QFormLayout *formLayout; + QLabel *label; + QWidget *source; + QHBoxLayout *horizontalLayout; + QLineEdit *sourceEdit; + QPushButton *browseSource; + + void setupUi(QFrame *RenderableWidget) + { + if (RenderableWidget->objectName().isEmpty()) + RenderableWidget->setObjectName(QStringLiteral("RenderableWidget")); + RenderableWidget->resize(311, 300); + RenderableWidget->setFrameShape(QFrame::StyledPanel); + RenderableWidget->setFrameShadow(QFrame::Raised); + formLayout = new QFormLayout(RenderableWidget); + formLayout->setObjectName(QStringLiteral("formLayout")); + formLayout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow); + label = new QLabel(RenderableWidget); + label->setObjectName(QStringLiteral("label")); + + formLayout->setWidget(1, QFormLayout::LabelRole, label); + + source = new QWidget(RenderableWidget); + source->setObjectName(QStringLiteral("source")); + horizontalLayout = new QHBoxLayout(source); + horizontalLayout->setObjectName(QStringLiteral("horizontalLayout")); + sourceEdit = new QLineEdit(source); + sourceEdit->setObjectName(QStringLiteral("sourceEdit")); + + horizontalLayout->addWidget(sourceEdit); + + browseSource = new QPushButton(source); + browseSource->setObjectName(QStringLiteral("browseSource")); + + horizontalLayout->addWidget(browseSource); + + + formLayout->setWidget(1, QFormLayout::FieldRole, source); + + + retranslateUi(RenderableWidget); + + QMetaObject::connectSlotsByName(RenderableWidget); + } // setupUi + + void retranslateUi(QFrame *RenderableWidget) + { + RenderableWidget->setWindowTitle(QApplication::translate("RenderableWidget", "Frame", 0)); + label->setText(QApplication::translate("RenderableWidget", "Source", 0)); + browseSource->setText(QApplication::translate("RenderableWidget", "...", 0)); + } // retranslateUi + +}; + +namespace Ui { + class RenderableWidget: public Ui_RenderableWidget {}; +} // namespace Ui + +QT_END_NAMESPACE + +#endif // UI_RENDERABLE_WIDGET_H diff --git a/qteditor/QtEditor/ui_script_widget.h b/qteditor/QtEditor/ui_script_widget.h new file mode 100644 index 000000000..dd36e524b --- /dev/null +++ b/qteditor/QtEditor/ui_script_widget.h @@ -0,0 +1,90 @@ +/******************************************************************************** +** Form generated from reading UI file 'script_widget.ui' +** +** Created by: Qt User Interface Compiler version 5.2.1 +** +** WARNING! All changes made in this file will be lost when recompiling UI file! +********************************************************************************/ + +#ifndef UI_SCRIPT_WIDGET_H +#define UI_SCRIPT_WIDGET_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class Ui_ScriptWidget +{ +public: + QFormLayout *formLayout; + QLabel *sourceLabel; + QWidget *sourceWidget; + QHBoxLayout *horizontalLayout; + QLineEdit *sourceEdit; + QPushButton *browseSourceButton; + + void setupUi(QFrame *ScriptWidget) + { + if (ScriptWidget->objectName().isEmpty()) + ScriptWidget->setObjectName(QStringLiteral("ScriptWidget")); + ScriptWidget->resize(272, 250); + ScriptWidget->setFrameShape(QFrame::StyledPanel); + ScriptWidget->setFrameShadow(QFrame::Raised); + formLayout = new QFormLayout(ScriptWidget); + formLayout->setObjectName(QStringLiteral("formLayout")); + formLayout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow); + sourceLabel = new QLabel(ScriptWidget); + sourceLabel->setObjectName(QStringLiteral("sourceLabel")); + + formLayout->setWidget(0, QFormLayout::LabelRole, sourceLabel); + + sourceWidget = new QWidget(ScriptWidget); + sourceWidget->setObjectName(QStringLiteral("sourceWidget")); + horizontalLayout = new QHBoxLayout(sourceWidget); + horizontalLayout->setObjectName(QStringLiteral("horizontalLayout")); + sourceEdit = new QLineEdit(sourceWidget); + sourceEdit->setObjectName(QStringLiteral("sourceEdit")); + + horizontalLayout->addWidget(sourceEdit); + + browseSourceButton = new QPushButton(sourceWidget); + browseSourceButton->setObjectName(QStringLiteral("browseSourceButton")); + + horizontalLayout->addWidget(browseSourceButton); + + + formLayout->setWidget(0, QFormLayout::FieldRole, sourceWidget); + + + retranslateUi(ScriptWidget); + + QMetaObject::connectSlotsByName(ScriptWidget); + } // setupUi + + void retranslateUi(QFrame *ScriptWidget) + { + ScriptWidget->setWindowTitle(QApplication::translate("ScriptWidget", "Frame", 0)); + sourceLabel->setText(QApplication::translate("ScriptWidget", "Source", 0)); + browseSourceButton->setText(QApplication::translate("ScriptWidget", "...", 0)); + } // retranslateUi + +}; + +namespace Ui { + class ScriptWidget: public Ui_ScriptWidget {}; +} // namespace Ui + +QT_END_NAMESPACE + +#endif // UI_SCRIPT_WIDGET_H diff --git a/src/editor/editor_client.cpp b/src/editor/editor_client.cpp index e2ddd9c65..dbbdbd38f 100644 --- a/src/editor/editor_client.cpp +++ b/src/editor/editor_client.cpp @@ -1,8 +1,9 @@ #include "editor_client.h" +#include "core/array.h" #include "core/blob.h" #include "core/crc32.h" #include "core/event_manager.h" -#include "core/array.h" +#include "core/mutex.h" #include "core/task.h" #include "core/tcp_connector.h" #include "core/tcp_stream.h" @@ -29,6 +30,11 @@ namespace Lux struct EditorClientImpl { + EditorClientImpl() + : m_mutex(false) + { + } + void sendMessage(uint32_t type, const void* data, int32_t size); void onMessage(uint8_t* data, int size); @@ -36,6 +42,9 @@ namespace Lux Net::TCPStream* m_stream; ReceiveTask m_task; EventManager m_event_manager; + MT::Mutex m_mutex; + Array m_messages; + string m_base_path; }; @@ -47,14 +56,18 @@ namespace Lux { if(m_client->m_stream->read(&data[0], 8)) { - int length = *(int*)&data[0]; - int guard = *(int*)&data[4]; + int32_t length = *(int32_t*)&data[0]; + int32_t guard = *(int32_t*)&data[4]; ASSERT(guard == 0x12345678); if(length > 0) { data.resize(length); - m_client->m_stream->read(&data[0], length); - m_client->onMessage(&data[0], data.size()); + /// TODO "stack" allocator + uint8_t* msg = LUX_NEW_ARRAY(uint8_t, length + 4); + m_client->m_stream->read(msg + 4, length); + ((int32_t*)msg)[0] = length; + MT::Lock lock(m_client->m_mutex); + m_client->m_messages.push(msg); } } } @@ -62,9 +75,22 @@ namespace Lux } - bool EditorClient::create() + void EditorClient::processMessages() + { + MT::Lock lock(m_impl->m_mutex); + for (int i = 0; i < m_impl->m_messages.size(); ++i) + { + m_impl->onMessage(m_impl->m_messages[i] + 4, *(int32_t*)m_impl->m_messages[i]); + LUX_DELETE_ARRAY(m_impl->m_messages[i]); + } + m_impl->m_messages.clear(); + } + + + bool EditorClient::create(const char* base_path) { m_impl = LUX_NEW(EditorClientImpl); + m_impl->m_base_path = base_path; m_impl->m_stream = m_impl->m_connector.connect("127.0.0.1", 10013); m_impl->m_task.m_client = m_impl; bool success = m_impl->m_task.create("ClientReceiver"); @@ -136,6 +162,12 @@ namespace Lux } + const char* EditorClient::getBasePath() const + { + return m_impl->m_base_path.c_str(); + } + + void EditorClient::addComponent(uint32_t type) { m_impl->sendMessage((uint32_t)ClientMessageType::ADD_COMPONENT, &type, sizeof(type)); diff --git a/src/editor/editor_client.h b/src/editor/editor_client.h index 023123bf1..61e112201 100644 --- a/src/editor/editor_client.h +++ b/src/editor/editor_client.h @@ -7,34 +7,36 @@ namespace Lux { - struct Entity; - class EventManager; - struct ServerMessage; - struct Vec3; + struct Entity; + class EventManager; + struct ServerMessage; + struct Vec3; - class LUX_ENGINE_API EditorClient - { - public: - EditorClient() { m_impl = 0; } + class LUX_ENGINE_API EditorClient + { + public: + EditorClient() { m_impl = 0; } - bool create(); - void destroy(); - void addEntity(); - void toggleGameMode(); - void addComponent(uint32_t type); - void mouseDown(int x, int y, int button); - void mouseUp(int x, int y, int button); - void mouseMove(int x, int y, int dx, int dy); - void requestProperties(uint32_t type_crc); - void setComponentProperty(const char* component, const char* property, const void* value, int32_t length); - void navigate(float forward, float right, int32_t fast); - void loadUniverse(const char* path); - void saveUniverse(const char* path); - void setEntityPosition(int32_t entity, const Vec3& position); - EventManager& getEventManager(); + bool create(const char* base_path); + void destroy(); + void processMessages(); + void addEntity(); + void toggleGameMode(); + void addComponent(uint32_t type); + void mouseDown(int x, int y, int button); + void mouseUp(int x, int y, int button); + void mouseMove(int x, int y, int dx, int dy); + void requestProperties(uint32_t type_crc); + void setComponentProperty(const char* component, const char* property, const void* value, int32_t length); + void navigate(float forward, float right, int32_t fast); + void loadUniverse(const char* path); + void saveUniverse(const char* path); + void setEntityPosition(int32_t entity, const Vec3& position); + const char* getBasePath() const; + EventManager& getEventManager(); - private: - struct EditorClientImpl* m_impl; - }; + private: + struct EditorClientImpl* m_impl; + }; } // ~namespace Lux \ No newline at end of file diff --git a/src/editor/editor_icon.cpp b/src/editor/editor_icon.cpp index 8a2e93f7a..5f1552d66 100644 --- a/src/editor/editor_icon.cpp +++ b/src/editor/editor_icon.cpp @@ -1,5 +1,6 @@ #include "editor_icon.h" #include "core/crc32.h" +#include "core/math_utils.h" #include "core/matrix.h" #include "graphics/irender_device.h" #include "graphics/pipeline.h" @@ -33,8 +34,6 @@ void EditorIcon::create(Entity& entity, const Component& cmp) void EditorIcon::destroy() { - //h3dRemoveNode(m_handle); - ASSERT(false); } @@ -52,6 +51,81 @@ void EditorIcon::hide() } + +float EditorIcon::hit(Renderer& renderer, Component camera, const Vec3& origin, const Vec3& dir) const +{ + Lux::Matrix mtx = camera.entity.getMatrix(); + + float fov; + renderer.getCameraFov(camera, fov); + float scale = tan(fov * Math::PI / 180.0f * 0.5f) * (m_entity.getPosition() - mtx.getTranslation()).length() / 20; + + mtx.setTranslation(m_entity.getPosition()); + Matrix scale_mtx = Matrix::IDENTITY; + scale_mtx.m11 = scale_mtx.m22 = scale_mtx.m33 = scale; + mtx = mtx * scale_mtx; + + Vec3 p[6]; + p[0].set(-1, -1, 0); + p[1].set(-1, 1, 0); + p[2].set(1, 1, 0); + p[3] = p[0]; + p[4] = p[2]; + p[5].set(1, -1, 0); + + Matrix inv = mtx; + inv.inverse(); + Vec3 local_origin = inv.mutliplyPosition(origin); + Vec3 local_dir = static_cast(inv * Vec4(dir.x, dir.y, dir.z, 0)); + + int32_t last_hit_index = -1; + for (int i = 0; i < 6; i += 3) + { + Vec3 p0 = p[i]; + Vec3 p1 = p[i + 1]; + Vec3 p2 = p[i + 2]; + Vec3 normal = crossProduct(p1 - p0, p2 - p0); + float q = dotProduct(normal, local_dir); + if (q == 0) + { + continue; + } + float d = -dotProduct(normal, p0); + float t = -(dotProduct(normal, local_origin) + d) / q; + if (t < 0) + { + continue; + } + Vec3 hit_point = local_origin + local_dir * t; + + Vec3 edge0 = p1 - p0; + Vec3 VP0 = hit_point - p0; + if (dotProduct(normal, crossProduct(edge0, VP0)) < 0) + { + continue; + } + + Vec3 edge1 = p2 - p1; + Vec3 VP1 = hit_point - p1; + if (dotProduct(normal, crossProduct(edge1, VP1)) < 0) + { + continue; + } + + Vec3 edge2 = p0 - p2; + Vec3 VP2 = hit_point - p2; + if (dotProduct(normal, crossProduct(edge2, VP2)) < 0) + { + continue; + } + + return t; + } + + return -1; +} + + void EditorIcon::render(Renderer* renderer, IRenderDevice& render_device) { Component camera = render_device.getPipeline().getCamera(0); @@ -59,7 +133,7 @@ void EditorIcon::render(Renderer* renderer, IRenderDevice& render_device) float fov; renderer->getCameraFov(camera, fov); - float scale = tan(fov * 0.5f) * (m_entity.getPosition() - mtx.getTranslation()).length() * 2; + float scale = tan(fov * Math::PI / 180 * 0.5f) * (m_entity.getPosition() - mtx.getTranslation()).length() / 20; mtx.setTranslation(m_entity.getPosition()); Matrix scale_mtx = Matrix::IDENTITY; @@ -69,10 +143,10 @@ void EditorIcon::render(Renderer* renderer, IRenderDevice& render_device) glPushMatrix(); glMultMatrixf(&mtx.m11); glBegin(GL_QUADS); - glVertex3f(-0.015f, -0.015f, 0); - glVertex3f(-0.015f, 0.015f, 0); - glVertex3f(0.015f, 0.015f, 0); - glVertex3f(0.015f, -0.015f, 0); + glVertex3f(-1, -1, 0); + glVertex3f(-1, 1, 0); + glVertex3f(1, 1, 0); + glVertex3f(1, -1, 0); glEnd(); glPopMatrix(); } diff --git a/src/editor/editor_icon.h b/src/editor/editor_icon.h index b85ff8c36..8f233211e 100644 --- a/src/editor/editor_icon.h +++ b/src/editor/editor_icon.h @@ -23,6 +23,7 @@ class EditorIcon void render(Renderer* renderer, IRenderDevice& render_device); void show(); void hide(); + float hit(Renderer& renderer, Component camera, const Vec3& origin, const Vec3& dir) const; //H3DNode getHandle() const { return m_handle; } Entity getEntity() const { return m_entity; } diff --git a/src/editor/editor_server.cpp b/src/editor/editor_server.cpp index 2c311d12f..ecbb78a6b 100644 --- a/src/editor/editor_server.cpp +++ b/src/editor/editor_server.cpp @@ -45,6 +45,13 @@ namespace Lux { +struct EditorIconHit +{ + EditorIcon* m_icon; + float m_t; +}; + + struct ClientMessageType { enum @@ -159,6 +166,7 @@ struct EditorServerImpl void save(FS::IFile& file); void load(FS::IFile& file); void onMessage(void* msgptr, int size); + EditorIconHit raycastEditorIcons(Component camera, const Vec3& origin, const Vec3& dir); const IPropertyDescriptor& getPropertyDescriptor(uint32_t type, uint32_t name_hash); void registerProperties(); @@ -172,8 +180,6 @@ struct EditorServerImpl void onLogError(const char* system, const char* message); void sendMessage(const uint8_t* data, int32_t length); - static void onEvent(void* data, Event& evt); - MT::Mutex m_universe_mutex; MT::Mutex m_send_mutex; Gizmo m_gizmo; @@ -202,7 +208,7 @@ struct EditorServerImpl static const uint32_t renderable_type = crc32("renderable"); static const uint32_t camera_type = crc32("camera"); -static const uint32_t point_light_type = crc32("point_light"); +static const uint32_t light_type = crc32("light"); static const uint32_t script_type = crc32("script"); static const uint32_t animable_type = crc32("animable"); @@ -316,7 +322,25 @@ void EditorServerImpl::registerProperties() m_component_properties[renderable_type].push(LUX_NEW(PropertyDescriptor)(crc32("cast shadows"), &Renderer::getCastShadows, &Renderer::setCastShadows)); m_component_properties[point_light_type].push(LUX_NEW(PropertyDescriptor)(crc32("fov"), &Renderer::getLightFov, &Renderer::setLightFov)); m_component_properties[point_light_type].push(LUX_NEW(PropertyDescriptor)(crc32("radius"), &Renderer::getLightRadius, &Renderer::setLightRadius)); - m_component_properties[script_type].push(LUX_NEW(PropertyDescriptor)(crc32("source"), &ScriptSystem::getScriptPath, &ScriptSystem::setScriptPath, IPropertyDescriptor::FILE));*/ + */m_component_properties[script_type].push(LUX_NEW(PropertyDescriptor)(crc32("source"), &ScriptSystem::getScriptPath, &ScriptSystem::setScriptPath, IPropertyDescriptor::FILE)); +} + + +EditorIconHit EditorServerImpl::raycastEditorIcons(Component camera, const Vec3& origin, const Vec3& dir) +{ + EditorIconHit hit; + hit.m_t = -1; + for (int i = 0; i < m_editor_icons.size(); ++i) + { + float t = m_editor_icons[i]->hit(m_engine.getRenderer(), camera, origin, dir); + if (t >= 0) + { + hit.m_icon = m_editor_icons[i]; + hit.m_t = t; + return hit; + } + } + return hit; } @@ -332,7 +356,12 @@ void EditorServerImpl::onPointerDown(int x, int y, MouseButton::Value button) Component camera_cmp = m_camera.getComponent(camera_type); m_engine.getRenderer().getRay(camera_cmp, (float)x, (float)y, origin, dir); RayCastModelHit hit = m_engine.getRenderer().castRay(origin, dir); - if(hit.m_is_hit) + EditorIconHit icon_hit = raycastEditorIcons(camera_cmp, origin, dir); + if (icon_hit.m_t >= 0 && (!hit.m_is_hit || hit.m_t > icon_hit.m_t)) + { + selectEntity(icon_hit.m_icon->getEntity()); + } + else if(hit.m_is_hit) { if(hit.m_renderable == m_gizmo.getRenderable()) { @@ -588,12 +617,11 @@ void EditorServerImpl::addComponent(uint32_t type_crc) } else if(type_crc == renderable_type) { - m_engine.getRenderer().createComponent(crc32("renderable"), m_selected_entity); + m_engine.getRenderer().createComponent(renderable_type, m_selected_entity); } - else if(type_crc == point_light_type) + else if(type_crc == light_type) { - ASSERT(false); - // m_engine.getRenderer().createPointLight(m_selected_entity); + m_engine.getRenderer().createComponent(light_type, m_selected_entity); } else if(type_crc == script_type) { @@ -686,27 +714,12 @@ void EditorServerImpl::newUniverse() void EditorServerImpl::load(FS::IFile& file) { - /*g_log_info.log("editor server", "parsing universe..."); - int selected_idx = m_selected_entity.index; + g_log_info.log("editor server", "parsing universe..."); destroyUniverse(); createUniverse(false, ""); JsonSerializer serializer(file, JsonSerializer::READ); - m_engine.deserialize(serializer); - serializer.deserialize("cam_pos_x", m_camera_pos.x); - serializer.deserialize("cam_pos_y", m_camera_pos.y); - serializer.deserialize("cam_pos_z", m_camera_pos.z); - serializer.deserialize("cam_rot_x", m_camera_rot.x); - serializer.deserialize("cam_rot_y", m_camera_rot.y); - serializer.deserialize("cam_rot_z", m_camera_rot.z); - serializer.deserialize("cam_rot_w", m_camera_rot.w); - selectEntity(Entity(m_engine.getUniverse(), selected_idx)); - Matrix mtx; - m_camera_rot.toMatrix(mtx); - mtx.setTranslation(m_camera_pos); - m_engine.getRenderer().setCameraMatrix(mtx); - g_log_info.log("editor server", "universe parsed");*/ - ASSERT(false); + g_log_info.log("editor server", "universe parsed"); } @@ -786,7 +799,7 @@ bool EditorServerImpl::create(HWND hwnd, HWND game_hwnd, const char* base_path) //glPopAttrib(); - if(!m_engine.loadPlugin("physics.dll")) + /*if(!m_engine.loadPlugin("physics.dll")) { g_log_info.log("plugins", "physics plugin has not been loaded"); } @@ -805,6 +818,12 @@ bool EditorServerImpl::create(HWND hwnd, HWND game_hwnd, const char* base_path) } +Component EditorServer::getCamera() const +{ + return m_impl->m_camera.getComponent(camera_type); +} + + void EditorServerImpl::destroy() { m_message_task->m_is_finished = true; @@ -1056,12 +1075,6 @@ void EditorServerImpl::selectEntity(Entity e) } -void EditorServerImpl::onEvent(void* data, Event& evt) -{ - static_cast(data)->onEvent(evt); -} - - void EditorServerImpl::onComponentEvent(ComponentEvent& e) { for(int i = 0; i < m_editor_icons.size(); ++i) @@ -1155,13 +1168,13 @@ void EditorServerImpl::createUniverse(bool create_scene, const char* base_path) m_camera.setPosition(0, 0, -5); m_camera.setRotation(Quat(Vec3(0, 1, 0), -Math::PI)); Component cmp = m_engine.getRenderer().createComponent(camera_type, m_camera); - - /*Entity light = m_engine.getUniverse()->createEntity(); +/* + Entity light = m_engine.getUniverse()->createEntity(); Matrix mtx = Matrix::IDENTITY; mtx.setXVector(Vec3(1, 0, 0)); - mtx.setYVector(Vec3(0, -1, 1).normalized()); - mtx.setZVector(Vec3(0, -1, -1).normalized()); - mtx.setTranslation(Vec3(0, 20, 20)); + mtx.setYVector(Vec3(0, 0, 1).normalized()); + mtx.setZVector(Vec3(0, -1, 0).normalized()); + mtx.setTranslation(Vec3(0, 20, 0)); light.setMatrix(mtx); m_engine.getRenderer().createComponent(crc32("light"), light); @@ -1174,17 +1187,15 @@ void EditorServerImpl::createUniverse(bool create_scene, const char* base_path) Component cmp3 = m_engine.getRenderer().createComponent(renderable_type, m_engine.getUniverse()->createEntity()); m_engine.getRenderer().setRenderablePath(cmp3, string("models/plane.msh")); - /* - universe->getEventManager()->addListener(EntityMovedEvent::type).bind(this); - universe->getEventManager()->addListener(ComponentEvent::type).bind(this); - universe->getEventManager()->addListener(EntityDestroyedEvent::type).bind(this); - - addEntity(); - */ + m_gizmo.create(base_path, m_engine.getRenderer()); m_gizmo.setUniverse(universe); m_gizmo.hide(); + universe->getEventManager()->addListener(EntityMovedEvent::type).bind(this); + universe->getEventManager()->addListener(ComponentEvent::type).bind(this); + universe->getEventManager()->addListener(EntityDestroyedEvent::type).bind(this); + m_selected_entity = Entity::INVALID; } diff --git a/src/editor/editor_server.h b/src/editor/editor_server.h index bb12a88e0..877bb64ef 100644 --- a/src/editor/editor_server.h +++ b/src/editor/editor_server.h @@ -33,6 +33,7 @@ namespace Lux void registerProperty(const char* component_type, IPropertyDescriptor* descriptor); Engine& getEngine(); void render(IRenderDevice& render_device); + Component getCamera() const; private: struct EditorServerImpl* m_impl; diff --git a/src/editor_native/main.cpp b/src/editor_native/main.cpp index c4358f05f..e0af75d3a 100644 --- a/src/editor_native/main.cpp +++ b/src/editor_native/main.cpp @@ -51,7 +51,7 @@ struct App GetCurrentDirectoryA(MAX_PATH, path); m_server.create(NULL, NULL, path); m_server.onResize(800, 600); - m_client.create(); + m_client.create(m_server.getEngine().getBasePath()); initGui(m_client, m_server); Lux::UI::Gui* gui = (Lux::UI::Gui*)m_server.getEngine().getPluginManager().getPlugin("gui"); diff --git a/src/editor_native/property_frame/property_frame.cpp b/src/editor_native/property_frame/property_frame.cpp index 091ea478e..58bec824e 100644 --- a/src/editor_native/property_frame/property_frame.cpp +++ b/src/editor_native/property_frame/property_frame.cpp @@ -160,7 +160,7 @@ void PropertyFrame::onEntitySelected(Lux::Event& evt) { ui = LUX_NEW(ScriptUI)(*this, m_component_container, *m_main_frame->getEditorClient()); } - else if(e.components[i] == crc32("point_light")) + else if(e.components[i] == crc32("light")) { ui = LUX_NEW(PointLightUI)(*this, m_component_container, *m_main_frame->getEditorClient()); } diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index 87f59748f..f32296c48 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -263,8 +263,7 @@ namespace Lux void Engine::serialize(ISerializer& serializer) { m_impl->m_universe->serialize(serializer); - //m_impl->m_renderer.serialize(serializer); - //ASSERT(false); + m_impl->m_renderer->serialize(serializer); m_impl->m_script_system.serialize(serializer); m_impl->m_plugin_manager.serialize(serializer); } @@ -273,8 +272,7 @@ namespace Lux void Engine::deserialize(ISerializer& serializer) { m_impl->m_universe->deserialize(serializer); - //m_impl->m_renderer.deserialize(serializer); - //ASSERT(false); + m_impl->m_renderer->deserialize(serializer); m_impl->m_script_system.deserialize(serializer); m_impl->m_plugin_manager.deserialize(serializer); } diff --git a/src/engine/iplugin.h b/src/engine/iplugin.h index a4eb5152e..591af3853 100644 --- a/src/engine/iplugin.h +++ b/src/engine/iplugin.h @@ -26,7 +26,7 @@ namespace Lux virtual void update(float) {} virtual Component createComponent(uint32_t, const Entity&) = 0; virtual const char* getName() const = 0; - virtual void sendMessage(const char* message) {}; + virtual void sendMessage(const char*) {}; }; diff --git a/src/graphics/model.cpp b/src/graphics/model.cpp index 98178d1b5..29735520c 100644 --- a/src/graphics/model.cpp +++ b/src/graphics/model.cpp @@ -53,7 +53,7 @@ RayCastModelHit Model::castRay(const Vec3& origin, const Vec3& dir, const Matrix Vec3 p1 = vertices[i+1]; Vec3 p2 = vertices[i+2]; Vec3 normal = crossProduct(p1 - p0, p2 - p0); - float q = dotProduct(normal, dir); + float q = dotProduct(normal, local_dir); if(q == 0) { continue; @@ -64,7 +64,7 @@ RayCastModelHit Model::castRay(const Vec3& origin, const Vec3& dir, const Matrix { continue; } - Vec3 hit_point = local_origin + dir * t; + Vec3 hit_point = local_origin + local_dir * t; Vec3 edge0 = p1 - p0; Vec3 VP0 = hit_point - p0; diff --git a/src/graphics/pipeline.cpp b/src/graphics/pipeline.cpp index e9f8e06ce..30642d907 100644 --- a/src/graphics/pipeline.cpp +++ b/src/graphics/pipeline.cpp @@ -327,6 +327,7 @@ struct PipelineImpl : public Pipeline void renderShadowmap() { + glViewport(0, 0, 800, 600); /// TODO Component light_cmp = m_renderer.getLight(0); if (!light_cmp.isValid()) { diff --git a/src/graphics/renderer.cpp b/src/graphics/renderer.cpp index f456fbd27..40d93c1d9 100644 --- a/src/graphics/renderer.cpp +++ b/src/graphics/renderer.cpp @@ -134,6 +134,22 @@ struct RendererImpl : public Renderer } + void clearScene() + { + m_lights.clear(); + for (int i = 0; i < m_cameras.size(); ++i) + { + LUX_DELETE(m_cameras[i]); + } + m_cameras.clear(); + for (int i = 0; i < m_renderables.size(); ++i) + { + LUX_DELETE(m_renderables[i].m_model); + } + m_renderables.clear(); + } + + virtual void setUniverse(Universe* universe) LUX_OVERRIDE { if(m_universe) @@ -141,6 +157,7 @@ struct RendererImpl : public Renderer EventManager::Listener cb; cb.bind(this); m_universe->getEventManager()->removeListener(EntityMovedEvent::type, cb); + clearScene(); } m_universe = universe; if(m_universe) @@ -182,7 +199,7 @@ struct RendererImpl : public Renderer Camera* camera = LUX_NEW(Camera); camera->m_is_active = false; camera->m_entity = entity; - camera->m_fov = 90; + camera->m_fov = 60; camera->m_width = 800; camera->m_height = 600; camera->m_aspect = 800.0f / 600.0f; @@ -358,6 +375,75 @@ struct RendererImpl : public Renderer } + virtual void serialize(ISerializer& serializer) LUX_OVERRIDE + { + serializer.serialize("camera_count", m_cameras.size()); + serializer.beginArray("cameras"); + for (int i = 0; i < m_cameras.size(); ++i) + { + serializer.serializeArrayItem(m_cameras[i]->m_far); + serializer.serializeArrayItem(m_cameras[i]->m_near); + serializer.serializeArrayItem(m_cameras[i]->m_fov); + serializer.serializeArrayItem(m_cameras[i]->m_is_active); + serializer.serializeArrayItem(m_cameras[i]->m_width); + serializer.serializeArrayItem(m_cameras[i]->m_height); + serializer.serializeArrayItem(m_cameras[i]->m_entity.index); + } + serializer.endArray(); + serializer.serialize("renderable_count", m_renderables.size()); + serializer.beginArray("renderables"); + for (int i = 0; i < m_renderables.size(); ++i) + { + serializer.serializeArrayItem(m_renderables[i].m_entity.index); + serializer.serializeArrayItem(m_renderables[i].m_model->getModel().getPath()); + Matrix mtx = m_renderables[i].m_model->getMatrix(); + for (int j = 0; j < 16; ++j) + { + serializer.serializeArrayItem((&mtx.m11)[j]); + } + } + serializer.endArray(); + } + + + virtual void deserialize(ISerializer& serializer) LUX_OVERRIDE + { + clearScene(); + int size; + serializer.deserialize("camera_count", size); + serializer.deserializeArrayBegin("cameras"); + for (int i = 0; i < size; ++i) + { + m_cameras.push(LUX_NEW(Camera)); + serializer.deserializeArrayItem(m_cameras[i]->m_far); + serializer.deserializeArrayItem(m_cameras[i]->m_near); + serializer.deserializeArrayItem(m_cameras[i]->m_fov); + serializer.deserializeArrayItem(m_cameras[i]->m_is_active); + serializer.deserializeArrayItem(m_cameras[i]->m_width); + serializer.deserializeArrayItem(m_cameras[i]->m_height); + m_cameras[i]->m_aspect = m_cameras[i]->m_width / m_cameras[i]->m_height; + serializer.deserializeArrayItem(m_cameras[i]->m_entity.index); + m_cameras[i]->m_entity.universe = m_universe; + } + serializer.deserializeArrayEnd(); + serializer.deserialize("renderable_count", size); + serializer.deserializeArrayBegin("renderables"); + for (int i = 0; i < size; ++i) + { + m_renderables.pushEmpty(); + serializer.deserializeArrayItem(m_renderables[i].m_entity.index); + m_renderables[i].m_entity.universe = m_universe; + char path[MAX_PATH]; + serializer.deserializeArrayItem(path, MAX_PATH); + m_renderables[i].m_model = LUX_NEW(ModelInstance)(static_cast(*m_engine->getResourceManager().get(ResourceManager::MODEL)->load(path))); + for (int j = 0; j < 16; ++j) + { + serializer.deserializeArrayItem((&m_renderables[i].m_model->getMatrix().m11)[j]); + } + } + serializer.deserializeArrayEnd(); + } + Engine* m_engine; Array m_cameras; Array m_lights; diff --git a/src/script/script_system.cpp b/src/script/script_system.cpp index 566136d40..e7793c796 100644 --- a/src/script/script_system.cpp +++ b/src/script/script_system.cpp @@ -211,7 +211,10 @@ namespace Lux FS::FileSystem& fs = m_impl->m_engine->getFileSystem(); FS::IFile* file = fs.open(fs.getDefaultDevice(), full_path, FS::Mode::OPEN_OR_CREATE | FS::Mode::WRITE); - fs.close(file); + if (file) + { + fs.close(file); + } m_impl->m_scripts.push(entity.index); m_impl->m_paths.push(string(path));