diff --git a/src/client/screen/script/JsScreen.cpp b/src/client/screen/script/JsScreen.cpp index 1472ec1..bf75db5 100644 --- a/src/client/screen/script/JsScreen.cpp +++ b/src/client/screen/script/JsScreen.cpp @@ -1,19 +1,76 @@ #include "pch.h" #include "JsScreen.h" +#include +#include +#include "sdk/common/client/gui/controls/VisualTree.h" +#include "sdk/common/client/gui/controls/UIControl.h" JsScreen::JsScreen(JsValueRef object, JsValueRef renderFunc) : renderFunc(renderFunc) { + JS::JsGetCurrentContext(&this->ctx); Chakra::GetStringProperty(object, L"name"); key = Chakra::GetIntProperty(object, L"key"); - + + Eventing::get().listen(this, (EventListenerFunc)&JsScreen::onRender, 1, true); + Eventing::get().listen(this, (EventListenerFunc)&JsScreen::onKey, 1); + Eventing::get().listen(this, (EventListenerFunc)&JsScreen::onClick, 1); + + this->eventListeners[L"enable"] = {}; + this->eventListeners[L"disable"] = {}; + this->eventListeners[L"render"] = {}; + this->eventListeners[L"key"] = {}; + this->eventListeners[L"click"] = {}; +} + +void JsScreen::onRender(Event& evG) { + auto& ev = reinterpret_cast(evG); + auto view = ev.getScreenView(); + if (view->visualTree->rootControl->name == "debug_screen") { + Chakra::SetContext(ctx); + + Event ev{ L"render", {} }; + auto ret = dispatchEvent(ev.name, ev); + if (ret != JS_INVALID_REFERENCE) { + Chakra::Release(ret); + } + } +} + +void JsScreen::onKey(Event& evG) { + auto ret = dispatchEvent(sEv.name, sEv); + if (ret != JS_INVALID_REFERENCE) { + Chakra::Release(ret); + } } -void JsScreen::onRender(Event& ev) -{ +void JsScreen::onClick(Event& evG) { + auto& ev = reinterpret_cast(evG); + Event sEv{ L"click", {Chakra::MakeInt(ev.getMouseButton()), Chakra::MakeInt(ev.getWheelDelta()), ev.isDown() ? Chakra::GetTrue() : Chakra::GetFalse() } }; + auto ret = dispatchEvent(sEv.name, sEv); + if (ret != JS_INVALID_REFERENCE) { + Chakra::Release(ret); + } } void JsScreen::onEnable(bool ignoreAnims) { + Latite::get().queueForClientThread([this, ignoreAnims]() { + Chakra::SetContext(ctx); + + Event ev{ L"enable", { (ignoreAnims ? Chakra::GetTrue() : Chakra::GetFalse()) }}; + auto ret = dispatchEvent(ev.name, ev); + if (ret != JS_INVALID_REFERENCE) { + Chakra::Release(ret); + } + }); } void JsScreen::onDisable() { + Latite::get().queueForClientThread([this]() { + Chakra::SetContext(ctx); + Event ev{ L"disable", { } }; + auto ret = dispatchEvent(ev.name, ev); + if (ret != JS_INVALID_REFERENCE) { + Chakra::Release(ret); + } + }); } diff --git a/src/client/screen/script/JsScreen.h b/src/client/screen/script/JsScreen.h index a15b398..0ec9d6c 100644 --- a/src/client/screen/script/JsScreen.h +++ b/src/client/screen/script/JsScreen.h @@ -6,14 +6,14 @@ #include #include #include +#include "client/script/feature/JsEvented.h" -class JsScreen : public Screen { + +class JsScreen : public Screen, public JsEvented { public: JsScreen(JsValueRef object, JsValueRef renderFunc); void onRender(class Event& ev); - void onCleanup(Event& ev); - void onInit(Event& ev); void onKey(Event& ev); void onClick(Event& ev); @@ -22,7 +22,9 @@ class JsScreen : public Screen { void onEnable(bool ignoreAnims) override; void onDisable() override; private: - JsValueRef object; - JsValueRef renderFunc; + JsValueRef object = JS_INVALID_REFERENCE; + JsValueRef renderFunc = JS_INVALID_REFERENCE; + JsContextRef ctx = JS_INVALID_REFERENCE; + std::string name; }; \ No newline at end of file diff --git a/src/client/script/JsScript.cpp b/src/client/script/JsScript.cpp index 6a3bcd2..3e58b13 100644 --- a/src/client/script/JsScript.cpp +++ b/src/client/script/JsScript.cpp @@ -33,6 +33,7 @@ #include "class/impl/JsSettingClass.h" #include "class/impl/JsCommandClass.h" #include "class/impl/JsNativeModule.h" +#include "class/impl/JsScreenClass.h" #include "class/impl/game/JsEntityClass.h" #include "class/impl/game/JsPlayerClass.h" #include "class/impl/game/JsLocalPlayerClass.h" @@ -497,6 +498,7 @@ void JsScript::loadScriptObjects() { this->classes.push_back(std::make_shared(this)); this->classes.push_back(std::make_shared(this)); this->classes.push_back(std::make_shared(this)); + this->classes.push_back(std::make_shared(this)); JsErrorCode err; JsValueRef globalObj = Chakra::GetGlobalObject(); diff --git a/src/client/script/class/impl/JsScreenClass.h b/src/client/script/class/impl/JsScreenClass.h index 6f70f09..3a39c08 100644 --- a/src/client/script/class/impl/JsScreenClass.h +++ b/src/client/script/class/impl/JsScreenClass.h @@ -1 +1,56 @@ #pragma once +#include "../JsWrapperClass.h" +#include "util/ChakraUtil.h" +#include "client/screen/script/JsScreen.h" + +class JsScreenClass : public JsWrapperClass { +protected: + static JsValueRef CALLBACK jsConstructor(JsValueRef callee, bool isConstructor, + JsValueRef* arguments, unsigned short argCount, void* callbackState) { + auto thi = reinterpret_cast(callbackState); + if (!Chakra::VerifyArgCount(argCount, 2)) return JS_INVALID_REFERENCE; + if (!Chakra::VerifyParameters({ {arguments[1], JsString}, {arguments[2], JsFunction} })) return JS_INVALID_REFERENCE; + + auto screen = new JsScreen(arguments[0], arguments[2]); + JsValueRef obj = thi->construct(screen, false); + return obj; + } + + static JsValueRef CALLBACK toStringCallback(JsValueRef callee, bool isConstructor, + JsValueRef* arguments, unsigned short argCount, void* callbackState) { + auto thi = reinterpret_cast(callbackState); + auto scn = Get(arguments[0]); + std::string add = std::format("{} ({})", util::WStrToStr(thi->name), scn->getName()); + return Chakra::MakeString(L"[object " + util::StrToWStr(add) + L"]"); + } + + static JsValueRef CALLBACK isActiveCallback(JsValueRef callee, bool isConstructor, + JsValueRef* arguments, unsigned short argCount, void* callbackState) { + + return Get(arguments[0])->isActive() ? Chakra::GetTrue() : Chakra::GetFalse(); + } +public: + inline static const wchar_t* class_name = L"Screen"; + + JsScreenClass(class JsScript* owner) : JsWrapperClass(owner, class_name) { + createConstructor(jsConstructor, this); + } + + /// + /// Constructs a JS screen. + /// + /// The C++ screen to create from. + /// Whether to destroy the C++ screen when the object goes out of scope or not. + /// + JsValueRef construct(JsScreen* screen, bool finalize) { + auto obj = __super::construct(screen, finalize); + + Chakra::SetPropertyString(obj, L"name", util::StrToWStr(screen->getName()), true); + return obj; + } + + void prepareFunctions() override { + Chakra::SetPropertyString(prototype, L"name", L"", true); + Chakra::DefineFunc(prototype, isActiveCallback, L"isActive", this); + }; +}; \ No newline at end of file