summaryrefslogtreecommitdiff
path: root/Source/tests
diff options
context:
space:
mode:
Diffstat (limited to 'Source/tests')
-rw-r--r--Source/tests/01-cursor/main.cpp10
-rw-r--r--Source/tests/02-luax/header.h60
-rw-r--r--Source/tests/02-luax/main.cpp305
-rw-r--r--Source/tests/02-luax/script.lua141
-rw-r--r--Source/tests/03-openal/main.cpp7
-rw-r--r--Source/tests/05-physfs/main.cpp88
-rw-r--r--Source/tests/05-physfs/ok.txt0
-rw-r--r--Source/tests/06-coroutine/main.cpp0
-rw-r--r--Source/tests/07-image/main.cpp0
-rw-r--r--Source/tests/win32/01-window/01_menu_bar.cpp95
-rw-r--r--Source/tests/win32/01-window/02_multi_window.cpp110
-rw-r--r--Source/tests/win32/01-window/03_sub_menu.cpp355
-rw-r--r--Source/tests/win32/01-window/config.h10
-rw-r--r--Source/tests/win32/common/window.cpp0
-rw-r--r--Source/tests/win32/common/window.h0
15 files changed, 1181 insertions, 0 deletions
diff --git a/Source/tests/01-cursor/main.cpp b/Source/tests/01-cursor/main.cpp
new file mode 100644
index 0000000..f8946d9
--- /dev/null
+++ b/Source/tests/01-cursor/main.cpp
@@ -0,0 +1,10 @@
+///
+/// ޸ʽ
+///
+
+#include "SDL2/SDL.h"
+
+int main(int argc, char* args[])
+{
+ return 0;
+} \ No newline at end of file
diff --git a/Source/tests/02-luax/header.h b/Source/tests/02-luax/header.h
new file mode 100644
index 0000000..386ae71
--- /dev/null
+++ b/Source/tests/02-luax/header.h
@@ -0,0 +1,60 @@
+
+#ifndef ASSERT
+#ifdef NDEBUG
+#define ASSERT(x) { false ? (void)(x) : (void)0; }
+#else
+#ifdef _WIN32
+#define ASURA_DEBUG_BREAK() __debugbreak()
+#else
+#define ASURA_DEBUG_BREAK() raise(SIGTRAP)
+#endif
+#define ASSERT(x) do { const volatile bool asura_assert_b____ = !(x); if(asura_assert_b____) ASURA_DEBUG_BREAK(); } while (false)
+#endif
+#endif
+
+///
+/// ̳Singletonڵһʵʱʵ֮ٴʵᱨ
+///
+template<class T>
+class Singleton
+{
+public:
+
+ static T* Get()
+ {
+ // ֮ǰûдһ
+ if (!instance) instance = new T;
+ // ʵ
+ return instance;
+ }
+
+ static void Destroy()
+ {
+ delete instance;
+ instance = nullptr;
+ }
+
+protected:
+
+ Singleton()
+ {
+ // instanceζִһʵǴġ
+ ASSERT(!instance);
+ // 򣬽ʵΪʵ
+ instance = static_cast<T*>(this);
+ };
+
+ virtual ~Singleton() {};
+
+ static T* instance;
+
+private:
+
+ Singleton(const Singleton& singleton);
+
+ Singleton& operator = (const Singleton& singleton);
+
+};
+
+template<class T>
+T* Singleton<T>::instance = nullptr;
diff --git a/Source/tests/02-luax/main.cpp b/Source/tests/02-luax/main.cpp
new file mode 100644
index 0000000..59a4bcb
--- /dev/null
+++ b/Source/tests/02-luax/main.cpp
@@ -0,0 +1,305 @@
+///
+/// Scripting with Lua.
+///
+extern "C"{
+#include <Lua51/lua.h>
+#include <Lua51/lauxlib.h>
+}
+#include <Luax/luax.h>
+
+#include "header.h"
+
+#include <iostream>
+#include <string>
+
+using namespace std;
+using namespace Luax;
+
+//--------------------------------------------------------------------------------//
+
+class School
+ : public Singleton<School>
+ , public LuaxNativeClass<School>
+{
+public:
+
+ School() : mName("Koko") {}
+
+private:
+
+ const char* mName;
+
+public:
+
+ LUAX_DECL_SINGLETON(School);
+
+ LUAX_DECL_METHOD(l_GetName);
+
+};
+
+int School::l_GetName(lua_State* L)
+{
+ LUAX_STATE(L);
+
+ School* school = Get();
+
+ state.Push(school->mName);
+ return 1;
+}
+
+void School::RegisterLuaxClass(LuaxState& state)
+{
+ state.SetField(-1, "Region", "Block 1"); // 101
+
+ luaL_Reg regTable[] = {
+ { "GetName", l_GetName },
+ { NULL, NULL }
+ };
+
+ state.RegisterMethods(regTable);
+
+}
+
+void School::RegisterLuaxPostprocess(Luax::LuaxState&)
+{
+}
+
+//--------------------------------------------------------------------------------//
+
+class Boy : public LuaxNativeClass<Boy>
+{
+public:
+
+ Boy(int age, const char* name) : mAge(age), mName(name){}
+
+ int mAge;
+
+ const char* mName;
+
+private:
+
+public:
+
+ LUAX_DECL_FACTORY(SimBoy);
+
+ // member methods
+ LUAX_DECL_METHOD(l_GetAge);
+ LUAX_DECL_METHOD(l_GetName);
+
+ // class method
+ LUAX_DECL_METHOD(l_New);
+ LUAX_DECL_METHOD(l_GetGender);
+
+ LUAX_DECL_METHOD(l_Write);
+ LUAX_DECL_METHOD(l_Speak);
+
+private:
+
+ LuaxMemberRef mCallbak;
+
+};
+
+int Boy::l_New(lua_State* L)
+{
+ LUAX_STATE(L);
+
+ int age = state.GetValue(1, 0);
+ const char* name = state.GetValue(2, "");
+
+ Boy* boy = new Boy(age, name);
+ boy->PushLuaxUserdata(state);
+
+ return 1;
+}
+
+int Boy::l_GetAge(lua_State* L)
+{
+ LUAX_SETUP(L, "U");
+ Boy* self = state.CheckUserdata<Boy>(1);
+ state.Push(self->mAge);
+ return 1;
+}
+
+int Boy::l_GetName(lua_State* L)
+{
+ LUAX_SETUP(L, "U");
+ Boy* self = state.CheckUserdata<Boy>(1);
+ state.Push(self->mName);
+ return 1;
+}
+
+int Boy::l_GetGender(lua_State* L)
+{
+ LUAX_SETUP(L, "*");
+ state.Push("male student!");
+ return 1;
+}
+
+int Boy::l_Speak(lua_State* L)
+{
+ LUAX_STATE(L);
+
+ Boy* self = state.CheckUserdata<Boy>(1);
+ self->PushLuaxMemberRef(state, self->mCallbak);
+ state.Call(0, 1);
+ return 1;
+}
+
+int Boy::l_Write(lua_State* L)
+{
+ LUAX_STATE(L);
+ // self, func
+ Boy* self = state.CheckUserdata<Boy>(1);
+ self->SetLuaxMemberRef(state, self->mCallbak, 2);
+ return 0;
+}
+
+void Boy::RegisterLuaxClass(LuaxState& state)
+{
+
+ LUAX_REGISTER_METHODS(state,
+ { "New", l_New },/**/
+ { "GetGender", l_GetGender },
+ { "GetAge", l_GetAge },
+ { "GetName", l_GetName },
+ { "Write", l_Write },
+ { "Speak", l_Speak }
+ );
+
+ // boyİ
+ LUAX_REGISTER_ENUM(state, "EHabits",
+ { "Computer", 1 },
+ { "Buscketball", 2 },
+ { "Baseball", 3 },
+ { "Girls", 4 }
+ );
+}
+
+void Boy::RegisterLuaxPostprocess(LuaxState& state)
+{
+ // boyİ
+ LUAX_REGISTER_ENUM(state, "EHabits",
+ { "Computer", 1 },
+ { "Buscketball", 2 },
+ { "Baseball", 3 },
+ { "Girls", 4 }
+ );
+}
+
+//--------------------------------------------------------------------------------//
+///
+/// Ӧsignalıհ
+///
+class Slot
+{
+public:
+ Slot(LuaxState& state, Boy* widget, int refID)
+ : mState(state)
+ , mRefID(refID)
+ , mWidget(widget)
+ {
+ }
+
+ void operator()()
+ {
+ ASSERT(mState);
+ ASSERT(mWidget);
+
+ mWidget->PushLuaxMemberRef(mState, mRefID);
+ if (lua_isfunction(mState, -1)) // callback
+ {
+ mState.Call(0, 0);
+ }
+ }
+
+private:
+ LuaxState & mState; //
+ Boy* mWidget; // ӦĿؼ
+ int mRefID; // ؼ
+
+};
+///
+/// ؼ¼
+///
+class Signal
+{
+public:
+ Signal();
+
+ ///
+ /// Fire¼connectļߣãconnectĺ
+ ///
+ void operator()()
+ {
+ for (auto callback : mCallbacks)
+ callback();
+ }
+
+ ///
+ /// עص
+ ///
+ void Connect(const Slot& callback)
+ {
+ mCallbacks.push_back(callback);
+ }
+
+ ///
+ ///
+ ///
+ void Disconnect();
+
+private:
+ std::vector<Slot> mCallbacks; //
+
+};
+
+//--------------------------------------------------------------------------------//
+
+#include "script.lua"
+
+//--------------------------------------------------------------------------------//
+
+int func(lua_State* L)
+{
+ LUAX_SETUP(L, "*");
+ state.Push("func ok");
+ return 1;
+}
+
+int main()
+{
+ LuaxRuntime& runtime = LuaxRuntime::Get();
+ lua_State* L = runtime.Open();
+
+ Luax::LuaxState& state = runtime[L].state;
+ state.OpenLibs();
+ state.PushGlobalNamespace();
+ state.PushNamespace("Asura");
+ state.RegisterPlainClassRegistry("Class"); // Asura.Class("Foo")
+ state.RegisterPlainEnumRegistry("Enum"); // Asura.Enum("EFoo", { ... });
+ //עenum
+ LuaxEnum EGender[] = {
+ { "BOY", 7 },
+ { "GIRL", 8 },
+ { "MID", 9 },
+ { 0, 0 },
+ };
+
+ state.RegisterEnum("EGender", EGender);
+
+ state.PushNamespace("author");
+ state.SetField(-1, "name", "chai");
+ state.SetField(-1, "func", func);
+ state.PopNamespace(); // Asura.author
+ state.SetField(-1, "version", 100);
+ cout << state.GetField<float>(-1, "version", 0);
+
+ state.RegisterSingleton<School>();
+ state.RegisterFactory<Boy>();
+
+ state.PopNamespace(); // Asura
+ state.PopNamespace(); // Global
+ state.DoString(script);
+
+ runtime.Close(L);
+} \ No newline at end of file
diff --git a/Source/tests/02-luax/script.lua b/Source/tests/02-luax/script.lua
new file mode 100644
index 0000000..7e553d2
--- /dev/null
+++ b/Source/tests/02-luax/script.lua
@@ -0,0 +1,141 @@
+string script = R"scriptcode(
+-- start script
+
+function main()
+ local a = 19
+ print(Asura.version)
+ print(Asura.author.name)
+ print("ok")
+ print(Asura.author.func())
+-- local boy = Asura.SimBoy.New("I am peter!", 19)
+-- boy:Say()
+-- print(Asura.SimSchool.GetName())
+ print(Asura.SimBoy.Class)
+ print(Asura.SimBoy.Gender)
+ print(Asura.SimBoy.GetClassName())
+ print(Asura.School.GetName())
+ print(Asura.School.Region)
+--[[
+ local Kid = Asura.SimBoy.Extend()
+ Asura.Kid = Kid
+ Kid.New = function(self, height, age)
+ self.base(age)
+ self.height = height
+ end
+ Kid.GetHeight = function(self)
+ print(self.height)
+ end
+ local kid = Kid.New(110, 12)
+ kid:GetHeight()
+ ]]
+ local kid = Asura.SimBoy.New(23, "Chai")
+ print(kid:GetAge())
+ print(kid:GetName())
+ kid.fruit = function()
+ return "apple"
+ end
+ print(kid.fruit())
+ print(Asura.SimBoy.GetGender())
+ Asura.SimBoy.Havefun = function()
+ return "Boys have some fun!"
+ end
+ print(Asura.SimBoy.Havefun())
+
+-- ޸෽
+ Asura.SimBoy.Foo = function()
+ return "SimBoy.Foo"
+ end
+ print(Asura.SimBoy.Foo())
+
+ print(Asura.EGender.BOY)
+ --Asura.EGender.BOY = 2
+ print(Asura.EGender.BOY)
+ print(Asura.SimBoy.EHabits.Girls)
+ print(Asura.EHabits.Girls)
+ print(kid)
+
+ kid:Write(function()
+ return "kid:Write()"
+ end )
+ print(kid:Speak())
+
+ kid:Write(function()
+ return "kid:Write() 2"
+ end )
+ print(kid:Speak())
+
+------------------- plain class test
+ local Foo = Asura.Class("Foo")
+ Foo.__init = function(self, age, name, boy)
+ self.age = age
+ self.name = name
+ self.boy = boy
+ end
+ Foo.GetAge = function(self)
+ return self.age
+ end
+ Foo.GetName = function(self)
+ return self.name
+ end
+ local foo = Foo.New(10, "lee", kid)
+ print(foo:GetName())
+ print(Foo.GetClassName())
+ print(foo.GetClassName())
+ print(foo.boy:GetAge())
+--------------------inherits test
+ local Coo = Foo.Extend("Coo")
+ print(Coo.GetClassName())
+ local coo = Coo.New(20, "Wang", kid)
+ print(coo:GetAge())
+ Coo.__init = function(self, age, name, boy)
+ self.age = age - 1
+ self.name = boy:GetName()
+ self.boy = boy
+ self.__base.__init(self, age, "Wangba", boy)
+ end
+ Coo.GetName = function(self)
+ local name = self.__base.GetName(self)
+ return "his name is " .. name
+ end
+ local coo2 = Coo.New(20, "Wang", kid)
+ print(coo2:GetAge())
+ print(coo2.GetClassName())
+ print(coo2:GetName())
+ print(coo2)
+ print(coo)
+ print(coo2:TypeOf("Foo"))
+---------------------plain enum test
+ local ERace = Asura.Enum("ERace", {
+ ["White"] = 1,
+ ["Asian"] = 2,
+ ["Black"] = 3,
+ })
+ print(ERace.White)
+ print(ERace.Asian)
+----------------------native class inherit test
+ -- local Boy2 = Asura.SimBoy.Extend("Boy2")
+ -- Boy2.Speak = function(self)
+ -- return self.__base.GetAge(self)
+ -- end
+ -- Boy2.__init = function(self, age, name)
+ -- print("__init " .. age)
+ -- print("__init " .. name)
+ -- end
+ -- local boy22 = Boy2.New(12, "Liu")
+ -- print(boy22)
+ -- print(boy22:Speak())
+
+------------------------gc test
+ local boy = Asura.SimBoy.New(11, "chaichai")
+ boy = nil
+
+ io.read()
+end
+function err(msg)
+ print(msg)
+end
+xpcall(main, err)
+
+
+-- end script
+)scriptcode"; \ No newline at end of file
diff --git a/Source/tests/03-openal/main.cpp b/Source/tests/03-openal/main.cpp
new file mode 100644
index 0000000..58b3a83
--- /dev/null
+++ b/Source/tests/03-openal/main.cpp
@@ -0,0 +1,7 @@
+
+
+
+int main()
+{
+
+}
diff --git a/Source/tests/05-physfs/main.cpp b/Source/tests/05-physfs/main.cpp
new file mode 100644
index 0000000..cb74292
--- /dev/null
+++ b/Source/tests/05-physfs/main.cpp
@@ -0,0 +1,88 @@
+#include <string>
+
+#include <asura-base/utils.h>
+
+using namespace std;
+using namespace AEScripting;
+
+string code = R"(
+local thread = nil
+local dst = nil
+function main()
+ local suc = Filesystem.Init(arg0)
+ print(suc)
+ suc = Filesystem.Mount("./", "root", true)
+ print(suc)
+ Filesystem.SetWriteDirectory("./")
+ local databuffer = DataBuffer.New(1024)
+ local str = "hello, world"
+ databuffer:Refactor(#str)
+ databuffer:Load(str)
+ local file = Filesystem.CreateFile("physfs.txt")
+ file:Open(EFileMode.WRITE)
+ file:Write(databuffer)
+ file:Close()
+ print(file:GetFileName())
+ print(file:GetExtension())
+ print(file:GetName())
+ dst = DataBuffer.New(138567)
+ thread = Thread.New()
+ local content = ""
+ local cont = "ok"
+ if true then
+ local buff=DataBuffer.New(10)
+ print(buff:GetCapacity())
+ buff = nil
+ end
+ local task = IOTask.New("root/physfs2.txt", dst, EIOTaskType.READ, function(db)
+ function _r()
+ print("test..............")
+ local c = db:GetData()
+ print(c)
+ end
+ function err(msg)
+ print(msg)
+ end
+ xpcall(_r, err)
+ thread:Stop()
+ end)
+ thread:AddTask(task)
+ task = nil
+ thread:Start()
+
+ while true do
+ thread:Dispatch()
+ Thread.Sleep(100)
+ end
+
+end
+
+function err(msg)
+ print(msg)
+end
+
+xpcall(main, err)
+)";
+
+int main(int argc, char* args[])
+{
+ AsuraEngine::UtilsModule utils;
+
+ // ÿһasura򱣴һlua stateһһlua߳
+ Luax::LuaxVM* vm = new Luax::LuaxVM();
+ vm->Setup();
+ Luax::LuaxState state = vm->GetMainState();
+
+ state.OpenLibs();
+ state.PushGlobalNamespace();
+ if(argc > 0)
+ state.SetField(-1, "arg0", args[0]);
+ utils.Initialize(state);
+ state.PopNamespace();
+
+ state.DoString(code);
+
+ delete vm;
+
+ return 0;
+} \ No newline at end of file
diff --git a/Source/tests/05-physfs/ok.txt b/Source/tests/05-physfs/ok.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/tests/05-physfs/ok.txt
diff --git a/Source/tests/06-coroutine/main.cpp b/Source/tests/06-coroutine/main.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/tests/06-coroutine/main.cpp
diff --git a/Source/tests/07-image/main.cpp b/Source/tests/07-image/main.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/tests/07-image/main.cpp
diff --git a/Source/tests/win32/01-window/01_menu_bar.cpp b/Source/tests/win32/01-window/01_menu_bar.cpp
new file mode 100644
index 0000000..95c95e4
--- /dev/null
+++ b/Source/tests/win32/01-window/01_menu_bar.cpp
@@ -0,0 +1,95 @@
+#include "config.h"
+
+#if _run_app == _menu_bar
+
+#include <windows.h>
+
+#include <windows.h>
+
+LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
+void AddMenus(HWND);
+
+#define IDM_FILE_NEW 1
+#define IDM_FILE_OPEN 2
+#define IDM_FILE_QUIT 3
+
+int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
+ PWSTR lpCmdLine, int nCmdShow) {
+
+ MSG msg;
+ WNDCLASSW wc = { 0 };
+ wc.lpszClassName = L"Simple menu";
+ wc.hInstance = hInstance;
+ wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
+ wc.lpfnWndProc = WndProc;
+ wc.hCursor = LoadCursor(0, IDC_ARROW);
+
+ RegisterClassW(&wc);
+ CreateWindowW(wc.lpszClassName, L"Simple menu",
+ WS_OVERLAPPEDWINDOW | WS_VISIBLE,
+ 100, 100, 350, 250, 0, 0, hInstance, 0);
+
+ while (GetMessage(&msg, NULL, 0, 0)) {
+
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+
+ return (int)msg.wParam;
+}
+
+LRESULT CALLBACK WndProc(HWND hwnd, UINT msg,
+ WPARAM wParam, LPARAM lParam) {
+
+ switch (msg) {
+
+ case WM_CREATE:
+
+ AddMenus(hwnd);
+ break;
+
+ case WM_COMMAND:
+
+ switch (LOWORD(wParam)) {
+
+ case IDM_FILE_NEW:
+ case IDM_FILE_OPEN:
+
+ MessageBeep(MB_ICONINFORMATION);
+ break;
+
+ case IDM_FILE_QUIT:
+
+ SendMessage(hwnd, WM_CLOSE, 0, 0);
+ break;
+ }
+
+ break;
+
+ case WM_DESTROY:
+
+ PostQuitMessage(0);
+ break;
+ }
+
+ return DefWindowProcW(hwnd, msg, wParam, lParam);
+}
+
+void AddMenus(HWND hwnd) {
+
+ HMENU hMenubar;
+ HMENU hMenu;
+
+ hMenubar = CreateMenu();
+ hMenu = CreateMenu();
+
+ AppendMenuW(hMenu, MF_STRING, IDM_FILE_NEW, L"&New");
+ AppendMenuW(hMenu, MF_STRING, IDM_FILE_OPEN, L"&Open");
+ AppendMenuW(hMenu, MF_SEPARATOR, 0, NULL);
+ AppendMenuW(hMenu, MF_STRING, IDM_FILE_QUIT, L"&Quit");
+
+ AppendMenuW(hMenubar, MF_POPUP, (UINT_PTR)hMenu, L"&File");
+ SetMenu(hwnd, hMenubar);
+}
+
+#endif // _run_app == _menu_bar \ No newline at end of file
diff --git a/Source/tests/win32/01-window/02_multi_window.cpp b/Source/tests/win32/01-window/02_multi_window.cpp
new file mode 100644
index 0000000..e83f1a3
--- /dev/null
+++ b/Source/tests/win32/01-window/02_multi_window.cpp
@@ -0,0 +1,110 @@
+#include "config.h"
+
+#if _run_app == _multi_window
+
+#include <windows.h>
+#include <GL/GfxDevice.h>
+#include <GL/glu.h>
+#define MAX_LOADSTRING 100
+HINSTANCE hInstance;
+HWND hWnd, hWnd2;
+
+struct WindowData {
+ HWND window;
+ HDC deviceContext;
+ HGLRC renderContext;
+};
+
+LONG WINAPI WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
+ static PAINTSTRUCT ps;
+ int pf;
+ PIXELFORMATDESCRIPTOR pfd;
+ HDC deviceContext;
+ HGLRC renderContext;
+ struct WindowData * windowData = (struct WindowData *) GetWindowLongPtr(hWnd, 0);
+ switch (uMsg) {
+ case WM_NCCREATE:
+ deviceContext = GetDC(hWnd);
+ renderContext = wglCreateContext(deviceContext);
+
+ memset(&pfd, 0, sizeof(pfd));
+ pfd.nSize = sizeof(pfd);
+ pfd.nVersion = 1;
+ pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
+ pfd.iPixelType = PFD_TYPE_RGBA;
+ pfd.cColorBits = 32;
+
+ pf = ChoosePixelFormat(deviceContext, &pfd);
+ SetPixelFormat(deviceContext, pf, &pfd);
+ DescribePixelFormat(deviceContext, pf, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
+ ReleaseDC(hWnd, deviceContext);
+ renderContext = wglCreateContext(deviceContext);
+ wglMakeCurrent(deviceContext, renderContext);
+
+ windowData = (struct WindowData *) malloc(sizeof(struct WindowData));
+ windowData->window = hWnd;
+ windowData->deviceContext = deviceContext;
+ windowData->renderContext = renderContext;
+ SetWindowLongPtr(hWnd, 0, (LONG)windowData);
+ return TRUE;
+ case WM_ACTIVATE:
+ wglMakeCurrent(windowData->deviceContext, windowData->renderContext);
+ break;
+ case WM_PAINT:
+ wglMakeCurrent(windowData->deviceContext, windowData->renderContext);
+ glClear(GL_COLOR_BUFFER_BIT);
+ glBegin(GL_TRIANGLES);
+ glVertex2i(0, 1);
+ glVertex2i(-1, -1);
+ glVertex2i(1, -1);
+ glEnd();
+ glFlush();
+ wglMakeCurrent(NULL, NULL);
+ BeginPaint(hWnd, &ps); EndPaint(hWnd, &ps);
+ return 0;
+ case WM_SIZE:
+ glViewport(0, 0, LOWORD(lParam), HIWORD(lParam)); PostMessage(hWnd, WM_PAINT, 0, 0); return 0;
+ case WM_CHAR:
+ if (wParam == 27) { PostQuitMessage(0); break; }
+ else { return 0; }
+ case WM_DESTROY:
+ ReleaseDC(hWnd, windowData->deviceContext);
+ wglDeleteContext(windowData->renderContext);
+ return 0;
+ case WM_CLOSE:
+ PostQuitMessage(0); return 0;
+ }
+ return DefWindowProc(hWnd, uMsg, wParam, lParam);
+}
+
+
+int WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPTSTR lpCmdLine, _In_ int nCmdShow) {
+ MSG msg;
+ WNDCLASS wc;
+ int pf;
+ PIXELFORMATDESCRIPTOR pfd;
+ hInstance = GetModuleHandle(NULL);
+
+ wc.style = CS_OWNDC;
+ wc.lpfnWndProc = (WNDPROC)WindowProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = sizeof(struct WindowData *);
+ wc.hInstance = hInstance;
+ wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wc.hbrBackground = NULL;
+ wc.lpszMenuName = NULL;
+ wc.lpszClassName = "OpenGL2";
+
+ RegisterClass(&wc);
+ hWnd = CreateWindow("OpenGL2", "Hi there", WS_VSCROLL|WS_TILEDWINDOW, 0, 0, 640, 480, NULL, NULL, hInstance, NULL);
+ hWnd2 = CreateWindow("OpenGL2", "Hi there", WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, 110, 110, 640, 480, NULL, NULL, hInstance, NULL);
+ ShowWindow(hWnd, nCmdShow);
+ ShowWindow(hWnd2, nCmdShow);
+ while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); }
+ wglMakeCurrent(NULL, NULL);
+ DestroyWindow(hWnd);
+ return msg.wParam;
+}
+
+#endif // _run_app == _multi_window \ No newline at end of file
diff --git a/Source/tests/win32/01-window/03_sub_menu.cpp b/Source/tests/win32/01-window/03_sub_menu.cpp
new file mode 100644
index 0000000..fed841d
--- /dev/null
+++ b/Source/tests/win32/01-window/03_sub_menu.cpp
@@ -0,0 +1,355 @@
+#include "config.h"
+#if _run_app == _sub_menu
+
+#include <asura-base/FileSystem/FileManager.h>
+#include <asura-base/FileSystem/DataBuffer.h>
+#include <asura-core/graphics/image.h>
+#include <asura-core/graphics/shader.h>
+#include <asura-core/image/ImageData.h>
+#include <asura-core/graphics/VertexBuffer.h>
+#include <SDL2/SDL.h>
+#include <string>
+
+using namespace std;
+using namespace AEFileSystem;
+using namespace AEGraphics;
+using namespace AEImage;
+
+LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
+void AddMenus(HWND);
+
+#define IDM_FILE_NEW 1
+#define IDM_FILE_IMPORT 2
+
+#define IDM_IMPORT_MAIL 11
+
+#define IDM_ASSET 20
+
+HWND wnd;
+HWND wnd2;
+
+AEMath::Recti viewport;
+
+string vert = R"(
+
+in vec2 position;
+in vec2 uv;
+
+uniform mat4 asura_projection_matrix;
+uniform mat4 asura_model_matrix;
+uniform mat4 asura_view_matrix;
+
+out vec2 texCoord;
+
+void main()
+{
+ gl_Position = asura_projection_matrix * asura_view_matrix * asura_model_matrix * vec4(position, 0, 1);
+ texCoord = uv;
+}
+)";
+
+string frag = R"(
+in vec2 texCoord;
+uniform sampler2D img;
+uniform vec4 color ;
+void main()
+{
+ //gl_FragColor = color * texture2D(img, texCoord);
+ gl_FragColor = color;
+}
+)";
+
+Shader* shader;
+VertexBuffer* vb;
+
+struct
+{
+ int pos;
+ int tex;
+ int m;
+ int v;
+ int p;
+ int color;
+} locs;
+
+struct Vert
+{
+ float x, y; // position
+ float s, t; // uv
+};
+
+int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR lpCmdLine, int nCmdShow)
+{
+
+ AEFileSystem::FileManager::Get()->Init("D:\Asura\bin\win64");
+ MSG msg;
+
+ WNDCLASSEXW wcex;
+ memset(&wcex, 0, sizeof(wcex));
+ wcex.cbSize = sizeof(wcex);
+ wcex.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
+ wcex.lpfnWndProc = WndProc;
+ wcex.cbClsExtra = 0;
+ wcex.cbWndExtra = 0;
+ wcex.hInstance = hInstance;
+ wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wcex.hbrBackground = NULL;
+ wcex.lpszMenuName = NULL;
+ wcex.lpszClassName = L"Submenu";
+
+ RegisterClassExW(&wcex);
+
+ //WNDCLASSW wc = { 0 };
+ //wc.lpszClassName = L"Submenu";
+ //wc.hInstance = hInstance;
+ //wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
+ //wc.lpfnWndProc = WndProc;
+ //wc.hCursor = LoadCursor(0, IDC_ARROW);
+ //RegisterClassW(&wc);
+
+ DWORD windowStyle = 0;
+ DWORD extendedStyle = 0;
+ windowStyle = WS_POPUP | WS_CLIPCHILDREN | WS_THICKFRAME | WS_VISIBLE;
+ extendedStyle = WS_EX_TOOLWINDOW;
+
+ windowStyle = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_CLIPCHILDREN | WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_VISIBLE;
+ extendedStyle = 0;
+
+ //windowStyle = WS_OVERLAPPEDWINDOW | WS_VISIBLE;WS_VISIBLE
+
+ RECT rect = { 100, 100, 500, 500 };
+ AdjustWindowRectEx(&rect, windowStyle, true, extendedStyle);
+
+ wnd = CreateWindowExW(extendedStyle, wcex.lpszClassName, L"", windowStyle,
+ rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
+ NULL, NULL, hInstance, NULL);
+
+ // child
+ windowStyle = WS_POPUP | WS_CLIPCHILDREN | WS_THICKFRAME | WS_VISIBLE;
+ extendedStyle = WS_EX_TOOLWINDOW;
+ rect = { 100, 100, 500, 500 };
+ AdjustWindowRectEx(&rect, windowStyle, false, extendedStyle);
+/*
+ wnd2 = CreateWindowExW(extendedStyle, wcex.lpszClassName, L"", windowStyle,
+ rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
+ NULL, NULL, hInstance, NULL);
+*/
+ //wnd = CreateWindowW(wcex.lpszClassName, L"Asura",
+ // WS_OVERLAPPEDWINDOW | WS_VISIBLE,
+ // 200, 200, 550, 450, 0, 0, hInstance, 0);
+
+ while (GetMessage(&msg, NULL, 0, 0)) {
+
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+
+ ::Sleep(1);
+ }
+
+ return (int)msg.wParam;
+}
+HDC hdc;
+HGLRC glc;
+HGLRC glc2;
+static PAINTSTRUCT ps;
+HBRUSH hBrush;
+HBRUSH hOldBrush;
+HPEN hPen;
+HPEN hOldPen;
+PIXELFORMATDESCRIPTOR pfd;
+int pf;
+File* file;
+File* file2;
+DataBuffer db(102400);
+AEFileSystem::FileManager* fs;
+ImageData* imgdata = new ImageData();
+AEGraphics::Image* img;
+GLint tex;
+LRESULT CALLBACK WndProc(HWND hwnd, UINT msg,
+ WPARAM wParam, LPARAM lParam) {
+
+ switch (msg) {
+
+ case WM_SIZE:
+ {
+ if (g_Device.Inited())
+ {
+ RECT rect;
+ GetClientRect(hwnd, &rect);
+ viewport.Set(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
+ g_Device.SetViewport(viewport);
+ }
+ }
+ case WM_PAINT:
+ if (!g_Device.Inited())
+ break;
+ glEnable(GL_BLEND);
+ glEnable(GL_DEPTH_TEST);
+ //hdc = GetDC(hwnd);
+ //glc = wglCreateContext(hdc);
+ glClearColor(0.16, 0.16, 0.16, 1);
+ //glColor4f(0.219, 0.219, 0.219, 1);
+ //glRectf(-0.5f, -0.5f, 0.5f, 0.5f);
+ //glColor4f(1, 1, 1, 1);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ tex = img->GetGLTexture();
+
+ glBindTexture(GL_TEXTURE_2D, tex); //
+
+ // Χ
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ // ˲
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+
+ {
+ int imgLoc = shader->GetUniformLocation("img");
+ int code = g_Device.GetError();
+ g_Device.SetActiveShader(shader);
+ shader->SetUniformTexture(imgLoc, *img);
+ g_Device.SetMatrixMode(MATRIX_MODE_PROJECTION);
+ g_Device.LoadIdentity();
+ g_Device.Ortho(0, viewport.w, viewport.h, 0, -1, 1);
+ g_Device.SetMatrixMode(MATRIX_MODE_MODEL);
+ g_Device.LoadIdentity();
+ g_Device.Translate(100, 100);
+ shader->SetUniformMatrix44(locs.m, g_Device.GetMatrix(MATRIX_MODE_MODEL));
+ shader->SetUniformMatrix44(locs.v, g_Device.GetMatrix(MATRIX_MODE_VIEW));
+ shader->SetUniformMatrix44(locs.p, g_Device.GetMatrix(MATRIX_MODE_PROJECTION));
+ shader->SetAttribute(locs.pos, vb, 0, 4);
+ shader->SetAttribute(locs.tex, vb, 2, 4);
+ g_Device.SetDrawColor(1, 1, 0, 1);
+ shader->SetUniformColor(locs.color, g_Device.GetDrawColor());
+ //glLineWidth(1);
+ g_Device.DrawArrays(GL_LINE_STRIP, 0, 5);
+ //g_Device.DrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ shader->DisableAttribute(locs.pos);
+ shader->DisableAttribute(locs.tex);
+ g_Device.SetActiveShader(NULL);
+ }
+ glFlush();
+ BeginPaint(hwnd, &ps); EndPaint(hwnd, &ps);
+ UpdateWindow(hwnd);
+ break;
+ case WM_CREATE:
+ AddMenus(hwnd);
+
+ hdc = GetDC(hwnd);
+ memset(&pfd, 0, sizeof(pfd));
+ pfd.nSize = sizeof(pfd);
+ pfd.nVersion = 1;
+ pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
+ pfd.iPixelType = PFD_TYPE_RGBA;
+ pfd.cColorBits = 32;
+
+ pf = ChoosePixelFormat(hdc, &pfd);
+ SetPixelFormat(hdc, pf, &pfd);
+ DescribePixelFormat(hdc, pf, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
+ //ReleaseDC(hwnd, hdc);
+ //glc = wglCreateContext(hdc);
+ glc = wglCreateContext(hdc);
+
+ // ͼƬ
+ fs = AEFileSystem::FileManager::Get();
+ fs->Mount(".", "root");
+ file = new File("root/img.jpg");
+ file->Open(File::FILE_MODE_READ);
+ file->ReadAll(&db);
+
+ wglMakeCurrent(hdc, glc);
+
+ RECT rect;
+ GetWindowRect(hwnd, &rect);
+ viewport.Set(0, 0, rect.right - rect.left, rect.bottom - rect.top);
+ if (!g_Device.Init(viewport))
+ return 0;
+
+ imgdata->Decode(db);
+ img = new Image();
+ img->Load(imgdata);
+ wglMakeCurrent(hdc, glc);
+
+ file2 = new File("root/img.png");
+ file2->Open(File::FILE_MODE_READ);
+ file2->ReadAll(&db);
+ imgdata->Decode(db);
+ img->Load(imgdata, { 50, 100 });
+ imgdata->Release();
+
+ // shader
+ shader = new Shader();
+ shader->Load(vert, frag);
+ {
+ int w = img->GetWidth();
+ int h = img->GetHeight();
+ //Vert v[] = {
+ // { 0.5f, 0.5f, 0, 0 },
+ //{ 0.5f, h + 0.5f, 0, 1 },
+ //{ w + 0.5f, 0.5f, 1, 0 },
+ //{ w + 0.5f, h + 0.5f, 1, 1 },
+ //};
+ Vert v[] = {
+ { 0.5f, 0.5f, 0, 0 },
+ { 0.5f, h + 55.8f, 0, 1 },
+ { w + 0.5f, h + 0.5f, 1, 1 },
+ { w + 0.5f, 0.5f, 1, 0 },
+ { 0.5f, 0.5f, 0, 0 },
+ };
+ vb = new VertexBuffer(BUFFER_USAGE_STATIC, BUFFER_DATA_TYPE_FLOAT, sizeof(v));
+ vb->Fill(v, sizeof(v));
+ };
+ locs.m = shader->GetUniformLocation("asura_model_matrix");
+ locs.v = shader->GetUniformLocation("asura_view_matrix");
+ locs.p = shader->GetUniformLocation("asura_projection_matrix");
+ locs.color = shader->GetUniformLocation("color");
+ locs.pos = shader->GetAttributeLocation("position");
+ locs.tex = shader->GetAttributeLocation("uv");
+
+ break;
+
+ case WM_COMMAND:
+
+ switch (LOWORD(wParam)) {
+
+ case IDM_FILE_NEW:
+ MessageBoxW(wnd, L"New file selected",
+ L"Information", MB_OK);
+ break;
+
+ case IDM_IMPORT_MAIL:
+ MessageBoxW(NULL, L"Import mail selected",
+ L"Information", MB_OK);
+ }
+
+ break;
+
+ case WM_DESTROY:
+
+ PostQuitMessage(0);
+ break;
+
+ }
+
+ return DefWindowProcW(hwnd, msg, wParam, lParam);
+}
+
+void AddMenus(HWND hwnd) {
+ HMENU hMenubar = CreateMenu();
+ HMENU hMenu = CreateMenu();
+ HMENU hSubMenu = CreatePopupMenu();
+ HMENU asserMenu = CreateMenu();
+
+ AppendMenuW(hMenu, MF_STRING, IDM_FILE_NEW, L"&New");
+
+ AppendMenuW(asserMenu, MF_STRING, IDM_ASSET, L"Import &mail &assets");
+ AppendMenuW(hSubMenu, MF_STRING | MF_POPUP, (UINT_PTR)asserMenu, L"Import &mail");
+ AppendMenuW(hMenu, MF_STRING | MF_POPUP, (UINT_PTR)hSubMenu, L"&Import");
+
+ AppendMenuW(hMenubar, MF_POPUP, (UINT_PTR)hMenu, L"&File");
+
+ SetMenu(hwnd, hMenubar);
+}
+
+#endif // _run_app == _sub_menu \ No newline at end of file
diff --git a/Source/tests/win32/01-window/config.h b/Source/tests/win32/01-window/config.h
new file mode 100644
index 0000000..cf7341a
--- /dev/null
+++ b/Source/tests/win32/01-window/config.h
@@ -0,0 +1,10 @@
+#ifndef __Config_H__
+#define __Config_H__
+
+#define _multi_window 1
+#define _menu_bar 2
+#define _sub_menu 3
+
+#define _run_app _sub_menu
+
+#endif \ No newline at end of file
diff --git a/Source/tests/win32/common/window.cpp b/Source/tests/win32/common/window.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/tests/win32/common/window.cpp
diff --git a/Source/tests/win32/common/window.h b/Source/tests/win32/common/window.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/tests/win32/common/window.h