summaryrefslogtreecommitdiff
path: root/source/libs/asura-lib-utils
diff options
context:
space:
mode:
Diffstat (limited to 'source/libs/asura-lib-utils')
-rw-r--r--source/libs/asura-lib-utils/exceptions/exception.cpp47
-rw-r--r--source/libs/asura-lib-utils/exceptions/exception.h44
-rw-r--r--source/libs/asura-lib-utils/io/binding/_compressor.cpp0
-rw-r--r--source/libs/asura-lib-utils/io/binding/_data_buffer.cpp123
-rw-r--r--source/libs/asura-lib-utils/io/binding/_file.cpp223
-rw-r--r--source/libs/asura-lib-utils/io/binding/_file_data.cpp60
-rw-r--r--source/libs/asura-lib-utils/io/binding/_file_system.cpp265
-rw-r--r--source/libs/asura-lib-utils/io/binding/_io_task.cpp46
-rw-r--r--source/libs/asura-lib-utils/io/compressor.cpp11
-rw-r--r--source/libs/asura-lib-utils/io/compressor.h30
-rw-r--r--source/libs/asura-lib-utils/io/data_buffer.cpp102
-rw-r--r--source/libs/asura-lib-utils/io/data_buffer.h62
-rw-r--r--source/libs/asura-lib-utils/io/decoded_data.cpp21
-rw-r--r--source/libs/asura-lib-utils/io/decoded_data.h42
-rw-r--r--source/libs/asura-lib-utils/io/file.cpp292
-rw-r--r--source/libs/asura-lib-utils/io/file.h146
-rw-r--r--source/libs/asura-lib-utils/io/file_data.cpp52
-rw-r--r--source/libs/asura-lib-utils/io/file_data.h69
-rw-r--r--source/libs/asura-lib-utils/io/file_system.cpp198
-rw-r--r--source/libs/asura-lib-utils/io/file_system.h112
-rw-r--r--source/libs/asura-lib-utils/io/io_batch_task.cpp0
-rw-r--r--source/libs/asura-lib-utils/io/io_batch_task.h31
-rw-r--r--source/libs/asura-lib-utils/io/io_task.cpp55
-rw-r--r--source/libs/asura-lib-utils/io/io_task.h57
-rw-r--r--source/libs/asura-lib-utils/io/reloadable.h29
-rw-r--r--source/libs/asura-lib-utils/manager.hpp14
-rw-r--r--source/libs/asura-lib-utils/math/curve.cpp0
-rw-r--r--source/libs/asura-lib-utils/math/curve.h0
-rw-r--r--source/libs/asura-lib-utils/math/functions.cpp0
-rw-r--r--source/libs/asura-lib-utils/math/functions.h0
-rw-r--r--source/libs/asura-lib-utils/math/matrix44.cpp0
-rw-r--r--source/libs/asura-lib-utils/math/matrix44.h24
-rw-r--r--source/libs/asura-lib-utils/math/quaternion.cpp0
-rw-r--r--source/libs/asura-lib-utils/math/quaternion.h0
-rw-r--r--source/libs/asura-lib-utils/math/ranged_value.cpp0
-rw-r--r--source/libs/asura-lib-utils/math/ranged_value.h0
-rw-r--r--source/libs/asura-lib-utils/math/rect.hpp47
-rw-r--r--source/libs/asura-lib-utils/math/rect.inl19
-rw-r--r--source/libs/asura-lib-utils/math/transform.cpp0
-rw-r--r--source/libs/asura-lib-utils/math/transform.h30
-rw-r--r--source/libs/asura-lib-utils/math/vector2.hpp70
-rw-r--r--source/libs/asura-lib-utils/math/vector2.inl114
-rw-r--r--source/libs/asura-lib-utils/math/vector3.hpp233
-rw-r--r--source/libs/asura-lib-utils/math/vector3.inl145
-rw-r--r--source/libs/asura-lib-utils/math/vector4.h234
-rw-r--r--source/libs/asura-lib-utils/math/vector4.inl152
-rw-r--r--source/libs/asura-lib-utils/module.h32
-rw-r--r--source/libs/asura-lib-utils/scripting/lua_env.h72
-rw-r--r--source/libs/asura-lib-utils/scripting/portable.hpp29
-rw-r--r--source/libs/asura-lib-utils/singleton.hpp59
-rw-r--r--source/libs/asura-lib-utils/stringmap.cpp0
-rw-r--r--source/libs/asura-lib-utils/stringmap.hpp29
-rw-r--r--source/libs/asura-lib-utils/threading/binding/_coroutine.cpp40
-rw-r--r--source/libs/asura-lib-utils/threading/binding/_thread.cpp210
-rw-r--r--source/libs/asura-lib-utils/threading/coroutine.cpp16
-rw-r--r--source/libs/asura-lib-utils/threading/coroutine.h40
-rw-r--r--source/libs/asura-lib-utils/threading/mutex.cpp106
-rw-r--r--source/libs/asura-lib-utils/threading/mutex.h126
-rw-r--r--source/libs/asura-lib-utils/threading/semaphore.cpp88
-rw-r--r--source/libs/asura-lib-utils/threading/semaphore.h70
-rw-r--r--source/libs/asura-lib-utils/threading/task.cpp12
-rw-r--r--source/libs/asura-lib-utils/threading/task.h45
-rw-r--r--source/libs/asura-lib-utils/threading/thread.cpp272
-rw-r--r--source/libs/asura-lib-utils/threading/thread.h221
-rw-r--r--source/libs/asura-lib-utils/threading/thread_impl_posix.cpp9
-rw-r--r--source/libs/asura-lib-utils/threading/thread_impl_posix.h0
-rw-r--r--source/libs/asura-lib-utils/threading/thread_impl_sdl.cpp0
-rw-r--r--source/libs/asura-lib-utils/threading/thread_impl_sdl.h0
-rw-r--r--source/libs/asura-lib-utils/threading/thread_impl_std.cpp0
-rw-r--r--source/libs/asura-lib-utils/threading/thread_impl_std.h43
-rw-r--r--source/libs/asura-lib-utils/threading/thread_impl_win32.cpp76
-rw-r--r--source/libs/asura-lib-utils/threading/thread_impl_win32.h47
-rw-r--r--source/libs/asura-lib-utils/threading/thread_task.cpp0
-rw-r--r--source/libs/asura-lib-utils/threading/thread_task.h44
-rw-r--r--source/libs/asura-lib-utils/type.h85
-rw-r--r--source/libs/asura-lib-utils/utils.h6
-rw-r--r--source/libs/asura-lib-utils/utils_config.h10
-rw-r--r--source/libs/asura-lib-utils/utils_module.cpp25
-rw-r--r--source/libs/asura-lib-utils/utils_module.h32
79 files changed, 5043 insertions, 0 deletions
diff --git a/source/libs/asura-lib-utils/exceptions/exception.cpp b/source/libs/asura-lib-utils/exceptions/exception.cpp
new file mode 100644
index 0000000..dbb36ca
--- /dev/null
+++ b/source/libs/asura-lib-utils/exceptions/exception.cpp
@@ -0,0 +1,47 @@
+#include "Exception.h"
+
+#include <cstdarg>
+#include <iostream>
+
+namespace AsuraEngine
+{
+
+ Exception::Exception(const char *fmt, ...)
+ {
+ va_list args;
+ int size_buffer = 256, size_out;
+ char *buffer;
+ while (true)
+ {
+ buffer = new char[size_buffer];
+ memset(buffer, 0, size_buffer);
+
+ va_start(args, fmt);
+ size_out = vsnprintf(buffer, size_buffer, fmt, args);
+ va_end(args);
+
+ // see http://perfec.to/vsnprintf/pasprintf.c
+ // if size_out ...
+ // == -1 --> output was truncated
+ // == size_buffer --> output was truncated
+ // == size_buffer-1 --> ambiguous, /may/ have been truncated
+ // > size_buffer --> output was truncated, and size_out
+ // bytes would have been written
+ if (size_out == size_buffer || size_out == -1 || size_out == size_buffer - 1)
+ size_buffer *= 2;
+ else if (size_out > size_buffer)
+ size_buffer = size_out + 2; // to avoid the ambiguous case
+ else
+ break;
+
+ delete[] buffer;
+ }
+ message = std::string(buffer);
+ delete[] buffer;
+ }
+
+ Exception::~Exception() throw()
+ {
+ }
+
+}
diff --git a/source/libs/asura-lib-utils/exceptions/exception.h b/source/libs/asura-lib-utils/exceptions/exception.h
new file mode 100644
index 0000000..57c9ed6
--- /dev/null
+++ b/source/libs/asura-lib-utils/exceptions/exception.h
@@ -0,0 +1,44 @@
+#ifndef __ASURA_ENGINE_EXCEPTION_H__
+#define __ASURA_ENGINE_EXCEPTION_H__
+
+#include <string>
+#include <exception>
+
+namespace AsuraEngine
+{
+
+ /**
+ * A convenient vararg-enabled exception class.
+ **/
+ class Exception : public std::exception
+ {
+ public:
+
+ /**
+ * Creates a new Exception according to printf-rules.
+ *
+ * See: http://www.cplusplus.com/reference/clibrary/cstdio/printf/
+ *
+ * @param fmt The format string (see printf).
+ **/
+ Exception(const char *fmt, ...);
+ virtual ~Exception() throw();
+
+ /**
+ * Returns a string containing reason for the exception.
+ * @return A description of the exception.
+ **/
+ inline virtual const char *what() const throw()
+ {
+ return message.c_str();
+ }
+
+ private:
+
+ std::string message;
+
+ }; // Exception
+
+}
+
+#endif \ No newline at end of file
diff --git a/source/libs/asura-lib-utils/io/binding/_compressor.cpp b/source/libs/asura-lib-utils/io/binding/_compressor.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/source/libs/asura-lib-utils/io/binding/_compressor.cpp
diff --git a/source/libs/asura-lib-utils/io/binding/_data_buffer.cpp b/source/libs/asura-lib-utils/io/binding/_data_buffer.cpp
new file mode 100644
index 0000000..cd73b31
--- /dev/null
+++ b/source/libs/asura-lib-utils/io/binding/_data_buffer.cpp
@@ -0,0 +1,123 @@
+#include "../data_buffer.h"
+
+using namespace Luax;
+
+namespace AsuraEngine
+{
+ namespace IO
+ {
+
+ LUAX_REGISTRY(DataBuffer)
+ {
+ LUAX_REGISTER_METHODS(state,
+ { "New", _New },
+ { "GetData", _GetData },
+ { "GetSize", _GetSize },
+ { "Refactor", _Refactor },
+ { "Load", _Load },
+ { "Clear", _Clear }
+ );
+ }
+
+ LUAX_POSTPROCESS(DataBuffer)
+ {
+ }
+
+ // databuffer = DataBuffer.New(lstring)
+ // databuffer = DataBuffer.New(size)
+ LUAX_IMPL_METHOD(DataBuffer, _New)
+ {
+ LUAX_STATE(L);
+
+ if (state.IsType(1, LUA_TSTRING))
+ {
+ size_t size;
+ const byte* bytes = lua_tolstring(L, 1, &size);
+ DataBuffer* buffer = new DataBuffer(bytes, size);
+ buffer->PushLuaxUserdata(state);
+ return 1;
+ }
+ else if (state.IsType(1, LUA_TNUMBER))
+ {
+ size_t size = lua_tonumber(L, 1);
+ DataBuffer* buffer = new DataBuffer(size);
+ buffer->PushLuaxUserdata(state);
+ return 1;
+ }
+ else
+ {
+ return state.ErrorType(1, "number or string");
+ }
+ }
+
+ // lsting, len = databuffer:GetData()
+ LUAX_IMPL_METHOD(DataBuffer, _GetData)
+ {
+ LUAX_SETUP(L, "U");
+
+ DataBuffer* self = state.GetUserdata<DataBuffer>(1);
+ lua_pushlstring(L, self->GetData(), self->GetSize());
+ return 1;
+ }
+
+ // length = databuffer:GetSize()
+ LUAX_IMPL_METHOD(DataBuffer, _GetSize)
+ {
+ LUAX_SETUP(L, "U");
+
+ DataBuffer* self = state.GetUserdata<DataBuffer>(1);
+ lua_pushinteger(L, self->GetSize());
+ return 1;
+ }
+
+ // databuffer:Refactor(size)
+ LUAX_IMPL_METHOD(DataBuffer, _Refactor)
+ {
+ LUAX_PREPARE(L, DataBuffer);
+
+ size_t size = state.CheckValue<int>(2);
+ self->Refactor(size);
+ return 0;
+ }
+
+ // size = databuffer:Load(lstring)
+ // size = databuffer:Load(src)
+ LUAX_IMPL_METHOD(DataBuffer, _Load)
+ {
+ LUAX_STATE(L);
+
+ DataBuffer* buffer = state.GetUserdata<DataBuffer>(1);
+ const byte* data;
+ size_t size;
+ if (state.IsType(2, LUA_TSTRING))
+ {
+ data = lua_tolstring(L, 2, &size);
+ size_t len = buffer->Load(data, size);
+ state.Push(len);
+ return 1;
+ }
+ else if(state.IsType(2, LUA_TUSERDATA))
+ {
+ DataBuffer* src = state.CheckUserdata<DataBuffer>(2);
+ size_t len = buffer->Load(*src);
+ state.Push(len);
+ return 1;
+ }
+ else
+ {
+ return state.ErrorType(1, "lstring or DataBuffer");
+ }
+ }
+
+ // databuffer:Clear()
+ LUAX_IMPL_METHOD(DataBuffer, _Clear)
+ {
+ LUAX_SETUP(L, "U");
+
+ DataBuffer* self = state.GetUserdata<DataBuffer>(1);
+ self->Clear();
+ return 0;
+ }
+
+ }
+} \ No newline at end of file
diff --git a/source/libs/asura-lib-utils/io/binding/_file.cpp b/source/libs/asura-lib-utils/io/binding/_file.cpp
new file mode 100644
index 0000000..c44bc90
--- /dev/null
+++ b/source/libs/asura-lib-utils/io/binding/_file.cpp
@@ -0,0 +1,223 @@
+#include "../file.h"
+
+namespace AsuraEngine
+{
+ namespace IO
+ {
+
+ LUAX_REGISTRY(File)
+ {
+ LUAX_REGISTER_METHODS(state,
+ { "New", _New },
+ { "Open", _Open },
+ { "Close", _Close },
+ { "IsOpen", _IsOpen },
+ { "GetMode", _GetMode },
+ { "GetSize", _GetSize },
+ { "Read", _Read },
+ { "IsEOF", _IsEOF },
+ { "Write", _Write },
+ { "Flush", _Flush },
+ { "Tell", _Tell },
+ { "Seek", _Seek },
+ { "SetBuffer", _SetBuffer },
+ { "GetBuffer", _GetBuffer },
+ { "GetFileName", _GetFileName },
+ { "GetExtension", _GetExtension },
+ { "GetName", _GetName }
+ );
+ }
+
+ LUAX_POSTPROCESS(File)
+ {
+ LUAX_REGISTER_ENUM(state, "EFileMode",
+ { "CLOSED", FILE_MODE_CLOSED },
+ { "READ", FILE_MODE_READ },
+ { "WRITE", FILE_MODE_WRITE },
+ { "APPEND", FILE_MODE_APPEND }
+ );
+
+ LUAX_REGISTER_ENUM(state, "EBufferMode",
+ { "NONE", BUFFER_MODE_NONE},
+ { "LINE", BUFFER_MODE_LINE},
+ { "FULL", BUFFER_MODE_FULL}
+ );
+ }
+
+ // file = File.New(name)
+ LUAX_IMPL_METHOD(File, _New)
+ {
+ LUAX_STATE(L);
+
+ cc8* name = state.CheckValue<cc8*>(1);
+ File* file = new File(name);
+ file->PushLuaxUserdata(state);
+ return 1;
+ }
+
+ // successsed = file:Open(mode)
+ LUAX_IMPL_METHOD(File, _Open)
+ {
+ LUAX_PREPARE(L, File);
+
+ File::FileMode mode = (File::FileMode)state.CheckValue<int>(2);
+ state.Push(self->Open(mode));
+ return 1;
+ }
+
+ // successed = file:Close()
+ LUAX_IMPL_METHOD(File, _Close)
+ {
+ LUAX_PREPARE(L, File);
+
+ state.Push(self->Close());
+ return 1;
+ }
+
+ // opened = file:IsOpen()
+ LUAX_IMPL_METHOD(File, _IsOpen)
+ {
+ LUAX_PREPARE(L, File);
+
+ state.Push(self->IsOpen());
+ return 1;
+ }
+
+ // mode = file:GetMode()
+ LUAX_IMPL_METHOD(File, _GetMode)
+ {
+ LUAX_PREPARE(L, File);
+
+ File::FileMode mode = self->GetMode();
+ state.Push((int)mode);
+ return 1;
+ }
+
+ // size = file:GetSize()
+ LUAX_IMPL_METHOD(File, _GetSize)
+ {
+ LUAX_PREPARE(L, File);
+
+ state.Push(self->GetSize());
+ return 1;
+ }
+
+ // size = file:Read(dst, len)
+ // returns:
+ // size ʵʶĴС
+ // params:
+ // self ļ
+ // dst Ŀ껺
+ // len ĴС
+ LUAX_IMPL_METHOD(File, _Read)
+ {
+ LUAX_PREPARE(L, File);
+
+ DataBuffer* db = state.CheckUserdata<DataBuffer>(2);
+ if (!db) return state.ErrorType(2, "DataBuffer");
+ int len = state.CheckValue<int>(3);
+ int size = self->Read(db, len);
+ state.Push(size);
+ return 1;
+ }
+
+ // isEOF = file:IsEOF()
+ LUAX_IMPL_METHOD(File, _IsEOF)
+ {
+ LUAX_PREPARE(L, File);
+
+ state.Push(self->IsEOF());
+ return 1;
+ }
+
+ // isWrite = file:Write(data buffer[, size])
+ LUAX_IMPL_METHOD(File, _Write)
+ {
+ LUAX_PREPARE(L, File);
+
+ DataBuffer* db = state.CheckUserdata<DataBuffer>(2);
+ if (!db) return state.ErrorType(2, "DataBuffer");
+ state.Push(self->Write(db));
+ return 1;
+ }
+
+ // isFlushed = file:Flush()
+ LUAX_IMPL_METHOD(File, _Flush)
+ {
+ LUAX_PREPARE(L, File);
+
+ state.Push(self->Flush());
+ return 1;
+ }
+
+ // pos = file:Tell()
+ LUAX_IMPL_METHOD(File, _Tell)
+ {
+ LUAX_PREPARE(L, File);
+
+ state.Push(self->Tell());
+ return 1;
+ }
+
+ // isSeek = file:Seek(pos)
+ LUAX_IMPL_METHOD(File, _Seek)
+ {
+ LUAX_PREPARE(L, File);
+
+ int pos = state.CheckValue<int>(2);
+ state.Push(self->Seek(pos));
+ return 1;
+ }
+
+ // isSetted = file:SetBuffer(mode, size)
+ LUAX_IMPL_METHOD(File, _SetBuffer)
+ {
+ LUAX_PREPARE(L, File);
+
+ BufferMode mode = (BufferMode)state.CheckValue<int>(2);
+ int size = state.CheckValue<int>(3);
+ state.Push(self->SetBuffer(mode, size));
+ return 1;
+ }
+
+ // size, mode = file:GetBuffer()
+ LUAX_IMPL_METHOD(File, _GetBuffer)
+ {
+ LUAX_PREPARE(L, File);
+
+ size_t size = 0;
+ BufferMode mode = self->GetBuffer(ASURA_OUT size);
+ state.Push((int)size);
+ state.Push((int)mode);
+ return 2;
+ }
+
+ // name = file:GetFileName()
+ LUAX_IMPL_METHOD(File, _GetFileName)
+ {
+ LUAX_PREPARE(L, File);
+
+ state.Push(self->GetFileName());
+ return 1;
+ }
+
+ // name = file:GetExtension()
+ LUAX_IMPL_METHOD(File, _GetExtension)
+ {
+ LUAX_PREPARE(L, File);
+
+ state.Push(self->GetExtension());
+ return 1;
+ }
+
+ // name = file:GetName()
+ LUAX_IMPL_METHOD(File, _GetName)
+ {
+ LUAX_PREPARE(L, File);
+
+ state.Push(self->GetName());
+ return 1;
+ }
+
+ }
+} \ No newline at end of file
diff --git a/source/libs/asura-lib-utils/io/binding/_file_data.cpp b/source/libs/asura-lib-utils/io/binding/_file_data.cpp
new file mode 100644
index 0000000..09a0643
--- /dev/null
+++ b/source/libs/asura-lib-utils/io/binding/_file_data.cpp
@@ -0,0 +1,60 @@
+#include "../file_data.h"
+
+using namespace std;
+
+namespace AsuraEngine
+{
+ namespace IO
+ {
+
+ LUAX_REGISTRY(FileData)
+ {
+ LUAX_REGISTER_METHODS(state,
+ { "GetFileName", _GetFileName },
+ { "GetExtension", _GetExtension },
+ { "GetName", _GetName },
+ { "GetDataBuffer", _GetDataBuffer }
+ );
+ }
+
+ LUAX_POSTPROCESS(FileData)
+ {
+ }
+
+ // filename = filedata:GetFileName()
+ LUAX_IMPL_METHOD(FileData, _GetFileName)
+ {
+ LUAX_PREPARE(L, FileData);
+ string filename = self->GetFileName();
+ state.Push(filename);
+ return 1;
+ }
+
+ // extension = filedata:GetExtension()
+ LUAX_IMPL_METHOD(FileData, _GetExtension)
+ {
+ LUAX_PREPARE(L, FileData);
+ string extension = self->GetExtension();
+ state.Push(extension);
+ return 1;
+ }
+
+ // name = filedata:GetName()
+ LUAX_IMPL_METHOD(FileData, _GetName)
+ {
+ LUAX_PREPARE(L, FileData);
+ string extension = self->GetName();
+ state.Push(extension);
+ return 1;
+ }
+
+ // databuffer = filedata:GetDataBuffer()
+ LUAX_IMPL_METHOD(FileData, _GetDataBuffer)
+ {
+ LUAX_PREPARE(L, FileData);
+ self->PushLuaxMemberRef(state, self->mDataRef);
+ return 1;
+ }
+
+ }
+} \ No newline at end of file
diff --git a/source/libs/asura-lib-utils/io/binding/_file_system.cpp b/source/libs/asura-lib-utils/io/binding/_file_system.cpp
new file mode 100644
index 0000000..3843451
--- /dev/null
+++ b/source/libs/asura-lib-utils/io/binding/_file_system.cpp
@@ -0,0 +1,265 @@
+#include "../file_system.h"
+
+using namespace Luax;
+
+namespace AsuraEngine
+{
+ namespace IO
+ {
+
+#define PREPARE(l) \
+ LUAX_STATE(l); \
+ Filesystem* fs = Filesystem::Get();
+
+ LUAX_REGISTRY(Filesystem)
+ {
+ LUAX_REGISTER_METHODS(state,
+ { "Init", _Init },
+ { "Mount", _Mount },
+ { "Unmount", _Unmount },
+ { "GetMountPoint", _GetMountPoint },
+ { "SetWriteDirectory", _SetWriteDirectory },
+ { "GetWriteDirectory", _GetWriteDirectory },
+ { "CreateFile", _CreateFile },
+ { "CreateDirectory", _CreateDirectory },
+ { "Write", _Write },
+ { "Append", _Append },
+ { "Remove", _Remove },
+ { "Read", _Read },
+ { "GetFileInfo", _GetFileInfo },
+ { "GetDirectoryItems", _GetDirectoryItems }
+ );
+ }
+
+ LUAX_POSTPROCESS(Filesystem)
+ {
+ LUAX_REGISTER_ENUM(state, "EFileType",
+ { "FILE", FILE_TYPE_FILE },
+ { "DIRECTORY", FILE_TYPE_DIRECTORY },
+ { "SYMLINK", FILE_TYPE_SYMLINK },
+ { "OTHER", FILE_TYPE_OTHER }
+ );
+ }
+
+ // Filesystem.Init(arg0)
+ LUAX_IMPL_METHOD(Filesystem, _Init)
+ {
+ PREPARE(L);
+
+ const char* arg0 = state.CheckValue<const char*>(1);
+ fs->Init(arg0);
+ return 0;
+ }
+
+ // successed = Filesystem.Mount(path, mountpoint[, prepend = false])
+ // successed = Filesystem.Mount(data buffer, archievename, mountpoint[, prepend = false])
+ LUAX_IMPL_METHOD(Filesystem, _Mount)
+ {
+ PREPARE(L);
+ bool mounted = false;
+
+ if (state.IsType(1, LUA_TSTRING))
+ {
+ cc8* path = state.GetValue<cc8*>(1, "");
+ cc8* moutpoint = state.GetValue<cc8*>(2, "/");
+ bool prepend = state.GetValue<bool>(3, false);
+ mounted = fs->Mount(path, moutpoint, prepend);
+ }
+ else if (state.IsType(1, LUA_TUSERDATA))
+ {
+ DataBuffer* db = state.CheckUserdata<DataBuffer>(1);
+ if (!db)
+ return state.ErrorType(1, "Data Buffer");
+ cc8* arcname = state.GetValue<cc8*>(2, "");
+ cc8* mountpoint = state.GetValue<cc8*>(3, "/");
+ bool prepend = state.GetValue<bool>(4, false);
+ mounted = fs->Mount(db, arcname, mountpoint, prepend);
+ // retain
+ fs->LuaxRetain<DataBuffer>(state, db);
+ }
+ state.Push(mounted);
+ return 1;
+ }
+
+ // successed = Filesystem.Unmount(path)
+ // successed = Filesystem.Unmount(data buffer)
+ LUAX_IMPL_METHOD(Filesystem, _Unmount)
+ {
+ PREPARE(L);
+ bool unmounted = false;
+
+ if (state.IsType(1, LUA_TSTRING))
+ {
+ cc8* path = state.GetValue<cc8*>(1, "");
+ unmounted = fs->Unmount(path);
+ }
+ else if (state.IsType(1, LUA_TUSERDATA))
+ {
+ DataBuffer* db = state.CheckUserdata<DataBuffer>(1);
+ if (!db)
+ return state.ErrorType(1, "Data Buffer");
+ unmounted = fs->Unmount(db);
+ if (unmounted)
+ fs->LuaxRelease<DataBuffer>(state, db);
+ }
+ state.Push(unmounted);
+ return 1;
+ }
+
+ // moutpoint = Filesystem.GetMountPoint(path)
+ LUAX_IMPL_METHOD(Filesystem, _GetMountPoint)
+ {
+ PREPARE(L);
+
+ cc8* path = state.CheckValue<cc8*>(1);
+ std::string mp;
+ if (fs->GetMountPoint(path, ASURA_OUT mp))
+ state.Push(mp);
+ else
+ state.PushNil();
+
+ return 1;
+ }
+
+ // Filesystem.SetWriteDirectory(dir)
+ LUAX_IMPL_METHOD(Filesystem, _SetWriteDirectory)
+ {
+ PREPARE(L);
+
+ cc8* dir = state.CheckValue<cc8*>(1);
+ fs->SetWriteDirectory(dir);
+ return 0;
+ }
+
+ // dir = Filesystem.GetWriteDirectory()
+ LUAX_IMPL_METHOD(Filesystem, _GetWriteDirectory)
+ {
+ PREPARE(L);
+
+ std::string dir = fs->GetWriteDirectory();
+ state.Push(dir);
+ return 1;
+ }
+
+ // file = Filesystem.CreateFile(name)
+ LUAX_IMPL_METHOD(Filesystem, _CreateFile)
+ {
+ PREPARE(L);
+
+ cc8* name = state.CheckValue<cc8*>(1);
+ File* file = fs->NewFile(name);
+ if (file)
+ file->PushLuaxUserdata(state);
+ else
+ state.PushNil();
+ return 1;
+ }
+
+ // successed = Filesystem.CreateDirectory(name)
+ LUAX_IMPL_METHOD(Filesystem, _CreateDirectory)
+ {
+ PREPARE(L);
+
+ cc8* path = state.CheckValue<cc8*>(1);
+ state.Push(fs->NewDirectory(path));
+ return 1;
+ }
+
+ // successed = Filesystem.Write(path, data buffer)
+ LUAX_IMPL_METHOD(Filesystem, _Write)
+ {
+ PREPARE(L);
+
+ cc8* path = state.CheckValue<cc8*>(1);
+ DataBuffer* db = state.CheckUserdata<DataBuffer>(2);
+ state.Push(fs->Write(path, db));
+ return 1;
+ }
+
+ // successed = Filesystem.Append(path, data buffer)
+ LUAX_IMPL_METHOD(Filesystem, _Append)
+ {
+ PREPARE(L);
+
+ cc8* path = state.CheckValue<cc8*>(1);
+ DataBuffer* db = state.CheckUserdata<DataBuffer>(2);
+ state.Push(fs->Append(path, db));
+ return 1;
+ }
+
+ // successed = Filesystem.Remove(path)
+ LUAX_IMPL_METHOD(Filesystem, _Remove)
+ {
+ PREPARE(L);
+
+ cc8* path = state.CheckValue<cc8*>(1);
+ state.Push(fs->Remove(path));
+ return 1;
+ }
+
+ // filedata = Filesystem.Read(path)
+ LUAX_IMPL_METHOD(Filesystem, _Read)
+ {
+ PREPARE(L);
+
+ cc8* path = state.CheckValue<cc8*>(1);
+ FileData* fd = fs->Read(path);
+ if (fd)
+ {
+ fd->mData->PushLuaxUserdata(state);
+ fd->SetLuaxMemberRef(state, fd->mDataRef, -1); // fd->mDataRef = data buffer
+ state.Pop(1); // data buffer
+ fd->PushLuaxUserdata(state);
+ }
+ else
+ {
+ state.PushNil();
+ }
+ return 1;
+ }
+
+ // fileinfo = Filesystem.GetFileInfo(path)
+ LUAX_IMPL_METHOD(Filesystem, _GetFileInfo)
+ {
+ PREPARE(L);
+
+ cc8* path = state.CheckValue<cc8*>(1);
+ FileInfo info;
+ if (fs->GetFileInfo(path, &info))
+ {
+ lua_newtable(L); // info table
+ state.SetField(-1, "size", info.size);
+ state.SetField(-1, "modtime", info.modtime);
+ state.SetField(-1, "type", info.type);
+ }
+ else
+ {
+ state.PushNil();
+ }
+ return 1;
+ }
+
+ // items = Filesystem.GetDirectoryItems(path)
+ LUAX_IMPL_METHOD(Filesystem, _GetDirectoryItems)
+ {
+ PREPARE(L);
+
+ cc8* path = state.CheckValue<cc8*>(1);
+ std::vector<std::string> items;
+ if(fs->GetDirectoryItems(path, ASURA_OUT items))
+ {
+ lua_newtable(L); // item list
+ for (int i = 0; i < items.size(); ++i)
+ {
+ state.SetFieldByIndex(-1, i + 1, items[i]);
+ }
+ }
+ else
+ {
+ state.PushNil();
+ }
+ return 1;
+ }
+
+ }
+} \ No newline at end of file
diff --git a/source/libs/asura-lib-utils/io/binding/_io_task.cpp b/source/libs/asura-lib-utils/io/binding/_io_task.cpp
new file mode 100644
index 0000000..b3c5988
--- /dev/null
+++ b/source/libs/asura-lib-utils/io/binding/_io_task.cpp
@@ -0,0 +1,46 @@
+#include "../io_task.h"
+
+using namespace std;
+
+namespace AsuraEngine
+{
+ namespace IO
+ {
+
+ LUAX_REGISTRY(IOTask)
+ {
+ LUAX_REGISTER_METHODS(state,
+ { "New", _New }
+ );
+ }
+
+ LUAX_POSTPROCESS(IOTask)
+ {
+ LUAX_REGISTER_ENUM(state, "EIOTaskType",
+ { "READ", IOTASK_TYPE_READ },
+ { "WRITE", IOTASK_TYPE_WRITE },
+ { "APPEND", IOTASK_TYPE_APPEND }
+ );
+
+ }
+
+ // task = IOTask.New(path, buffer, type, callback)
+ LUAX_IMPL_METHOD(IOTask, _New)
+ {
+ LUAX_STATE(L);
+
+ cc8* path = state.CheckValue<cc8*>(1);
+ DataBuffer* db = state.CheckUserdata<DataBuffer>(2);
+ IOTaskType type = (IOTaskType)state.CheckValue<int>(3);
+ bool cbk = state.GetTop() >= 4 && state.IsType(4, LUA_TFUNCTION);
+
+ IOTask* task = new IOTask(path, db, type);
+ task->SetLuaxMemberRef(state, task->mBufferRef, 2);
+ if(cbk)
+ task->SetLuaxMemberRef(state, task->mCallback, 4);
+ task->PushLuaxUserdata(state);
+ return 1;
+ }
+
+ }
+}
diff --git a/source/libs/asura-lib-utils/io/compressor.cpp b/source/libs/asura-lib-utils/io/compressor.cpp
new file mode 100644
index 0000000..095eff4
--- /dev/null
+++ b/source/libs/asura-lib-utils/io/compressor.cpp
@@ -0,0 +1,11 @@
+#include "compressor.h"
+
+namespace AsuraEngine
+{
+ namespace IO
+ {
+
+
+
+ }
+} \ No newline at end of file
diff --git a/source/libs/asura-lib-utils/io/compressor.h b/source/libs/asura-lib-utils/io/compressor.h
new file mode 100644
index 0000000..30a074c
--- /dev/null
+++ b/source/libs/asura-lib-utils/io/compressor.h
@@ -0,0 +1,30 @@
+#ifndef __ASURA_COMPRESSOR_H__
+#define __ASURA_COMPRESSOR_H__
+
+#include "../scripting/portable.hpp"
+
+namespace AsuraEngine
+{
+ namespace IO
+ {
+
+ class Compressor ASURA_FINAL
+ : public AEScripting::Portable<Compressor>
+ {
+ public:
+
+ LUAX_DECL_SINGLETON(Compressor);
+
+ private:
+
+ LUAX_DECL_METHOD(_Compress);
+ LUAX_DECL_METHOD(_Decompress);
+
+
+
+ };
+
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/source/libs/asura-lib-utils/io/data_buffer.cpp b/source/libs/asura-lib-utils/io/data_buffer.cpp
new file mode 100644
index 0000000..5049b38
--- /dev/null
+++ b/source/libs/asura-lib-utils/io/data_buffer.cpp
@@ -0,0 +1,102 @@
+#include <cstdlib>
+#include <cstring>
+#include "data_buffer.h"
+
+using namespace AEThreading;
+
+namespace AsuraEngine
+{
+ namespace IO
+ {
+
+ DataBuffer::DataBuffer(DataBuffer& src)
+ {
+ Load(src);
+ }
+
+ DataBuffer::DataBuffer(std::size_t size)
+ : mSize(size)
+ , mBytes(nullptr)
+ {
+ lock(mMutex);
+ mBytes = new byte[size];
+ memset(mBytes, 0, size);
+ }
+
+ DataBuffer::DataBuffer(const void* data, std::size_t size)
+ : mSize(size)
+ , mBytes(nullptr)
+ {
+ Load(data, size);
+ }
+
+ DataBuffer::~DataBuffer()
+ {
+ delete[] mBytes;
+ }
+
+ void DataBuffer::Refactor(size_t size)
+ {
+ lock(mMutex);
+ if (!mBytes || mSize != size)
+ {
+ delete[] mBytes;
+ mBytes = new byte[size];
+ mSize = size;
+ }
+ memset(mBytes, 0, size * sizeof(byte));
+ }
+
+ size_t DataBuffer::Load(DataBuffer& db)
+ {
+ return Load(db.GetData(), db.GetSize());
+ }
+
+ size_t DataBuffer::Load(const void* data, std::size_t size)
+ {
+ lock(mMutex);
+ size_t len = mSize > size ? size : mSize;
+ memcpy(mBytes, data, len);
+ return len;
+ }
+
+ void DataBuffer::Move(void* bytes, std::size_t size)
+ {
+ lock(mMutex);
+ if (!mBytes)
+ {
+ delete[] mBytes;
+ }
+ mBytes = (byte*)bytes;
+ mSize = size;
+ }
+
+ byte* DataBuffer::GetData()
+ {
+ return mBytes;
+ }
+
+ void DataBuffer::Clear()
+ {
+ lock(mMutex);
+ if (mBytes)
+ memset(mBytes, 0, mSize);
+ }
+
+ std::size_t DataBuffer::GetSize()
+ {
+ return mSize;
+ }
+
+ void DataBuffer::Lock()
+ {
+ mMutex.Lock();
+ }
+
+ void DataBuffer::Unlock()
+ {
+ mMutex.Unlock();
+ }
+
+ }
+} \ No newline at end of file
diff --git a/source/libs/asura-lib-utils/io/data_buffer.h b/source/libs/asura-lib-utils/io/data_buffer.h
new file mode 100644
index 0000000..445bdf4
--- /dev/null
+++ b/source/libs/asura-lib-utils/io/data_buffer.h
@@ -0,0 +1,62 @@
+#ifndef __ASURA_ENGINE_DATABUFFER_H__
+#define __ASURA_ENGINE_DATABUFFER_H__
+
+#include <cstdlib>
+
+#include "../scripting/portable.hpp"
+#include "../threading/mutex.h"
+
+namespace AsuraEngine
+{
+ namespace IO
+ {
+
+ ///
+ /// ڴݵķװеʹData bufferװֱʹconst void*ͨresource managerȡ
+ ///
+ class DataBuffer ASURA_FINAL
+ : public AEScripting::Portable<DataBuffer>
+ {
+ public:
+
+ LUAX_DECL_FACTORY(DataBuffer);
+
+ DataBuffer(DataBuffer& src);
+ DataBuffer(std::size_t size);
+ DataBuffer(const void* bytes, std::size_t size);
+ ~DataBuffer();
+
+ byte* GetData();
+ size_t GetSize();
+
+ void Refactor(size_t size);
+ size_t Load(DataBuffer& db);
+ size_t Load(const void* bytes, std::size_t size);
+ void Move(void* bytes, std::size_t size);
+ void Clear();
+
+ void Lock();
+ void Unlock();
+
+ private:
+
+ byte* mBytes;
+ size_t mSize;
+
+ AEThreading::Mutex mMutex;
+
+ LUAX_DECL_METHOD(_New);
+ LUAX_DECL_METHOD(_GetData);
+ LUAX_DECL_METHOD(_GetSize);
+ LUAX_DECL_METHOD(_Refactor);
+ LUAX_DECL_METHOD(_Load);
+ LUAX_DECL_METHOD(_Clear);
+
+ };
+
+ }
+}
+
+namespace AEIO = AsuraEngine::IO;
+
+#endif \ No newline at end of file
diff --git a/source/libs/asura-lib-utils/io/decoded_data.cpp b/source/libs/asura-lib-utils/io/decoded_data.cpp
new file mode 100644
index 0000000..358a7a5
--- /dev/null
+++ b/source/libs/asura-lib-utils/io/decoded_data.cpp
@@ -0,0 +1,21 @@
+#include "../exceptions/exception.h"
+
+#include "decoded_data.h"
+
+namespace AsuraEngine
+{
+ namespace IO
+ {
+
+ DecodedData::DecodedData(const DataBuffer& databuffer)
+ {
+ Decode(databuffer);
+ }
+
+ DecodedData::~DecodedData()
+ {
+
+ }
+
+ }
+}
diff --git a/source/libs/asura-lib-utils/io/decoded_data.h b/source/libs/asura-lib-utils/io/decoded_data.h
new file mode 100644
index 0000000..e201e91
--- /dev/null
+++ b/source/libs/asura-lib-utils/io/decoded_data.h
@@ -0,0 +1,42 @@
+#ifndef __ASURA_ENGINE_DATA_H__
+#define __ASURA_ENGINE_DATA_H__
+
+#include <cstdlib>
+
+#include "../scripting/portable.hpp"
+
+#include "data_buffer.h"
+
+namespace AsuraEngine
+{
+ namespace IO
+ {
+
+ ///
+ /// һ̹߳data̳дࡣͼƬݡƵݵȣһ߳нԭļڲݸʽ
+ /// ȡ
+ ///
+ ASURA_ABSTRACT class DecodedData
+ {
+ public:
+
+ ///
+ /// ڴйdataԷһ߳棬Դϵͳء
+ ///
+ DecodedData(const DataBuffer& databuffer);
+
+ virtual ~DecodedData();
+
+ protected:
+
+ ///
+ /// ڴеݡ
+ ///
+ virtual void Decode(const DataBuffer& buffer) = 0;
+
+ };
+
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/source/libs/asura-lib-utils/io/file.cpp b/source/libs/asura-lib-utils/io/file.cpp
new file mode 100644
index 0000000..0ff8c90
--- /dev/null
+++ b/source/libs/asura-lib-utils/io/file.cpp
@@ -0,0 +1,292 @@
+#include <physfs/physfs.h>
+
+#include <asura-lib-utils/exceptions/exception.h>
+
+#include "file.h"
+
+namespace AsuraEngine
+{
+ namespace IO
+ {
+
+ File::File(const std::string& filename)
+ : mFileName(filename)
+ , mFileHandle(nullptr)
+ , mMode(FILE_MODE_CLOSED)
+ , mBufferMode(BUFFER_MODE_NONE)
+ , mBufferSize(0)
+ {
+ size_t dot = filename.rfind('.');
+ if (dot != std::string::npos)
+ {
+ mExtension = filename.substr(dot + 1);
+ mName = filename.substr(0, dot);
+ }
+ else
+ mName = filename;
+ }
+
+ File::~File()
+ {
+ if (mMode != FILE_MODE_CLOSED)
+ Close();
+ }
+
+ bool File::Open(FileMode mode)
+ {
+ if (!PHYSFS_isInit())
+ throw Exception("Physfs is NOT initialized.");
+
+ if (mode == FILE_MODE_CLOSED)
+ return false;
+
+ if (mode == FILE_MODE_READ && !PHYSFS_exists(mFileName.c_str()))
+ throw Exception("Could NOT open file %s. Does not exist.", mFileName.c_str());
+
+ if (mode == FILE_MODE_APPEND || mode == FILE_MODE_WRITE)
+ {
+ if (!PHYSFS_getWriteDir())
+ {
+ throw Exception("Could NOT set write directory.");
+ }
+ }
+
+ // Ѿ֮ǰ򿪹Ͳٴµhandle
+ if (mFileHandle != nullptr)
+ return true;
+
+ PHYSFS_getLastErrorCode();
+
+ PHYSFS_File* handle = nullptr;
+
+ switch (mode)
+ {
+ case FILE_MODE_READ:
+ handle = PHYSFS_openRead(mFileName.c_str());
+ break;
+ case FILE_MODE_APPEND:
+ handle = PHYSFS_openAppend(mFileName.c_str());
+ break;
+ case FILE_MODE_WRITE:
+ handle = PHYSFS_openWrite(mFileName.c_str());
+ break;
+ }
+
+ if (handle == nullptr)
+ {
+ const char *err = PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode());
+ if (err == nullptr)
+ err = "unknown error";
+ throw Exception("Could not open file %s (%s)", mFileName.c_str(), err);
+ }
+
+ mFileHandle = handle;
+ mMode = mode;
+
+ if (mFileHandle && !SetBuffer(mBufferMode,mBufferSize))
+ {
+ mBufferMode = BUFFER_MODE_NONE;
+ mBufferSize = 0;
+ }
+
+ return mFileHandle != nullptr;
+ }
+
+ bool File::Close()
+ {
+ if (mFileHandle == nullptr || !PHYSFS_close(mFileHandle))
+ return false;
+ mMode = FILE_MODE_CLOSED;
+ mFileHandle = nullptr;
+ return true;
+ }
+
+ bool File::IsOpen()
+ {
+ return mMode != FILE_MODE_CLOSED && mFileHandle != nullptr;
+ }
+
+ size_t File::GetSize()
+ {
+ if (mFileHandle == nullptr)
+ {
+ Open(FILE_MODE_READ);
+ size_t size = PHYSFS_fileLength(mFileHandle);
+ Close();
+ return size;
+ }
+ return PHYSFS_fileLength(mFileHandle);
+ }
+
+ size_t File::Read(ASURA_OUT DataBuffer* dst, size_t length)
+ {
+ ASSERT(dst);
+
+ if (dst->GetSize() < length)
+ throw Exception("Data buffer is too small compares to read length.");
+
+ if (!mFileHandle || mMode != FILE_MODE_READ)
+ throw Exception("File \"%s\" is not opened for reading", mFileName);
+
+ size_t max = PHYSFS_fileLength(mFileHandle);
+ length = (length > max) ? max : length;
+
+ if (length < 0)
+ throw Exception("Invalid read size.");
+
+ dst->Lock();
+ size_t size = PHYSFS_readBytes(mFileHandle, dst->GetData(), length);
+ dst->Unlock();
+ return size;
+ }
+
+ size_t File::ReadAll(ASURA_OUT DataBuffer* dst)
+ {
+ ASSERT(dst);
+
+ if (!mFileHandle || mMode != FILE_MODE_READ)
+ throw Exception("File \"%s\" is not opened for reading", mFileName);
+
+ size_t length = PHYSFS_fileLength(mFileHandle);
+
+ if (dst->GetSize() < length)
+ throw Exception("Data buffer is too small compares to file length.");
+
+ dst->Lock();
+ size_t size = PHYSFS_readBytes(mFileHandle, dst->GetData(), length);
+ dst->Unlock();
+ return size;
+ }
+
+#ifdef ASURA_WINDOWS
+ inline bool test_eof(File *that, PHYSFS_File *)
+ {
+ int64 pos = that->Tell();
+ int64 size = that->GetSize();
+ return pos == -1 || size == -1 || pos >= size;
+ }
+#else
+ inline bool test_eof(File *, PHYSFS_File *file)
+ {
+ return PHYSFS_eof(file);
+ }
+#endif
+
+ bool File::IsEOF()
+ {
+ return mFileHandle == nullptr || test_eof(this, mFileHandle);
+ }
+
+ size_t File::Tell()
+ {
+ if (!mFileHandle)
+ return - 1;
+
+ return PHYSFS_tell(mFileHandle);
+ }
+
+ bool File::Seek(size_t pos)
+ {
+ return mFileHandle != nullptr && PHYSFS_seek(mFileHandle, pos) != 0;
+ }
+
+ bool File::Write(ASURA_REF DataBuffer* src)
+ {
+ if (!mFileHandle || (mMode != FILE_MODE_APPEND && mMode != FILE_MODE_WRITE))
+ throw Exception("File is not opened for writing.");
+
+ byte* data = src->GetData();
+ int size = src->GetSize();
+
+ if (size < 0)
+ throw Exception("Invalid write size.");
+
+ size_t written = PHYSFS_writeBytes(mFileHandle, data, size);
+
+ if (written != src->GetSize())
+ return false;
+
+ // л
+ if (mBufferSize == BUFFER_MODE_LINE && mBufferSize > size)
+ {
+ if (memchr(data, '\n', size) != nullptr)
+ Flush();
+ }
+
+ return true;
+ }
+
+ bool File::Flush()
+ {
+ if (!mFileHandle || (mMode != FILE_MODE_WRITE && mMode != FILE_MODE_APPEND))
+ throw Exception("File is not opened for writing.");
+
+ return PHYSFS_flush(mFileHandle) != 0;
+ }
+
+ bool File::SetBuffer(BufferMode mode, size_t size)
+ {
+ if (size < 0)
+ return false;
+
+ // If the file isn't open, we'll make sure the buffer values are set in
+ // File::open.
+ if (!IsOpen())
+ {
+ mBufferMode = mode;
+ mBufferSize = size;
+ return true;
+ }
+
+ int ret = 1;
+
+ switch (mode)
+ {
+ case BUFFER_MODE_NONE:
+ default:
+ ret = PHYSFS_setBuffer(mFileHandle, 0);
+ size = 0;
+ break;
+ case BUFFER_MODE_LINE:
+ case BUFFER_MODE_FULL:
+ ret = PHYSFS_setBuffer(mFileHandle, size);
+ break;
+ }
+
+ if (ret == 0)
+ return false;
+
+ mBufferMode = mode;
+ mBufferSize = size;
+
+ return true;
+ }
+
+ File::BufferMode File::GetBuffer(ASURA_OUT size_t& size)
+ {
+ size = mBufferSize;
+ return mBufferMode;
+ }
+
+ const std::string& File::GetFileName()
+ {
+ return mFileName;
+ }
+
+ const std::string& File::GetName()
+ {
+ return mName;
+ }
+
+ const std::string& File::GetExtension()
+ {
+ return mExtension;
+ }
+
+ File::FileMode File::GetMode()
+ {
+ return mMode;
+ }
+
+ }
+} \ No newline at end of file
diff --git a/source/libs/asura-lib-utils/io/file.h b/source/libs/asura-lib-utils/io/file.h
new file mode 100644
index 0000000..56077e0
--- /dev/null
+++ b/source/libs/asura-lib-utils/io/file.h
@@ -0,0 +1,146 @@
+#ifndef __ASURA_ENGINE_FILE_H__
+#define __ASURA_ENGINE_FILE_H__
+
+#include "physfs/physfs.h"
+
+#include "../scripting/portable.hpp"
+#include "../threading/thread.h"
+
+#include "file_data.h"
+
+namespace AsuraEngine
+{
+ namespace IO
+ {
+
+ ///
+ /// ʽļָд㡢Сʹȡʱʹñ࣬ʹFilesystem.read()ֱӶȡļȫ
+ /// ݣһFileData
+ ///
+ class File ASURA_FINAL
+ : public AEScripting::Portable<File>
+ {
+ public:
+
+ LUAX_DECL_FACTORY(File);
+
+ ///
+ /// ļдģʽ
+ ///
+ enum FileMode
+ {
+ FILE_MODE_CLOSED,
+ FILE_MODE_READ,
+ FILE_MODE_WRITE,
+ FILE_MODE_APPEND,
+ };
+
+ ///
+ /// ļдʱΪ
+ ///
+ enum BufferMode
+ {
+ BUFFER_MODE_NONE, ///< ʹû壬дļ
+ BUFFER_MODE_LINE, ///< л壬зߴﵽСʱдļ
+ BUFFER_MODE_FULL, ///< ȫ壬ʱдļ
+ };
+
+ File(const std::string& filename);
+ ~File();
+
+ bool Open(FileMode mode);
+ bool Close();
+ bool IsOpen();
+ FileMode GetMode();
+ size_t GetSize();
+
+ ///
+ /// ȡdata bufferض
+ ///
+ size_t Read(ASURA_OUT DataBuffer* dst, size_t length);
+ size_t ReadAll(ASURA_OUT DataBuffer* dst);
+ size_t ReadAsync(ASURA_OUT DataBuffer* dst);
+
+ ///
+ /// Ƿļβ
+ ///
+ bool IsEOF();
+
+ ///
+ /// data bufferед룬Ƿɹ
+ ///
+ bool Write(ASURA_REF DataBuffer* src);
+
+ ///
+ /// 첽дļдļtaskthreadĶС
+ ///
+ bool WriteAsync(ASURA_REF DataBuffer* src, AEThreading::Thread* thread);
+
+ ///
+ /// ˻壬ǿջдļ
+ ///
+ bool Flush();
+
+ ///
+ /// صǰдλ
+ ///
+ size_t Tell();
+
+ ///
+ /// Ӧλ
+ ///
+ bool Seek(size_t pos);
+
+ ///
+ /// ûСģʽ
+ ///
+ bool SetBuffer(BufferMode mode, size_t size);
+
+ ///
+ /// ȡСģʽ
+ ///
+ BufferMode GetBuffer(ASURA_OUT size_t& size);
+
+ const std::string& GetFileName();
+ const std::string& GetName();
+ const std::string& GetExtension();
+
+ private:
+
+ PHYSFS_File* mFileHandle; ///< physfs ļ
+ std::string mFileName; ///< ļ
+ std::string mExtension; ///< չ
+ std::string mName; ///< չļ
+ FileMode mMode; ///< ļģʽ
+ BufferMode mBufferMode; ///< д뻺ģʽ
+ size_t mBufferSize; ///< д뻺С
+
+ LUAX_DECL_ENUM(FileMode);
+ LUAX_DECL_ENUM(BufferMode);
+
+ LUAX_DECL_METHOD(_New);
+ LUAX_DECL_METHOD(_Open);
+ LUAX_DECL_METHOD(_Close);
+ LUAX_DECL_METHOD(_IsOpen);
+ LUAX_DECL_METHOD(_GetMode);
+ LUAX_DECL_METHOD(_GetSize);
+ LUAX_DECL_METHOD(_Read);
+ LUAX_DECL_METHOD(_Write);
+ LUAX_DECL_METHOD(_ReadAsync);
+ LUAX_DECL_METHOD(_WriteAsync);
+ LUAX_DECL_METHOD(_IsEOF);
+ LUAX_DECL_METHOD(_Flush);
+ LUAX_DECL_METHOD(_Tell);
+ LUAX_DECL_METHOD(_Seek);
+ LUAX_DECL_METHOD(_SetBuffer);
+ LUAX_DECL_METHOD(_GetBuffer);
+ LUAX_DECL_METHOD(_GetFileName);
+ LUAX_DECL_METHOD(_GetExtension);
+ LUAX_DECL_METHOD(_GetName);
+
+ };
+
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/source/libs/asura-lib-utils/io/file_data.cpp b/source/libs/asura-lib-utils/io/file_data.cpp
new file mode 100644
index 0000000..92333cf
--- /dev/null
+++ b/source/libs/asura-lib-utils/io/file_data.cpp
@@ -0,0 +1,52 @@
+#include "file_data.h"
+
+namespace AsuraEngine
+{
+ namespace IO
+ {
+
+ FileData::FileData(const std::string& filename)
+ : mData(nullptr)
+ , mFileName(filename)
+ {
+ size_t dot = filename.rfind('.');
+ if (dot != std::string::npos)
+ {
+ mExtension = filename.substr(dot + 1);
+ mName = filename.substr(0, dot);
+ }
+ else
+ mName = filename;
+ }
+
+ FileData::~FileData()
+ {
+ }
+
+ const std::string& FileData::GetFileName()
+ {
+ return mFileName;
+ }
+
+ const std::string& FileData::GetExtension()
+ {
+ return mExtension;
+ }
+
+ const std::string& FileData::GetName()
+ {
+ return mName;
+ }
+
+ void FileData::BindData(ASURA_MOVE DataBuffer* buffer)
+ {
+ mData = buffer;
+ }
+
+ DataBuffer* FileData::GetDataBuffer()
+ {
+ return mData;
+ }
+
+ }
+}
diff --git a/source/libs/asura-lib-utils/io/file_data.h b/source/libs/asura-lib-utils/io/file_data.h
new file mode 100644
index 0000000..9aa0e3b
--- /dev/null
+++ b/source/libs/asura-lib-utils/io/file_data.h
@@ -0,0 +1,69 @@
+#ifndef __ASURA_ENGINE_FILE_DATA_H__
+#define __ASURA_ENGINE_FILE_DATA_H__
+
+#include <string>
+
+#include <asura-lib-utils/scripting/portable.hpp>
+
+#include "data_buffer.h"
+
+namespace AsuraEngine
+{
+ namespace IO
+ {
+
+ class Filesystem;
+
+ ///
+ /// filesystemֱӶȡļʱFileDataļݺϢFilesystem
+ ///
+ class FileData ASURA_FINAL
+ : public AEScripting::Portable<FileData>
+ {
+ public:
+
+ LUAX_DECL_FACTORY(FileData);
+
+ ~FileData();
+
+ ///
+ /// ļݣͨDatabufferݺʹСڲӿڶData bufferΪҲdata buffer
+ ///
+ DataBuffer* GetDataBuffer();
+
+ const std::string& GetFileName();
+ const std::string& GetExtension();
+ const std::string& GetName();
+
+ private:
+
+ friend class Filesystem;
+
+ FileData(const std::string& name);
+
+ ///
+ /// data buffer
+ ///
+ void BindData(ASURA_MOVE DataBuffer* buffer);
+
+ ///
+ /// Data bufferfiledataʱ٣luaüΪ0ʱluaGC١mDataʱһԱá
+ ///
+ ASURA_REF DataBuffer* mData;
+ Luax::LuaxMemberRef mDataRef;
+
+ std::string mFileName; ///< չļ
+ std::string mExtension; ///< չ
+ std::string mName; ///< ͺ׺ļ
+
+ LUAX_DECL_METHOD(_GetDataBuffer);
+ LUAX_DECL_METHOD(_GetFileName);
+ LUAX_DECL_METHOD(_GetExtension);
+ LUAX_DECL_METHOD(_GetName);
+
+ };
+
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/source/libs/asura-lib-utils/io/file_system.cpp b/source/libs/asura-lib-utils/io/file_system.cpp
new file mode 100644
index 0000000..20f3cb2
--- /dev/null
+++ b/source/libs/asura-lib-utils/io/file_system.cpp
@@ -0,0 +1,198 @@
+#include <physfs/physfs.h>
+
+#include "../exceptions/exception.h"
+
+#include "file.h"
+#include "file_data.h"
+#include "file_system.h"
+
+using namespace std;
+
+namespace AsuraEngine
+{
+ namespace IO
+ {
+
+#ifdef ASURA_WINDOWS
+ #include <windows.h>
+ #include <direct.h>
+#else
+ #include <sys/param.h>
+ #include <unistd.h>
+#endif
+
+ Filesystem::~Filesystem()
+ {
+ if (mInited) //PHYSFS_isInit
+ PHYSFS_deinit();
+ }
+
+ void Filesystem::Init(const char* arg0)
+ {
+ if (!PHYSFS_init(arg0))
+ throw Exception("Failed to initialize filesystem: %s", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
+
+ mInited = true;
+ }
+
+ bool Filesystem::Mount(const std::string& locpath, const std::string& montpoint/* = "/"*/, bool prepend /*= false*/)
+ {
+ if (!mInited)
+ return false;
+
+ return PHYSFS_mount(locpath.c_str(), montpoint.c_str(), !prepend);
+ }
+
+ bool Filesystem::Mount(DataBuffer* db, const std::string& archivename, const std::string& mountpoint /*= "/"*/, bool prepend /*= false*/)
+ {
+ if (!mInited)
+ return false;
+ if (PHYSFS_mountMemory(db->GetData(), db->GetSize(), nullptr, archivename.c_str(), mountpoint.c_str(), !prepend))
+ {
+ mMountData[archivename] = db;
+ return true;
+ }
+ return false;
+ }
+
+ bool Filesystem::Unmount(const std::string& locpath)
+ {
+ if (!mInited)
+ return false;
+
+ // ǹ鵵ӳɾ
+ auto datait = mMountData.find(locpath);
+ if (datait != mMountData.end() && PHYSFS_unmount(locpath.c_str()) != 0)
+ {
+ mMountData.erase(datait);
+ return true;
+ }
+
+ return PHYSFS_unmount(locpath.c_str());
+ }
+
+ bool Filesystem::Unmount(DataBuffer* db)
+ {
+ for (const auto& dp : mMountData)
+ {
+ if (dp.second == db)
+ {
+ std::string archive = dp.first;
+ return Unmount(archive);
+ }
+ }
+ }
+
+ bool Filesystem::GetMountPoint(const std::string& locpath, ASURA_OUT std::string& mountpoint)
+ {
+ if (!mInited)
+ return false;
+ const char* point = PHYSFS_getMountPoint(locpath.c_str());
+ if (point != nullptr)
+ {
+ mountpoint = point;
+ return true;
+ }
+ return false;
+ }
+
+ void Filesystem::SetWriteDirectory(const std::string locpath)
+ {
+ if (!mInited)
+ return;
+ if (!PHYSFS_setWriteDir(locpath.c_str()))
+ throw Exception("Failed to set write directory %s", locpath.c_str());
+ }
+
+ std::string Filesystem::GetWriteDirectory()
+ {
+ return PHYSFS_getWriteDir();
+ }
+
+ File* Filesystem::NewFile(const std::string& name)
+ {
+ return new File(name);
+ }
+
+ bool Filesystem::NewDirectory(const std::string& path)
+ {
+ if (!mInited)
+ return false;
+ if (!PHYSFS_getWriteDir())
+ return false;
+ if (!PHYSFS_mkdir(path.c_str()))
+ return false;
+ return true;
+ }
+
+ bool Filesystem::Write(const std::string& name, ASURA_REF DataBuffer* buffer)
+ {
+ File file(name);
+ file.Open(File::FILE_MODE_WRITE);
+ if (!file.Write(buffer))
+ throw Exception("Data could not be written.");
+ }
+
+ bool Filesystem::Append(const std::string& name, ASURA_REF DataBuffer* buffer)
+ {
+ File file(name);
+ file.Open(File::FILE_MODE_APPEND);
+ if (!file.Write(buffer))
+ throw Exception("Data could not be append.");
+ }
+
+ FileData* Filesystem::Read(const std::string& name)
+ {
+ File file = File(name);
+ file.Open(File::FILE_MODE_READ);
+ int size = file.GetSize();
+ DataBuffer* db = new DataBuffer(size);
+ if (db)
+ {
+ file.ReadAll(db);
+ FileData* fd = new FileData(name);
+ fd->BindData(db);
+ return fd;
+ }
+ return nullptr;
+ }
+
+ bool Filesystem::Remove(const std::string& path)
+ {
+ if (!mInited)
+ return false;
+ if (PHYSFS_getWriteDir() == 0)
+ return false;
+
+ if (!PHYSFS_delete(path.c_str()))
+ return false;
+
+ return true;
+ }
+
+ bool Filesystem::GetFileInfo(const std::string& filepath, ASURA_OUT FileInfo* info)
+ {
+ if (!mInited)
+ return false;
+
+ PHYSFS_Stat stat = {};
+ if (!PHYSFS_stat(filepath.c_str(), &stat))
+ return false;
+
+ info->size = (int64)stat.filesize;
+ info->modtime = (int64)stat.modtime;
+
+ if (stat.filetype == PHYSFS_FILETYPE_REGULAR)
+ info->type = FILE_TYPE_FILE;
+ else if (stat.filetype == PHYSFS_FILETYPE_DIRECTORY)
+ info->type = FILE_TYPE_DIRECTORY;
+ else if (stat.filetype == PHYSFS_FILETYPE_SYMLINK)
+ info->type = FILE_TYPE_SYMLINK;
+ else
+ info->type = FILE_TYPE_OTHER;
+
+ return true;
+ }
+
+ }
+} \ No newline at end of file
diff --git a/source/libs/asura-lib-utils/io/file_system.h b/source/libs/asura-lib-utils/io/file_system.h
new file mode 100644
index 0000000..849cbb6
--- /dev/null
+++ b/source/libs/asura-lib-utils/io/file_system.h
@@ -0,0 +1,112 @@
+#ifndef __ASURA_ENGINE_FILESYSTEM_H__
+#define __ASURA_ENGINE_FILESYSTEM_H__
+
+#include <map>
+#include <string>
+
+#include "../scripting/portable.hpp"
+#include "../singleton.hpp"
+#include "../type.h"
+
+#include "file_data.h"
+#include "file.h"
+
+namespace AsuraEngine
+{
+ namespace IO
+ {
+
+ enum FileType
+ {
+ FILE_TYPE_FILE, ///< ļ
+ FILE_TYPE_DIRECTORY, ///< ļ
+ FILE_TYPE_SYMLINK, ///<
+ FILE_TYPE_OTHER, ///<
+ };
+
+ struct FileInfo
+ {
+ int64 size;
+ int64 modtime;
+ FileType type;
+ };
+
+ ///
+ /// Դء洢ԴָĿ¼ȡ۱༭ʱҪƷʵĻƣûIJϷĿ¼
+ /// £file systemµġFilesystemʱͱ༭õ࣬AssetDatabaseԴ࣬framework
+ /// ʵ֣߼дFilesystemʵ֣AssetDatabaseṩļݴӦԴķ
+ ///
+ class Filesystem ASURA_FINAL
+ : public Singleton<Filesystem>
+ , public AEScripting::Portable<Filesystem>
+ {
+ public:
+
+ LUAX_DECL_SINGLETON(Filesystem);
+
+ ~Filesystem();
+
+ void Init(const char* arg0);
+
+ ///
+ /// ǰִļļ
+ ///
+ std::string GetWorkingDirectory();
+
+ bool Mount(const std::string& locpath, const std::string& montpoint = "/", bool prepend = false);
+ bool Mount(DataBuffer* db, const std::string& archivename, const std::string& mountpoint = "/", bool prepend = false);
+
+ bool Unmount(const std::string& locpath);
+ bool Unmount(DataBuffer* db);
+
+ bool GetMountPoint(const std::string& locpath, ASURA_OUT std::string& mountpoint);
+
+ void SetWriteDirectory(const std::string locpath);
+ std::string GetWriteDirectory();
+ File* NewFile(const std::string& name);
+ bool NewDirectory(const std::string& path);
+ bool Write(const std::string& path, ASURA_REF DataBuffer* buffer);
+ bool Append(const std::string& path, ASURA_REF DataBuffer* buffer);
+ bool Remove(const std::string& path);
+
+ FileData* Read(const std::string& path);
+ bool GetFileInfo(const std::string& path, ASURA_OUT FileInfo* info);
+
+ bool GetDirectoryItems(const std::string& path, ASURA_OUT std::vector<std::string>& items) { return false; };
+
+ private:
+
+ typedef std::map<std::string, DataBuffer*> MountDataMap;
+
+ bool mInited; ///< Ƿʼɹ
+ std::string mCwd; ///< ǰִļĹĿ¼
+ MountDataMap mMountData; ///< ·ѹĵӳ
+
+ LUAX_DECL_METHOD(_Init);
+ LUAX_DECL_METHOD(_Mount);
+ LUAX_DECL_METHOD(_Unmount);
+ LUAX_DECL_METHOD(_GetMountPoint);
+
+ LUAX_DECL_METHOD(_SetWriteDirectory);
+ LUAX_DECL_METHOD(_GetWriteDirectory);
+ LUAX_DECL_METHOD(_CreateFile);
+ LUAX_DECL_METHOD(_CreateDirectory);
+
+ LUAX_DECL_METHOD(_Write);
+ LUAX_DECL_METHOD(_Append);
+ LUAX_DECL_METHOD(_Remove);
+
+ LUAX_DECL_METHOD(_Read);
+
+ LUAX_DECL_METHOD(_GetFileInfo);
+
+ LUAX_DECL_METHOD(_GetDirectoryItems);
+
+ };
+
+ }
+}
+
+namespace AEIO = AsuraEngine::IO;
+
+#endif \ No newline at end of file
diff --git a/source/libs/asura-lib-utils/io/io_batch_task.cpp b/source/libs/asura-lib-utils/io/io_batch_task.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/source/libs/asura-lib-utils/io/io_batch_task.cpp
diff --git a/source/libs/asura-lib-utils/io/io_batch_task.h b/source/libs/asura-lib-utils/io/io_batch_task.h
new file mode 100644
index 0000000..c0be921
--- /dev/null
+++ b/source/libs/asura-lib-utils/io/io_batch_task.h
@@ -0,0 +1,31 @@
+#ifndef __ASURA_IO_BATCH_TASK_H__
+#define __ASURA_IO_BATCH_TASK_H__
+
+#include "io_task.h"
+
+namespace AsuraEngine
+{
+ namespace IO
+ {
+
+ ///
+ /// дһύһtableδ󷵻ؽ
+ ///
+ class IOBatchTask ASURA_FINAL : public AEThreading::Task
+ {
+ public:
+
+ private:
+
+ ///
+ /// ÿһĽṹ£
+ /// { path = "", }
+ ///
+ Luax::LuaxMemberRef mTasks;
+
+ };
+
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/source/libs/asura-lib-utils/io/io_task.cpp b/source/libs/asura-lib-utils/io/io_task.cpp
new file mode 100644
index 0000000..361b9c5
--- /dev/null
+++ b/source/libs/asura-lib-utils/io/io_task.cpp
@@ -0,0 +1,55 @@
+#include "file_system.h"
+#include "io_task.h"
+
+#include <iostream>
+
+using namespace AEScripting;
+using namespace Luax;
+
+namespace AsuraEngine
+{
+ namespace IO
+ {
+
+ IOTask::IOTask(const std::string& path, DataBuffer* buffer, IOTaskType type)
+ : mPath(path)
+ , mBuffer(buffer)
+ {
+ }
+
+ IOTask::~IOTask()
+ {
+ }
+
+ bool IOTask::Execute()
+ {
+ File file(mPath);
+ if (mType == IOTASK_TYPE_WRITE)
+ {
+
+ }
+ // pathȡݱmBuffer
+ else if (mType == IOTASK_TYPE_READ)
+ {
+ file.Open(File::FILE_MODE_READ);
+ file.ReadAll(mBuffer);
+ file.Close();
+ }
+ return true;
+ }
+
+ void IOTask::Invoke(lua_State* invokeThreaad)
+ {
+ if (mCallback)
+ {
+ LuaxScopedState state(invokeThreaad);
+ if (PushLuaxMemberRef(state, mCallback))
+ {
+ PushLuaxMemberRef(state, mBufferRef);
+ state.Call(1, 0);
+ }
+ }
+ }
+
+ }
+}
diff --git a/source/libs/asura-lib-utils/io/io_task.h b/source/libs/asura-lib-utils/io/io_task.h
new file mode 100644
index 0000000..8f04142
--- /dev/null
+++ b/source/libs/asura-lib-utils/io/io_task.h
@@ -0,0 +1,57 @@
+#ifndef __ASURA_IO_TASK_H__
+#define __ASURA_IO_TASK_H__
+
+#include <string>
+
+#include "../scripting/portable.hpp"
+#include "../threading/task.h"
+
+#include "data_buffer.h"
+
+namespace AsuraEngine
+{
+ namespace IO
+ {
+
+ enum IOTaskType
+ {
+ IOTASK_TYPE_READ,
+ IOTASK_TYPE_WRITE,
+ IOTASK_TYPE_APPEND,
+ };
+
+ ///
+ /// ȡļ
+ ///
+ class IOTask ASURA_FINAL
+ : public AEThreading::Task
+ , public AEScripting::Portable<IOTask>
+ {
+ public:
+
+ LUAX_DECL_FACTORY(IOTask);
+
+ IOTask(const std::string& path, DataBuffer* buffer, IOTaskType type);
+ ~IOTask();
+
+ bool Execute() override ;
+ void Invoke(lua_State* invokeThreaad) override;
+
+ private:
+
+ LUAX_DECL_ENUM(IOTaskType);
+
+ LUAX_DECL_METHOD(_New);
+
+ std::string mPath;
+ IOTaskType mType;
+
+ ASURA_REF DataBuffer* mBuffer;
+ Luax::LuaxMemberRef mBufferRef;
+
+ };
+
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/source/libs/asura-lib-utils/io/reloadable.h b/source/libs/asura-lib-utils/io/reloadable.h
new file mode 100644
index 0000000..22a721c
--- /dev/null
+++ b/source/libs/asura-lib-utils/io/reloadable.h
@@ -0,0 +1,29 @@
+#ifndef __ASURA_ENGINE_RELOADABLE_H__
+#define __ASURA_ENGINE_RELOADABLE_H__
+
+#include "../scripting/portable.hpp"
+
+namespace AsuraEngine
+{
+ namespace IO
+ {
+
+ ///
+ /// ¹ݽṹͼƬƵ֣ⲿݿֱӹڱ༭¹ڲıhandleԴ
+ ///
+ ASURA_ABSTRACT class Reloadable
+ {
+ public:
+ Reloadable();
+ virtual ~Reloadable();
+
+ // ̳ReloadableҪṩһload
+
+ };
+
+ }
+}
+
+namespace AEIO = AsuraEngine::IO;
+
+#endif \ No newline at end of file
diff --git a/source/libs/asura-lib-utils/manager.hpp b/source/libs/asura-lib-utils/manager.hpp
new file mode 100644
index 0000000..7b4e272
--- /dev/null
+++ b/source/libs/asura-lib-utils/manager.hpp
@@ -0,0 +1,14 @@
+#ifndef __ASURA_ENGINE_MANAGER_H__
+#define __ASURA_ENGINE_MANAGER_H__
+
+namespace AsuraEngine
+{
+
+ class Manager
+ {
+
+ };
+
+}
+
+#endif \ No newline at end of file
diff --git a/source/libs/asura-lib-utils/math/curve.cpp b/source/libs/asura-lib-utils/math/curve.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/source/libs/asura-lib-utils/math/curve.cpp
diff --git a/source/libs/asura-lib-utils/math/curve.h b/source/libs/asura-lib-utils/math/curve.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/source/libs/asura-lib-utils/math/curve.h
diff --git a/source/libs/asura-lib-utils/math/functions.cpp b/source/libs/asura-lib-utils/math/functions.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/source/libs/asura-lib-utils/math/functions.cpp
diff --git a/source/libs/asura-lib-utils/math/functions.h b/source/libs/asura-lib-utils/math/functions.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/source/libs/asura-lib-utils/math/functions.h
diff --git a/source/libs/asura-lib-utils/math/matrix44.cpp b/source/libs/asura-lib-utils/math/matrix44.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/source/libs/asura-lib-utils/math/matrix44.cpp
diff --git a/source/libs/asura-lib-utils/math/matrix44.h b/source/libs/asura-lib-utils/math/matrix44.h
new file mode 100644
index 0000000..4ab3c0b
--- /dev/null
+++ b/source/libs/asura-lib-utils/math/matrix44.h
@@ -0,0 +1,24 @@
+#ifndef __ASURA_ENGINE_MATRIX44_H__
+#define __ASURA_ENGINE_MATRIX44_H__
+
+namespace AsuraEngine
+{
+ namespace Math
+ {
+
+ ///
+ /// 4x4
+ ///
+ class Matrix44
+ {
+ public:
+
+ private:
+
+
+ };
+
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/source/libs/asura-lib-utils/math/quaternion.cpp b/source/libs/asura-lib-utils/math/quaternion.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/source/libs/asura-lib-utils/math/quaternion.cpp
diff --git a/source/libs/asura-lib-utils/math/quaternion.h b/source/libs/asura-lib-utils/math/quaternion.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/source/libs/asura-lib-utils/math/quaternion.h
diff --git a/source/libs/asura-lib-utils/math/ranged_value.cpp b/source/libs/asura-lib-utils/math/ranged_value.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/source/libs/asura-lib-utils/math/ranged_value.cpp
diff --git a/source/libs/asura-lib-utils/math/ranged_value.h b/source/libs/asura-lib-utils/math/ranged_value.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/source/libs/asura-lib-utils/math/ranged_value.h
diff --git a/source/libs/asura-lib-utils/math/rect.hpp b/source/libs/asura-lib-utils/math/rect.hpp
new file mode 100644
index 0000000..1751634
--- /dev/null
+++ b/source/libs/asura-lib-utils/math/rect.hpp
@@ -0,0 +1,47 @@
+#ifndef __ASURA_ENGINE_RECT_H__
+#define __ASURA_ENGINE_RECT_H__
+
+namespace AsuraEngine
+{
+ namespace Math
+ {
+
+ template<typename T>
+ struct Rect
+ {
+ public:
+ Rect();
+ ~Rect(T x, T y, T w, T h);
+
+ ///
+ /// x,yǷrectڡ
+ ///
+ bool Contain(T x, T y);
+
+ ///
+ /// Ƿཻཻľ
+ ///
+ bool Intersect(const Rect& src, Rect& intersection);
+
+ ///
+ /// Ƿཻཻľ
+ ///
+ static bool Intersect(const Rect<T>& src1, const Rect<T>& src2, Rect<T>& intersection);
+
+ T x, y, w, h;
+ };
+
+#include "Rect.inl"
+
+ // Define the most common types
+ typedef Rect<int> Recti;
+ typedef Rect<unsigned int> Rectu;
+ typedef Rect<float> Rectf;
+ typedef Rect<long> Reftl;
+
+ }
+}
+
+namespace AEMath = AsuraEngine::Math;
+
+#endif \ No newline at end of file
diff --git a/source/libs/asura-lib-utils/math/rect.inl b/source/libs/asura-lib-utils/math/rect.inl
new file mode 100644
index 0000000..891a3f8
--- /dev/null
+++ b/source/libs/asura-lib-utils/math/rect.inl
@@ -0,0 +1,19 @@
+template <typename T>
+inline Rect<T>::Rect()
+ : x(0)
+ , y(0)
+ , w(0)
+ , h(0)
+{
+
+}
+
+template <typename T>
+inline Rect<T>::Rect(T X, T Y, T W, T H)
+ : x(X)
+ , y(Y)
+ , w(W)
+ , h(H)
+{
+
+}
diff --git a/source/libs/asura-lib-utils/math/transform.cpp b/source/libs/asura-lib-utils/math/transform.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/source/libs/asura-lib-utils/math/transform.cpp
diff --git a/source/libs/asura-lib-utils/math/transform.h b/source/libs/asura-lib-utils/math/transform.h
new file mode 100644
index 0000000..be4c850
--- /dev/null
+++ b/source/libs/asura-lib-utils/math/transform.h
@@ -0,0 +1,30 @@
+#ifndef __ASURA_ENGINE_TRANSFORM_H__
+#define __ASURA_ENGINE_TRANSFORM_H__
+
+#include "../scripting/portable.hpp"
+
+namespace AsuraEngine
+{
+ namespace Math
+ {
+
+ class Transform
+ {
+ public:
+
+ void Set(float x, float y, float sx, float sy, float ox, float oy, float r);
+
+ void LoadIdentity();
+
+ void Move(float dx = 0, float dy = 0);
+ void Rotate(float r);
+ void Scale(float sx, float sy);
+
+ float m[16]; //4x4 matrix
+
+ };
+
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/source/libs/asura-lib-utils/math/vector2.hpp b/source/libs/asura-lib-utils/math/vector2.hpp
new file mode 100644
index 0000000..df78255
--- /dev/null
+++ b/source/libs/asura-lib-utils/math/vector2.hpp
@@ -0,0 +1,70 @@
+#ifndef __ASURA_ENGINE_VECTOR2_H__
+#define __ASURA_ENGINE_VECTOR2_H__
+
+namespace AsuraEngine
+{
+ namespace Math
+ {
+ template <typename T>
+ class Vector2
+ {
+ public:
+ Vector2();
+ Vector2(T X, T Y);
+
+ template <typename U>
+ explicit Vector2(const Vector2<U>& vector);
+
+ Set(T X, T Y);
+
+ T x; ///< X coordinate of the vector
+ T y; ///< Y coordinate of the vector
+ };
+
+ template <typename T>
+ Vector2<T> operator -(const Vector2<T>& right);
+
+ template <typename T>
+ Vector2<T>& operator +=(Vector2<T>& left, const Vector2<T>& right);
+
+ template <typename T>
+ Vector2<T>& operator -=(Vector2<T>& left, const Vector2<T>& right);
+
+ template <typename T>
+ Vector2<T> operator +(const Vector2<T>& left, const Vector2<T>& right);
+
+ template <typename T>
+ Vector2<T> operator -(const Vector2<T>& left, const Vector2<T>& right);
+
+ template <typename T>
+ Vector2<T> operator *(const Vector2<T>& left, T right);
+
+ template <typename T>
+ Vector2<T> operator *(T left, const Vector2<T>& right);
+
+ template <typename T>
+ Vector2<T>& operator *=(Vector2<T>& left, T right);
+
+ template <typename T>
+ Vector2<T> operator /(const Vector2<T>& left, T right);
+
+ template <typename T>
+ Vector2<T>& operator /=(Vector2<T>& left, T right);
+
+ template <typename T>
+ bool operator ==(const Vector2<T>& left, const Vector2<T>& right);
+
+ template <typename T>
+ bool operator !=(const Vector2<T>& left, const Vector2<T>& right);
+
+#include "Vector2.inl"
+
+ // Define the most common types
+ typedef Vector2<int> Vector2i;
+ typedef Vector2<unsigned int> Vector2u;
+ typedef Vector2<float> Vector2f;
+
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/source/libs/asura-lib-utils/math/vector2.inl b/source/libs/asura-lib-utils/math/vector2.inl
new file mode 100644
index 0000000..9e131a7
--- /dev/null
+++ b/source/libs/asura-lib-utils/math/vector2.inl
@@ -0,0 +1,114 @@
+template <typename T>
+inline Vector2<T>::Vector2() :
+ x(0),
+ y(0)
+{
+
+}
+
+template <typename T>
+inline Vector2<T>::Vector2(T X, T Y) :
+ x(X),
+ y(Y)
+{
+
+}
+
+template <typename T>
+template <typename U>
+inline Vector2<T>::Vector2(const Vector2<U>& vector) :
+ x(static_cast<T>(vector.x)),
+ y(static_cast<T>(vector.y))
+{
+}
+
+template <typename T>
+inline Vector2<T>::Set(T X, T Y)
+{
+ x = X;
+ y = Y;
+}
+
+template <typename T>
+inline Vector2<T> operator -(const Vector2<T>& right)
+{
+ return Vector2<T>(-right.x, -right.y);
+}
+
+template <typename T>
+inline Vector2<T>& operator +=(Vector2<T>& left, const Vector2<T>& right)
+{
+ left.x += right.x;
+ left.y += right.y;
+
+ return left;
+}
+
+template <typename T>
+inline Vector2<T>& operator -=(Vector2<T>& left, const Vector2<T>& right)
+{
+ left.x -= right.x;
+ left.y -= right.y;
+
+ return left;
+}
+
+template <typename T>
+inline Vector2<T> operator +(const Vector2<T>& left, const Vector2<T>& right)
+{
+ return Vector2<T>(left.x + right.x, left.y + right.y);
+}
+
+template <typename T>
+inline Vector2<T> operator -(const Vector2<T>& left, const Vector2<T>& right)
+{
+ return Vector2<T>(left.x - right.x, left.y - right.y);
+}
+
+template <typename T>
+inline Vector2<T> operator *(const Vector2<T>& left, T right)
+{
+ return Vector2<T>(left.x * right, left.y * right);
+}
+
+template <typename T>
+inline Vector2<T> operator *(T left, const Vector2<T>& right)
+{
+ return Vector2<T>(right.x * left, right.y * left);
+}
+
+template <typename T>
+inline Vector2<T>& operator *=(Vector2<T>& left, T right)
+{
+ left.x *= right;
+ left.y *= right;
+
+ return left;
+}
+
+template <typename T>
+inline Vector2<T> operator /(const Vector2<T>& left, T right)
+{
+ return Vector2<T>(left.x / right, left.y / right);
+}
+
+template <typename T>
+inline Vector2<T>& operator /=(Vector2<T>& left, T right)
+{
+ left.x /= right;
+ left.y /= right;
+
+ return left;
+}
+
+template <typename T>
+inline bool operator ==(const Vector2<T>& left, const Vector2<T>& right)
+{
+ return (left.x == right.x) && (left.y == right.y);
+}
+
+template <typename T>
+inline bool operator !=(const Vector2<T>& left, const Vector2<T>& right)
+{
+ return (left.x != right.x) || (left.y != right.y);
+}
diff --git a/source/libs/asura-lib-utils/math/vector3.hpp b/source/libs/asura-lib-utils/math/vector3.hpp
new file mode 100644
index 0000000..2b23406
--- /dev/null
+++ b/source/libs/asura-lib-utils/math/vector3.hpp
@@ -0,0 +1,233 @@
+#ifndef __ASURA_ENGINE_VECTOR3_H__
+#define __ASURA_ENGINE_VECTOR3_H__
+
+namespace AsuraEngine
+{
+ namespace Math
+ {
+ template <typename T>
+ class Vector3
+ {
+ public:
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Default constructor
+ ///
+ /// Creates a Vector3(0, 0, 0).
+ ///
+ ////////////////////////////////////////////////////////////
+ Vector3();
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Construct the vector from its coordinates
+ ///
+ /// \param X X coordinate
+ /// \param Y Y coordinate
+ /// \param Z Z coordinate
+ ///
+ ////////////////////////////////////////////////////////////
+ Vector3(T X, T Y, T Z);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Construct the vector from another type of vector
+ ///
+ /// This constructor doesn't replace the copy constructor,
+ /// it's called only when U != T.
+ /// A call to this constructor will fail to compile if U
+ /// is not convertible to T.
+ ///
+ /// \param vector Vector to convert
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename U>
+ explicit Vector3(const Vector3<U>& vector);
+
+ ////////////////////////////////////////////////////////////
+ // Member data
+ ////////////////////////////////////////////////////////////
+ T x; ///< X coordinate of the vector
+ T y; ///< Y coordinate of the vector
+ T z; ///< Z coordinate of the vector
+ };
+
+ ////////////////////////////////////////////////////////////
+ /// \relates Vector3
+ /// \brief Overload of unary operator -
+ ///
+ /// \param left Vector to negate
+ ///
+ /// \return Memberwise opposite of the vector
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename T>
+ Vector3<T> operator -(const Vector3<T>& left);
+
+ ////////////////////////////////////////////////////////////
+ /// \relates Vector3
+ /// \brief Overload of binary operator +=
+ ///
+ /// This operator performs a memberwise addition of both vectors,
+ /// and assigns the result to \a left.
+ ///
+ /// \param left Left operand (a vector)
+ /// \param right Right operand (a vector)
+ ///
+ /// \return Reference to \a left
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename T>
+ Vector3<T>& operator +=(Vector3<T>& left, const Vector3<T>& right);
+
+ ////////////////////////////////////////////////////////////
+ /// \relates Vector3
+ /// \brief Overload of binary operator -=
+ ///
+ /// This operator performs a memberwise subtraction of both vectors,
+ /// and assigns the result to \a left.
+ ///
+ /// \param left Left operand (a vector)
+ /// \param right Right operand (a vector)
+ ///
+ /// \return Reference to \a left
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename T>
+ Vector3<T>& operator -=(Vector3<T>& left, const Vector3<T>& right);
+
+ ////////////////////////////////////////////////////////////
+ /// \relates Vector3
+ /// \brief Overload of binary operator +
+ ///
+ /// \param left Left operand (a vector)
+ /// \param right Right operand (a vector)
+ ///
+ /// \return Memberwise addition of both vectors
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename T>
+ Vector3<T> operator +(const Vector3<T>& left, const Vector3<T>& right);
+
+ ////////////////////////////////////////////////////////////
+ /// \relates Vector3
+ /// \brief Overload of binary operator -
+ ///
+ /// \param left Left operand (a vector)
+ /// \param right Right operand (a vector)
+ ///
+ /// \return Memberwise subtraction of both vectors
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename T>
+ Vector3<T> operator -(const Vector3<T>& left, const Vector3<T>& right);
+
+ ////////////////////////////////////////////////////////////
+ /// \relates Vector3
+ /// \brief Overload of binary operator *
+ ///
+ /// \param left Left operand (a vector)
+ /// \param right Right operand (a scalar value)
+ ///
+ /// \return Memberwise multiplication by \a right
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename T>
+ Vector3<T> operator *(const Vector3<T>& left, T right);
+
+ ////////////////////////////////////////////////////////////
+ /// \relates Vector3
+ /// \brief Overload of binary operator *
+ ///
+ /// \param left Left operand (a scalar value)
+ /// \param right Right operand (a vector)
+ ///
+ /// \return Memberwise multiplication by \a left
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename T>
+ Vector3<T> operator *(T left, const Vector3<T>& right);
+
+ ////////////////////////////////////////////////////////////
+ /// \relates Vector3
+ /// \brief Overload of binary operator *=
+ ///
+ /// This operator performs a memberwise multiplication by \a right,
+ /// and assigns the result to \a left.
+ ///
+ /// \param left Left operand (a vector)
+ /// \param right Right operand (a scalar value)
+ ///
+ /// \return Reference to \a left
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename T>
+ Vector3<T>& operator *=(Vector3<T>& left, T right);
+
+ ////////////////////////////////////////////////////////////
+ /// \relates Vector3
+ /// \brief Overload of binary operator /
+ ///
+ /// \param left Left operand (a vector)
+ /// \param right Right operand (a scalar value)
+ ///
+ /// \return Memberwise division by \a right
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename T>
+ Vector3<T> operator /(const Vector3<T>& left, T right);
+
+ ////////////////////////////////////////////////////////////
+ /// \relates Vector3
+ /// \brief Overload of binary operator /=
+ ///
+ /// This operator performs a memberwise division by \a right,
+ /// and assigns the result to \a left.
+ ///
+ /// \param left Left operand (a vector)
+ /// \param right Right operand (a scalar value)
+ ///
+ /// \return Reference to \a left
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename T>
+ Vector3<T>& operator /=(Vector3<T>& left, T right);
+
+ ////////////////////////////////////////////////////////////
+ /// \relates Vector3
+ /// \brief Overload of binary operator ==
+ ///
+ /// This operator compares strict equality between two vectors.
+ ///
+ /// \param left Left operand (a vector)
+ /// \param right Right operand (a vector)
+ ///
+ /// \return True if \a left is equal to \a right
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename T>
+ bool operator ==(const Vector3<T>& left, const Vector3<T>& right);
+
+ ////////////////////////////////////////////////////////////
+ /// \relates Vector3
+ /// \brief Overload of binary operator !=
+ ///
+ /// This operator compares strict difference between two vectors.
+ ///
+ /// \param left Left operand (a vector)
+ /// \param right Right operand (a vector)
+ ///
+ /// \return True if \a left is not equal to \a right
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename T>
+ bool operator !=(const Vector3<T>& left, const Vector3<T>& right);
+
+#include "Vector3.inl"
+
+ // Define the most common types
+ typedef Vector3<int> Vector3i;
+ typedef Vector3<float> Vector3f;
+
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/source/libs/asura-lib-utils/math/vector3.inl b/source/libs/asura-lib-utils/math/vector3.inl
new file mode 100644
index 0000000..3a2aa93
--- /dev/null
+++ b/source/libs/asura-lib-utils/math/vector3.inl
@@ -0,0 +1,145 @@
+
+
+////////////////////////////////////////////////////////////
+template <typename T>
+inline Vector3<T>::Vector3() :
+ x(0),
+ y(0),
+ z(0)
+{
+
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename T>
+inline Vector3<T>::Vector3(T X, T Y, T Z) :
+ x(X),
+ y(Y),
+ z(Z)
+{
+
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename T>
+template <typename U>
+inline Vector3<T>::Vector3(const Vector3<U>& vector) :
+ x(static_cast<T>(vector.x)),
+ y(static_cast<T>(vector.y)),
+ z(static_cast<T>(vector.z))
+{
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename T>
+inline Vector3<T> operator -(const Vector3<T>& left)
+{
+ return Vector3<T>(-left.x, -left.y, -left.z);
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename T>
+inline Vector3<T>& operator +=(Vector3<T>& left, const Vector3<T>& right)
+{
+ left.x += right.x;
+ left.y += right.y;
+ left.z += right.z;
+
+ return left;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename T>
+inline Vector3<T>& operator -=(Vector3<T>& left, const Vector3<T>& right)
+{
+ left.x -= right.x;
+ left.y -= right.y;
+ left.z -= right.z;
+
+ return left;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename T>
+inline Vector3<T> operator +(const Vector3<T>& left, const Vector3<T>& right)
+{
+ return Vector3<T>(left.x + right.x, left.y + right.y, left.z + right.z);
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename T>
+inline Vector3<T> operator -(const Vector3<T>& left, const Vector3<T>& right)
+{
+ return Vector3<T>(left.x - right.x, left.y - right.y, left.z - right.z);
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename T>
+inline Vector3<T> operator *(const Vector3<T>& left, T right)
+{
+ return Vector3<T>(left.x * right, left.y * right, left.z * right);
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename T>
+inline Vector3<T> operator *(T left, const Vector3<T>& right)
+{
+ return Vector3<T>(right.x * left, right.y * left, right.z * left);
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename T>
+inline Vector3<T>& operator *=(Vector3<T>& left, T right)
+{
+ left.x *= right;
+ left.y *= right;
+ left.z *= right;
+
+ return left;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename T>
+inline Vector3<T> operator /(const Vector3<T>& left, T right)
+{
+ return Vector3<T>(left.x / right, left.y / right, left.z / right);
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename T>
+inline Vector3<T>& operator /=(Vector3<T>& left, T right)
+{
+ left.x /= right;
+ left.y /= right;
+ left.z /= right;
+
+ return left;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename T>
+inline bool operator ==(const Vector3<T>& left, const Vector3<T>& right)
+{
+ return (left.x == right.x) && (left.y == right.y) && (left.z == right.z);
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename T>
+inline bool operator !=(const Vector3<T>& left, const Vector3<T>& right)
+{
+ return (left.x != right.x) || (left.y != right.y) || (left.z != right.z);
+}
diff --git a/source/libs/asura-lib-utils/math/vector4.h b/source/libs/asura-lib-utils/math/vector4.h
new file mode 100644
index 0000000..13a9d8a
--- /dev/null
+++ b/source/libs/asura-lib-utils/math/vector4.h
@@ -0,0 +1,234 @@
+#ifndef __ASURA_ENGINE_VECTOR4_H__
+#define __ASURA_ENGINE_VECTOR4_H__
+
+namespace AsuraEngine
+{
+ namespace Math
+ {
+ template <typename T>
+ class Vector4
+ {
+ public:
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Default constructor
+ ///
+ /// Creates a Vector4(0, 0, 0).
+ ///
+ ////////////////////////////////////////////////////////////
+ Vector4();
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Construct the vector from its coordinates
+ ///
+ /// \param X X coordinate
+ /// \param Y Y coordinate
+ /// \param Z Z coordinate
+ ///
+ ////////////////////////////////////////////////////////////
+ Vector4(T X, T Y, T Z, T W);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Construct the vector from another type of vector
+ ///
+ /// This constructor doesn't replace the copy constructor,
+ /// it's called only when U != T.
+ /// A call to this constructor will fail to compile if U
+ /// is not convertible to T.
+ ///
+ /// \param vector Vector to convert
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename U>
+ explicit Vector4(const Vector4<U>& vector);
+
+ ////////////////////////////////////////////////////////////
+ // Member data
+ ////////////////////////////////////////////////////////////
+ T x; ///< X coordinate of the vector
+ T y; ///< Y coordinate of the vector
+ T z; ///< Z coordinate of the vector
+ T w; ///< W coordinate of the vector
+ };
+
+ ////////////////////////////////////////////////////////////
+ /// \relates Vector4
+ /// \brief Overload of unary operator -
+ ///
+ /// \param left Vector to negate
+ ///
+ /// \return Memberwise opposite of the vector
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename T>
+ Vector4<T> operator -(const Vector4<T>& left);
+
+ ////////////////////////////////////////////////////////////
+ /// \relates Vector4
+ /// \brief Overload of binary operator +=
+ ///
+ /// This operator performs a memberwise addition of both vectors,
+ /// and assigns the result to \a left.
+ ///
+ /// \param left Left operand (a vector)
+ /// \param right Right operand (a vector)
+ ///
+ /// \return Reference to \a left
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename T>
+ Vector4<T>& operator +=(Vector4<T>& left, const Vector4<T>& right);
+
+ ////////////////////////////////////////////////////////////
+ /// \relates Vector4
+ /// \brief Overload of binary operator -=
+ ///
+ /// This operator performs a memberwise subtraction of both vectors,
+ /// and assigns the result to \a left.
+ ///
+ /// \param left Left operand (a vector)
+ /// \param right Right operand (a vector)
+ ///
+ /// \return Reference to \a left
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename T>
+ Vector4<T>& operator -=(Vector4<T>& left, const Vector4<T>& right);
+
+ ////////////////////////////////////////////////////////////
+ /// \relates Vector4
+ /// \brief Overload of binary operator +
+ ///
+ /// \param left Left operand (a vector)
+ /// \param right Right operand (a vector)
+ ///
+ /// \return Memberwise addition of both vectors
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename T>
+ Vector4<T> operator +(const Vector4<T>& left, const Vector4<T>& right);
+
+ ////////////////////////////////////////////////////////////
+ /// \relates Vector4
+ /// \brief Overload of binary operator -
+ ///
+ /// \param left Left operand (a vector)
+ /// \param right Right operand (a vector)
+ ///
+ /// \return Memberwise subtraction of both vectors
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename T>
+ Vector4<T> operator -(const Vector4<T>& left, const Vector4<T>& right);
+
+ ////////////////////////////////////////////////////////////
+ /// \relates Vector4
+ /// \brief Overload of binary operator *
+ ///
+ /// \param left Left operand (a vector)
+ /// \param right Right operand (a scalar value)
+ ///
+ /// \return Memberwise multiplication by \a right
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename T>
+ Vector4<T> operator *(const Vector4<T>& left, T right);
+
+ ////////////////////////////////////////////////////////////
+ /// \relates Vector4
+ /// \brief Overload of binary operator *
+ ///
+ /// \param left Left operand (a scalar value)
+ /// \param right Right operand (a vector)
+ ///
+ /// \return Memberwise multiplication by \a left
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename T>
+ Vector4<T> operator *(T left, const Vector4<T>& right);
+
+ ////////////////////////////////////////////////////////////
+ /// \relates Vector4
+ /// \brief Overload of binary operator *=
+ ///
+ /// This operator performs a memberwise multiplication by \a right,
+ /// and assigns the result to \a left.
+ ///
+ /// \param left Left operand (a vector)
+ /// \param right Right operand (a scalar value)
+ ///
+ /// \return Reference to \a left
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename T>
+ Vector4<T>& operator *=(Vector4<T>& left, T right);
+
+ ////////////////////////////////////////////////////////////
+ /// \relates Vector4
+ /// \brief Overload of binary operator /
+ ///
+ /// \param left Left operand (a vector)
+ /// \param right Right operand (a scalar value)
+ ///
+ /// \return Memberwise division by \a right
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename T>
+ Vector4<T> operator /(const Vector4<T>& left, T right);
+
+ ////////////////////////////////////////////////////////////
+ /// \relates Vector4
+ /// \brief Overload of binary operator /=
+ ///
+ /// This operator performs a memberwise division by \a right,
+ /// and assigns the result to \a left.
+ ///
+ /// \param left Left operand (a vector)
+ /// \param right Right operand (a scalar value)
+ ///
+ /// \return Reference to \a left
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename T>
+ Vector4<T>& operator /=(Vector4<T>& left, T right);
+
+ ////////////////////////////////////////////////////////////
+ /// \relates Vector4
+ /// \brief Overload of binary operator ==
+ ///
+ /// This operator compares strict equality between two vectors.
+ ///
+ /// \param left Left operand (a vector)
+ /// \param right Right operand (a vector)
+ ///
+ /// \return True if \a left is equal to \a right
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename T>
+ bool operator ==(const Vector4<T>& left, const Vector4<T>& right);
+
+ ////////////////////////////////////////////////////////////
+ /// \relates Vector4
+ /// \brief Overload of binary operator !=
+ ///
+ /// This operator compares strict difference between two vectors.
+ ///
+ /// \param left Left operand (a vector)
+ /// \param right Right operand (a vector)
+ ///
+ /// \return True if \a left is not equal to \a right
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename T>
+ bool operator !=(const Vector4<T>& left, const Vector4<T>& right);
+
+#include "Vector4.inl"
+
+ // Define the most common types
+ typedef Vector4<int> Vector4i;
+ typedef Vector4<float> Vector4f;
+
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/source/libs/asura-lib-utils/math/vector4.inl b/source/libs/asura-lib-utils/math/vector4.inl
new file mode 100644
index 0000000..025bfcc
--- /dev/null
+++ b/source/libs/asura-lib-utils/math/vector4.inl
@@ -0,0 +1,152 @@
+
+
+////////////////////////////////////////////////////////////
+template <typename T>
+inline Vector4<T>::Vector4() :
+ x(0),
+ y(0),
+ z(0),
+ w(0)
+{
+
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename T>
+inline Vector4<T>::Vector4(T X, T Y, T Z) :
+ x(X),
+ y(Y),
+ z(Z),
+ w(0)
+{
+
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename T>
+template <typename U>
+inline Vector4<T>::Vector4(const Vector4<U>& vector) :
+ x(static_cast<T>(vector.x)),
+ y(static_cast<T>(vector.y)),
+ z(static_cast<T>(vector.z))
+ w(static_cast<T>(vector.w))
+{
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename T>
+inline Vector4<T> operator -(const Vector4<T>& left)
+{
+ return Vector4<T>(-left.x, -left.y, -left.z, -left.w);
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename T>
+inline Vector4<T>& operator +=(Vector4<T>& left, const Vector4<T>& right)
+{
+ left.x += right.x;
+ left.y += right.y;
+ left.z += right.z;
+ left.w += right.w;
+
+ return left;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename T>
+inline Vector4<T>& operator -=(Vector4<T>& left, const Vector4<T>& right)
+{
+ left.x -= right.x;
+ left.y -= right.y;
+ left.z -= right.z;
+ left.w -= right.w;
+
+ return left;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename T>
+inline Vector4<T> operator +(const Vector4<T>& left, const Vector4<T>& right)
+{
+ return Vector4<T>(left.x + right.x, left.y + right.y, left.z + right.z, left.w + right.w);
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename T>
+inline Vector4<T> operator -(const Vector4<T>& left, const Vector4<T>& right)
+{
+ return Vector4<T>(left.x - right.x, left.y - right.y, left.z - right.z, left.w - right.w);
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename T>
+inline Vector4<T> operator *(const Vector4<T>& left, T right)
+{
+ return Vector4<T>(left.x * right, left.y * right, left.z * right, left.w * right);
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename T>
+inline Vector4<T> operator *(T left, const Vector4<T>& right)
+{
+ return Vector4<T>(right.x * left, right.y * left, right.z * left, right.w * left);
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename T>
+inline Vector4<T>& operator *=(Vector4<T>& left, T right)
+{
+ left.x *= right;
+ left.y *= right;
+ left.z *= right;
+ left.w *= right;
+
+ return left;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename T>
+inline Vector4<T> operator /(const Vector4<T>& left, T right)
+{
+ return Vector4<T>(left.x / right, left.y / right, left.z / right, left.w / right);
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename T>
+inline Vector4<T>& operator /=(Vector4<T>& left, T right)
+{
+ left.x /= right;
+ left.y /= right;
+ left.z /= right;
+ left.w /= right;
+
+ return left;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename T>
+inline bool operator ==(const Vector4<T>& left, const Vector4<T>& right)
+{
+ return (left.x == right.x) && (left.y == right.y) && (left.z == right.z) && (left.w == right.w);
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename T>
+inline bool operator !=(const Vector4<T>& left, const Vector4<T>& right)
+{
+ return (left.x != right.x) || (left.y != right.y) || (left.z != right.z) || (left.w != right.w);
+}
diff --git a/source/libs/asura-lib-utils/module.h b/source/libs/asura-lib-utils/module.h
new file mode 100644
index 0000000..b22c68c
--- /dev/null
+++ b/source/libs/asura-lib-utils/module.h
@@ -0,0 +1,32 @@
+#ifndef __ASURA_MODULE_H__
+#define __ASURA_MODULE_H__
+
+#include "type.h"
+#include "scripting/portable.hpp"
+
+namespace AsuraEngine
+{
+
+ ///
+ /// Asura libs Ҫ̳д࣬Կעᡣģа˳Щģ飬Ȼ˳InitializeFinalizeʼ
+ /// رЩģ顣
+ ///
+ ASURA_ABSTRACT class Module
+ {
+ public:
+
+ ///
+ /// ʼģ顣
+ ///
+ virtual void Initialize(Luax::LuaxState& state) = 0;
+
+ ///
+ /// رģ顣
+ ///
+ virtual void Finalize(Luax::LuaxState& state) = 0;
+
+ };
+
+}
+
+#endif \ No newline at end of file
diff --git a/source/libs/asura-lib-utils/scripting/lua_env.h b/source/libs/asura-lib-utils/scripting/lua_env.h
new file mode 100644
index 0000000..e2fc4fc
--- /dev/null
+++ b/source/libs/asura-lib-utils/scripting/lua_env.h
@@ -0,0 +1,72 @@
+#ifndef __ASURA_LUA_ENV_H__
+#define __ASURA_LUA_ENV_H__
+
+extern "C"
+{
+#include <Lua51/lua.h>
+#include <Lua51/lauxlib.h>
+}
+#include <Luax/luax.h>
+
+#include "../singleton.hpp"
+
+namespace AsuraEngine
+{
+ namespace Scripting
+ {
+
+ ///
+ /// ͨӿڷlua stateAsura˼ǣ߳άһluaӦ
+ /// Ҫ߼ڴlua߳߽ջ
+ ///
+ class LuaEnv ASURA_FINAL : public Singleton<LuaEnv>
+ {
+ public:
+
+ LuaEnv() : mVM(0) {};
+ ~LuaEnv() {};
+
+ ///
+ /// ִջ
+ ///
+ inline void Init()
+ {
+ ASSERT(!mVM);
+ mVM = new Luax::LuaxVM();
+ ASSERT(mVM);
+ mVM->Setup();
+ };
+
+ inline lua_State* GetMainThread()
+ {
+ return mVM->GetMainThread();
+ };
+
+ inline void Exit()
+ {
+ delete mVM;
+ mVM = nullptr;
+ }
+
+ private:
+
+ ///
+ /// ̱߳һluaһAsuraԶֻһ󲿷ִ붼
+ /// УֻһΡ߳\ִջӦglobal_Stateģ
+ ///
+ /// struct lua_State *mainthread;
+ ///
+ /// ʹlua_newstate()ᴴһһglobal_Stateṹһ
+ /// ߳lua_Stateءglobal_State̹߳˵һ
+ /// ߳lua_newstate()⣬߳lua_newthread()
+ ///
+ Luax::LuaxVM* mVM;
+
+ };
+
+ }
+}
+
+namespace AEScripting = AsuraEngine::Scripting;
+
+#endif \ No newline at end of file
diff --git a/source/libs/asura-lib-utils/scripting/portable.hpp b/source/libs/asura-lib-utils/scripting/portable.hpp
new file mode 100644
index 0000000..5badf8d
--- /dev/null
+++ b/source/libs/asura-lib-utils/scripting/portable.hpp
@@ -0,0 +1,29 @@
+#ifndef __ASURA_ENGINE_PORTABLE_H__
+#define __ASURA_ENGINE_PORTABLE_H__
+
+#include "../type.h"
+
+#include "lua_env.h"
+
+namespace AsuraEngine
+{
+ namespace Scripting
+ {
+
+ ///
+ /// ҪעluanativeҪ̳дģ塣
+ ///
+ template<typename T>
+ using Portable = Luax::LuaxNativeClass<T>;
+
+ ///
+ /// ҪΪ࣬userdatamember ref̳д࣬ע̳С
+ ///
+ using NativeAccessor = Luax::ILuaxNativeAccessor;
+
+ }
+}
+
+namespace AEScripting = AsuraEngine::Scripting;
+
+#endif \ No newline at end of file
diff --git a/source/libs/asura-lib-utils/singleton.hpp b/source/libs/asura-lib-utils/singleton.hpp
new file mode 100644
index 0000000..0d2777e
--- /dev/null
+++ b/source/libs/asura-lib-utils/singleton.hpp
@@ -0,0 +1,59 @@
+#ifndef __ASURA_SINGLETON_H__
+#define __ASURA_SINGLETON_H__
+
+#include "utils_config.h"
+
+namespace AsuraEngine
+{
+
+ ///
+ /// ̳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;
+
+}
+
+#endif // __ASURA_SINGLETON_H__ \ No newline at end of file
diff --git a/source/libs/asura-lib-utils/stringmap.cpp b/source/libs/asura-lib-utils/stringmap.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/source/libs/asura-lib-utils/stringmap.cpp
diff --git a/source/libs/asura-lib-utils/stringmap.hpp b/source/libs/asura-lib-utils/stringmap.hpp
new file mode 100644
index 0000000..ddba128
--- /dev/null
+++ b/source/libs/asura-lib-utils/stringmap.hpp
@@ -0,0 +1,29 @@
+#ifndef __ASURA_ENGINE_STRINGMAP_H__
+#define __ASURA_ENGINE_STRINGMAP_H__
+
+#include <string>
+
+namespace AsuraEngine
+{
+
+ ///
+ /// һ˫һһӦӳ䣬shader uniformsstatemathine state parameterID
+ ///
+ template<typename key_type>
+ class StringMap
+ {
+ public:
+
+ bool ContainsKey(const key_type& key);
+
+ bool ContainsString(const String& str);
+
+ std::string GetStringByKey(const key_type& key);
+
+ key_type GetKeyByString(const String& str);
+
+ };
+
+}
+
+#endif \ No newline at end of file
diff --git a/source/libs/asura-lib-utils/threading/binding/_coroutine.cpp b/source/libs/asura-lib-utils/threading/binding/_coroutine.cpp
new file mode 100644
index 0000000..7f74cca
--- /dev/null
+++ b/source/libs/asura-lib-utils/threading/binding/_coroutine.cpp
@@ -0,0 +1,40 @@
+#include "../coroutine.h"
+
+using namespace std;
+
+namespace AsuraEngine
+{
+ namespace Threading
+ {
+
+ LUAX_REGISTRY(Coroutine)
+ {
+ LUAX_REGISTER_METHODS(state,
+ { "New", _New },
+ { "Run", _Run }
+ );
+ }
+
+ LUAX_POSTPROCESS(Coroutine)
+ {
+
+ }
+
+ // Coroutine.New()
+ LUAX_IMPL_METHOD(Coroutine, _New)
+ {
+ LUAX_STATE(L);
+
+ return 0;
+ }
+
+ // coroutine:Run()
+ LUAX_IMPL_METHOD(Coroutine, _Run)
+ {
+ LUAX_PREPARE(L, Coroutine);
+
+ return 0;
+ }
+
+ }
+}
diff --git a/source/libs/asura-lib-utils/threading/binding/_thread.cpp b/source/libs/asura-lib-utils/threading/binding/_thread.cpp
new file mode 100644
index 0000000..a5aff03
--- /dev/null
+++ b/source/libs/asura-lib-utils/threading/binding/_thread.cpp
@@ -0,0 +1,210 @@
+#include "../thread.h"
+
+using namespace std;
+
+namespace AsuraEngine
+{
+ namespace Threading
+ {
+
+ LUAX_REGISTRY(Thread)
+ {
+ LUAX_REGISTER_METHODS(state,
+ { "New", _New },
+ { "AddTask", _AddTask },
+ { "Start", _Start },
+ { "Idle", _Idle },
+ { "Pause", _Pause },
+ { "Resume", _Resume },
+ { "Stop", _Stop },
+ { "Join", _Join },
+ { "IsRunning", _IsRunning },
+ { "IsPaused", _IsPaused },
+ { "IsStopped", _IsStopped },
+ { "IsCurrent", _IsCurrent },
+ { "Sleep", _Sleep },
+ { "Post", _Post },
+ { "GetName", _GetName },
+ { "GetType", _GetType },
+ { "GetState", _GetState }
+ );
+ }
+
+ LUAX_POSTPROCESS(Thread)
+ {
+ LUAX_REGISTER_ENUM(state, "EThreadType",
+ { "DEFERRED", THREAD_TYPE_DEFERRED },
+ { "IMMEDIATE", THREAD_TYPE_IMMEDIATE }
+ );
+ LUAX_REGISTER_ENUM(state, "EThreadState",
+ { "READY", THREAD_STATE_IDLE },
+ { "RUNNING", THREAD_STATE_RUNNING },
+ { "PAUSED", THREAD_STATE_PAUSED },
+ { "STOPPED", THREAD_STATE_STOPPED }
+ );
+ }
+
+ // thread = Thread.New(thread_type, sleepTime, name)
+ LUAX_IMPL_METHOD(Thread, _New)
+ {
+ LUAX_STATE(L);
+
+ ThreadType type = (ThreadType)state.GetValue<int>(1, THREAD_TYPE_DEFERRED);
+ uint sleepTime = state.GetValue<uint>(2,1);
+ cc8* name = state.GetValue<cc8*>(3, "");
+
+ Thread* thread = new Thread(state, type, sleepTime, name);
+ thread->PushLuaxUserdata(state);
+
+ return 1;
+ }
+
+ // thread:AddTask(task)
+ LUAX_IMPL_METHOD(Thread, _AddTask)
+ {
+ LUAX_PREPARE(L, Thread);
+
+ Task* task = state.GetUserdata<Task>(2);
+ self->AddTask(task);
+ self->LuaxRetain<Task>(state, task);
+ return 0;
+ }
+
+ // successed = thread:Start(isDeamon, stackSize)
+ LUAX_IMPL_METHOD(Thread, _Start)
+ {
+ LUAX_PREPARE(L, Thread);
+
+ bool isDaemon = state.GetValue(2, true);
+ uint stackSize = state.GetValue(3, 0);
+
+ state.Push(self->Start(isDaemon, stackSize));
+ return 1;
+ }
+
+ // thread:Idle()
+ LUAX_IMPL_METHOD(Thread, _Idle)
+ {
+ LUAX_PREPARE(L, Thread);
+ self->Idle();
+ return 0;
+ }
+
+ // thread:Pause()
+ LUAX_IMPL_METHOD(Thread, _Pause)
+ {
+ LUAX_PREPARE(L, Thread);
+ self->Pause();
+ return 0;
+ }
+
+ // thread:Resume()
+ LUAX_IMPL_METHOD(Thread, _Resume)
+ {
+ LUAX_PREPARE(L, Thread);
+ self->Resume();
+ return 0;
+ }
+
+ // thread:Stop()
+ LUAX_IMPL_METHOD(Thread, _Stop)
+ {
+ LUAX_PREPARE(L, Thread);
+ self->Stop();
+ return 0;
+ }
+
+ // thread:Join()
+ LUAX_IMPL_METHOD(Thread, _Join)
+ {
+ LUAX_PREPARE(L, Thread);
+ self->Join();
+ return 0;
+ }
+
+ // thread:IsRunning()
+ LUAX_IMPL_METHOD(Thread, _IsRunning)
+ {
+ LUAX_PREPARE(L, Thread);
+ state.Push(self->IsRunning());
+ return 1;
+ }
+
+ // thread:IsPaused()
+ LUAX_IMPL_METHOD(Thread, _IsPaused)
+ {
+ LUAX_PREPARE(L, Thread);
+ state.Push(self->IsPaused());
+ return 1;
+ }
+
+ // thread:IsStopped()
+ LUAX_IMPL_METHOD(Thread, _IsStopped)
+ {
+ LUAX_PREPARE(L, Thread);
+ state.Push(self->IsStopped());
+ return 1;
+ }
+
+ // thread:IsCurrent()
+ LUAX_IMPL_METHOD(Thread, _IsCurrent)
+ {
+ LUAX_PREPARE(L, Thread);
+ state.Push(self->IsCurrent());
+ return 1;
+ }
+
+ // Thread.Sleep(ms)
+ LUAX_IMPL_METHOD(Thread, _Sleep)
+ {
+ LUAX_STATE(L);
+ uint ms = state.GetValue(1, 0);
+#ifdef _WIN32
+ ::Sleep(ms);
+#endif
+ return 0;
+ }
+
+ // thread:Post()
+ LUAX_IMPL_METHOD(Thread, _Post)
+ {
+ LUAX_PREPARE(L, Thread);
+ self->Post();
+ return 0;
+ }
+
+ // thread:GetName()
+ LUAX_IMPL_METHOD(Thread, _GetName)
+ {
+ LUAX_PREPARE(L, Thread);
+ state.Push(self->GetName());
+ return 1;
+ }
+
+ // thread:GetType()
+ LUAX_IMPL_METHOD(Thread, _GetType)
+ {
+ LUAX_PREPARE(L, Thread);
+ state.Push(self->mType);
+ return 1;
+ }
+
+ // thread:GetState()
+ LUAX_IMPL_METHOD(Thread, _GetState)
+ {
+ LUAX_PREPARE(L, Thread);
+ state.Push(self->mState);
+ return 1;
+ }
+
+ // thread:SetSleepTime(sleepTime)
+ LUAX_IMPL_METHOD(Thread, _SetSleepTime)
+ {
+ LUAX_PREPARE(L, Thread);
+ uint time = state.CheckValue<uint>(2);
+ self->SetSleepTime(time);
+ return 0;
+ }
+
+ }
+}
diff --git a/source/libs/asura-lib-utils/threading/coroutine.cpp b/source/libs/asura-lib-utils/threading/coroutine.cpp
new file mode 100644
index 0000000..9f65c5f
--- /dev/null
+++ b/source/libs/asura-lib-utils/threading/coroutine.cpp
@@ -0,0 +1,16 @@
+#include "coroutine.h"
+
+namespace AsuraEngine
+{
+ namespace Threading
+ {
+/*
+ Coroutine::Coroutine()
+ {
+
+ }
+*/
+
+
+ }
+}
diff --git a/source/libs/asura-lib-utils/threading/coroutine.h b/source/libs/asura-lib-utils/threading/coroutine.h
new file mode 100644
index 0000000..01af654
--- /dev/null
+++ b/source/libs/asura-lib-utils/threading/coroutine.h
@@ -0,0 +1,40 @@
+#ifndef __ASURA_COROUTINE_H__
+#define __ASURA_COROUTINE_H__
+
+#include "../scripting/portable.hpp"
+
+namespace AsuraEngine
+{
+ namespace Threading
+ {
+
+ ///
+ /// luaЭ̣һЩ߼
+ ///
+ class Coroutine ASURA_FINAL
+ : public AEScripting::Portable<Coroutine>
+ {
+ public:
+
+ LUAX_DECL_FACTORY(Coroutine);
+
+
+
+ private:
+
+ ///
+ /// ǰЭ̵state
+ ///
+ lua_State* mThreadState;
+
+ LUAX_DECL_METHOD(_New);
+ LUAX_DECL_METHOD(_Run);
+
+ };
+
+ }
+}
+
+namespace AEThreading = AsuraEngine::Threading;
+
+#endif \ No newline at end of file
diff --git a/source/libs/asura-lib-utils/threading/mutex.cpp b/source/libs/asura-lib-utils/threading/mutex.cpp
new file mode 100644
index 0000000..663ac28
--- /dev/null
+++ b/source/libs/asura-lib-utils/threading/mutex.cpp
@@ -0,0 +1,106 @@
+#include <asura-lib-utils/exceptions/exception.h>
+
+#include "mutex.h"
+
+namespace AsuraEngine
+{
+ namespace Threading
+ {
+
+#define try_create_mutex(impl)\
+ if (!mImpl) \
+ { \
+ try \
+ { \
+ mImpl = new impl(); \
+ } \
+ catch (Exception& e) \
+ { \
+ mImpl = nullptr; \
+ } \
+ }
+
+ Mutex::Mutex()
+ : mImpl(nullptr)
+ {
+#if ASURA_MUTEX_WIN32_CRITICLE_SECTION
+ try_create_mutex(MutexImplWin32_CS);
+#endif
+#if ASURA_MUTEX_WIN32_KERNAL_MUTEX
+ try_create_mutex(MutexImplWin32_KM);
+#endif
+ ASSERT(mImpl);
+ }
+
+ Mutex::~Mutex()
+ {
+ delete mImpl;
+ }
+
+ void Mutex::Lock()
+ {
+ ASSERT(mImpl);
+
+ mImpl->Lock();
+ }
+
+ void Mutex::Unlock()
+ {
+ ASSERT(mImpl);
+
+ mImpl->Unlock();
+ }
+
+#if ASURA_MUTEX_WIN32_CRITICLE_SECTION
+
+ MutexImplWin32_CS::MutexImplWin32_CS()
+ {
+ ::InitializeCriticalSection(&mMutex);
+ }
+
+ MutexImplWin32_CS::~MutexImplWin32_CS()
+ {
+ ::DeleteCriticalSection(&mMutex);
+ }
+
+ void MutexImplWin32_CS::Lock()
+ {
+ ::EnterCriticalSection(&mMutex);
+ }
+
+ void MutexImplWin32_CS::Unlock()
+ {
+ ::LeaveCriticalSection(&mMutex);
+ }
+
+#endif // ASURA_MUTEX_WIN32_CRITICLE_SECTION
+
+#if ASURA_MUTEX_WIN32_KERNAL_MUTEX
+
+ MutexImplWin32_KM::MutexImplWin32_KM()
+ {
+ mHandle = ::CreateMutex(NULL, FALSE, NULL);
+ if (!mHandle)
+ throw Exception("Cant use win32 mutex.");
+ }
+
+ MutexImplWin32_KM::~MutexImplWin32_KM()
+ {
+ ::CloseHandle(mHandle);
+ mHandle = NULL;
+ }
+
+ void MutexImplWin32_KM::Lock()
+ {
+ ::WaitForSingleObject(mHandle, INFINITE);
+ }
+
+ void MutexImplWin32_KM::Unlock()
+ {
+ ::ReleaseMutex(mHandle);
+ }
+
+#endif // ASURA_MUTEX_WIN32_KERNAL_MUTEX
+
+ }
+}
diff --git a/source/libs/asura-lib-utils/threading/mutex.h b/source/libs/asura-lib-utils/threading/mutex.h
new file mode 100644
index 0000000..7e7d877
--- /dev/null
+++ b/source/libs/asura-lib-utils/threading/mutex.h
@@ -0,0 +1,126 @@
+#ifndef __ASURA_MUTEX_H__
+#define __ASURA_MUTEX_H__
+
+#include <asura-lib-utils/type.h>
+
+#include "../utils_config.h"
+
+#if ASURA_THREAD_WIN32
+ #include <windows.h>
+#endif
+
+namespace AsuraEngine
+{
+ namespace Threading
+ {
+
+ class MutexImpl;
+
+ class Mutex
+ {
+ public:
+
+ Mutex();
+ ~Mutex();
+
+ void Lock();
+ void Unlock();
+
+ private:
+
+ MutexImpl* mImpl;
+
+ };
+
+ class _mutex_locker
+ {
+ public:
+ _mutex_locker(Mutex& mutex)
+ : m(mutex)
+ {
+ m.Lock();
+ };
+ ~_mutex_locker()
+ {
+ m.Unlock();
+ }
+ private:
+ void* operator new(size_t);
+ Mutex& m;
+ };
+
+// ڵջӴλÿʼջΪٽ
+#define lock(mutex) _mutex_locker _asura_scoped_lock_0x0(mutex)
+#define lock2(mutex) _mutex_locker _asura_scoped_lock_0x1(mutex)
+#define lock3(mutex) _mutex_locker _asura_scoped_lock_0x2(mutex)
+#define lock4(mutex) _mutex_locker _asura_scoped_lock_0x3(mutex)
+#define lock5(mutex) _mutex_locker _asura_scoped_lock_0x4(mutex)
+
+ ASURA_ABSTRACT class MutexImpl
+ {
+ public:
+
+ MutexImpl() {};
+ virtual ~MutexImpl() {};
+
+ virtual void Lock() = 0;
+ virtual void Unlock() = 0;
+
+ };
+
+#if ASURA_MUTEX_WIN32_CRITICLE_SECTION
+
+ //https://blog.csdn.net/l799623787/article/details/18259949
+ class MutexImplWin32_CS ASURA_FINAL : public MutexImpl
+ {
+ public:
+
+ MutexImplWin32_CS();
+ ~MutexImplWin32_CS();
+
+ void Lock() override;
+ void Unlock() override;
+
+ private:
+
+ //HANDLE mHandle;
+ CRITICAL_SECTION mMutex;
+
+ };
+
+#endif // ASURA_MUTEX_WIN32_CRITICLE_SECTION
+
+#if ASURA_MUTEX_WIN32_KERNAL_MUTEX
+
+ class MutexImplWin32_KM ASURA_FINAL : public MutexImpl
+ {
+ public:
+
+ MutexImplWin32_KM();
+ ~MutexImplWin32_KM();
+
+ void Lock() override;
+ void Unlock() override;
+
+ private:
+
+ HANDLE mHandle;
+
+ };
+
+#endif // ASURA_MUTEX_WIN32_KERNAL_MUTEX
+
+#if ASURA_THREAD_STD
+
+ class MutexImplSTD ASURA_FINAL : public MutexImpl
+ {
+ };
+
+#endif // ASURA_THREAD_STD
+
+ }
+}
+
+namespace AEThreading = AsuraEngine::Threading;
+
+#endif \ No newline at end of file
diff --git a/source/libs/asura-lib-utils/threading/semaphore.cpp b/source/libs/asura-lib-utils/threading/semaphore.cpp
new file mode 100644
index 0000000..d59ec78
--- /dev/null
+++ b/source/libs/asura-lib-utils/threading/semaphore.cpp
@@ -0,0 +1,88 @@
+#include "../exceptions/exception.h"
+#include "../type.h"
+
+#include "semaphore.h"
+
+namespace AsuraEngine
+{
+ namespace Threading
+ {
+
+#define try_create_semaphore(impl) \
+ if (!mImpl) \
+ { \
+ try \
+ { \
+ mImpl = new impl(init_count); \
+ } \
+ catch (Exception& e) \
+ { \
+ mImpl = nullptr; \
+ } \
+ }
+
+ Semaphore::Semaphore(unsigned int init_count)
+ : mImpl(nullptr)
+ {
+#ifdef ASURA_THREAD_WIN32
+ try_create_semaphore(SemaphoreWin32);
+#endif
+ ASSERT(mImpl);
+ }
+
+ Semaphore::~Semaphore()
+ {
+ if (mImpl) delete mImpl;
+ }
+
+ void Semaphore::Signal()
+ {
+ ASSERT(mImpl);
+ mImpl->Signal();
+ }
+
+ void Semaphore::Wait(int timeout)
+ {
+ ASSERT(mImpl);
+ mImpl->Wait(timeout);
+ }
+
+#if ASURA_THREAD_WIN32
+
+ SemaphoreWin32::SemaphoreWin32(unsigned int init_value)
+ : SemaphoreImpl(init_value)
+ {
+ mSem = CreateSemaphore(NULL, init_value, UINT_MAX, NULL);
+ if (!mSem)
+ throw Exception("Cant use win32 semaphore.");
+ }
+
+ SemaphoreWin32::~SemaphoreWin32()
+ {
+ CloseHandle(mSem);
+ }
+
+ void SemaphoreWin32::Signal()
+ {
+ InterlockedIncrement(&mCount);
+ if (ReleaseSemaphore(mSem, 1, NULL) == FALSE)
+ InterlockedDecrement(&mCount);
+ }
+
+ bool SemaphoreWin32::Wait(int timeout)
+ {
+ int result;
+ result = WaitForSingleObject(mSem, timeout < 0 ? INFINITE : timeout);
+ if (result == WAIT_OBJECT_0)
+ {
+ InterlockedDecrement(&mCount);
+ return true;
+ }
+ else
+ return false;
+ }
+
+#endif // ASURA_THREAD_WIN32
+
+ }
+} \ No newline at end of file
diff --git a/source/libs/asura-lib-utils/threading/semaphore.h b/source/libs/asura-lib-utils/threading/semaphore.h
new file mode 100644
index 0000000..80773d8
--- /dev/null
+++ b/source/libs/asura-lib-utils/threading/semaphore.h
@@ -0,0 +1,70 @@
+#ifndef __ASURA_SEMAPHORE_H__
+#define __ASURA_SEMAPHORE_H__
+
+#include "../utils_config.h"
+
+#if ASURA_THREAD_WIN32
+#include <windows.h>
+#endif
+
+namespace AsuraEngine
+{
+ namespace Threading
+ {
+
+ class SemaphoreImpl;
+
+ ///
+ /// ź
+ ///
+ class Semaphore
+ {
+ public:
+
+ Semaphore(unsigned int init_count = 1);
+ ~Semaphore();
+
+ void Signal();
+ void Wait(int timeout = 0);
+
+ private:
+ SemaphoreImpl* mImpl;
+ };
+
+ class SemaphoreImpl
+ {
+ public:
+ SemaphoreImpl(unsigned int init_value)
+ : mCount(init_value)
+ {
+ };
+ virtual ~SemaphoreImpl() {};
+ virtual void Signal() = 0;
+ virtual bool Wait(int timeout) = 0;
+ inline int Current() { return mCount; }
+ protected:
+ unsigned int mCount;
+ };
+
+#define wait(sem) sem.Wait();
+#define signal(sem) sem.Signal();
+
+#if ASURA_THREAD_WIN32
+
+ class SemaphoreWin32 : public SemaphoreImpl
+ {
+ public:
+ SemaphoreWin32(unsigned int init_value);
+ ~SemaphoreWin32();
+ void Signal() override;
+ bool Wait(int timeout) override;
+ private:
+ HANDLE mSem;
+ };
+
+#endif // ASURA_THREAD_WIN32
+
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/source/libs/asura-lib-utils/threading/task.cpp b/source/libs/asura-lib-utils/threading/task.cpp
new file mode 100644
index 0000000..2e84ed4
--- /dev/null
+++ b/source/libs/asura-lib-utils/threading/task.cpp
@@ -0,0 +1,12 @@
+#include "task.h"
+#include "../scripting/lua_env.h"
+
+using namespace AEScripting;
+
+namespace AsuraEngine
+{
+ namespace Threading
+ {
+
+ }
+}
diff --git a/source/libs/asura-lib-utils/threading/task.h b/source/libs/asura-lib-utils/threading/task.h
new file mode 100644
index 0000000..fb7aa5f
--- /dev/null
+++ b/source/libs/asura-lib-utils/threading/task.h
@@ -0,0 +1,45 @@
+#ifndef __ASURA_THRAD_TASK_H__
+#define __ASURA_THRAD_TASK_H__
+
+#include <asura-lib-utils/type.h>
+#include <asura-lib-utils/scripting/portable.hpp>
+
+namespace AsuraEngine
+{
+ namespace Threading
+ {
+
+ ///
+ /// ϣһ̴߳񣬼̳TaskдExecute
+ ///
+ ASURA_ABSTRACT class Task
+ : public virtual AEScripting::NativeAccessor
+ {
+ public:
+
+ Task() {};
+ virtual ~Task() {};
+
+ ///
+ /// ִɺ󷵻trueûص
+ ///
+ virtual bool Execute() = 0;
+
+ ///
+ /// ûصinvoke threadص
+ ///
+ virtual void Invoke(lua_State* invokeThreaad) = 0;
+
+ protected:
+
+ // ȡص
+ Luax::LuaxMemberRef mCallback;
+
+ };
+
+ }
+}
+
+namespace AEThreading = AsuraEngine::Threading;
+
+#endif \ No newline at end of file
diff --git a/source/libs/asura-lib-utils/threading/thread.cpp b/source/libs/asura-lib-utils/threading/thread.cpp
new file mode 100644
index 0000000..0f4f5da
--- /dev/null
+++ b/source/libs/asura-lib-utils/threading/thread.cpp
@@ -0,0 +1,272 @@
+#include "thread.h"
+
+#include "thread_impl_win32.h"
+#include "thread_impl_posix.h"
+#include "thread_impl_sdl.h"
+#include "thread_impl_std.h"
+
+namespace AsuraEngine
+{
+ namespace Threading
+ {
+
+ Thread::Thread(lua_State* luaThread, ThreadType type /*= THREAD_TYPE_DEFERRED*/, uint sleepTime /*= 0*/, const std::string& name /*= ""*/)
+ : mName(name)
+ , mState(THREAD_STATE_IDLE)
+ , mType(type)
+ , mLuaThread(luaThread)
+ , mCallbackThread(nullptr)
+ , mSleepTime(sleepTime)
+ {
+ LUAX_STATE(luaThread);
+ if (type == THREAD_TYPE_IMMEDIATE)
+ {
+ Luax::LuaxVM* vm = state.GetVM();
+ ASSERT(vm);
+ mCallbackThread = vm->CreateThread();
+ ASSERT(mCallbackThread);
+ SetLuaxMemberRef(state, mCallbackThreadRef, -1);
+ state.Pop(); // callback thread
+ }
+ }
+
+ Thread::~Thread()
+ {
+ if (mImpl)
+ {
+ delete mImpl;
+ mImpl = nullptr;
+ }
+ }
+
+ bool Thread::AddTask(Task* task)
+ {
+ lock(mTaskQueueMutex);
+ mTaskQueue.push(task);
+ return true;
+ }
+
+ uint Thread::GetTaskCount()
+ {
+ return mTaskQueue.size();
+ }
+
+ void Thread::Idle()
+ {
+ mState = THREAD_STATE_IDLE;
+ }
+
+#define try_start_thread(impl)\
+ if (!mImpl) \
+ { \
+ mImpl = new impl(); \
+ if (!mImpl->Start(this, stacksize)) \
+ { \
+ delete mImpl; \
+ mImpl = nullptr; \
+ } \
+ }
+
+ bool Thread::Start(bool isDaemon /*= true*/, uint32 stacksize /*= 0*/)
+ {
+ if (mState != THREAD_STATE_IDLE)
+ return false;
+
+ // Ѿһ֮ǰģر
+ if (mImpl)
+ {
+ delete mImpl;
+ mImpl = nullptr;
+ }
+
+#if ASURA_THREAD_WIN32
+ try_start_thread(ThreadImplWin32);
+#endif
+
+ if (!mImpl)
+ return false;
+
+ mIsDaemon = isDaemon;
+ mStateMutex.Lock();
+ mState = THREAD_STATE_RUNNING;
+ mStateMutex.Unlock();
+ }
+
+ void Thread::Pause()
+ {
+ ASSERT(mImpl);
+
+ lock(mStateMutex);
+ mState = THREAD_STATE_PAUSED;
+ }
+
+ void Thread::Resume()
+ {
+ ASSERT(mImpl);
+
+ lock(mStateMutex);
+ if(mState == THREAD_STATE_PAUSED)
+ mState = THREAD_STATE_RUNNING;
+ }
+
+ void Thread::Stop()
+ {
+ ASSERT(mImpl);
+
+ lock(mStateMutex);
+ mState = THREAD_STATE_STOPPED;
+ }
+
+ void Thread::PauseSync()
+ {
+ Pause();
+ wait(mSemPause);
+ }
+
+ void Thread::ResumeSync()
+ {
+ Resume();
+ wait(mSemResume);
+ }
+
+ void Thread::StopSync()
+ {
+ Stop();
+ wait(mSemStop);
+ }
+
+ void Thread::Join()
+ {
+ ASSERT(mImpl);
+ mImpl->Join();
+ }
+
+ ThreadState Thread::GetState()
+ {
+ ThreadState state;
+ mStateMutex.Lock();
+ state = mState;
+ mStateMutex.Unlock();
+ return state;
+ }
+
+ bool Thread::IsRunning()
+ {
+ ASSERT(mImpl);
+
+ return GetState() == THREAD_STATE_RUNNING;
+ }
+
+ bool Thread::IsPaused()
+ {
+ ASSERT(mImpl);
+
+ return GetState() == THREAD_STATE_PAUSED;
+ }
+
+ bool Thread::IsStopped()
+ {
+ ASSERT(mImpl);
+
+ return GetState() == THREAD_STATE_STOPPED;
+ }
+
+ bool Thread::IsCurrent()
+ {
+ ASSERT(mImpl);
+
+ return mImpl->IsCurrent();
+ }
+
+ const std::string& Thread::GetName()
+ {
+ return mName;
+ }
+
+ void Thread::Process()
+ {
+ LUAX_STATE(mLuaThread);
+
+ do{
+ if (IsRunning())
+ {
+ while (!mTaskQueue.empty())
+ {
+ Task* task = mTaskQueue.front();
+ if (task && task->Execute())
+ {
+ if (mType == THREAD_TYPE_DEFERRED)
+ {
+ mFinishedMutex.Lock();
+ mFinishedTasks.push(task);
+ mFinishedMutex.Unlock();
+ }
+ else if (mType == THREAD_TYPE_IMMEDIATE)
+ {
+ task->Invoke(mCallbackThread);
+ this->LuaxRelease<Task>(state, task);
+ }
+ mTaskQueueMutex.Lock();
+ mTaskQueue.pop();
+ mTaskQueueMutex.Unlock();
+ }
+ }
+ }
+
+ // ˳ѭ
+ if (IsStopped())
+ break;
+
+ // CPUʹ
+ Sleep(mSleepTime);
+
+ } while (mIsDaemon);
+
+ // ػ̣߳еstop״̬
+ if (!mIsDaemon)
+ Stop();
+
+ signal(mSemStop);
+
+ // ״̬ΪIdle
+ Idle();
+ }
+
+ ///
+ /// ӳģʽص
+ ///
+ void Thread::Post()
+ {
+ ASSERT(mType == THREAD_TYPE_DEFERRED);
+
+ LUAX_STATE(mLuaThread);
+ while (!mFinishedTasks.empty())
+ {
+ Task* task = mFinishedTasks.front();
+ if (task)
+ {
+ task->Invoke(mLuaThread);
+ this->LuaxRelease<Task>(state, task);
+ mFinishedMutex.Lock();
+ mFinishedTasks.pop();
+ mFinishedMutex.Unlock();
+ }
+ }
+ }
+
+ void Thread::Sleep(uint ms)
+ {
+ ASSERT(mImpl);
+ if (mImpl)
+ {
+ mImpl->Sleep(ms);
+ }
+ }
+
+ void Thread::SetSleepTime(uint ms)
+ {
+ mSleepTime = ms;
+ }
+
+ }
+} \ No newline at end of file
diff --git a/source/libs/asura-lib-utils/threading/thread.h b/source/libs/asura-lib-utils/threading/thread.h
new file mode 100644
index 0000000..0e75770
--- /dev/null
+++ b/source/libs/asura-lib-utils/threading/thread.h
@@ -0,0 +1,221 @@
+#ifndef __ASURA_THREAD_H__
+#define __ASURA_THREAD_H__
+
+#include <string>
+#include <queue>
+
+#include <asura-lib-utils/scripting/portable.hpp>
+
+#include "task.h"
+#include "mutex.h"
+#include "semaphore.h"
+
+namespace AsuraEngine
+{
+ namespace Threading
+ {
+
+ class ThreadImpl;
+
+ ///
+ /// ̵߳ļֲͬʵ֣
+ /// 1: Deferredӳģʽ߳ϵɺҪ̵ֶ߳Post
+ /// ̵߳ص첽Ϊͬlua_Stateͻ⡣
+ /// 2: Immediateģʽÿһ߳άһlua_newthreadlua_State
+ /// صڲͬlua_Stateеãⲻ̷ͬ߳ͬһlua_State
+ ///
+ enum ThreadType
+ {
+ THREAD_TYPE_DEFERRED,
+ THREAD_TYPE_IMMEDIATE,
+ };
+
+ enum ThreadState
+ {
+ THREAD_STATE_IDLE, ///< ãδں˶
+ THREAD_STATE_RUNNING, ///< ѭ
+ THREAD_STATE_PAUSED, ///< ѭͣ
+ THREAD_STATE_STOPPED, ///< ˳ѭ
+ };
+
+ ///
+ /// ߳壬ÿ߳άһtask queue
+ ///
+ class Thread ASURA_FINAL
+ : public AEScripting::Portable<Thread>
+ {
+ public:
+
+ LUAX_DECL_FACTORY(Thread);
+
+ Thread(lua_State* luaThread, ThreadType type = THREAD_TYPE_DEFERRED, uint sleepTime = 1, const std::string& name = "");
+ ~Thread();
+
+ bool AddTask(Task* task);
+ ///
+ /// õȴ
+ ///
+ uint GetTaskCount();
+
+ void Idle();
+
+ ///
+ /// ں˶󣬲Сdaemonȴֶstopijʱ̶ɺԶstop
+ ///
+ bool Start(bool daemon = true, uint32 stacksize = 0);
+
+ ///
+ /// ͬ߳̿ƣʵʱġҪ߳ʹIsȷϵָ״̬
+ ///
+ void Pause();
+ void Resume();
+ void Stop();
+
+ ///
+ /// ͬ߳̿ƣȷźźִС̵߳ȴ
+ ///
+ void PauseSync();
+ void ResumeSync();
+ void StopSync();
+
+ ///
+ /// ̵߳ȴ߳̽żִС
+ ///
+ void Join();
+
+ ThreadState GetState();
+
+ ///
+ /// ߼߳״̬
+ /// 1: IdleУ̴߳Ĭ״̬ʱStart
+ /// 2: RunningУں˶´Ѿں˵УTask
+ /// 3: PausedͣȻںУ˶Ĵ߼ͣ
+ /// 4: StoppedֹͣȻںУѾ޷
+ ///
+ bool IsIdle();
+ bool IsRunning();
+ bool IsPaused();
+ bool IsStopped();
+
+ bool IsCurrent();
+
+ ///
+ /// ִС
+ ///
+ void Process();
+
+ const std::string& GetName();
+
+ ///
+ /// ص
+ ///
+ void Post();
+
+ ///
+ /// ߺ
+ ///
+ void Sleep(uint ms);
+
+ ///
+ /// ʱ
+ ///
+ void SetSleepTime(uint ms);
+
+ private:
+
+ //----------------------------------------------------------------------------//
+
+ LUAX_DECL_ENUM(ThreadType);
+ LUAX_DECL_ENUM(ThreadState);
+
+ LUAX_DECL_METHOD(_New);
+ LUAX_DECL_METHOD(_AddTask);
+ LUAX_DECL_METHOD(_Start);
+ LUAX_DECL_METHOD(_Idle);
+ LUAX_DECL_METHOD(_Pause);
+ LUAX_DECL_METHOD(_Resume);
+ LUAX_DECL_METHOD(_Stop);
+ LUAX_DECL_METHOD(_Join);
+ LUAX_DECL_METHOD(_IsRunning);
+ LUAX_DECL_METHOD(_IsPaused);
+ LUAX_DECL_METHOD(_IsStopped);
+ LUAX_DECL_METHOD(_IsCurrent);
+ LUAX_DECL_METHOD(_Sleep);
+ LUAX_DECL_METHOD(_Post);
+ LUAX_DECL_METHOD(_GetName);
+ LUAX_DECL_METHOD(_GetType);
+ LUAX_DECL_METHOD(_GetState);
+ LUAX_DECL_METHOD(_SetSleepTime);
+
+ //----------------------------------------------------------------------------//
+
+ ///
+ /// ˴Ƿػģʽ
+ ///
+ bool mIsDaemon;
+
+ lua_State* mLuaThread;
+
+ ThreadImpl* mImpl;
+ std::string mName;
+ ThreadType mType;
+ uint mSleepTime;
+
+ ThreadState mState;
+ Mutex mStateMutex;
+
+ ///
+ /// ͬصź
+ ///
+ Semaphore mSemPause;
+ Semaphore mSemResume;
+ Semaphore mSemStop;
+
+ ///
+ /// С
+ ///
+ std::queue<Task*> mTaskQueue;
+ Mutex mTaskQueueMutex;
+
+ ///
+ /// ӳģʽʹ
+ ///
+ std::queue<Task*> mFinishedTasks;
+ Mutex mFinishedMutex;
+
+ ///
+ /// ģʽʹãصʹõlua߳
+ ///
+ lua_State* mCallbackThread;
+ Luax::LuaxMemberRef mCallbackThreadRef;
+
+ };
+
+ ///
+ /// ̵߳ľʵ֣û͸ģһ׼ֲԣ
+ /// 1: win32
+ /// 2: posix
+ /// 3: SDL
+ /// 4: std::thread
+ ///
+ ASURA_ABSTRACT class ThreadImpl
+ {
+ public:
+ ThreadImpl() {};
+ virtual ~ThreadImpl() {};
+
+ virtual bool Start(Thread* thread, uint32 stacksize = 0) = 0;
+ virtual void Join() = 0;
+ virtual void Kill() = 0;
+
+ virtual void Sleep(uint ms) = 0;
+
+ virtual bool IsRunning() = 0;
+ virtual bool IsCurrent() = 0;
+
+ };
+
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/source/libs/asura-lib-utils/threading/thread_impl_posix.cpp b/source/libs/asura-lib-utils/threading/thread_impl_posix.cpp
new file mode 100644
index 0000000..d2ad7af
--- /dev/null
+++ b/source/libs/asura-lib-utils/threading/thread_impl_posix.cpp
@@ -0,0 +1,9 @@
+#include "thread_impl_posix.h"
+
+namespace AsuraEngine
+{
+ namespace Threading
+ {
+
+ }
+} \ No newline at end of file
diff --git a/source/libs/asura-lib-utils/threading/thread_impl_posix.h b/source/libs/asura-lib-utils/threading/thread_impl_posix.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/source/libs/asura-lib-utils/threading/thread_impl_posix.h
diff --git a/source/libs/asura-lib-utils/threading/thread_impl_sdl.cpp b/source/libs/asura-lib-utils/threading/thread_impl_sdl.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/source/libs/asura-lib-utils/threading/thread_impl_sdl.cpp
diff --git a/source/libs/asura-lib-utils/threading/thread_impl_sdl.h b/source/libs/asura-lib-utils/threading/thread_impl_sdl.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/source/libs/asura-lib-utils/threading/thread_impl_sdl.h
diff --git a/source/libs/asura-lib-utils/threading/thread_impl_std.cpp b/source/libs/asura-lib-utils/threading/thread_impl_std.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/source/libs/asura-lib-utils/threading/thread_impl_std.cpp
diff --git a/source/libs/asura-lib-utils/threading/thread_impl_std.h b/source/libs/asura-lib-utils/threading/thread_impl_std.h
new file mode 100644
index 0000000..0e7d3da
--- /dev/null
+++ b/source/libs/asura-lib-utils/threading/thread_impl_std.h
@@ -0,0 +1,43 @@
+#ifndef __ASURA_THREAD_STD_H__
+#define __ASURA_THREAD_STD_H__
+
+#include "../utils_config.h"
+
+#if ASURA_THREAD_STD
+
+#include <windows.h>
+
+#include "thread.h"
+
+namespace AsuraEngine
+{
+ namespace Threading
+ {
+
+ ///
+ /// Threadstd::threadʵ֡
+ ///
+ class ThreadImplSTD : public ThreadImpl
+ {
+ public:
+
+ ThreadImplSTD();
+ ~ThreadImplSTD();
+
+ bool Start(Thread* thread, uint32 stacksize) override;
+ void Join() override;
+ void Kill() override;
+
+ bool IsRunning() override;
+ bool IsCurrent() override;
+
+ private:
+
+ };
+
+ }
+}
+
+#endif // #if ASURA_THREAD_STD
+
+#endif // __ASURA_THREAD_STD_H__ \ No newline at end of file
diff --git a/source/libs/asura-lib-utils/threading/thread_impl_win32.cpp b/source/libs/asura-lib-utils/threading/thread_impl_win32.cpp
new file mode 100644
index 0000000..6871c2d
--- /dev/null
+++ b/source/libs/asura-lib-utils/threading/thread_impl_win32.cpp
@@ -0,0 +1,76 @@
+#include "thread_impl_win32.h"
+#include "thread.h"
+
+#include <iostream>
+
+namespace AsuraEngine
+{
+ namespace Threading
+ {
+
+ static DWORD WINAPI _thread_win32_runner(LPVOID param)
+ {
+ Thread* thread = (Thread*)param;
+ thread->Process();
+ return 0;
+ }
+
+ ThreadImplWin32::ThreadImplWin32()
+ {
+ }
+
+ ThreadImplWin32::~ThreadImplWin32()
+ {
+ if (!mHandle) return;
+ ::CloseHandle(mHandle);
+ mHandle = 0;
+ }
+
+ bool ThreadImplWin32::Start(Thread* thread, uint32 stacksize/*=0*/)
+ {
+ assert(!IsRunning());
+ mHandle = ::CreateThread(
+ NULL
+ , stacksize
+ , _thread_win32_runner
+ , thread
+ , 0 /*е*/
+ , NULL);
+
+ return mHandle;
+ }
+
+ void ThreadImplWin32::Join()
+ {
+ // ̵߳ȴ̷߳
+ ::WaitForSingleObject(mHandle, INFINITE);
+ }
+
+ void ThreadImplWin32::Kill()
+ {
+ ::TerminateThread(mHandle, FALSE);
+ }
+
+ void ThreadImplWin32::Sleep(uint ms)
+ {
+ ::Sleep(ms);
+ }
+
+ bool ThreadImplWin32::IsRunning()
+ {
+ if (mHandle) {
+ DWORD exitCode = 0;
+ // https://blog.csdn.net/yuanmeng567/article/details/19485719
+ ::GetExitCodeThread(mHandle, &exitCode);
+ return exitCode == STILL_ACTIVE;
+ }
+ return false;
+ }
+
+ bool ThreadImplWin32::IsCurrent()
+ {
+ return mHandle == ::GetCurrentThread();
+ }
+
+ }
+} \ No newline at end of file
diff --git a/source/libs/asura-lib-utils/threading/thread_impl_win32.h b/source/libs/asura-lib-utils/threading/thread_impl_win32.h
new file mode 100644
index 0000000..a22aeef
--- /dev/null
+++ b/source/libs/asura-lib-utils/threading/thread_impl_win32.h
@@ -0,0 +1,47 @@
+#ifndef __ASURA_THREAD_WIN32_H__
+#define __ASURA_THREAD_WIN32_H__
+
+#include "../utils_config.h"
+
+#if ASURA_THREAD_WIN32
+
+#include <windows.h>
+
+#include "thread.h"
+
+namespace AsuraEngine
+{
+ namespace Threading
+ {
+
+ ///
+ /// Threadwin32ʵ֡
+ ///
+ class ThreadImplWin32 : public ThreadImpl
+ {
+ public:
+
+ ThreadImplWin32();
+ ~ThreadImplWin32();
+
+ bool Start(Thread* thread, uint32 stacksize) override;
+ void Join() override;
+ void Kill() override;
+
+ void Sleep(uint ms) override;
+
+ bool IsRunning() override;
+ bool IsCurrent() override;
+
+ private:
+
+ HANDLE mHandle;
+
+ };
+
+ }
+}
+
+#endif // #if ASURA_THREAD_WIN32
+
+#endif // __ASURA_THREAD_WIN32_H__ \ No newline at end of file
diff --git a/source/libs/asura-lib-utils/threading/thread_task.cpp b/source/libs/asura-lib-utils/threading/thread_task.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/source/libs/asura-lib-utils/threading/thread_task.cpp
diff --git a/source/libs/asura-lib-utils/threading/thread_task.h b/source/libs/asura-lib-utils/threading/thread_task.h
new file mode 100644
index 0000000..1ea0a1a
--- /dev/null
+++ b/source/libs/asura-lib-utils/threading/thread_task.h
@@ -0,0 +1,44 @@
+#ifndef __ASURA_THRAD_TASK_H__
+#define __ASURA_THRAD_TASK_H__
+
+#include <asura-lib-utils/type.h>
+#include <asura-lib-utils/scripting/portable.hpp>
+
+namespace AsuraEngine
+{
+ namespace Threading
+ {
+
+ ///
+ /// ϣһ̴߳񣬼̳TaskдExecute
+ ///
+ ASURA_ABSTRACT class ThreadTask
+ : virtual public AEScripting::NativeAccessor
+ {
+ public:
+
+ ThreadTask();
+ virtual ~ThreadTask();
+
+ ///
+ /// ִɺ󷵻trueûص
+ ///
+ virtual bool Execute() = 0;
+
+ ///
+ /// ûص
+ ///
+ virtual void Invoke() = 0;
+
+ protected:
+
+ Luax::LuaxMemberRef mCallback;
+
+ };
+
+ }
+}
+
+namespace AEThreading = AsuraEngine::Threading;
+
+#endif \ No newline at end of file
diff --git a/source/libs/asura-lib-utils/type.h b/source/libs/asura-lib-utils/type.h
new file mode 100644
index 0000000..1ed2d42
--- /dev/null
+++ b/source/libs/asura-lib-utils/type.h
@@ -0,0 +1,85 @@
+#ifndef __ASURA_UTILS_TYPE_H__
+#define __ASURA_UTILS_TYPE_H__
+
+#include <cstdlib>
+#include <stdint.h>
+
+namespace AsuraEngine
+{
+
+ //--------------------------------------------------------------------------------//
+
+ typedef int8_t int8;
+ typedef uint8_t uint8;
+ //typedef uint8 byte;
+ typedef char byte;
+ typedef int16_t int16;
+ typedef uint16_t uint16;
+ typedef int32_t int32;
+ typedef uint32_t uint32;
+ typedef int64_t int64;
+ typedef uint64_t uint64;
+
+ typedef uint32_t uint;
+ typedef int32_t sint;
+
+ typedef std::size_t size_t;
+
+ typedef const char cc8;
+
+ //--------------------------------------------------------------------------------//
+
+#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
+
+ //--------------------------------------------------------------------------------//
+
+#ifdef _WIN32
+ #define ASURA_FINAL final
+ #define ASURA_LIBRARY_EXPORT __declspec(dllexport)
+ #define ASURA_LIBRARY_IMPORT __declspec(dllimport)
+ #define ASURA_FORCE_INLINE __forceinline
+ #define ASURA_RESTRICT __restrict
+ #define ASURA_ATTRIBUTE_USED
+ #define ASURA_ABSTRACT
+ #define ASURA_API ASURA_LIBRARY_EXPORT
+
+ #define ASURA_WINDOWS 1
+#else
+ #define ASURA_FINAL final
+ #define ASURA_LIBRARY_EXPORT __attribute__((visibility("default")))
+ #define ASURA_LIBRARY_IMPORT
+ #define ASURA_FORCE_INLINE __attribute__((always_inline)) inline
+ #define ASURA_RESTRICT __restrict__
+ #define ASURA_ATTRIBUTE_USED __attribute__((used))
+ #define ASURA_ABSTRACT
+ #define ASURA_API ASURA_LIBRARY_EXPORT
+#endif
+
+ ///
+ /// ò
+ ///
+#define ASURA_OUT
+#define ASURA_REF
+ ///
+ /// ƶָȨ
+ ///
+#define ASURA_MOVE
+
+ //--------------------------------------------------------------------------------//
+
+#define ASURA_SDL_HOST 1
+
+} // namespace AsuraEngine
+
+#endif // __ASURA_CONFIG_H__ \ No newline at end of file
diff --git a/source/libs/asura-lib-utils/utils.h b/source/libs/asura-lib-utils/utils.h
new file mode 100644
index 0000000..ce1c6a1
--- /dev/null
+++ b/source/libs/asura-lib-utils/utils.h
@@ -0,0 +1,6 @@
+#ifndef __ASURA_UTILS_H__
+#define __ASURA_UTILS_H__
+
+#include "utils_module.h"
+
+#endif \ No newline at end of file
diff --git a/source/libs/asura-lib-utils/utils_config.h b/source/libs/asura-lib-utils/utils_config.h
new file mode 100644
index 0000000..02837dc
--- /dev/null
+++ b/source/libs/asura-lib-utils/utils_config.h
@@ -0,0 +1,10 @@
+#ifndef __ASURA_UTILS_CONFIG_H__
+#define __ASURA_UTILS_CONFIG_H__
+
+#define ASURA_THREAD_WIN32 1
+#define ASURA_THREAD_STD 1
+
+#define ASURA_MUTEX_WIN32_CRITICLE_SECTION 1
+#define ASURA_MUTEX_WIN32_KERNAL_MUTEX 1
+
+#endif \ No newline at end of file
diff --git a/source/libs/asura-lib-utils/utils_module.cpp b/source/libs/asura-lib-utils/utils_module.cpp
new file mode 100644
index 0000000..61780e6
--- /dev/null
+++ b/source/libs/asura-lib-utils/utils_module.cpp
@@ -0,0 +1,25 @@
+#include "utils_module.h"
+
+using namespace AsuraEngine::IO;
+using namespace AsuraEngine::Threading;
+
+namespace AsuraEngine
+{
+
+ void UtilsModule::Initialize(Luax::LuaxState& state)
+ {
+ // IO
+ LUAX_REGISTER_SINGLETON(state, Filesystem);
+ LUAX_REGISTER_FACTORY(state, DataBuffer);
+ LUAX_REGISTER_FACTORY(state, FileData);
+ LUAX_REGISTER_FACTORY(state, File);
+ LUAX_REGISTER_FACTORY(state, IOTask);
+ // Threading
+ LUAX_REGISTER_FACTORY(state, Thread);
+ }
+
+ void UtilsModule::Finalize(Luax::LuaxState& state)
+ {
+ }
+
+} \ No newline at end of file
diff --git a/source/libs/asura-lib-utils/utils_module.h b/source/libs/asura-lib-utils/utils_module.h
new file mode 100644
index 0000000..e802730
--- /dev/null
+++ b/source/libs/asura-lib-utils/utils_module.h
@@ -0,0 +1,32 @@
+#ifndef __ASURA_LIBS_UTIL_MODULE_H__
+#define __ASURA_LIBS_UTIL_MODULE_H__
+
+#include "io/file_system.h"
+#include "io/data_buffer.h"
+#include "io/file_data.h"
+#include "io/file.h"
+#include "io/io_task.h"
+
+#include "threading/thread.h"
+
+#include "module.h"
+
+namespace AsuraEngine
+{
+
+ ///
+ /// Asuraģ
+ ///
+ class UtilsModule ASURA_FINAL : public Module
+ {
+ public:
+
+ void Initialize(Luax::LuaxState& state) override;
+
+ void Finalize(Luax::LuaxState& state) override;
+
+ };
+
+}
+
+#endif \ No newline at end of file