diff --git a/DMS/Connection.h b/DMS/Connection.h index 1fdfcf7..48f1da0 100644 --- a/DMS/Connection.h +++ b/DMS/Connection.h @@ -1,23 +1,20 @@ #pragma once +#include #include -#include + namespace multi { - /* - - */ - template + template class connection { - // bool = func(void* v) - std::vector funcs; + std::vector> funcs; std::vector _funcs; public: - int32_t connect(void(*func)(T)) { + int32_t connect(std::function func) { funcs.push_back(func); - return funcs.size() - 1; + return (int32_t)funcs.size() - 1; } int32_t connect(void(*func)()) { _funcs.push_back(func); - return (_funcs.size())*-1; + return (_funcs.size()) * -1; } void fire(T arg) { // Calls everything in the funcs and _funcs list @@ -32,7 +29,19 @@ namespace multi { f(); } } - int32_t operator+=(void(*func)(T)) { + void remove(int32_t id) { + if (id < 0) { + _funcs.erase((id * -1) - 1); //Normalize the id so it works with the vector + // Dealing with now obj connections + return; + } + funcs.eraase(id); + return; + } + void operator-=(int32_t id) { + remove(id); + } + int32_t operator+=(std::function func) { return connect(func); } int32_t operator+=(void(*func)()) { diff --git a/DMS/DMS.cpp b/DMS/DMS.cpp index 8e5d190..9f206a5 100644 --- a/DMS/DMS.cpp +++ b/DMS/DMS.cpp @@ -3,16 +3,16 @@ #include #include "pch.h" #include "dms.h" +#include "gui.h" +#include "actors.h" using namespace dms; int main() { // TODO fix disp cmd to handle the standard - - - /*milliseconds ms = duration_cast(system_clock::now().time_since_epoch()); - utils::print(ms.count());*/ + multi::runner run; + LineParser parser = LineParser("test.dms"); dms_state* state = parser.Parse(); // Load audio stuff @@ -22,30 +22,40 @@ int main() sf::RenderWindow window(sf::VideoMode(1024, 768, 32), "Background Test"); - sf::Texture texture; - texture.loadFromFile("background.jpg"); - sf::Sprite sprite; - sf::Vector2u size = texture.getSize(); - sprite.setTexture(texture); - sprite.setOrigin(0, 0); + gui::gui& root = gui::Root(); + //gui::framebase testframe(gui::DualDim(0, 0, 100, 100), gui::DualDim(0, 0, 0, 0)); + + gui::gui& test = root.newFrame(gui::DualDim(0, 0, 100, 100), gui::DualDim(0, 0, 0, 0)); + multi::alarm alarmtest(&run, 3, [&](multi::alarm* a) { + test.Offset.Position.Set(10, 10); + }); + //std::cout << "Testing " << test.Parent; + //gui::framebase frame(gui::DualDim(0,0,100,100), gui::DualDim(0, 0, 0, 0)); - sf::Font font; - font.loadFromFile("font.ttf"); + //sf::Texture texture; + //texture.loadFromFile("background.jpg"); + //sf::Sprite sprite; + //sf::Vector2u size = texture.getSize(); + //sprite.setTexture(texture); + //sprite.setOrigin(0, 0); - sf::Text text("Hello this is a test|!", font); - text.setCharacterSize(30); - text.setStyle(sf::Text::Bold); - text.setFillColor(sf::Color::Black); - auto test = text.getGlobalBounds(); - std::cout << test.left << "," << test.top << "," << test.width << "," << test.height << std::endl; - text.setPosition(11, 768 - 110 - (test.height-test.top)); - //std::cout << test << std::endl; + //sf::Font font; + //font.loadFromFile("font.ttf"); - sf::RectangleShape rectangle; - rectangle.setSize(sf::Vector2f(1004, 100)); - rectangle.setOutlineColor(sf::Color::Red); - rectangle.setOutlineThickness(1); - rectangle.setPosition(10, 768-110); + //sf::Text text("Hello this is a test|!", font); + //text.setCharacterSize(30); + //text.setStyle(sf::Text::Bold); + //text.setFillColor(sf::Color::Black); + //auto test = text.getGlobalBounds(); + //std::cout << test.left << "," << test.top << "," << test.width << "," << test.height << std::endl; + //text.setPosition(11, 768 - 110 - (test.height-test.top)); + ////std::cout << test << std::endl; + + //sf::RectangleShape rectangle; + //rectangle.setSize(sf::Vector2f(1004, 100)); + //rectangle.setOutlineColor(sf::Color::Red); + //rectangle.setOutlineThickness(1); + //rectangle.setPosition(10, 768-110); //// run the program as long as the window is open while (window.isOpen()) @@ -66,11 +76,17 @@ int main() // We should clean up some stuff here! break; } + // Update the runner + run.update(); // draw everything here... - window.draw(sprite); - window.draw(rectangle); - window.draw(text); + + gui::Draw(&window); + + //testframe.Draw(&window); + //window.draw(sprite); + //window.draw(rectangle); + //window.draw(text); // end the current frame window.display(); diff --git a/DMS/DMS.vcxproj b/DMS/DMS.vcxproj index d996c82..01d3582 100644 --- a/DMS/DMS.vcxproj +++ b/DMS/DMS.vcxproj @@ -168,6 +168,7 @@ + @@ -175,6 +176,7 @@ + @@ -190,9 +192,9 @@ - + @@ -211,13 +213,13 @@ + - diff --git a/DMS/DMS.vcxproj.filters b/DMS/DMS.vcxproj.filters index d9f4329..9956f62 100644 --- a/DMS/DMS.vcxproj.filters +++ b/DMS/DMS.vcxproj.filters @@ -52,6 +52,15 @@ {584d8d2d-e56e-4a89-a1fe-08a13c3d08a9} + + {f3de0fc4-d3ed-4241-9432-4b9136f0b672} + + + {8b07822b-59fb-4826-89ce-7481977f640b} + + + {490b48c7-06fe-4e6f-9b95-93a0b01a963c} + @@ -120,8 +129,11 @@ Source Files\DMS\platformdep - - Source Files\DMS\platformdep + + Source Files\multi + + + Source Files\gui @@ -194,14 +206,17 @@ Header Files\multi - - Header Files\DMS\libraries - Header Files\DMS\libraries - - Header Files\DMS\libraries + + Header Files\multi + + + Header Files\multi + + + Header Files\DMS\gui \ No newline at end of file diff --git a/DMS/actors.h b/DMS/actors.h new file mode 100644 index 0000000..92207e1 --- /dev/null +++ b/DMS/actors.h @@ -0,0 +1,182 @@ +#pragma once +#include "multibase.h" +#include +namespace multi { + class event : public mbase { + public: + event(runner* run, void(*func)(event*)) : mbase(mtype::mEvent,run) { + OnEvent += func; + } + event(runner* run) : mbase(mtype::mEvent,run) {} + connection OnEvent; + }; + template + class alarm : public mbase { + long long milli; + timer t; + public: + alarm(runner* run, long long milli, std::function func) : mbase(mtype::mAlarm,run) { + this->milli = milli; + OnRing += func; + t.start(); + } + alarm(runner* run, long long milli) : mbase(mtype::mAlarm,run) { + this->milli = milli; + t.start(); + } + alarm(runner* run, void(*func)(alarm*)) : mbase(mtype::mAlarm,run) { + OnRing += func; + milli = 1000; + t.start(); + } + alarm(runner* run) : mbase(mtype::mAlarm, run) { + milli = 1000; + t.start(); + }; + void set(long long milli) { + this->milli = milli; + t.start(); + } + void reset(long long milli) { + set(milli); + mbase::reset(); + } + void reset() { + t.start(); + mbase::reset(); + } + void act(int id) override { + if (!active) return; + if (t.get() >= milli) { + stop(); + OnRing.fire(this); + } + } + connection OnRing; + }; + class step : public mbase { + int start; + int endAt; + int count; + bool loop; + int pos; + public: + step(runner* run, int start, int endAt, int count = 1, bool loop = false) : mbase(mtype::mStep,run) { + update(start, endAt, count, loop); + } + void reset() { + pos = start; + mbase::reset(); + } + void update(int start, int endAt, int count = 1, bool loop = false) { + this->start = start; + pos = start; + this->endAt = endAt; + this->count = count; + if (start > endAt && count == 1) + this->count = -1; + this->loop = loop; + } + void act(int id) override { + if (!active) return; + if (pos == start) OnStepBegin.fire(this); + OnStep.fire(pos); + pos += count; + if ((count > start && pos > endAt) || (count < start && pos < endAt)) { + stop(); + OnStepEnd.fire(this); + } + } + connection OnStepBegin; // before all steps start + connection OnStep; // each step + connection OnStepEnd; // After end of all steps + }; + class loop : public mbase { + public: + loop(runner* run,void(*func)(loop*)) : mbase(mtype::mLoop,run) { + OnLoop += func; + } + void act(int id) override { + if (!active) return; + OnLoop.fire(this); + } + loop(runner* run) : mbase(mtype::mLoop,run) {} + connection OnLoop; + }; + template + class tstep : public mbase { + long long milli; + timer t; + int start; + int endAt; + int count; + bool loop; + int pos; + public: + tstep(runner* run, long long milli, int start, int endAt, int count = 1, bool loop = false) : mbase(mtype::mTStep, run) { + update(start, endAt, count, loop); + reset(milli); + } + void reset() override { + pos = start; + mbase::reset(); + } + void reset(long long milli) { + pos = start; + set(milli); + mbase::reset(); + } + void set(long long milli) { + this->milli = milli; + t.start(); + } + void update(int start, int endAt, int count = 1, bool loop = false) { + this->start = start; + pos = start; + this->endAt = endAt; + this->count = count; + if (start > endAt && count == 1) + this->count = -1; + this->loop = loop; + } + void act(int id) override { + if (!active) return; + if (t.get() >= milli) { + if (pos == start) OnStepBegin.fire(this); + OnStep.fire(pos); + pos += count; + t.start(); + if ((count > start && pos > endAt) || (count < start && pos < endAt)) { + stop(); + OnStepEnd.fire(this); + } + } + } + connection OnStepBegin; // before all steps start + connection OnStep; // each step + connection OnStepEnd; // After end of all steps + }; + template + class tloop : public mbase { + long long milli; + timer t; + public: + tloop(runner* run, long long milli, void(*func)(tloop*)) : mbase(mtype::mTLoop, run) { + OnLoop += func; + this->milli = milli; + } + void set(long long milli) { + this->milli = milli; + t.start(); + } + void act(int id) override { + if (!active) return; + if (t.get() >= milli) { + OnLoop.fire(this); + t.start(); + reset(); + } + } + connection OnLoop; + }; +} \ No newline at end of file diff --git a/DMS/dump.bin b/DMS/dump.bin index 6bba8ff..8dc1d1c 100644 Binary files a/DMS/dump.bin and b/DMS/dump.bin differ diff --git a/DMS/dump.txt b/DMS/dump.txt index 35a38a0..2dd69d1 100644 Binary files a/DMS/dump.txt and b/DMS/dump.txt differ diff --git a/DMS/gui.h b/DMS/gui.h index 2b7bf5c..3e532dd 100644 --- a/DMS/gui.h +++ b/DMS/gui.h @@ -1,17 +1,17 @@ #pragma once -#include "window.h" #include "pch.h" #include "dms_state.h" +#include +#include +#include +#include "multibase.h" namespace gui { using namespace std; using namespace dms; - int __ElementCount = 0; - void init(dms_state* state) { - // While very unlikely it is possible multiple windows to be created! It might be a good idea to support it sometime down the line - window::OnWindowCreated += [](sf::RenderWindow* window) { - - }; - } + /// + /// This is the number of gui elements that exist! It isn't constant, but set as a read only variable. + /// + const int GuiElementCount = 0; /* textbox textbutton @@ -27,33 +27,58 @@ namespace gui { */ - enum class gui_types{frame,text,text,image,sprite,video}; + enum class gui_types{root, frame,text,image,sprite,video}; struct Dim { - float x; - float y; - Dim() {x = 0;y = 0;} - Dim(const Dim &d) { x = d.x; y = d.y;} - Dim(float x, float y) { this->x = x; this->y = y;} - inline void Set(Dim d) {x = d.x; y = d.y;} - inline void Set(float x, float y) { this->x = x; this->y = y;} + const float x = 0; + const float y = 0; + Dim() : x(0), y(0) {} + Dim(const Dim &d) : x(d.x),y(d.y) {} + Dim(float x, float y) : x(x),y(y) {} + inline void Set(Dim d) { const_cast(x) = d.x; const_cast(y) = d.y; OnValueChanged.fire(this); } + inline void Set(float x, float y) { const_cast(this->x) = x; const_cast(this->y) = y; OnValueChanged.fire(this);} + void operator=(const Dim& dd) { + Set(dd); + } + void operator=(const sf::Vector2u& v) { + Set(v.x, v.y); + } + operator sf::Vector2u () { + return sf::Vector2u((int)x, (int)y); + } + operator sf::Vector2f() { + return sf::Vector2f(x, y); + } + multi::connection OnValueChanged; }; struct DualDim { Dim Position; Dim Size; - DualDim() {Position.x = 0;Position.y = 0;Size.x = 0;Size.y = 0;} - DualDim(const DualDim& d) { Position = d.Position; Size = d.Size;} - DualDim(Dim pos, Dim size) { Position = pos; Size = size;} - DualDim(float x, float y, float x2, float y2) { Position.x = x; Position.y = y; Size.x = x2; Size.y = y2; } - inline void Set(DualDim d){ Position = d.Position; Size = d.Size;} - inline void Set(Dim pos, Dim size) {Position.x = pos.x;Position.y = pos.y;Size.x = size.x;Size.y = size.y;} - inline void Set(float x, float y, float x2, float y2) { Position.x = x; Position.y = y; Size.x = x2; Size.y = y2;} + void init() { + Position.OnValueChanged += [&](Dim* d) { + OnValueChanged.fire(this); + }; + Size.OnValueChanged += [&](Dim* d) { + OnValueChanged.fire(this); + }; + } + DualDim() : Position(0,0),Size(0,0) { init(); } + DualDim(const DualDim& d) : Position(d.Position.x,d.Position.y), Size(d.Size.x,d.Size.y) {init(); } + DualDim(Dim pos, Dim size) : Position(pos.x,pos.y), Size(size.x,size.y) { init(); } + DualDim(float x, float y, float x2, float y2) : Position(x,y),Size(x2,y2) { init(); } + inline void Set(DualDim d){ Position.Set(d.Position); Size.Set(d.Size);OnValueChanged.fire(this);} + inline void Set(Dim pos, Dim size) { Position.Set(pos); Size.Set(size); OnValueChanged.fire(this);} + inline void Set(float x, float y, float x2, float y2) { Position.Set(x, y), Size.Set(x2, y2); OnValueChanged.fire(this);} + DualDim operator=(const DualDim& dd) { + Set(dd); + } + multi::connection OnValueChanged; }; struct MouseStats { - float x; - float y; - float dx; - float dy; - char button; + float x = 0; + float y = 0; + float dx = 0; + float dy = 0; + char button = 0; MouseStats(Dim pos, char b) { x = pos.x; y = pos.y; @@ -75,7 +100,57 @@ namespace gui { struct Keyboard { // }; - struct guibase { + + class gui { + + public: + gui_types Type = gui_types::root; + DualDim Offset; + DualDim Scale; + Dim AbsolutePosition; + Dim AbsoluteSize; + gui* Parent = nullptr; + vector Children; + bool Visible = true; + + //map Named; + + gui() { + const_cast(GuiElementCount) += 1; + + } + gui(DualDim offset, DualDim scale) : gui() { Offset.Set(offset); Scale.Set(scale);} + gui(float x,float y,float w,float h,float sx,float sy,float sw,float sh) : gui() { + Offset.Set(x, y, w, h); + Scale.Set(sx, sy, sw, sh); + } + void SetDualDim(DualDim offset,DualDim scale) {Offset = offset;Scale.Set(scale);} + + virtual void Draw(sf::RenderWindow* window) { + return; // Override this. + } + + inline vector& GetChildren() {return Children;} + inline void GetAllChildren(vector& ref) { + auto temp = GetChildren(); + for (int i = 0; i < temp.size(); i++) { + ref.push_back(temp[i]); + temp[i]->GetAllChildren(ref); + } + } + inline vector GetAllChildren() { + auto temp = GetChildren(); + vector everything; + everything.reserve(GuiElementCount); // Reserve Space for all the current elements that exist + for (int i = 0; i < temp.size(); i++) { + everything.push_back(temp[i]); + temp[i]->GetAllChildren(everything); + } + return everything; + } + + gui& newFrame(DualDim offset, DualDim scale); + //Connections and objects to inheret multi::connection OnPressed; multi::connection OnReleased; @@ -89,54 +164,46 @@ namespace gui { multi::connection OnUpdate; - }; - class gui : guibase { - public: - gui_types Type; - DualDim Offset; - DualDim Scale; - DualDim Absolute; - vector Children; - bool Visible = true; + - //map Named; + struct framebase : public gui { + sf::RectangleShape rect; + framebase(DualDim offset, DualDim scale) : gui(offset,scale) { + Type = gui_types::frame; + rect.setFillColor(sf::Color(120, 120, 120, 255)); + rect.setOutlineColor(sf::Color::Red); + rect.setSize(offset.Size); + rect.setPosition(offset.Position); + Offset.OnValueChanged += [&](DualDim* o) { + rect.setSize(o->Size); + rect.setPosition(o->Position); + }; + Scale.OnValueChanged += [](DualDim* s) { - gui() {__ElementCount++;} - gui(DualDim offset, DualDim scale) { Offset = offset; Scale = scale;} - gui(float x,float y,float w,float h,float sx,float sy,float sw,float sh){Offset.Position.x = x;Offset.Position.y = y;Offset.Size.x = w;Offset.Size.y = h;Scale.Position.x = sx;Scale.Position.y = sy;Scale.Size.x = sw;Scale.Size.y = sh;} - void SetDualDim(DualDim offset,DualDim scale) {Offset = offset;Scale = scale;} - - virtual void Draw() { - return; // Override this. + }; } - - inline vector& GetChildren() {return Children;} - inline void GetAllChildren(vector& ref) { - auto temp = GetChildren(); - for (int i = 0; i < temp.size(); i++) { - ref.push_back(&temp[i]); - temp[i].GetAllChildren(ref); - } - } - inline vector GetAllChildren() { - auto temp = GetChildren(); - vector everything; - everything.reserve(__ElementCount); // Reserve all the current elements that exist - for (int i = 0; i < temp.size(); i++) { - everything.push_back(&temp[i]); - temp[i].GetAllChildren(everything); - } - return everything; + void Draw(sf::RenderWindow* window) override { + window->draw(rect); } }; - // Draw Everything - gui _Root; - void Draw() { - auto childs = _Root.GetAllChildren(); - for (int i = 0; i < childs.size(); i++) { - childs[i]->Draw(); + struct imagebase : public framebase { + sf::Texture texture; + imagebase(std::string imagepath, DualDim offset, DualDim scale) : framebase(offset,scale) { + Type = gui_types::image; + texture.loadFromFile(imagepath); + sf::Sprite sprite; + sf::Vector2u size = texture.getSize(); + sprite.setTexture(texture); + sprite.setOrigin(0, 0); } - } + }; + struct textbase : public framebase { + textbase(std::string text, sf::Font font, DualDim offset, DualDim scale) : framebase(offset, scale) { + Type = gui_types::text; + } + }; + gui& Root(); + void Draw(sf::RenderWindow* window); } \ No newline at end of file diff --git a/DMS/guiimpl.cpp b/DMS/guiimpl.cpp new file mode 100644 index 0000000..ea6e81a --- /dev/null +++ b/DMS/guiimpl.cpp @@ -0,0 +1,22 @@ +#include "gui.h" +namespace gui { + gui& gui::newFrame(DualDim offset, DualDim scale) { + gui* fb = new framebase(offset, scale); + fb->Parent = this; + Children.push_back(fb); + return *fb; + } + // Draw Everything + gui _Root; + std::vector childs; // This tends to always grow, rarely strinking. So make it once so we arent allocating meme each loop! + void Draw(sf::RenderWindow* window) { + _Root.AbsoluteSize = window->getSize(); + childs = _Root.GetAllChildren(); + for (int i = 0; i < childs.size(); i++) { + childs[i]->Draw(window); + } + } + gui& Root() { + return _Root; + } +} \ No newline at end of file diff --git a/DMS/multibase.h b/DMS/multibase.h new file mode 100644 index 0000000..68c4600 --- /dev/null +++ b/DMS/multibase.h @@ -0,0 +1,109 @@ +#pragma once +#include "connection.h" +#include +#include +#include +#include +namespace multi { + // Keeps track of time. + typedef std::chrono::high_resolution_clock Clock; + typedef std::chrono::nanoseconds nanoseconds; + typedef std::chrono::microseconds microseconds; + typedef std::chrono::milliseconds milliseconds; + typedef std::chrono::seconds seconds; + typedef std::chrono::minutes minutes; + typedef std::chrono::hours hours; + + const char _nanosecond = 0x0; + const char _microsecond = 0x1; + const char _millisecond = 0x2; + const char _second = 0x3; + const char _minute = 0x4; + const char _hour = 0x5; + + typedef std::chrono::time_point time; + template + struct timer { + inline void start() { + t = Clock::now(); + } + inline long long get() const { + return std::chrono::duration_cast(Clock::now() - t).count(); + } + inline void sleep(long long s) { + std::this_thread::sleep_for(T(s)); + } + private: + time t; + }; + class mbase; + enum class mtype { mEvent, mStep, mLoop, mAlarm, mTStep, mTLoop, mService, mUpdater }; + const std::unordered_map mtypes { + {mtype::mEvent,"Event"}, + {mtype::mStep,"Step"}, + {mtype::mLoop,"Loop"}, + {mtype::mAlarm,"Alarm"}, + {mtype::mTStep,"TStep"}, + {mtype::mTLoop,"TLoop"}, + {mtype::mService,"Service"}, + {mtype::mUpdater,"Updater"} + }; + /// + /// Class responsible for driving multi objects + /// + class runner { + friend class mbase; + bool active = true; + std::vector mObjects; + public: + bool update(); + void mainloop(); + /// + /// Event Triggered when the multi object is created + /// + connection OnCreate; + /// + /// Event Triggered when the multi object is destroyed + /// + connection OnDestroyed; + }; + class mbase { + public: + runner* Parent = nullptr; + const mtype Type; + const bool active = true; + const bool paused = false; + mbase(mtype type, runner* run) : Type(type) { + Parent = run; + run->mObjects.push_back(this); + } + virtual void act(int mid) {} + virtual void reset() { const_cast(active) = true; }; + void pause() { + if (!paused) + OnPaused.fire(this); + const_cast(paused) = true; + } + void resume() { + if (paused) + OnResume.fire(this); + const_cast(paused) = false; + } + void stop() { + OnStopped.fire(this); + const_cast(active) = false; + } + /// + /// Event Triggered when the multi object is paused + /// + connection OnPaused; + /// + /// Event Triggered when the multi object is resumed + /// + connection OnResume; + /// + /// Event Triggered when the multi object is stopped + /// + connection OnStopped; + }; +} \ No newline at end of file diff --git a/DMS/multiimpl.cpp b/DMS/multiimpl.cpp new file mode 100644 index 0000000..25be226 --- /dev/null +++ b/DMS/multiimpl.cpp @@ -0,0 +1,15 @@ +#include "actors.h" +namespace multi { + bool runner::update() { + if (!active) + return false; + size_t id = 0; + for (auto mobj : mObjects) { + mobj->act(id++); + } + return active; + } + void runner::mainloop() { + while (update()); + } +} \ No newline at end of file diff --git a/DMS/window.cpp b/DMS/window.cpp deleted file mode 100644 index 9e403c0..0000000 --- a/DMS/window.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include "pch.h" -#include "window.h" -namespace dms::window { - Invoker* inv = new Invoker; - void init(dms_state* state) { - /* - inv->registerFunction("getStatus", getStatus); - - state->assoiateType("audiostream",inv); - state->invoker.registerFunction("loadMusic", loadMusic); - */ - } - value newWindow(void* self, dms_state* state, dms_args* args) { - if (dms::utils::valueassert(*args, state, datatypes::number, datatypes::number, datatypes::number)) { - - } - else if (dms::utils::valueassert(*args, state, datatypes::int64, datatypes::int64, datatypes::int64)) { - - } - sf::RenderWindow window(sf::VideoMode(1024, 768, 32), "Background Test"); - } -} \ No newline at end of file diff --git a/DMS/window.h b/DMS/window.h deleted file mode 100644 index d695a85..0000000 --- a/DMS/window.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once -#include -#include -#include "dms_state.h" -#include "utils.h" -#include -#include "Connection.h" -namespace dms::window { - multi::connection OnWindowCreated; - void init(dms_state*); - bool windowIsReady = false; - std::vector windows; - value newWindow(void*, dms_state*, dms_args*); -} \ No newline at end of file