diff --git a/CMakeLists.txt b/CMakeLists.txt index 5b06bc5..590322a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,11 +7,28 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) add_executable(Atlas-Launcher - source/main.cpp - # AngelScript external/angelscript/add_on/scriptbuilder/scriptbuilder.cpp external/angelscript/add_on/scriptstdstring/scriptstdstring.cpp + external/angelscript/add_on/scriptstdstring/scriptstdstring_utils.cpp + external/angelscript/add_on/datetime/datetime.cpp + external/angelscript/add_on/scriptany/scriptany.cpp + external/angelscript/add_on/scriptarray/scriptarray.cpp + external/angelscript/add_on/scriptgrid/scriptgrid.cpp + external/angelscript/add_on/scriptdictionary/scriptdictionary.cpp + external/angelscript/add_on/scripthandle/scripthandle.cpp + external/angelscript/add_on/weakref/weakref.cpp + external/angelscript/add_on/scriptmath/scriptmath.cpp + external/angelscript/add_on/scripthelper/scripthelper.cpp + + # Source + source/main.cpp + source/script/module/debug/load.cpp + source/script/module/debug/load.hpp + source/script/module/debug/log.cpp + source/script/module/debug/log.hpp + source/script/engine/Engine.cpp + source/script/engine/Engine.hpp ) target_include_directories(Atlas-Launcher PRIVATE source/ diff --git a/source/javascript/engine/AtlasJsEngine.cpp b/source/javascript/engine/AtlasJsEngine.cpp deleted file mode 100644 index aa51309..0000000 --- a/source/javascript/engine/AtlasJsEngine.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "AtlasJsEngine.hpp" - - -AtlasJsEngine::AtlasJsEngine(QObject *parent) : QJSEngine(parent) { - // instanciate a new Atlas module - this->moduleAtlas = std::make_unique(this); - - // convert it into a javascript object - const QJSValue jsModuleAtlas = this->newQObject(this->moduleAtlas.get()); - // make it accessible as "atlas" in the javascript code - this->globalObject().setProperty("atlas", jsModuleAtlas); -} - - -vfs::VirtualFileSystem& AtlasJsEngine::getFileSystem() { - return this->fileSystem; -} diff --git a/source/javascript/engine/AtlasJsEngine.hpp b/source/javascript/engine/AtlasJsEngine.hpp deleted file mode 100644 index a896a42..0000000 --- a/source/javascript/engine/AtlasJsEngine.hpp +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -#include "javascript/module/AtlasJsModule.hpp" - - -/** - * This class represent a Qt JavaScript engine modified to support the Atlas framework. - */ -class AtlasJsEngine : public QJSEngine { - -public: - explicit AtlasJsEngine(QObject* parent); - - vfs::VirtualFileSystem& getFileSystem(); - -protected: - vfs::VirtualFileSystem fileSystem; - -private: - std::shared_ptr moduleAtlas; -}; diff --git a/source/javascript/module/debug/DebugJsModule.cpp b/source/javascript/module/debug/DebugJsModule.cpp deleted file mode 100644 index b5d011e..0000000 --- a/source/javascript/module/debug/DebugJsModule.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include "DebugJsModule.hpp" - -#include - - -DebugJsModule::DebugJsModule(AtlasJsEngine* engine) : BaseJsModule(engine) {} - -void DebugJsModule::information(const QString& text) { - qDebug() << text; -} diff --git a/source/javascript/module/debug/DebugJsModule.hpp b/source/javascript/module/debug/DebugJsModule.hpp deleted file mode 100644 index 811331d..0000000 --- a/source/javascript/module/debug/DebugJsModule.hpp +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#include "../_base/BaseJsModule.hpp" - - -/** - * This module implements useful feature to help with debugging - */ -class DebugJsModule : public BaseJsModule { - Q_OBJECT - -public: - explicit DebugJsModule(AtlasJsEngine* engine); - - /** - * Print an informational message - */ - Q_INVOKABLE static void information(const QString& text); -}; diff --git a/source/main.cpp b/source/main.cpp index d102661..2ab3a8d 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -4,45 +4,35 @@ #include #include #include -#include #include - -void print(const std::string& in) { - std::cout << in; -} +#include "script/engine/Engine.hpp" +#include "script/module/debug/load.hpp" int main(int argc, char* argv[]) { int error; - // prepare a virtual file system - auto fileSystem = std::make_unique(); - - auto fileSystemTmp = std::make_shared(); - fileSystemTmp->Initialize(); - fileSystem->AddFileSystem("/tmp", fileSystemTmp); - // engine - asIScriptEngine* engine = asCreateScriptEngine(); - if (engine == nullptr) - throw std::runtime_error("Could not create the AngelScript Engine."); - - RegisterStdString(engine); + const auto atlasEngine = std::make_unique(); + auto* asEngine = atlasEngine->getAsEngine(); // functions - error = engine->RegisterGlobalFunction("void print(const string& in)", asFUNCTION(print), asCALL_CDECL); - if (error < 0) - throw std::runtime_error("Could not register the print function."); + atlas::script::module::debug::load(atlasEngine.get()); // script CScriptBuilder builder; - error = builder.StartNewModule(engine, "script"); + error = builder.StartNewModule(asEngine, "script"); if (error < 0) throw std::runtime_error("Could not start a new module."); - error = builder.AddSectionFromMemory("script", "void main() { print(\"hello world !\"); }"); + error = builder.AddSectionFromMemory("script", R"( + void main() { + array data(256); + atlas::debug::log("main", "hello world !"); + } + )"); if (error < 0) throw std::runtime_error("Could not add a section to the module."); @@ -51,7 +41,7 @@ int main(int argc, char* argv[]) { throw std::runtime_error("Could not build the module."); // execution - asIScriptModule *module = engine->GetModule("script"); + asIScriptModule *module = asEngine->GetModule("script"); if (module == nullptr) throw std::runtime_error("Could not get the module."); @@ -59,7 +49,7 @@ int main(int argc, char* argv[]) { if (function == nullptr) throw std::runtime_error("Could not get the main function."); - asIScriptContext *context = engine->CreateContext(); + asIScriptContext *context = asEngine->CreateContext(); if (context == nullptr) throw std::runtime_error("Could not create the context."); @@ -71,7 +61,6 @@ int main(int argc, char* argv[]) { // clean up context->Release(); - engine->Release(); return error; } diff --git a/source/script/engine/Engine.cpp b/source/script/engine/Engine.cpp new file mode 100644 index 0000000..9f1aeb0 --- /dev/null +++ b/source/script/engine/Engine.cpp @@ -0,0 +1,91 @@ +#include "Engine.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace atlas::script::engine { + +Engine::Engine() { + // create a new AngelScript engine + this->asEngine = asCreateScriptEngine(); + if (this->asEngine == nullptr) + throw std::runtime_error("Could not create the AngelScript Engine."); + + this->asEngine->SetMessageCallback(asFUNCTION(this->asCallback), nullptr, asCALL_CDECL); + + // AngelScript standard library + RegisterScriptArray(this->asEngine, true); + RegisterScriptGrid(this->asEngine); + RegisterStdString(this->asEngine); + RegisterStdStringUtils(this->asEngine); + RegisterScriptDictionary(this->asEngine); + RegisterScriptDateTime(this->asEngine); + RegisterScriptAny(this->asEngine); + RegisterScriptHandle(this->asEngine); + RegisterScriptWeakRef(this->asEngine); + RegisterExceptionRoutines(this->asEngine); + RegisterScriptMath(this->asEngine); + + // initialise the file system + this->fileSystem = std::make_unique(); + + // TODO(Faraphel): is the memory fs + auto memoryFileSystem = std::make_unique(); + memoryFileSystem->Initialize(); + + this->fileSystem->AddFileSystem("/tmp", std::move(memoryFileSystem)); +} + +void Engine::asCallback(const asSMessageInfo *message, void *args) { + std::string type = "UNKNOWN"; + std::ostream* output = &std::cout; + + // get a representation for the message type + switch (message->type) { + case asMSGTYPE_INFORMATION: + type = "INFO"; + output = &std::cout; + case asMSGTYPE_WARNING: + type = "WARN"; + output = &std::cerr; + case asMSGTYPE_ERROR: + type = "ERROR"; + output = &std::cerr; + } + + // display the message + + + *output << std::format( + "{} ({}, {}) [{}] {}", + message->section, + message->row, + message->col, + type, + message->message + ) << std::endl; +} + +Engine::~Engine() { + // release the engine + this->asEngine->ShutDownAndRelease(); +} + +asIScriptEngine *Engine::getAsEngine() const { + return this->asEngine; +} + +} diff --git a/source/script/engine/Engine.hpp b/source/script/engine/Engine.hpp new file mode 100644 index 0000000..d74513d --- /dev/null +++ b/source/script/engine/Engine.hpp @@ -0,0 +1,36 @@ +#pragma once + +#include +#include + + +namespace atlas::script::engine { + +/** + * @brief The Atlas script engine + * @details a wrapper around the AngelScript engine + */ +class Engine { +public: + explicit Engine(); + ~Engine(); + + /** + * The AngelScript message handler + * @param message an AngelScript message + * @param args additionnal arguments + */ + static void asCallback(const asSMessageInfo *message, void *args); + + /** + * get the AngelScript engine + * @return the AngelScript engine + */ + [[nodiscard]] asIScriptEngine* getAsEngine() const; +private: + asIScriptEngine* asEngine; + std::unique_ptr fileSystem; +}; + +} + diff --git a/source/javascript/module/debug/README.md b/source/script/module/debug/README.md similarity index 100% rename from source/javascript/module/debug/README.md rename to source/script/module/debug/README.md diff --git a/source/script/module/debug/load.cpp b/source/script/module/debug/load.cpp new file mode 100644 index 0000000..e63a857 --- /dev/null +++ b/source/script/module/debug/load.cpp @@ -0,0 +1,34 @@ +#include "load.hpp" + +#include + +#include "log.hpp" + + +namespace atlas::script::module::debug { + +void load(const engine::Engine* atlasEngine) { + asIScriptEngine* asEngine = atlasEngine->getAsEngine(); + int error; + + // start namespace + error = asEngine->SetDefaultNamespace("atlas::debug"); + if (error < 0) + throw std::runtime_error("Could not enter the \"atlas::debug\" namespace."); + + // functions + error = asEngine->RegisterGlobalFunction( + "void log(const string& in, const string& in)", + asFUNCTION(log), + asCALL_CDECL + ); + if (error < 0) + throw std::runtime_error("Could not register the \"load\" function."); + + // end namespace + error = asEngine->SetDefaultNamespace(""); + if (error < 0) + throw std::runtime_error("Could not reset the namespace."); +} + +} diff --git a/source/script/module/debug/load.hpp b/source/script/module/debug/load.hpp new file mode 100644 index 0000000..2a47569 --- /dev/null +++ b/source/script/module/debug/load.hpp @@ -0,0 +1,10 @@ +#pragma once + +#include "script/engine/Engine.hpp" + + +namespace atlas::script::module::debug { + +void load(const engine::Engine* atlasEngine); + +} diff --git a/source/script/module/debug/log.cpp b/source/script/module/debug/log.cpp new file mode 100644 index 0000000..b163866 --- /dev/null +++ b/source/script/module/debug/log.cpp @@ -0,0 +1,22 @@ +#include "log.hpp" + +#include +#include + + +namespace atlas::script::module::debug { + +void log(const std::string& category, const std::string& message) { + // get the current time + auto now = std::chrono::system_clock::now(); + + // display it into the standard output + std::cout << std::format( + "[{:%Y-%m-%dT%H:%M:%S}] ({}) {}", + now, + category, + message + ) << std::endl; +} + +} \ No newline at end of file diff --git a/source/script/module/debug/log.hpp b/source/script/module/debug/log.hpp new file mode 100644 index 0000000..e822a7e --- /dev/null +++ b/source/script/module/debug/log.hpp @@ -0,0 +1,10 @@ +#pragma once + +#include + + +namespace atlas::script::module::debug { + +void log(const std::string& category, const std::string& message); + +} diff --git a/source/utils/qt/fileOpenMode.cpp b/source/utils/qt/fileOpenMode.cpp deleted file mode 100644 index 418972c..0000000 --- a/source/utils/qt/fileOpenMode.cpp +++ /dev/null @@ -1,24 +0,0 @@ -#include "fileOpenMode.hpp" - - -QIODevice::OpenMode fileModeFromString(const QString& modeString) { - QIODevice::OpenMode modeFlags = QIODevice::NotOpen; - - // if the mode don't contains a "b", set the text mode - if (!modeString.contains("b")) - modeFlags |= QIODevice::Text; - - // if the mode contains a "r", set the read mode - if (modeString.contains("r")) - modeFlags |= QIODevice::ReadOnly; - - // if the mode contains a "w", set the write mode - if (modeString.contains("w")) - modeFlags |= QIODevice::WriteOnly; - - // if the mode contains a "a", set the append mode - if (modeString.contains("a")) - modeFlags |= QIODevice::Append; - - return modeFlags; -} diff --git a/source/utils/qt/fileOpenMode.hpp b/source/utils/qt/fileOpenMode.hpp deleted file mode 100644 index f494f93..0000000 --- a/source/utils/qt/fileOpenMode.hpp +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include - - -/** - * convert a string representing a file mode to the corresponding Qt flags. - * @param modeString the mode as a string - * @return the mode as a flag - */ -QIODevice::OpenMode fileModeFromString(const QString& modeString);