From 7797b0b38794ba02f9f5b01763d85f52ff1139a8 Mon Sep 17 00:00:00 2001 From: Mike Nolan Date: Thu, 12 Jun 2025 15:48:44 -0500 Subject: [PATCH] Add GUI Support --- src/runtime_methods/sdl2.cpp | 1181 ++++++++++++++++++++++++++++++++++ 1 file changed, 1181 insertions(+) create mode 100644 src/runtime_methods/sdl2.cpp diff --git a/src/runtime_methods/sdl2.cpp b/src/runtime_methods/sdl2.cpp new file mode 100644 index 0000000..7941b26 --- /dev/null +++ b/src/runtime_methods/sdl2.cpp @@ -0,0 +1,1181 @@ + +#include +#include "CrossLang.hpp" +#include +#if defined(TESSESFRAMEWORK_ENABLE_SDL2) +#include +#include +#include +#include +#include +#include +#include +#include +#include +using namespace Tesses::Framework::SDL2; +#endif + +namespace Tesses::CrossLang +{ + #if defined(TESSESFRAMEWORK_ENABLE_SDL2) + TDictionary* SDL_Event2Dict(GCList& ls, SDL_Event& event) + { + TDictionary* dict= TDictionary::Create(ls,{ + TDItem("Type",(int64_t)event.common.type), + TDItem("Timestamp",(int64_t)event.common.timestamp) + }); + switch(event.type) + { + case SDL_DISPLAYEVENT: + { + ls.GetGC()->BarrierBegin(); + dict->SetValue("Display",TDictionary::Create(ls,{ + TDItem("Display",(int64_t)event.display.display), + TDItem("Data1",(int64_t)event.display.data1), + TDItem("Event",(int64_t)event.display.event) + })); + ls.GetGC()->BarrierEnd(); + } + break; + case SDL_WINDOWEVENT: + { + ls.GetGC()->BarrierBegin(); + dict->SetValue("Window",TDictionary::Create(ls,{ + TDItem("WindowId",(int64_t)event.window.windowID), + TDItem("Data1",(int64_t)event.window.data1), + TDItem("Data2",(int64_t)event.window.data2), + TDItem("Event",(int64_t)event.window.event) + })); + ls.GetGC()->BarrierEnd(); + } + break; + case SDL_SYSWMEVENT: + { + ls.GetGC()->BarrierBegin(); + dict->SetValue("Message",TNative::Create(ls,event.syswm.msg,[](void*)->void{})); + ls.GetGC()->BarrierEnd(); + } + break; + case SDL_KEYDOWN: + case SDL_KEYUP: + { + ls.GetGC()->BarrierBegin(); + dict->SetValue("Key",TDictionary::Create(ls,{ + TDItem("WindowId",(int64_t)event.key.windowID), + TDItem("State",(int64_t)event.key.state), + TDItem("Repeat",(int64_t)event.key.repeat), + TDItem("Mod",(int64_t)event.key.keysym.mod), + + TDItem("Scancode",(int64_t)event.key.keysym.scancode), + TDItem("Sym",(int64_t)event.key.keysym.sym), + TDItem("Event",(int64_t)event.window.event) + })); + ls.GetGC()->BarrierEnd(); + } + break; + case SDL_TEXTEDITING: + { + ls.GetGC()->BarrierBegin(); + dict->SetValue("Edit",TDictionary::Create(ls,{ + TDItem("WindowId",(int64_t)event.edit.windowID), + TDItem("Start",(int64_t)event.edit.start), + TDItem("Length",(int64_t)event.edit.length), + TDItem("Text",(std::string)event.edit.text), + })); + ls.GetGC()->BarrierEnd(); + } + break; + case SDL_TEXTEDITING_EXT: + { + std::string text = event.editExt.text; + SDL_free(event.editExt.text); + ls.GetGC()->BarrierBegin(); + dict->SetValue("Edit",TDictionary::Create(ls,{ + TDItem("WindowId",(int64_t)event.editExt.windowID), + TDItem("Start",(int64_t)event.editExt.start), + TDItem("Length",(int64_t)event.editExt.length), + TDItem("Text",text), + })); + ls.GetGC()->BarrierEnd(); + } + break; + case SDL_TEXTINPUT: + { + ls.GetGC()->BarrierBegin(); + dict->SetValue("Text",TDictionary::Create(ls,{ + TDItem("WindowId",(int64_t)event.text.windowID), + TDItem("Text",(std::string)event.text.text), + })); + ls.GetGC()->BarrierEnd(); + } + break; + case SDL_MOUSEMOTION: + { + ls.GetGC()->BarrierBegin(); + dict->SetValue("Motion",TDictionary::Create(ls,{ + TDItem("WindowId",(int64_t)event.motion.windowID), + TDItem("X",(int64_t)event.motion.x), + TDItem("Y",(int64_t)event.motion.y), + TDItem("XRel",(int64_t)event.motion.xrel), + TDItem("YRel",(int64_t)event.motion.yrel), + TDItem("State",(int64_t)event.motion.state), + TDItem("Which",(int64_t)event.motion.which) + })); + ls.GetGC()->BarrierEnd(); + } + break; + case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEBUTTONUP: + { + ls.GetGC()->BarrierBegin(); + dict->SetValue("Motion",TDictionary::Create(ls,{ + TDItem("WindowId",(int64_t)event.button.windowID), + TDItem("X",(int64_t)event.button.x), + TDItem("Y",(int64_t)event.button.y), + TDItem("State",(int64_t)event.button.state), + TDItem("Clicks",(int64_t)event.button.clicks), + TDItem("Which",(int64_t)event.button.which), + TDItem("Button",(int64_t)event.button.button) + })); + ls.GetGC()->BarrierEnd(); + } + break; + case SDL_MOUSEWHEEL: + { + + ls.GetGC()->BarrierBegin(); + dict->SetValue("Motion",TDictionary::Create(ls,{ + TDItem("WindowId",(int64_t)event.wheel.windowID), + TDItem("X",(int64_t)event.wheel.x), + TDItem("Y",(int64_t)event.wheel.y), + TDItem("Direction",(int64_t)event.wheel.direction), + TDItem("MouseX",(int64_t)event.wheel.mouseX), + TDItem("MouseY",(int64_t)event.wheel.mouseY), + TDItem("PreciseX",(double)event.wheel.preciseX), + TDItem("PreciseY",(double)event.wheel.preciseY), + TDItem("Which",(int64_t)event.wheel.which), + + })); + ls.GetGC()->BarrierEnd(); + } + break; + } + return dict; + } + class SDL2_Window; + class SDL2_Renderer; + class SDL2_Color; + class SDL2_Rectangle; + class SDL2_Texture; + class SDL2_FontCache; + class SDL2_Surface; + class SDL2_Window : public TNativeObject { + private: + SDL_Window* window; + public: + SDL2_Window(std::string title, int x, int y, int w, int h,uint32_t flags) + { + window = SDL_CreateWindow(title.c_str(),x,y,w,h,flags); + } + TObject CallMethod(GCList& ls,std::string name, std::vector args) + { + if(name == "setTitle") + { + std::string title; + if(GetArgument(args,0,title)) + { + SDL_SetWindowTitle(window,title.c_str()); + return title; + } + } + if(name == "getTitle") + { + return std::string(SDL_GetWindowTitle(window)); + } + + return Undefined(); + } + std::string TypeName() + { + return "SDL2.Window"; + } + ~SDL2_Window() + { + SDL_DestroyWindow(window); + } + friend class SDL2_Renderer; + friend class SDL2_Texture; + + }; + + class SDL2_Color : public TNativeObject { + SDL_Color color; + + public: + SDL2_Color() + { + color={0}; + } + SDL2_Color(SDL_Color color) + { + this->color = color; + } + SDL2_Color(uint8_t r, uint8_t g, uint8_t b, uint8_t a) + { + this->color = {.r=r,.g=g,.b=b,.a=a}; + } + TObject CallMethod(GCList& ls,std::string name, std::vector args) + { + if(name == "getR") + { + return (int64_t)this->color.r; + } + if(name == "setR") + { + int64_t v; + if(GetArgument(args,0,v)) + { + this->color.r = (uint8_t)v; + return v & 0xFF; + } + + } + if(name == "getG") + { + return (int64_t)this->color.g; + } + if(name == "setG") + { + int64_t v; + if(GetArgument(args,0,v)) + { + this->color.g = (uint8_t)v; + return v & 0xFF; + } + + } + if(name == "getB") + { + return (int64_t)this->color.b; + } + if(name == "setB") + { + int64_t v; + if(GetArgument(args,0,v)) + { + this->color.b = (uint8_t)v; + return v & 0xFF; + } + + } + if(name == "getA") + { + return (int64_t)this->color.a; + } + if(name == "setA") + { + int64_t v; + if(GetArgument(args,0,v)) + { + this->color.a = (uint8_t)v; + return v & 0xFF; + } + + } + if(name == "ToString") + { + std::string res="Red: "; + res.append(std::to_string((int64_t)color.r)); + res.append(", Green: "); + res.append(std::to_string((int64_t)color.g)); + res.append(", Blue: "); + res.append(std::to_string((int64_t)color.b)); + res.append(", Alpha: "); + res.append(std::to_string((int64_t)color.a)); + return res; + } + return Undefined(); + } + std::string TypeName() + { + return "SDL2.Color"; + } + friend class SDL2_Renderer; + friend class SDL2_FontCache; + }; + + class SDL2_Rectangle : public TNativeObject { + SDL_Rect rect; + + public: + SDL2_Rectangle() + { + rect={0}; + } + SDL2_Rectangle(SDL_Rect rect) + { + this->rect = rect; + } + SDL2_Rectangle(int x, int y, int w, int h) + { + this->rect = {.x=x,.y=y,.w=w,.h=h}; + } + TObject CallMethod(GCList& ls,std::string name, std::vector args) + { + if(name == "getX") + { + return (int64_t)this->rect.x; + } + if(name == "setX") + { + int64_t v; + if(GetArgument(args,0,v)) + { + this->rect.x = (int)v; + return v; + } + + } + if(name == "getY") + { + return (int64_t)this->rect.y; + } + if(name == "setY") + { + int64_t v; + if(GetArgument(args,0,v)) + { + this->rect.y = (int)v; + return v; + } + + } + if(name == "getWidth") + { + return (int64_t)this->rect.w; + } + if(name == "setWidth") + { + int64_t v; + if(GetArgument(args,0,v)) + { + this->rect.w = (int)v; + return v; + } + + } + if(name == "getHeight") + { + return (int64_t)this->rect.h; + } + if(name == "setHeight") + { + int64_t v; + if(GetArgument(args,0,v)) + { + this->rect.h = (int)v; + return v; + } + + } + if(name == "ToString") + { + std::string res="X: "; + res.append(std::to_string((int64_t)rect.x)); + res.append(", Y: "); + res.append(std::to_string((int64_t)rect.y)); + res.append(", Width: "); + res.append(std::to_string((int64_t)rect.w)); + res.append(", Height: "); + res.append(std::to_string((int64_t)rect.h)); + return res; + } + return Undefined(); + } + std::string TypeName() + { + return "SDL2.Rectangle"; + } + friend class SDL2_Renderer; + }; + class SDL2_Surface : public TNativeObject { + TObject ToTexture(GCList& ls, std::vector args); + SDL_Surface* surface; + public: + SDL2_Surface(SDL_Surface* surf) + { + this->surface = surf; + } + ~SDL2_Surface() + { + SDL_FreeSurface(surface); + } + std::string TypeName() + { + return "SDL2.Surface"; + } + TObject CallMethod(GCList& ls, std::string key, std::vector args) + { + + if(key == "getWidth" && this->surface != nullptr) + { + return (int64_t)this->surface->w; + } + + if(key == "getHeight" && this->surface != nullptr) + { + return (int64_t)this->surface->w; + } + if(key == "ToTexture") + { + return ToTexture(ls,args); + } + + if(key == "ToString") + { + return "SDL2.Surface"; + } + return Undefined(); + } + friend class SDL2_Texture; + }; + class SDL2_Texture : public TNativeObject { + THeapObject* cache; + SDL_Texture* tex; + + public: + SDL2_Texture(THeapObject* cache, SDL_Texture* tex) + { + this->cache=cache; + this->tex = tex; + } + SDL2_Texture(SDL_Texture* tex) + { + this->cache = nullptr; + this->tex = tex; + } + SDL2_Texture(SDL2_Renderer* renderer,SDL2_Surface* surface); + void Mark() + { + if(this->marked) return; + this->marked=true; + if(this->cache != nullptr) this->cache->Mark(); + } + + TObject CallMethod(GCList& ls,std::string key,std::vector args) + { + if(key == "getSize") + { + int w,h; + if(SDL_QueryTexture(this->tex,NULL,NULL,&w,&h)==0) + return TList::Create(ls,{ + (int64_t)w, + (int64_t)h + }); + } + if(key == "getWidth") + { + int w; + if(SDL_QueryTexture(this->tex,NULL,NULL,&w,NULL)==0) + return (int64_t)w; + } + if(key == "getHeight") + { + int h; + if(SDL_QueryTexture(this->tex,NULL,NULL,NULL,&h)==0) + return (int64_t)h; + } + return Undefined(); + } + + std::string TypeName() + { + return "SDL2.Texture"; + } + ~SDL2_Texture() + { + if(this->cache == nullptr) SDL_DestroyTexture(this->tex); + } + friend class SDL2_FontCache; + friend class SDL2_Renderer; + }; + + + class SDL2_Renderer : public TNativeObject { + SDL_Renderer* renderer; + public: + SDL2_Renderer(SDL2_Window* window, int index, uint32_t flags) + { + renderer = SDL_CreateRenderer(window->window,index,flags); + } + TObject CallMethod(GCList& ls,std::string name, std::vector args) + { + if(name == "Clear") + { + return (int64_t)SDL_RenderClear(renderer); + } + + if(name == "getDrawColor") + { + SDL_Color c; + if(SDL_GetRenderDrawColor(renderer,&c.r,&c.g,&c.b,&c.a)==0) + { + return TNativeObject::Create(ls,c); + } + } + + if(name == "setDrawColor") + { + SDL2_Color* c; + if(GetArgumentHeap(args,0,c)) + { + SDL_SetRenderDrawColor(renderer,c->color.r,c->color.g,c->color.b,c->color.a); + return c; + } + } + + + if(name == "Copy") + { + SDL2_Texture* tex; + SDL2_Rectangle *src=nullptr,*dest=nullptr; + if(GetArgumentHeap(args,0,tex)) + { + GetArgumentHeap(args,1,src); + + GetArgumentHeap(args,2,dest); + SDL_RenderCopy(this->renderer,tex->tex,src == nullptr ? (SDL_Rect*)nullptr : &src->rect,dest == nullptr ? (SDL_Rect*)nullptr : &dest->rect); + } + } + + if(name == "Present") + { + SDL_RenderPresent(renderer); + } + + return Undefined(); + } + + std::string TypeName() + { + return "SDL2.Renderer"; + } + + ~SDL2_Renderer() + { + SDL_DestroyRenderer(renderer); + } + friend class SDL2_FontCache; + friend class SDL2_Texture; + }; + TObject SDL2_Surface::ToTexture(GCList& ls,std::vector args) + { + SDL2_Renderer* renderer; + if(GetArgumentHeap(args,0,renderer)) + { + return TNativeObject::Create(ls,renderer,this); + } + return Undefined(); + } + SDL2_Texture::SDL2_Texture(SDL2_Renderer* renderer,SDL2_Surface* surface) + { + this->cache = nullptr; + this->tex = SDL_CreateTextureFromSurface(renderer->renderer,surface->surface); + } + class SDL2_FontCache : public TNativeObject { + Tesses::Framework::SDL2::FontCache* cache; + std::array textures; + SDL2_FontCache(GCList& ls, Tesses::Framework::SDL2::FontCache* fc) + { + this->cache = fc; + for(size_t i = 0; i < 96; i++) + { + textures[i] = TNativeObject::Create(ls,this, fc->operator[](i+32)); + } + } + public: + SDL2_FontCache(GCList& ls,SDL2_Renderer* renderer, int pt) : SDL2_FontCache(ls,new Tesses::Framework::SDL2::FontCache(renderer->renderer,pt)) + { + + } + SDL2_FontCache(GCList& ls,SDL2_Renderer* renderer,TByteArray* ba, int pt) : SDL2_FontCache(ls,new Tesses::Framework::SDL2::FontCache(renderer->renderer,ba->data,pt)) + { + + } + SDL2_FontCache(GCList& ls,SDL2_Renderer* renderer,TTF_Font* font, int pt) : SDL2_FontCache(ls,new Tesses::Framework::SDL2::FontCache(renderer->renderer,font)) + { + + } + + TObject CallMethod(GCList& ls,std::string key,std::vector args) + { + if(key == "GetAt") + { + char c; + if(GetArgument(args,0,c)) + { + if(c >= 32 && c <= 126) + { + return this->textures[c-32]; + } + return this->textures[95]; + } + } + if(key == "getPointSize") + { + return (int64_t)this->cache->PointSize(); + } + if(key == "getMaxWidth") + { + return (int64_t)this->cache->MaxWidth(); + } + if(key == "getMaxHeight") + { + return (int64_t)this->cache->MaxHeight(); + } + if(key == "ToStirng") + { + return "SDL2.FontCache"; + } + return Undefined(); + } + + std::string TypeName() + { + return "SDL2.FontCache"; + } + + void Mark() + { + if(this->marked) return; + this->marked=true; + for(auto item : this->textures) item->Mark(); + } + + ~SDL2_FontCache() + { + delete cache; + } + }; + + template + class GUI_EventInstance : public Tesses::Framework::Event + { + public: + GCList* ls; + TCallable* callable; + TObject myObj; + GUI_EventInstance(GC* gc,TObject parent,TCallable* call) + { + this->ls = new GCList(gc); + this->callable = call; + this->myObj = parent; + } + void Invoke(Tesses::Framework::SDL2::View* _v,T& _e) + { + GCList ls2(this->ls->GetGC()); + Tesses::Framework::SDL2::GUIEventArgs* e= &_e; + + auto btnE = dynamic_cast(e); + if(btnE != nullptr) + { + + callable->Call(ls2,{ + myObj,TDictionary::Create(ls2,{ + TDItem("Type",std::string("GUI.MouseButtonEventArgs")), + TDItem("Which",(int64_t)btnE->which), + TDItem("X",(int64_t)btnE->x), + TDItem("Y",(int64_t)btnE->y), + TDItem("Button",(int64_t)btnE->button) + }) + }); + } + + else { + callable->Call(ls2,{ + myObj,TDictionary::Create(ls2,{ + TDItem("Type",std::string("GUI.EventArgs")) + }) + }); + } + } + + ~GUI_EventInstance() + { + delete ls; + } + }; + + + class GUI_View : public TNativeObject { + protected: + template + void AddEvent(GC* gc,Tesses::Framework::EventList& el,TCallable* callable) + { + el +=std::make_shared>(gc, this, callable); + } + template + void RemoveEvent(Tesses::Framework::EventList& el,TCallable* callable) + { + el.Remove([callable](auto e)->bool{ + auto res = dynamic_cast*>(e.get()); + return res != nullptr && res->callable == callable; + + }); + } + template + TDictionary* CreateEventDict(GCList& ls,Tesses::Framework::EventList* el) + { + return TDictionary::Create(ls,{ + TDItem("operator+",TExternalMethod::Create(ls,"",{"right"},[el,this](GCList& ls, std::vector args)->TObject { + TCallable* callable; + if(GetArgumentHeap(args,0,callable)) + { + this->AddEvent(ls.GetGC(),*el,callable); + } + return nullptr; + })), + TDItem("operator-",TExternalMethod::Create(ls,"",{"right"},[el,this](GCList& ls, std::vector args)->TObject { + TCallable* callable; + if(GetArgumentHeap(args,0,callable)) + { + this->RemoveEvent(*el,callable); + } + return nullptr; + })), + }); + } + public: + Tesses::Framework::SDL2::View* view; + GUI_View() + { + this->view = nullptr; + } + + GUI_View(Tesses::Framework::SDL2::View* view) + { + this->view = view; + } + TObject FindViewById(GCList& ls,std::string id); + + + + virtual TObject CallMethod(GCList& ls,std::string key, std::vector args) + { + if(key == "getClick") + { + return CreateEventDict(ls,&this->view->Click); + } + if(key == "FindViewById") + { + std::string id; + if(GetArgument(args,0,id)) + { + return FindViewById(ls,id); + } + return nullptr; + } + if(key == "getText") + { + return this->view->GetText(); + } + if(key == "setText") + { + std::string str; + if(GetArgument(args,0,str)) + { + this->view->SetText(str); + return str; + } + } + return Undefined(); + } + + + }; + class GUI_ButtonView : public GUI_View { + public: + GUI_ButtonView(Views::ButtonView* view) : GUI_View(view) + { + + } + GUI_ButtonView(std::string text) : GUI_View(new Views::ButtonView(text)) + { + + } + std::string TypeName() + { + return "GUI.ButtonView"; + } + }; + class GUI_ContainerView : public GUI_View { + public: + virtual std::string TypeName() + { + return "GUI.ContainerView"; + } + }; + + + + class GUI_Window : public GUI_ContainerView { + Tesses::Framework::SDL2::GUIPalette Default() + { + return Tesses::Framework::SDL2::GUIPalette(true,{.r=192,.g=255,.b=0,.a=255}); + } + public: + + //"title","width","height","flags","$pallete" + GUI_Window(std::string title, int width, int height, Uint32 flags, Tesses::Framework::SDL2::GUIPalette* palette) + { + this->view = new Tesses::Framework::SDL2::GUIWindow(title,width,height,flags,palette != nullptr ? *palette : Default()); + } + + std::string TypeName() + { + return "GUI.Window"; + } + + TObject CallMethod(GCList& ls, std::string key, std::vector args) + { + auto win = dynamic_cast(this->view); + if(win != nullptr) + { + if(key == "setView") + { + GUI_View* v; + if(GetArgumentHeap(args,0,v)) + { + win->SetView(v->view,true); + } + } + } + return GUI_ContainerView::CallMethod(ls,key,args); + } + }; + + static TObject New_SDL2_Window(GCList& ls, std::vector args) + { + std::string title; + int64_t x,y,w,h,flags; + + if(GetArgument(args,0,title) && GetArgument(args,1,x) && GetArgument(args,2,y) && GetArgument(args,3,w) && GetArgument(args,4,h) && GetArgument(args,5,flags)) + { + return TNativeObject::Create(ls,title,(int)x,(int)y,(int)w,(int)h,(uint32_t)(uint64_t)flags); + } + return Undefined(); + } + static TObject New_SDL2_Renderer(GCList& ls, std::vector args) + { + SDL2_Window* window; + int64_t index,flags; + + if(GetArgumentHeap(args,0,window) && GetArgument(args,1,index) && GetArgument(args,2,flags)) + { + return TNativeObject::Create(ls,window,(int)index,(uint32_t)(uint64_t)flags); + } + return Undefined(); + } + static TObject New_SDL2_Color(GCList& ls, std::vector args) + { + int64_t r=0,g=0,b=0,a=255; + GetArgument(args,0,r); + GetArgument(args,1,g); + GetArgument(args,2,b); + GetArgument(args,3,a); + return TNativeObject::Create(ls,r,g,b,a); + + + } + static TObject New_SDL2_Rectangle(GCList& ls, std::vector args) + { + int64_t x=0,y=0,w=0,h=0; + GetArgument(args,0,x); + GetArgument(args,1,y); + GetArgument(args,2,w); + GetArgument(args,3,h); + return TNativeObject::Create(ls,x,y,w,h); + + + } + static TObject New_SDL2_Image(GCList& ls, std::vector args) + { + TVFSHeapObject* vfs; + Tesses::Framework::Filesystem::VFSPath path; + TByteArray* ba; + TStreamHeapObject* mstrm; + + + if(GetArgumentHeap(args,0,vfs) && GetArgumentAsPath(args,1,path)) + { + auto strm = vfs->vfs->OpenFile(path,"rb"); + if(strm != nullptr) + { + if(strm->CanRead()) + { + auto strm2 = Tesses::Framework::SDL2::RwopsFromStream(strm); + return TNativeObject::Create(ls,IMG_Load_RW(strm2,1)); + } + delete strm; + } + } + else if(GetArgumentHeap(args,0,ba)) + { + auto ms =new Tesses::Framework::Streams::MemoryStream(false); + ms->GetBuffer() = ba->data; + return TNativeObject::Create(ls,IMG_Load_RW(Tesses::Framework::SDL2::RwopsFromStream(ms),1)); + } + else if(GetArgumentHeap(args,0,mstrm)) + { + return TNativeObject::Create(ls,IMG_Load_RW(Tesses::Framework::SDL2::RwopsFromStream(mstrm->stream,false),1)); + } + else if(args.size() == 1) { + return TNativeObject::Create(ls,IMG_Load_RW(Tesses::Framework::SDL2::RwopsFromStream(new TObjectStream(ls.GetGC(),args[0])),1)); + } + return Undefined(); + } + static TObject New_SDL2_FontCache(GCList& ls, std::vector args) + { + SDL2_Renderer* renderer; + int64_t pt; + if(GetArgumentHeap(args,0,renderer) && GetArgument(args,2,pt)) + { + TByteArray* ba; + + TStreamHeapObject* strm; + if(GetArgumentHeap(args,1,ba)) + { + return TNativeObject::Create(ls,ls,renderer,ba,pt); + } + else if(GetArgumentHeap(args,1,strm)) + { + auto res = TTF_OpenFontRW(Tesses::Framework::SDL2::RwopsFromStream(strm->stream,false),1,pt); + auto res2= TNativeObject::Create(ls,ls,renderer,res,pt); + TTF_CloseFont(res); + return res2; + } + else if(args.size() > 1 && !std::holds_alternative(args[1])) + { + + auto res = TTF_OpenFontRW(Tesses::Framework::SDL2::RwopsFromStream(new TObjectStream(ls.GetGC(),args[1])),1,pt); + auto res2= TNativeObject::Create(ls,ls,renderer,res,pt); + TTF_CloseFont(res); + return res2; + } + return TNativeObject::Create(ls,ls,renderer,pt); + } + return Undefined(); + } + static TObject New_GUI_ButtonView(GCList& ls, std::vector args) + { + std::string text; + GetArgument(args,0,text); + + return TNativeObject::Create(ls,text); + } + static TObject New_GUI_Window(GCList& ls, std::vector args) + { + //"title","width","height","flags" + std::string title; + int64_t w; + int64_t h; + int64_t flags; + if(GetArgument(args,0,title) && GetArgument(args,1,w) && GetArgument(args,2,h) && GetArgument(args,3,flags)) + { + return TNativeObject::Create(ls,title,w,h,flags,nullptr); + } + + return nullptr; + } + class SDL2_getEvents_Enumerator : public TEnumerator + { + SDL_Event event; + bool has; + public: + static SDL2_getEvents_Enumerator* Create(GCList& ls) + { + SDL2_getEvents_Enumerator* e=new SDL2_getEvents_Enumerator(); + auto gc = ls.GetGC(); + ls.Add(e); + gc->Watch(e); + return e; + } + bool MoveNext(GC* ls) + { + has = SDL_PollEvent(&event); + return has; + } + TObject GetCurrent(GCList& ls) + { + return SDL_Event2Dict(ls, event); + } + }; + TObject GUI_View::FindViewById(GCList& ls,std::string id) + { + auto view = this->view->FindViewById(id); + auto buttonView = dynamic_cast(view); + if(buttonView != nullptr) + { + return TNativeObject::Create(ls,buttonView); + } + return nullptr; + } + static TObject SDL2_getEvents(GCList& ls, std::vector args) + { + return TDictionary::Create(ls,{ + TDItem("GetEnumerator", TExternalMethod::Create(ls,"GetEnumerator",{},[](GCList& ls,std::vector args)->TObject { + return SDL2_getEvents_Enumerator::Create(ls); + })) + }); + } + static TObject GUI_Window_FromDictionary(GCList& ls, std::vector args) + { + int64_t flags; + TObject o; + + if(args.size() >= 1) + { + GetArgument(args,1,flags); + std::string jsonText = ToString(ls.GetGC(),args[0]); + GUI_Window* window = TNativeObject::Create(ls,std::string("Unnamed Window"),320,240,flags,nullptr); + + dynamic_cast(window->view)->SetView(Tesses::Framework::Serialization::Json::Json::Decode(jsonText)); + return window; + } + return nullptr; + } + + + #endif + void TStd::RegisterSDL2(GC* gc,TRootEnvironment* env) + { + env->permissions.canRegisterSDL2=true; + #if defined(TESSESFRAMEWORK_ENABLE_SDL2) + GCList ls(gc); + + + + auto newDict=env->EnsureDictionary(gc,"New"); + + TDictionary* sdl2_new = TDictionary::Create(ls,{ + TDItem("Image",TExternalMethod::Create(ls, "Load image",{"streamOrBA"},New_SDL2_Image)), + TDItem("FontCache",TExternalMethod::Create(ls, "Create font cache",{"renderer","font","pt","color"},New_SDL2_FontCache)), + TDItem("Window",TExternalMethod::Create(ls,"Create window for SDL2",{"title","x","y","w","h","flags"},New_SDL2_Window)), + TDItem("Renderer",TExternalMethod::Create(ls,"Create renderer for SDL2",{"window","index","flags"},New_SDL2_Renderer)), + TDItem("Rectangle",TExternalMethod::Create(ls,"Create rectangle for SDL2",{"$x","$y","$w","$h"},New_SDL2_Rectangle)), + TDItem("Color",TExternalMethod::Create(ls,"Create color for SDL2",{"$r","$g","$b","$a"},New_SDL2_Color)) + }); + TDictionary* gui_new = TDictionary::Create(ls, { + TDItem("ButtonView",TExternalMethod::Create(ls,"Create a button",{"$text"},New_GUI_ButtonView)), + TDItem("Window",TExternalMethod::Create(ls,"Create the window",{"title","width","height","flags","$pallete"},New_GUI_Window)) + }); + + TDictionary* gui_d = TDictionary::Create(ls, { + TDItem("Window",TDictionary::Create(ls, { + TDItem("FromJSON",TExternalMethod::Create(ls, "Create window from JSON (anything that returns valid stringifed json via ToString)",{"dictOrStringOrByteArray","$flags"},GUI_Window_FromDictionary)) + })) + }); + + TDictionary* sdl2_d = TDictionary::Create(ls,{ + TDItem("getEvents",TExternalMethod::Create(ls,"Get events",{},SDL2_getEvents)), + TDItem("WindowPos",TDictionary::Create(ls,{ + TDItem("Undefined",(int64_t)SDL_WINDOWPOS_UNDEFINED), + TDItem("Centered",(int64_t)SDL_WINDOWPOS_CENTERED) + })), + TDItem("Window",TDictionary::Create(ls,{ + TDItem("Fullscreen",(int64_t)SDL_WINDOW_FULLSCREEN), + TDItem("OpenGL",(int64_t)SDL_WINDOW_OPENGL), + TDItem("Shown",(int64_t)SDL_WINDOW_SHOWN), + TDItem("Hidden",(int64_t)SDL_WINDOW_HIDDEN), + TDItem("Borderless",(int64_t)SDL_WINDOW_BORDERLESS), + TDItem("Resizable",(int64_t)SDL_WINDOW_RESIZABLE), + TDItem("Minimized",(int64_t)SDL_WINDOW_MINIMIZED), + TDItem("Maximized",(int64_t)SDL_WINDOW_MAXIMIZED), + TDItem("MouseGrabbed",(int64_t)SDL_WINDOW_MOUSE_GRABBED), + TDItem("InputFocus",(int64_t)SDL_WINDOW_INPUT_FOCUS), + TDItem("MouseFocus",(int64_t)SDL_WINDOW_MOUSE_FOCUS), + TDItem("FullscreenDesktop",(int64_t)SDL_WINDOW_FULLSCREEN_DESKTOP), + TDItem("Foreign",(int64_t)SDL_WINDOW_FOREIGN), + TDItem("AllowHighDPI",(int64_t)SDL_WINDOW_ALLOW_HIGHDPI), + TDItem("MouseCapture",(int64_t)SDL_WINDOW_MOUSE_CAPTURE), + TDItem("AlwaysOnTop",(int64_t)SDL_WINDOW_ALWAYS_ON_TOP), + TDItem("SkipTaskbar",(int64_t)SDL_WINDOW_SKIP_TASKBAR), + TDItem("Utility",(int64_t)SDL_WINDOW_UTILITY), + TDItem("Tooltip",(int64_t)SDL_WINDOW_TOOLTIP), + TDItem("PopupMenu",(int64_t)SDL_WINDOW_POPUP_MENU), + TDItem("KeyboardGrabbed",(int64_t)SDL_WINDOW_KEYBOARD_GRABBED), + TDItem("Vulkan",(int64_t)SDL_WINDOW_VULKAN), + TDItem("Metal",(int64_t)SDL_WINDOW_METAL), + TDItem("InputGrabbed",(int64_t)SDL_WINDOW_INPUT_GRABBED) + })), + TDItem("Event",TDictionary::Create(ls,{ + TDItem("Quit",(int64_t)SDL_QUIT), + TDItem("AppTerminating",(int64_t)SDL_APP_TERMINATING), + TDItem("AppLowMemory",(int64_t)SDL_APP_LOWMEMORY), + TDItem("AppWillEnterBackground",(int64_t)SDL_APP_WILLENTERBACKGROUND), + TDItem("AppDidEnterBackground",(int64_t)SDL_APP_DIDENTERBACKGROUND), + TDItem("AppWillEnterForeground",(int64_t)SDL_APP_WILLENTERFOREGROUND), + TDItem("AppDidEnterForeground",(int64_t)SDL_APP_DIDENTERFOREGROUND), + TDItem("LocaleChanged",(int64_t)SDL_LOCALECHANGED), + TDItem("DisplayEvent",(int64_t)SDL_DISPLAYEVENT), + TDItem("WindowEvent",(int64_t)SDL_WINDOWEVENT), + TDItem("SysWMEvent",(int64_t)SDL_SYSWMEVENT), + TDItem("KeyDown",(int64_t)SDL_KEYDOWN), + TDItem("KeyUp",(int64_t)SDL_KEYUP), + TDItem("TextEditing",(int64_t)SDL_TEXTEDITING), + TDItem("TextInput",(int64_t)SDL_TEXTINPUT), + TDItem("KeyMapChanged",(int64_t)SDL_KEYMAPCHANGED), + TDItem("TextEditingExt",(int64_t)SDL_TEXTEDITING_EXT), + TDItem("MouseMotion",(int64_t)SDL_MOUSEMOTION), + TDItem("MouseButtonDown",(int64_t)SDL_MOUSEBUTTONDOWN), + TDItem("MouseButtonUp",(int64_t)SDL_MOUSEBUTTONUP), + TDItem("MouseWheel",(int64_t)SDL_MOUSEWHEEL), + TDItem("JoyAxisMotion",(int64_t)SDL_JOYAXISMOTION), + TDItem("JoyBallMotion",(int64_t)SDL_JOYBALLMOTION), + TDItem("JoyHatMotion",(int64_t)SDL_JOYHATMOTION), + TDItem("JoyButtonDown",(int64_t)SDL_JOYBUTTONDOWN), + TDItem("JoyButtonUp",(int64_t)SDL_JOYBUTTONUP), + TDItem("JoyButtonDown",(int64_t)SDL_JOYBUTTONDOWN), + TDItem("JoyDeviceAdded",(int64_t)SDL_JOYDEVICEADDED), + TDItem("JoyDeviceRemoved",(int64_t)SDL_JOYDEVICEREMOVED), + TDItem("JoyBatteryUpdated",(int64_t)SDL_JOYBATTERYUPDATED), + TDItem("ControllerAxisMotion",(int64_t)SDL_CONTROLLERAXISMOTION), + TDItem("ControllerButtonDown",(int64_t)SDL_CONTROLLERBUTTONDOWN), + TDItem("ControllerButtonUp",(int64_t)SDL_CONTROLLERBUTTONUP), + TDItem("ControllerDeviceAdded",(int64_t)SDL_CONTROLLERDEVICEADDED), + TDItem("ControllerDeviceRemoved",(int64_t)SDL_CONTROLLERDEVICEREMOVED), + TDItem("ControllerDeviceRemapped",(int64_t)SDL_CONTROLLERDEVICEREMAPPED), + TDItem("ControllerTouchpadDown",(int64_t)SDL_CONTROLLERTOUCHPADDOWN), + TDItem("ControllerTouchpadMotion",(int64_t)SDL_CONTROLLERTOUCHPADMOTION), + TDItem("ControllerTouchPadUp",(int64_t)SDL_CONTROLLERTOUCHPADUP), + TDItem("ControllerSensorUpdate",(int64_t)SDL_CONTROLLERSENSORUPDATE), + TDItem("ControllerSteamHandleUpdated",(int64_t)SDL_CONTROLLERSTEAMHANDLEUPDATED), + TDItem("FingerDown",(int64_t)SDL_FINGERDOWN), + TDItem("FingerUp",(int64_t)SDL_FINGERUP), + TDItem("FingerMotion",(int64_t)SDL_FINGERMOTION), + TDItem("DollarGesture",(int64_t)SDL_DOLLARGESTURE), + TDItem("DollarRecord",(int64_t)SDL_DOLLARRECORD), + TDItem("MultiGesture",(int64_t)SDL_MULTIGESTURE), + TDItem("ClipboardUpdate",(int64_t)SDL_CLIPBOARDUPDATE), + TDItem("DropFile",(int64_t)SDL_DROPFILE), + TDItem("DropText",(int64_t)SDL_DROPTEXT), + TDItem("DropBegin",(int64_t)SDL_DROPBEGIN), + TDItem("DropComplete",(int64_t)SDL_DROPCOMPLETE), + TDItem("AudioDeviceAdded",(int64_t)SDL_AUDIODEVICEADDED), + TDItem("AudioDeviceRemoved",(int64_t)SDL_AUDIODEVICEREMOVED), + TDItem("SensorUpdate",(int64_t)SDL_SENSORUPDATE), + TDItem("RenderTargetsReset",(int64_t)SDL_RENDER_TARGETS_RESET), + TDItem("RenderDeviceReset",(int64_t)SDL_RENDER_DEVICE_RESET) + })) + }); + + gc->BarrierBegin(); + newDict->SetValue("SDL2",sdl2_new); + newDict->SetValue("GUI",gui_new); + env->SetVariable("SDL2",sdl2_d); + env->SetVariable("GUI",gui_d); + gc->BarrierEnd(); + + #endif + } +} \ No newline at end of file