summaryrefslogtreecommitdiff
path: root/Source/modules/asura-base
diff options
context:
space:
mode:
Diffstat (limited to 'Source/modules/asura-base')
-rw-r--r--Source/modules/asura-base/BuildConfigure.h8
-rw-r--r--Source/modules/asura-base/Classes.h9
-rw-r--r--Source/modules/asura-base/Configure.h58
-rw-r--r--Source/modules/asura-base/Exception.cpp40
-rw-r--r--Source/modules/asura-base/Exception.h30
-rw-r--r--Source/modules/asura-base/FileSystem/Binding/_compressor.cpp0
-rw-r--r--Source/modules/asura-base/FileSystem/Binding/_data_buffer.cpp132
-rw-r--r--Source/modules/asura-base/FileSystem/Binding/_file.cpp223
-rw-r--r--Source/modules/asura-base/FileSystem/Binding/_file_data.cpp60
-rw-r--r--Source/modules/asura-base/FileSystem/Binding/_file_manager.cpp265
-rw-r--r--Source/modules/asura-base/FileSystem/Binding/_io_task.cpp46
-rw-r--r--Source/modules/asura-base/FileSystem/Compressor.cpp11
-rw-r--r--Source/modules/asura-base/FileSystem/Compressor.h28
-rw-r--r--Source/modules/asura-base/FileSystem/DataBuffer.cpp156
-rw-r--r--Source/modules/asura-base/FileSystem/DataBuffer.h87
-rw-r--r--Source/modules/asura-base/FileSystem/DecodedData.h41
-rw-r--r--Source/modules/asura-base/FileSystem/File.cpp294
-rw-r--r--Source/modules/asura-base/FileSystem/File.h146
-rw-r--r--Source/modules/asura-base/FileSystem/FileData.cpp59
-rw-r--r--Source/modules/asura-base/FileSystem/FileData.h69
-rw-r--r--Source/modules/asura-base/FileSystem/FileManager.cpp198
-rw-r--r--Source/modules/asura-base/FileSystem/FileManager.h112
-rw-r--r--Source/modules/asura-base/FileSystem/IOBatchTask.cpp0
-rw-r--r--Source/modules/asura-base/FileSystem/IOBatchTask.h31
-rw-r--r--Source/modules/asura-base/FileSystem/IOTask.cpp61
-rw-r--r--Source/modules/asura-base/FileSystem/IOTask.h56
-rw-r--r--Source/modules/asura-base/FileSystem/Renewable.h27
-rw-r--r--Source/modules/asura-base/Manager.hpp14
-rw-r--r--Source/modules/asura-base/Math/Curve.cpp0
-rw-r--r--Source/modules/asura-base/Math/Curve.h0
-rw-r--r--Source/modules/asura-base/Math/Functions.cpp0
-rw-r--r--Source/modules/asura-base/Math/Functions.h0
-rw-r--r--Source/modules/asura-base/Math/Matrix44.cpp217
-rw-r--r--Source/modules/asura-base/Math/Matrix44.h96
-rw-r--r--Source/modules/asura-base/Math/Quaternion.cpp0
-rw-r--r--Source/modules/asura-base/Math/Quaternion.h18
-rw-r--r--Source/modules/asura-base/Math/Random.h88
-rw-r--r--Source/modules/asura-base/Math/RangedValue.cpp0
-rw-r--r--Source/modules/asura-base/Math/RangedValue.h0
-rw-r--r--Source/modules/asura-base/Math/Rect.hpp50
-rw-r--r--Source/modules/asura-base/Math/Rect.inc28
-rw-r--r--Source/modules/asura-base/Math/Transform.cpp0
-rw-r--r--Source/modules/asura-base/Math/Transform.h30
-rw-r--r--Source/modules/asura-base/Math/Vector2.hpp72
-rw-r--r--Source/modules/asura-base/Math/Vector2.inc114
-rw-r--r--Source/modules/asura-base/Math/Vector3.hpp235
-rw-r--r--Source/modules/asura-base/Math/Vector3.inc145
-rw-r--r--Source/modules/asura-base/Math/Vector4.h234
-rw-r--r--Source/modules/asura-base/Math/Vector4.inc152
-rw-r--r--Source/modules/asura-base/Module.h32
-rw-r--r--Source/modules/asura-base/Scripting/Scripting.h30
-rw-r--r--Source/modules/asura-base/Singleton.hpp59
-rw-r--r--Source/modules/asura-base/Threads/Conditional.cpp84
-rw-r--r--Source/modules/asura-base/Threads/Conditional.h41
-rw-r--r--Source/modules/asura-base/Threads/Coroutine.cpp15
-rw-r--r--Source/modules/asura-base/Threads/Coroutine.h40
-rw-r--r--Source/modules/asura-base/Threads/Mutex.cpp105
-rw-r--r--Source/modules/asura-base/Threads/Mutex.h128
-rw-r--r--Source/modules/asura-base/Threads/Semaphore.cpp99
-rw-r--r--Source/modules/asura-base/Threads/Semaphore.h68
-rw-r--r--Source/modules/asura-base/Threads/Task.cpp10
-rw-r--r--Source/modules/asura-base/Threads/Task.h43
-rw-r--r--Source/modules/asura-base/Threads/Thread.cpp287
-rw-r--r--Source/modules/asura-base/Threads/Thread.h222
-rw-r--r--Source/modules/asura-base/Threads/ThreadImplPosix.cpp0
-rw-r--r--Source/modules/asura-base/Threads/ThreadImplPosix.h2
-rw-r--r--Source/modules/asura-base/Threads/ThreadImplSDL.cpp0
-rw-r--r--Source/modules/asura-base/Threads/ThreadImplSDL.h0
-rw-r--r--Source/modules/asura-base/Threads/ThreadImplStd.cpp0
-rw-r--r--Source/modules/asura-base/Threads/ThreadImplStd.h41
-rw-r--r--Source/modules/asura-base/Threads/ThreadImplWin32.cpp77
-rw-r--r--Source/modules/asura-base/Threads/ThreadImplWin32.h44
-rw-r--r--Source/modules/asura-base/Threads/Threadable.h23
-rw-r--r--Source/modules/asura-base/Threads/binding/_coroutine.cpp38
-rw-r--r--Source/modules/asura-base/Threads/binding/_thread.cpp208
-rw-r--r--Source/modules/asura-base/Type.h37
-rw-r--r--Source/modules/asura-base/Utilities/Hash128.cpp0
-rw-r--r--Source/modules/asura-base/Utilities/Hash128.h0
-rw-r--r--Source/modules/asura-base/Utilities/LinkedList.cpp0
-rw-r--r--Source/modules/asura-base/Utilities/LinkedList.h0
-rw-r--r--Source/modules/asura-base/Utilities/StringMap.cpp0
-rw-r--r--Source/modules/asura-base/Utilities/StringMap.hpp29
-rw-r--r--Source/modules/asura-base/Utilities/dynamic_bitset.h1150
-rw-r--r--Source/modules/asura-base/Utils.h6
-rw-r--r--Source/modules/asura-base/UtilsConfig.h13
-rw-r--r--Source/modules/asura-base/UtilsModule.cpp25
-rw-r--r--Source/modules/asura-base/UtilsModule.h34
87 files changed, 6730 insertions, 0 deletions
diff --git a/Source/modules/asura-base/BuildConfigure.h b/Source/modules/asura-base/BuildConfigure.h
new file mode 100644
index 0000000..6fd3aad
--- /dev/null
+++ b/Source/modules/asura-base/BuildConfigure.h
@@ -0,0 +1,8 @@
+// Copy to asura-configure folder
+
+#ifndef _ASURA_EDITOR_CONFIGURE_H_
+#define _ASURA_EDITOR_CONFIGURE_H_
+
+#define ASURA_EDITOR 1
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-base/Classes.h b/Source/modules/asura-base/Classes.h
new file mode 100644
index 0000000..b2700f0
--- /dev/null
+++ b/Source/modules/asura-base/Classes.h
@@ -0,0 +1,9 @@
+#ifndef _ASURAENGINE_CLASSES_H_
+#define _ASURAENGINE_CLASSES_H_
+
+#define GET_SET(TYPE,PROP_NAME,VAR_NAME) void Set##PROP_NAME (TYPE val) { VAR_NAME = val; } TYPE Get##PROP_NAME () {return VAR_NAME; }
+
+#define namespace_begin(NAMESPACE) namespace NAMESPACE {
+#define namespace_end }
+
+#endif
diff --git a/Source/modules/asura-base/Configure.h b/Source/modules/asura-base/Configure.h
new file mode 100644
index 0000000..07926d0
--- /dev/null
+++ b/Source/modules/asura-base/Configure.h
@@ -0,0 +1,58 @@
+#ifndef _ASURA_BASE_CONFIG_H_
+#define _ASURA_BASE_CONFIG_H_
+
+#include "BuildConfigure.h"
+
+#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_EXPORT __declspec(dllexport)
+ #define ASURA_IMPORT __declspec(dllimport)
+ #define ASURA_FORCE_INLINE __forceinline
+ #define ASURA_RESTRICT __restrict
+ #define ASURA_API ASURA_EXPORT
+ #define ASURA_ATTRIBUTE_USED
+ #define ASURA_ABSTRACT
+ #define ASURA_WINDOWS 1
+#else
+ #define ASURA_FINAL final
+ #define ASURA_EXPORT __attribute__((visibility("default")))
+ #define ASURA_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_EXPORT
+#endif
+
+///
+/// ƶָȨ
+///
+#define ASURA_MOVE
+
+#define ASURA_DEBUG 0
+
+#define ASURA_SDL_HOST 1
+
+#define ASURA_LITTLE_ENDIAN 1
+
+// չؼ
+
+#define ASURA_THROW(ex) throw(ex) // ʾ׳쳣
+
+#define ASURA_OUT
+#define ASURA_REF
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-base/Exception.cpp b/Source/modules/asura-base/Exception.cpp
new file mode 100644
index 0000000..5240c49
--- /dev/null
+++ b/Source/modules/asura-base/Exception.cpp
@@ -0,0 +1,40 @@
+#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);
+
+ 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;
+ else
+ break;
+
+ delete[] buffer;
+ }
+ message = std::string(buffer);
+ delete[] buffer;
+ }
+
+ Exception::~Exception() throw()
+ {
+ }
+
+}
diff --git a/Source/modules/asura-base/Exception.h b/Source/modules/asura-base/Exception.h
new file mode 100644
index 0000000..73c0861
--- /dev/null
+++ b/Source/modules/asura-base/Exception.h
@@ -0,0 +1,30 @@
+#ifndef _ASURA_ENGINE_EXCEPTION_H_
+#define _ASURA_ENGINE_EXCEPTION_H_
+
+#include <string>
+#include <exception>
+
+namespace AsuraEngine
+{
+
+class Exception : public std::exception
+{
+public:
+
+ Exception(const char *fmt, ...);
+ virtual ~Exception() throw();
+
+ 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/modules/asura-base/FileSystem/Binding/_compressor.cpp b/Source/modules/asura-base/FileSystem/Binding/_compressor.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-base/FileSystem/Binding/_compressor.cpp
diff --git a/Source/modules/asura-base/FileSystem/Binding/_data_buffer.cpp b/Source/modules/asura-base/FileSystem/Binding/_data_buffer.cpp
new file mode 100644
index 0000000..ff1f0dc
--- /dev/null
+++ b/Source/modules/asura-base/FileSystem/Binding/_data_buffer.cpp
@@ -0,0 +1,132 @@
+#include "../DataBuffer.h"
+
+using namespace Luax;
+
+namespace AsuraEngine
+{
+ namespace FileSystem
+ {
+
+ LUAX_REGISTRY(DataBuffer)
+ {
+ LUAX_REGISTER_METHODS(state,
+ { "New", _New },
+ { "GetData", _GetData },
+ { "GetSize", _GetSize },
+ { "GetCapacity", _GetCapacity },
+ { "Refactor", _Refactor },
+ { "Load", _Load },
+ { "Clear", _Clear }
+ );
+ }
+
+ LUAX_POSTPROCESS(DataBuffer)
+ {
+ }
+
+ // databuffer = DataBuffer.New(lstring)
+ // databuffer = DataBuffer.New(capacity)
+ 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 capacity = lua_tonumber(L, 1);
+ DataBuffer* buffer = new DataBuffer(capacity);
+ 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;
+ }
+
+ // capacity = databuffer:GetCapacity()
+ LUAX_IMPL_METHOD(DataBuffer, _GetCapacity)
+ {
+ LUAX_SETUP(L, "U");
+
+ DataBuffer* self = state.GetUserdata<DataBuffer>(1);
+ lua_pushinteger(L, self->GetCapacity());
+ return 1;
+ }
+
+ // databuffer:Refactor(capacity)
+ LUAX_IMPL_METHOD(DataBuffer, _Refactor)
+ {
+ LUAX_PREPARE(L, DataBuffer);
+
+ size_t capacity = state.CheckValue<int>(2);
+ self->Refactor(capacity);
+ 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);
+ buffer->Load(data, size);
+ return 0;
+ }
+ else if(state.IsType(2, LUA_TUSERDATA))
+ {
+ DataBuffer* src = state.CheckUserdata<DataBuffer>(2);
+ buffer->Load(*src);
+ return 0;
+ }
+ 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/modules/asura-base/FileSystem/Binding/_file.cpp b/Source/modules/asura-base/FileSystem/Binding/_file.cpp
new file mode 100644
index 0000000..d19c02a
--- /dev/null
+++ b/Source/modules/asura-base/FileSystem/Binding/_file.cpp
@@ -0,0 +1,223 @@
+#include "../file.h"
+
+namespace AsuraEngine
+{
+ namespace FileSystem
+ {
+
+ 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/modules/asura-base/FileSystem/Binding/_file_data.cpp b/Source/modules/asura-base/FileSystem/Binding/_file_data.cpp
new file mode 100644
index 0000000..ca872d2
--- /dev/null
+++ b/Source/modules/asura-base/FileSystem/Binding/_file_data.cpp
@@ -0,0 +1,60 @@
+#include "../FileData.h"
+
+using namespace std;
+
+namespace AsuraEngine
+{
+ namespace FileSystem
+ {
+
+ 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->m_DataRef);
+ return 1;
+ }
+
+ }
+} \ No newline at end of file
diff --git a/Source/modules/asura-base/FileSystem/Binding/_file_manager.cpp b/Source/modules/asura-base/FileSystem/Binding/_file_manager.cpp
new file mode 100644
index 0000000..7781d99
--- /dev/null
+++ b/Source/modules/asura-base/FileSystem/Binding/_file_manager.cpp
@@ -0,0 +1,265 @@
+#include "../FileManager.h"
+
+using namespace Luax;
+
+namespace AsuraEngine
+{
+ namespace FileSystem
+ {
+
+#define PREPARE(l) \
+ LUAX_STATE(l); \
+ FileManager* fs = FileManager::Get();
+
+ LUAX_REGISTRY(FileManager)
+ {
+ 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(FileManager)
+ {
+ LUAX_REGISTER_ENUM(state, "EFileType",
+ { "FILE", FILE_TYPE_FILE },
+ { "DIRECTORY", FILE_TYPE_DIRECTORY },
+ { "SYMLINK", FILE_TYPE_SYMLINK },
+ { "OTHER", FILE_TYPE_OTHER }
+ );
+ }
+
+ // FileManager.Init(arg0)
+ LUAX_IMPL_METHOD(FileManager, _Init)
+ {
+ PREPARE(L);
+
+ const char* arg0 = state.CheckValue<const char*>(1);
+ fs->Init(arg0);
+ return 0;
+ }
+
+ // successed = FileManager.Mount(path, mountpoint[, prepend = false])
+ // successed = FileManager.Mount(data buffer, archievename, mountpoint[, prepend = false])
+ LUAX_IMPL_METHOD(FileManager, _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 = FileManager.Unmount(path)
+ // successed = FileManager.Unmount(data buffer)
+ LUAX_IMPL_METHOD(FileManager, _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 = FileManager.GetMountPoint(path)
+ LUAX_IMPL_METHOD(FileManager, _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;
+ }
+
+ // FileManager.SetWriteDirectory(dir)
+ LUAX_IMPL_METHOD(FileManager, _SetWriteDirectory)
+ {
+ PREPARE(L);
+
+ cc8* dir = state.CheckValue<cc8*>(1);
+ fs->SetWriteDirectory(dir);
+ return 0;
+ }
+
+ // dir = FileManager.GetWriteDirectory()
+ LUAX_IMPL_METHOD(FileManager, _GetWriteDirectory)
+ {
+ PREPARE(L);
+
+ std::string dir = fs->GetWriteDirectory();
+ state.Push(dir);
+ return 1;
+ }
+
+ // file = FileManager.CreateFile(name)
+ LUAX_IMPL_METHOD(FileManager, _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 = FileManager.CreateDirectory(name)
+ LUAX_IMPL_METHOD(FileManager, _CreateDirectory)
+ {
+ PREPARE(L);
+
+ cc8* path = state.CheckValue<cc8*>(1);
+ state.Push(fs->NewDirectory(path));
+ return 1;
+ }
+
+ // successed = FileManager.Write(path, data buffer)
+ LUAX_IMPL_METHOD(FileManager, _Write)
+ {
+ PREPARE(L);
+
+ cc8* path = state.CheckValue<cc8*>(1);
+ DataBuffer* db = state.CheckUserdata<DataBuffer>(2);
+ state.Push(fs->Write(path, db));
+ return 1;
+ }
+
+ // successed = FileManager.Append(path, data buffer)
+ LUAX_IMPL_METHOD(FileManager, _Append)
+ {
+ PREPARE(L);
+
+ cc8* path = state.CheckValue<cc8*>(1);
+ DataBuffer* db = state.CheckUserdata<DataBuffer>(2);
+ state.Push(fs->Append(path, db));
+ return 1;
+ }
+
+ // successed = FileManager.Remove(path)
+ LUAX_IMPL_METHOD(FileManager, _Remove)
+ {
+ PREPARE(L);
+
+ cc8* path = state.CheckValue<cc8*>(1);
+ state.Push(fs->Remove(path));
+ return 1;
+ }
+
+ // filedata = FileManager.Read(path)
+ LUAX_IMPL_METHOD(FileManager, _Read)
+ {
+ PREPARE(L);
+
+ cc8* path = state.CheckValue<cc8*>(1);
+ FileData* fd = fs->Read(path);
+ if (fd)
+ {
+ fd->m_Data->PushLuaxUserdata(state);
+ fd->SetLuaxMemberRef(state, fd->m_DataRef, -1); // fd->m_DataRef = data buffer
+ state.Pop(1); // data buffer
+ fd->PushLuaxUserdata(state);
+ }
+ else
+ {
+ state.PushNil();
+ }
+ return 1;
+ }
+
+ // fileinfo = FileManager.GetFileInfo(path)
+ LUAX_IMPL_METHOD(FileManager, _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 = FileManager.GetDirectoryItems(path)
+ LUAX_IMPL_METHOD(FileManager, _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/modules/asura-base/FileSystem/Binding/_io_task.cpp b/Source/modules/asura-base/FileSystem/Binding/_io_task.cpp
new file mode 100644
index 0000000..a3d82d5
--- /dev/null
+++ b/Source/modules/asura-base/FileSystem/Binding/_io_task.cpp
@@ -0,0 +1,46 @@
+#include "../IOTask.h"
+
+using namespace std;
+
+namespace AsuraEngine
+{
+ namespace FileSystem
+ {
+
+ 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->m_BufferRef, 2);
+ if(cbk)
+ task->SetLuaxMemberRef(state, task->m_Callback, 4);
+ task->PushLuaxUserdata(state);
+ return 1;
+ }
+
+ }
+}
diff --git a/Source/modules/asura-base/FileSystem/Compressor.cpp b/Source/modules/asura-base/FileSystem/Compressor.cpp
new file mode 100644
index 0000000..eaa59a2
--- /dev/null
+++ b/Source/modules/asura-base/FileSystem/Compressor.cpp
@@ -0,0 +1,11 @@
+#include "Compressor.h"
+
+namespace AsuraEngine
+{
+ namespace FileSystem
+ {
+
+
+
+ }
+} \ No newline at end of file
diff --git a/Source/modules/asura-base/FileSystem/Compressor.h b/Source/modules/asura-base/FileSystem/Compressor.h
new file mode 100644
index 0000000..9fd0808
--- /dev/null
+++ b/Source/modules/asura-base/FileSystem/Compressor.h
@@ -0,0 +1,28 @@
+#ifndef _ASURA_COMPRESSOR_H_
+#define _ASURA_COMPRESSOR_H_
+
+#include "../Scripting/Scripting.h"
+
+namespace AsuraEngine
+{
+ namespace FileSystem
+ {
+
+ 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/modules/asura-base/FileSystem/DataBuffer.cpp b/Source/modules/asura-base/FileSystem/DataBuffer.cpp
new file mode 100644
index 0000000..71431e1
--- /dev/null
+++ b/Source/modules/asura-base/FileSystem/DataBuffer.cpp
@@ -0,0 +1,156 @@
+#include <cstdlib>
+#include <cstring>
+#include "DataBuffer.h"
+
+using namespace AEThreading;
+
+namespace AsuraEngine
+{
+ namespace FileSystem
+ {
+
+ DataBuffer::DataBuffer(DataBuffer& src)
+ : m_Size(0)
+ , m_Capacity(0)
+ , m_Bytes(nullptr)
+ {
+ // ʼ
+ lock(m_Mutex)
+ {
+ m_Capacity = src.m_Size;
+ m_Bytes = new byte[m_Capacity];
+ Clear();
+
+ Load(src);
+ }
+ }
+
+ DataBuffer::DataBuffer(std::size_t capacity)
+ : m_Size(0)
+ , m_Capacity(0)
+ , m_Bytes(nullptr)
+ {
+ lock(m_Mutex)
+ {
+ m_Capacity = capacity;
+ m_Bytes = new byte[m_Capacity];
+ Clear();
+ }
+ }
+
+ DataBuffer::DataBuffer(const void* data, std::size_t size)
+ : m_Capacity(0)
+ , m_Size(0)
+ , m_Bytes(nullptr)
+ {
+ lock(m_Mutex)
+ {
+ m_Capacity = size;
+ m_Bytes = new byte[m_Capacity];
+ Clear();
+
+ Load(data, size);
+ }
+ }
+
+ DataBuffer::~DataBuffer()
+ {
+ lock(m_Mutex)
+ {
+ delete[] m_Bytes;
+ }
+ }
+
+ void DataBuffer::Refactor(size_t capacity)
+ {
+ lock(m_Mutex)
+ {
+ if (!m_Bytes || m_Capacity != capacity)
+ {
+ if(m_Bytes)
+ delete[] m_Bytes;
+ m_Capacity = capacity;
+ m_Bytes = new byte[m_Capacity];
+ m_Size = 0;
+ }
+ Clear();
+ }
+ }
+
+ void DataBuffer::Load(DataBuffer& db)
+ {
+ lock(m_Mutex)
+ {
+ Load(db.GetData(), db.GetSize());
+ }
+ }
+
+ void DataBuffer::Load(const void* data, std::size_t size)
+ {
+ lock(m_Mutex)
+ {
+ ASSERT(m_Capacity >= size);
+ memcpy(m_Bytes, data, size);
+ m_Size = size;
+ }
+ }
+
+ void DataBuffer::Move(void* bytes, std::size_t size)
+ {
+ lock(m_Mutex)
+ {
+ if (m_Bytes == bytes)
+ {
+ // sizeֵڶļʱ
+ m_Size = size;
+ }
+ else
+ {
+ if (m_Bytes)
+ delete[] m_Bytes;
+ m_Bytes = (byte*)bytes;
+ m_Size = size;
+ m_Capacity = size;
+ }
+ }
+ }
+
+ byte* DataBuffer::GetData()
+ {
+ return m_Bytes;
+ }
+
+ void DataBuffer::Clear()
+ {
+ lock(m_Mutex)
+ {
+ if (m_Bytes)
+ {
+ memset(m_Bytes, 0, m_Size);
+ m_Size = 0;
+ }
+ }
+ }
+
+ std::size_t DataBuffer::GetSize()
+ {
+ return m_Size;
+ }
+
+ std::size_t DataBuffer::GetCapacity()
+ {
+ return m_Capacity;
+ }
+
+ void DataBuffer::Lock()
+ {
+ m_Mutex.Lock();
+ }
+
+ void DataBuffer::Unlock()
+ {
+ m_Mutex.Unlock();
+ }
+
+ }
+} \ No newline at end of file
diff --git a/Source/modules/asura-base/FileSystem/DataBuffer.h b/Source/modules/asura-base/FileSystem/DataBuffer.h
new file mode 100644
index 0000000..ace372e
--- /dev/null
+++ b/Source/modules/asura-base/FileSystem/DataBuffer.h
@@ -0,0 +1,87 @@
+#ifndef _ASURA_ENGINE_DATABUFFER_H_
+#define _ASURA_ENGINE_DATABUFFER_H_
+
+#include <cstdlib>
+
+#include "../Scripting/Scripting.h"
+#include "../Threads/Mutex.h"
+
+namespace AsuraEngine
+{
+ namespace FileSystem
+ {
+
+ ///
+ /// ڴݵķװеʹ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 capacity);
+ DataBuffer(const void* bytes, std::size_t size);
+ ~DataBuffer();
+
+ byte* GetData();
+ size_t GetSize();
+ size_t GetCapacity();
+
+ ///
+ /// ޸
+ ///
+ void Refactor(size_t capacity);
+
+ ///
+ /// Դ˻
+ ///
+ void Load(DataBuffer& db);
+ void Load(const void* bytes, std::size_t size);
+
+ ///
+ /// bytesӵȨcapacityΪsize
+ ///
+ void Move(void* bytes, std::size_t size);
+
+ ///
+ ///
+ ///
+ void Clear();
+
+ void Lock();
+ void Unlock();
+
+ private:
+
+ LUAX_DECL_METHOD(_New);
+ LUAX_DECL_METHOD(_GetData);
+ LUAX_DECL_METHOD(_GetSize);
+ LUAX_DECL_METHOD(_GetCapacity);
+ LUAX_DECL_METHOD(_Refactor);
+ LUAX_DECL_METHOD(_Load);
+ LUAX_DECL_METHOD(_Clear);
+
+ ///
+ /// Buffer׵ַݵij
+ ///
+ byte* m_Bytes;
+ size_t m_Size;
+
+ ///
+ /// Buffer
+ ///
+ size_t m_Capacity;
+
+ AEThreading::Mutex m_Mutex;
+
+ };
+
+ }
+}
+
+namespace AEFileSystem = AsuraEngine::FileSystem;
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-base/FileSystem/DecodedData.h b/Source/modules/asura-base/FileSystem/DecodedData.h
new file mode 100644
index 0000000..1744233
--- /dev/null
+++ b/Source/modules/asura-base/FileSystem/DecodedData.h
@@ -0,0 +1,41 @@
+#ifndef _ASURA_ENGINE_DATA_H_
+#define _ASURA_ENGINE_DATA_H_
+
+#include <cstdlib>
+
+#include <asura-base/Threads/Thread.h>
+
+#include "../Scripting/Scripting.h"
+
+#include "DataBuffer.h"
+
+namespace AsuraEngine
+{
+ namespace FileSystem
+ {
+
+ ///
+ /// һ̹߳data̳дࡣͼƬݡƵݵȣһ߳нԭ
+ /// ļڲݸʽصȡ
+ ///
+ ASURA_ABSTRACT class DecodedData
+ {
+ public:
+
+ ///
+ /// ڴйdataԷһ߳棬Դϵͳء
+ ///
+ DecodedData() {};
+ virtual ~DecodedData() {};
+
+ ///
+ /// ڴеݲijָʽ档
+ ///
+ virtual void Decode(DataBuffer& buffer) = 0;
+
+ };
+
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-base/FileSystem/File.cpp b/Source/modules/asura-base/FileSystem/File.cpp
new file mode 100644
index 0000000..ec8a9bf
--- /dev/null
+++ b/Source/modules/asura-base/FileSystem/File.cpp
@@ -0,0 +1,294 @@
+#include <physfs/physfs.h>
+
+#include <asura-base/Exception.h>
+
+#include "File.h"
+
+namespace AsuraEngine
+{
+ namespace FileSystem
+ {
+
+ File::File(const std::string& filename)
+ : m_FileName(filename)
+ , m_FileHandle(nullptr)
+ , m_Mode(FILE_MODE_CLOSED)
+ , m_BufferMode(BUFFER_MODE_NONE)
+ , m_BufferSize(0)
+ {
+ size_t dot = filename.rfind('.');
+ if (dot != std::string::npos)
+ {
+ m_Extension = filename.substr(dot + 1);
+ m_Name = filename.substr(0, dot);
+ }
+ else
+ m_Name = filename;
+ }
+
+ File::~File()
+ {
+ if (m_Mode != 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(m_FileName.c_str()))
+ throw Exception("Could NOT open file %s. Does not exist.", m_FileName.c_str());
+
+ if (mode == FILE_MODE_APPEND || mode == FILE_MODE_WRITE)
+ {
+ if (!PHYSFS_getWriteDir())
+ {
+ throw Exception("Could NOT set write directory.");
+ }
+ }
+
+ // Ѿ֮ǰ򿪹Ͳٴµhandle
+ if (m_FileHandle != nullptr)
+ return true;
+
+ PHYSFS_getLastErrorCode();
+
+ PHYSFS_File* handle = nullptr;
+
+ switch (mode)
+ {
+ case FILE_MODE_READ:
+ handle = PHYSFS_openRead(m_FileName.c_str());
+ break;
+ case FILE_MODE_APPEND:
+ handle = PHYSFS_openAppend(m_FileName.c_str());
+ break;
+ case FILE_MODE_WRITE:
+ handle = PHYSFS_openWrite(m_FileName.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)", m_FileName.c_str(), err);
+ }
+
+ m_FileHandle = handle;
+ m_Mode = mode;
+
+ if (m_FileHandle && !SetBuffer(m_BufferMode,m_BufferSize))
+ {
+ m_BufferMode = BUFFER_MODE_NONE;
+ m_BufferSize = 0;
+ }
+
+ return m_FileHandle != nullptr;
+ }
+
+ bool File::Close()
+ {
+ if (m_FileHandle == nullptr || !PHYSFS_close(m_FileHandle))
+ return false;
+ m_Mode = FILE_MODE_CLOSED;
+ m_FileHandle = nullptr;
+ return true;
+ }
+
+ bool File::IsOpen()
+ {
+ return m_Mode != FILE_MODE_CLOSED && m_FileHandle != nullptr;
+ }
+
+ size_t File::GetSize()
+ {
+ if (m_FileHandle == nullptr)
+ {
+ Open(FILE_MODE_READ);
+ size_t size = PHYSFS_fileLength(m_FileHandle);
+ Close();
+ return size;
+ }
+ return PHYSFS_fileLength(m_FileHandle);
+ }
+
+ size_t File::Read(ASURA_OUT DataBuffer* dst, size_t length)
+ {
+ ASSERT(dst);
+
+ if (dst->GetCapacity() < length)
+ throw Exception("Data buffer is too small compares to read length.");
+
+ if (!m_FileHandle || m_Mode != FILE_MODE_READ)
+ throw Exception("File \"%s\" is not opened for reading", m_FileName);
+
+ size_t max = PHYSFS_fileLength(m_FileHandle);
+ length = (length > max) ? max : length;
+
+ if (length < 0)
+ throw Exception("Invalid read size.");
+
+ dst->Lock();
+ size_t size = PHYSFS_readBytes(m_FileHandle, dst->GetData(), length);
+ dst->Unlock();
+ return size;
+ }
+
+ size_t File::ReadAll(ASURA_OUT DataBuffer* dst)
+ {
+ ASSERT(dst);
+
+ if (!m_FileHandle || m_Mode != FILE_MODE_READ)
+ throw Exception("File \"%s\" is not opened for reading", m_FileName);
+
+ size_t length = PHYSFS_fileLength(m_FileHandle);
+
+ if (dst->GetCapacity() < length)
+ throw Exception("Data buffer is too small compares to file length.");
+
+ dst->Lock();
+ byte* data = dst->GetData();
+ size_t size = PHYSFS_readBytes(m_FileHandle, data, length);
+ dst->Move(data, 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 m_FileHandle == nullptr || test_eof(this, m_FileHandle);
+ }
+
+ size_t File::Tell()
+ {
+ if (!m_FileHandle)
+ return - 1;
+
+ return PHYSFS_tell(m_FileHandle);
+ }
+
+ bool File::Seek(size_t pos)
+ {
+ return m_FileHandle != nullptr && PHYSFS_seek(m_FileHandle, pos) != 0;
+ }
+
+ bool File::Write(ASURA_REF DataBuffer* src)
+ {
+ if (!m_FileHandle || (m_Mode != FILE_MODE_APPEND && m_Mode != 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(m_FileHandle, data, size);
+
+ if (written != src->GetSize())
+ return false;
+
+ // л
+ if (m_BufferSize == BUFFER_MODE_LINE && m_BufferSize > size)
+ {
+ if (memchr(data, '\n', size) != nullptr)
+ Flush();
+ }
+
+ return true;
+ }
+
+ bool File::Flush()
+ {
+ if (!m_FileHandle || (m_Mode != FILE_MODE_WRITE && m_Mode != FILE_MODE_APPEND))
+ throw Exception("File is not opened for writing.");
+
+ return PHYSFS_flush(m_FileHandle) != 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())
+ {
+ m_BufferMode = mode;
+ m_BufferSize = size;
+ return true;
+ }
+
+ int ret = 1;
+
+ switch (mode)
+ {
+ case BUFFER_MODE_NONE:
+ default:
+ ret = PHYSFS_setBuffer(m_FileHandle, 0);
+ size = 0;
+ break;
+ case BUFFER_MODE_LINE:
+ case BUFFER_MODE_FULL:
+ ret = PHYSFS_setBuffer(m_FileHandle, size);
+ break;
+ }
+
+ if (ret == 0)
+ return false;
+
+ m_BufferMode = mode;
+ m_BufferSize = size;
+
+ return true;
+ }
+
+ File::BufferMode File::GetBuffer(ASURA_OUT size_t& size)
+ {
+ size = m_BufferSize;
+ return m_BufferMode;
+ }
+
+ const std::string& File::GetFileName()
+ {
+ return m_FileName;
+ }
+
+ const std::string& File::GetName()
+ {
+ return m_Name;
+ }
+
+ const std::string& File::GetExtension()
+ {
+ return m_Extension;
+ }
+
+ File::FileMode File::GetMode()
+ {
+ return m_Mode;
+ }
+
+ }
+} \ No newline at end of file
diff --git a/Source/modules/asura-base/FileSystem/File.h b/Source/modules/asura-base/FileSystem/File.h
new file mode 100644
index 0000000..be772e0
--- /dev/null
+++ b/Source/modules/asura-base/FileSystem/File.h
@@ -0,0 +1,146 @@
+#ifndef _ASURA_ENGINE_FILE_H_
+#define _ASURA_ENGINE_FILE_H_
+
+#include "physfs/physfs.h"
+
+#include "../Scripting/Scripting.h"
+#include "../Threads/Thread.h"
+
+#include "FileData.h"
+
+namespace AsuraEngine
+{
+ namespace FileSystem
+ {
+
+ ///
+ /// ʽļָд㡢Сʹȡʱʹñ࣬ʹ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* m_FileHandle; ///< physfs ļ
+ std::string m_FileName; ///< ļ
+ std::string m_Extension; ///< չ
+ std::string m_Name; ///< չļ
+ FileMode m_Mode; ///< ļģʽ
+ BufferMode m_BufferMode; ///< д뻺ģʽ
+ size_t m_BufferSize; ///< д뻺С
+
+ 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/modules/asura-base/FileSystem/FileData.cpp b/Source/modules/asura-base/FileSystem/FileData.cpp
new file mode 100644
index 0000000..b29a95b
--- /dev/null
+++ b/Source/modules/asura-base/FileSystem/FileData.cpp
@@ -0,0 +1,59 @@
+#include "FileData.h"
+
+namespace AsuraEngine
+{
+ namespace FileSystem
+ {
+
+ FileData::FileData(const std::string& filename)
+ : m_Data(nullptr)
+ , m_FileName(filename)
+ {
+ size_t dot = filename.rfind('.');
+ if (dot != std::string::npos)
+ {
+ m_Extension = filename.substr(dot + 1);
+ m_Name = filename.substr(0, dot);
+ }
+ else
+ m_Name = filename;
+ }
+
+ FileData::~FileData()
+ {
+ if (m_Data)
+ m_Data->Release();
+ }
+
+ const std::string& FileData::GetFileName()
+ {
+ return m_FileName;
+ }
+
+ const std::string& FileData::GetExtension()
+ {
+ return m_Extension;
+ }
+
+ const std::string& FileData::GetName()
+ {
+ return m_Name;
+ }
+
+ void FileData::BindData(ASURA_MOVE DataBuffer* buffer)
+ {
+ if (!buffer)
+ return;
+ if (m_Data)
+ m_Data->Release();
+ m_Data = buffer;
+ m_Data->Retain();
+ }
+
+ DataBuffer* FileData::GetDataBuffer()
+ {
+ return m_Data;
+ }
+
+ }
+} \ No newline at end of file
diff --git a/Source/modules/asura-base/FileSystem/FileData.h b/Source/modules/asura-base/FileSystem/FileData.h
new file mode 100644
index 0000000..d0acd26
--- /dev/null
+++ b/Source/modules/asura-base/FileSystem/FileData.h
@@ -0,0 +1,69 @@
+#ifndef _ASURA_ENGINE_FILE_DATA_H_
+#define _ASURA_ENGINE_FILE_DATA_H_
+
+#include <string>
+
+#include <asura-base/Scripting/Scripting.h>
+
+#include "DataBuffer.h"
+
+namespace AsuraEngine
+{
+ namespace FileSystem
+ {
+
+ 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 FileManager;
+
+ FileData(const std::string& name);
+
+ ///
+ /// data buffer
+ ///
+ void BindData(ASURA_MOVE DataBuffer* buffer);
+
+ ///
+ /// Data bufferfiledataʱ٣luaüΪ0ʱluaGC١mDataʱһԱá
+ ///
+ ASURA_REF DataBuffer* m_Data;
+ Luax::LuaxMemberRef m_DataRef;
+
+ std::string m_FileName; ///< չļ
+ std::string m_Extension; ///< չ
+ std::string m_Name; ///< ͺ׺ļ
+
+ 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/modules/asura-base/FileSystem/FileManager.cpp b/Source/modules/asura-base/FileSystem/FileManager.cpp
new file mode 100644
index 0000000..bdb4069
--- /dev/null
+++ b/Source/modules/asura-base/FileSystem/FileManager.cpp
@@ -0,0 +1,198 @@
+#include <physfs/physfs.h>
+
+#include "../Exception.h"
+
+#include "File.h"
+#include "FileData.h"
+#include "FileManager.h"
+
+using namespace std;
+
+namespace AsuraEngine
+{
+ namespace FileSystem
+ {
+
+#ifdef ASURA_WINDOWS
+ #include <windows.h>
+ #include <direct.h>
+#else
+ #include <sys/param.h>
+ #include <unistd.h>
+#endif
+
+ FileManager::~FileManager()
+ {
+ if (m_Inited) //PHYSFS_isInit
+ PHYSFS_deinit();
+ }
+
+ void FileManager::Init(const char* arg0)
+ {
+ if (!PHYSFS_init(arg0))
+ throw Exception("Failed to initialize filesystem: %s", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
+
+ m_Inited = true;
+ }
+
+ bool FileManager::Mount(const std::string& locpath, const std::string& montpoint/* = "/"*/, bool prepend /*= false*/)
+ {
+ if (!m_Inited)
+ return false;
+
+ return PHYSFS_mount(locpath.c_str(), montpoint.c_str(), !prepend);
+ }
+
+ bool FileManager::Mount(DataBuffer* db, const std::string& archivename, const std::string& mountpoint /*= "/"*/, bool prepend /*= false*/)
+ {
+ if (!m_Inited)
+ return false;
+ if (PHYSFS_mountMemory(db->GetData(), db->GetSize(), nullptr, archivename.c_str(), mountpoint.c_str(), !prepend))
+ {
+ m_MountData[archivename] = db;
+ return true;
+ }
+ return false;
+ }
+
+ bool FileManager::Unmount(const std::string& locpath)
+ {
+ if (!m_Inited)
+ return false;
+
+ // ǹ鵵ӳɾ
+ auto datait = m_MountData.find(locpath);
+ if (datait != m_MountData.end() && PHYSFS_unmount(locpath.c_str()) != 0)
+ {
+ m_MountData.erase(datait);
+ return true;
+ }
+
+ return PHYSFS_unmount(locpath.c_str());
+ }
+
+ bool FileManager::Unmount(DataBuffer* db)
+ {
+ for (const auto& dp : m_MountData)
+ {
+ if (dp.second == db)
+ {
+ std::string archive = dp.first;
+ return Unmount(archive);
+ }
+ }
+ }
+
+ bool FileManager::GetMountPoint(const std::string& locpath, ASURA_OUT std::string& mountpoint)
+ {
+ if (!m_Inited)
+ return false;
+ const char* point = PHYSFS_getMountPoint(locpath.c_str());
+ if (point != nullptr)
+ {
+ mountpoint = point;
+ return true;
+ }
+ return false;
+ }
+
+ void FileManager::SetWriteDirectory(const std::string locpath)
+ {
+ if (!m_Inited)
+ return;
+ if (!PHYSFS_setWriteDir(locpath.c_str()))
+ throw Exception("Failed to set write directory %s", locpath.c_str());
+ }
+
+ std::string FileManager::GetWriteDirectory()
+ {
+ return PHYSFS_getWriteDir();
+ }
+
+ File* FileManager::NewFile(const std::string& name)
+ {
+ return new File(name);
+ }
+
+ bool FileManager::NewDirectory(const std::string& path)
+ {
+ if (!m_Inited)
+ return false;
+ if (!PHYSFS_getWriteDir())
+ return false;
+ if (!PHYSFS_mkdir(path.c_str()))
+ return false;
+ return true;
+ }
+
+ bool FileManager::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 FileManager::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* FileManager::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 FileManager::Remove(const std::string& path)
+ {
+ if (!m_Inited)
+ return false;
+ if (PHYSFS_getWriteDir() == 0)
+ return false;
+
+ if (!PHYSFS_delete(path.c_str()))
+ return false;
+
+ return true;
+ }
+
+ bool FileManager::GetFileInfo(const std::string& filepath, ASURA_OUT FileInfo* info)
+ {
+ if (!m_Inited)
+ 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/modules/asura-base/FileSystem/FileManager.h b/Source/modules/asura-base/FileSystem/FileManager.h
new file mode 100644
index 0000000..ac97da3
--- /dev/null
+++ b/Source/modules/asura-base/FileSystem/FileManager.h
@@ -0,0 +1,112 @@
+#ifndef _ASURA_ENGINE_FILESYSTEM_H_
+#define _ASURA_ENGINE_FILESYSTEM_H_
+
+#include <map>
+#include <string>
+
+#include "../Scripting/Scripting.h"
+#include "../Singleton.hpp"
+#include "../Type.h"
+
+#include "FileData.h"
+#include "File.h"
+
+namespace AsuraEngine
+{
+ namespace FileSystem
+ {
+
+ 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µġFileManagerʱͱ༭õ࣬AssetDatabaseԴ࣬framework
+ /// ʵ֣߼дFileManagerʵ֣AssetDatabaseṩļݴӦԴķ
+ ///
+ class FileManager ASURA_FINAL
+ : public Singleton<FileManager>
+ , public AEScripting::Portable<FileManager>
+ {
+ public:
+
+ LUAX_DECL_SINGLETON(FileManager);
+
+ ~FileManager();
+
+ 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 m_Inited; ///< Ƿʼɹ
+ std::string m_Cwd; ///< ǰִļĹĿ¼
+ MountDataMap m_MountData; ///< ·ѹĵӳ
+
+ 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 AEFileSystem = AsuraEngine::FileSystem;
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-base/FileSystem/IOBatchTask.cpp b/Source/modules/asura-base/FileSystem/IOBatchTask.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-base/FileSystem/IOBatchTask.cpp
diff --git a/Source/modules/asura-base/FileSystem/IOBatchTask.h b/Source/modules/asura-base/FileSystem/IOBatchTask.h
new file mode 100644
index 0000000..8d73e93
--- /dev/null
+++ b/Source/modules/asura-base/FileSystem/IOBatchTask.h
@@ -0,0 +1,31 @@
+#ifndef _ASURA_IO_BATCH_TASK_H_
+#define _ASURA_IO_BATCH_TASK_H_
+
+#include "IOTask.h"
+
+namespace AsuraEngine
+{
+ namespace FileSystem
+ {
+
+ ///
+ /// дһύһtableδ󷵻ؽ
+ ///
+ class IOBatchTask ASURA_FINAL : public AEThreading::Task
+ {
+ public:
+
+ private:
+
+ ///
+ /// ÿһĽṹ£
+ /// { path = "", }
+ ///
+ Luax::LuaxMemberRef m_Tasks;
+
+ };
+
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-base/FileSystem/IOTask.cpp b/Source/modules/asura-base/FileSystem/IOTask.cpp
new file mode 100644
index 0000000..9152a6e
--- /dev/null
+++ b/Source/modules/asura-base/FileSystem/IOTask.cpp
@@ -0,0 +1,61 @@
+#include "FileManager.h"
+#include "IOTask.h"
+
+#include <iostream>
+
+using namespace AEScripting;
+using namespace Luax;
+
+namespace AsuraEngine
+{
+ namespace FileSystem
+ {
+
+ IOTask::IOTask(const std::string& path, DataBuffer* buffer, IOTaskType type)
+ : m_Path(path)
+ , m_Buffer(buffer)
+ {
+ if (buffer)
+ buffer->Retain();
+ }
+
+ IOTask::~IOTask()
+ {
+ if (m_Buffer)
+ m_Buffer->Release();
+ }
+
+ bool IOTask::Execute()
+ {
+ File file(m_Path);
+ if (m_Type == IOTASK_TYPE_WRITE)
+ {
+
+ }
+ // pathȡݱmBuffer
+ else if (m_Type == IOTASK_TYPE_READ)
+ {
+ if (!m_Buffer)
+ return false;
+ file.Open(File::FILE_MODE_READ);
+ file.ReadAll(m_Buffer);
+ file.Close();
+ }
+ return true;
+ }
+
+ void IOTask::Invoke(lua_State* invokeThreaad)
+ {
+ if (m_Callback)
+ {
+ LuaxScopedState state(invokeThreaad);
+ if (this->PushLuaxMemberRef(state, m_Callback))
+ {
+ this->PushLuaxMemberRef(state, m_BufferRef);
+ state.Call(1, 0);
+ }
+ }
+ }
+
+ }
+}
diff --git a/Source/modules/asura-base/FileSystem/IOTask.h b/Source/modules/asura-base/FileSystem/IOTask.h
new file mode 100644
index 0000000..da54fdc
--- /dev/null
+++ b/Source/modules/asura-base/FileSystem/IOTask.h
@@ -0,0 +1,56 @@
+#ifndef _ASURA_IO_TASK_H_
+#define _ASURA_IO_TASK_H_
+
+#include <string>
+
+#include "../Scripting/Scripting.h"
+#include "../Threads/Task.h"
+
+#include "DataBuffer.h"
+
+namespace AsuraEngine
+{
+ namespace FileSystem
+ {
+
+ enum IOTaskType
+ {
+ IOTASK_TYPE_READ,
+ IOTASK_TYPE_WRITE,
+ IOTASK_TYPE_APPEND,
+ };
+
+ ///
+ /// ȡļ
+ ///
+ class IOTask ASURA_FINAL
+ : public AEScripting::Portable<IOTask, AEThreading::Task>
+ {
+ 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 m_Path;
+ IOTaskType m_Type;
+
+ DataBuffer* m_Buffer;
+ Luax::LuaxMemberRef m_BufferRef;
+
+ };
+
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-base/FileSystem/Renewable.h b/Source/modules/asura-base/FileSystem/Renewable.h
new file mode 100644
index 0000000..ff44303
--- /dev/null
+++ b/Source/modules/asura-base/FileSystem/Renewable.h
@@ -0,0 +1,27 @@
+#ifndef __ASURA_ENGINE_RENEWABLE_H__
+#define __ASURA_ENGINE_RENEWABLE_H__
+
+#include "DecodedData.h"
+
+namespace AsuraEngine
+{
+ namespace FileSystem
+ {
+
+ ///
+ /// ¹ݽṹͼƬƵ֣ӽݿֱӹڱ༭
+ /// ¹޸handleֵı䲻߱ƻԣڲıhandleԴ
+ ///
+ ASURA_ABSTRACT class Renewable
+ {
+ public:
+ Renewable() {};
+ virtual ~Renewable() {};
+ };
+
+ }
+}
+
+namespace AEFileSystem = AsuraEngine::FileSystem;
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-base/Manager.hpp b/Source/modules/asura-base/Manager.hpp
new file mode 100644
index 0000000..c6817b1
--- /dev/null
+++ b/Source/modules/asura-base/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/modules/asura-base/Math/Curve.cpp b/Source/modules/asura-base/Math/Curve.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-base/Math/Curve.cpp
diff --git a/Source/modules/asura-base/Math/Curve.h b/Source/modules/asura-base/Math/Curve.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-base/Math/Curve.h
diff --git a/Source/modules/asura-base/Math/Functions.cpp b/Source/modules/asura-base/Math/Functions.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-base/Math/Functions.cpp
diff --git a/Source/modules/asura-base/Math/Functions.h b/Source/modules/asura-base/Math/Functions.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-base/Math/Functions.h
diff --git a/Source/modules/asura-base/Math/Matrix44.cpp b/Source/modules/asura-base/Math/Matrix44.cpp
new file mode 100644
index 0000000..9ecf448
--- /dev/null
+++ b/Source/modules/asura-base/Math/Matrix44.cpp
@@ -0,0 +1,217 @@
+#include "Matrix44.h"
+
+#include <cstring> // memcpy
+#include <cmath>
+
+namespace AsuraEngine
+{
+ namespace Math
+ {
+
+ const Matrix44 Matrix44::Identity;
+
+ // | e0 e4 e8 e12 |
+ // | e1 e5 e9 e13 |
+ // | e2 e6 e10 e14 |
+ // | e3 e7 e11 e15 |
+
+ Matrix44::Matrix44()
+ {
+ SetIdentity();
+ }
+
+ Matrix44::Matrix44(const Matrix44& m)
+ {
+ memcpy(&e, &m.e, 16 * sizeof(float));
+ }
+
+ Matrix44::~Matrix44()
+ {
+ }
+
+ void Matrix44::operator = (const Matrix44& m)
+ {
+ memcpy(&e, &m.e, 16 * sizeof(float));
+ }
+
+ void Matrix44::SetOrtho(float l, float r, float b, float t, float n, float f)
+ {
+ SetIdentity();
+ float w = r - l;
+ float h = t - b;
+ float z = f - n;
+ e[0] = 2 / w;
+ e[5] = 2 / h;
+ e[10] = -2 / z;
+ e[12] = -(r + l) / w;
+ e[13] = -(t + b) / h;
+ e[14] = -(f + n) / z;
+ e[15] = 1;
+ }
+
+ // | e0 e4 e8 e12 |
+ // | e1 e5 e9 e13 |
+ // | e2 e6 e10 e14 |
+ // | e3 e7 e11 e15 |
+ // | e0 e4 e8 e12 |
+ // | e1 e5 e9 e13 |
+ // | e2 e6 e10 e14 |
+ // | e3 e7 e11 e15 |
+
+ Matrix44 Matrix44::operator * (const Matrix44 & m) const
+ {
+ Matrix44 t;
+
+ t.e[0] = (e[0] * m.e[0]) + (e[4] * m.e[1]) + (e[8] * m.e[2]) + (e[12] * m.e[3]);
+ t.e[4] = (e[0] * m.e[4]) + (e[4] * m.e[5]) + (e[8] * m.e[6]) + (e[12] * m.e[7]);
+ t.e[8] = (e[0] * m.e[8]) + (e[4] * m.e[9]) + (e[8] * m.e[10]) + (e[12] * m.e[11]);
+ t.e[12] = (e[0] * m.e[12]) + (e[4] * m.e[13]) + (e[8] * m.e[14]) + (e[12] * m.e[15]);
+
+ t.e[1] = (e[1] * m.e[0]) + (e[5] * m.e[1]) + (e[9] * m.e[2]) + (e[13] * m.e[3]);
+ t.e[5] = (e[1] * m.e[4]) + (e[5] * m.e[5]) + (e[9] * m.e[6]) + (e[13] * m.e[7]);
+ t.e[9] = (e[1] * m.e[8]) + (e[5] * m.e[9]) + (e[9] * m.e[10]) + (e[13] * m.e[11]);
+ t.e[13] = (e[1] * m.e[12]) + (e[5] * m.e[13]) + (e[9] * m.e[14]) + (e[13] * m.e[15]);
+
+ t.e[2] = (e[2] * m.e[0]) + (e[6] * m.e[1]) + (e[10] * m.e[2]) + (e[14] * m.e[3]);
+ t.e[6] = (e[2] * m.e[4]) + (e[6] * m.e[5]) + (e[10] * m.e[6]) + (e[14] * m.e[7]);
+ t.e[10] = (e[2] * m.e[8]) + (e[6] * m.e[9]) + (e[10] * m.e[10]) + (e[14] * m.e[11]);
+ t.e[14] = (e[2] * m.e[12]) + (e[6] * m.e[13]) + (e[10] * m.e[14]) + (e[14] * m.e[15]);
+
+ t.e[3] = (e[3] * m.e[0]) + (e[7] * m.e[1]) + (e[11] * m.e[2]) + (e[15] * m.e[3]);
+ t.e[7] = (e[3] * m.e[4]) + (e[7] * m.e[5]) + (e[11] * m.e[6]) + (e[15] * m.e[7]);
+ t.e[11] = (e[3] * m.e[8]) + (e[7] * m.e[9]) + (e[11] * m.e[10]) + (e[15] * m.e[11]);
+ t.e[15] = (e[3] * m.e[12]) + (e[7] * m.e[13]) + (e[11] * m.e[14]) + (e[15] * m.e[15]);
+
+ return t;
+ }
+
+ void Matrix44::operator *= (const Matrix44 & m)
+ {
+ Matrix44 t = (*this) * m;
+ memcpy((void*)this->e, (void*)t.e, sizeof(float) * 16);
+ }
+
+ const float * Matrix44::GetElements() const
+ {
+ return e;
+ }
+
+ void Matrix44::SetIdentity()
+ {
+ memset(e, 0, sizeof(float) * 16);
+ e[0] = e[5] = e[10] = e[15] = 1;
+ }
+
+ void Matrix44::SetTranslation(float x, float y)
+ {
+ SetIdentity();
+ e[12] = x;
+ e[13] = y;
+ }
+
+ void Matrix44::SetRotation(float rad)
+ {
+ SetIdentity();
+ float c = cos(rad), s = sin(rad);
+ e[0] = c; e[4] = -s;
+ e[1] = s; e[5] = c;
+ }
+
+ void Matrix44::SetScale(float sx, float sy)
+ {
+ SetIdentity();
+ e[0] = sx;
+ e[5] = sy;
+ }
+
+ void Matrix44::SetShear(float kx, float ky)
+ {
+ SetIdentity();
+ e[1] = ky;
+ e[4] = kx;
+ }
+
+ void Matrix44::SetTransformation(float x, float y, float angle, float sx, float sy, float ox, float oy)
+ {
+ memset(e, 0, sizeof(float) * 16); // zero out matrix
+ float c = cos(angle), s = sin(angle);
+ // matrix multiplication carried out on paper:
+ // |1 x| |c -s | |sx | |1 -ox|
+ // | 1 y| |s c | | sy | | 1 -oy|
+ // | 1 | | 1 | | 1 | | 1 |
+ // | 1| | 1| | 1| | 1 |
+ // move rotate scale origin
+ e[10] = e[15] = 1.0f;
+ e[0] = c * sx; // = a
+ e[1] = s * sx; // = b
+ e[4] = -s * sy; // = c
+ e[5] = c * sy; // = d
+ e[12] = x - ox * e[0] - oy * e[4];
+ e[13] = y - ox * e[1] - oy * e[5];
+ }
+
+ void Matrix44::Translate(float x, float y)
+ {
+ Matrix44 t;
+ t.SetTranslation(x, y);
+ this->operator *=(t);
+ }
+
+ void Matrix44::Rotate(float rad)
+ {
+ Matrix44 t;
+ t.SetRotation(rad);
+ this->operator *=(t);
+ }
+
+ void Matrix44::Scale(float sx, float sy)
+ {
+ Matrix44 t;
+ t.SetScale(sx, sy);
+ this->operator *=(t);
+ }
+
+ void Matrix44::Shear(float kx, float ky)
+ {
+ Matrix44 t;
+ t.SetShear(kx, ky);
+ this->operator *=(t);
+ }
+
+ void Matrix44::Transform(float x, float y, float angle, float sx, float sy, float ox, float oy)
+ {
+ Matrix44 t;
+ t.SetTransformation(x, y, angle, sx, sy, ox, oy);
+ this->operator *=(t);
+ }
+
+ void Matrix44::Ortho(float left, float right, float bottom, float top, float near, float far)
+ {
+ Matrix44 t;
+ t.SetOrtho(left, right, bottom, top, near, far);
+ this->operator *=(t);
+ }
+
+ // | x |
+ // | y |
+ // | 0 |
+ // | 1 |
+ // | e0 e4 e8 e12 |
+ // | e1 e5 e9 e13 |
+ // | e2 e6 e10 e14 |
+ // | e3 e7 e11 e15 |
+
+ //void Matrix44::transform(Graphics::Vertex* dst, const Graphics::Vertex* src, int size) const
+ //{
+ // for (int i = 0; i<size; ++i)
+ // {
+ // // Store in temp variables in case src = dst
+ // float x = (e[0] * src[i].xy.x()) + (e[4] * src[i].xy.y()) + (0) + (e[12]);
+ // float y = (e[1] * src[i].xy.x()) + (e[5] * src[i].xy.y()) + (0) + (e[13]);
+
+ // dst[i].xy.Set(x, y);
+ // }
+ //}
+
+ } // namespace Math
+} // namespace JinEngine \ No newline at end of file
diff --git a/Source/modules/asura-base/Math/Matrix44.h b/Source/modules/asura-base/Math/Matrix44.h
new file mode 100644
index 0000000..e987dd4
--- /dev/null
+++ b/Source/modules/asura-base/Math/Matrix44.h
@@ -0,0 +1,96 @@
+#ifndef _ASURA_MATRIX_H_
+#define _ASURA_MATRIX_H_
+
+#include <asura-base/Classes.h>
+
+#include "../Scripting/Scripting.h"
+
+namespace_begin(AsuraEngine)
+namespace_begin(Math)
+
+/// ҪתõOpenGLglm::mat4
+/// https://blog.csdn.net/candycat1992/article/details/8830894
+class Matrix44
+{
+public:
+
+ static const Matrix44 Identity;
+
+ Matrix44();
+
+ Matrix44(const Matrix44& m);
+
+ ~Matrix44();
+
+ void operator = (const Matrix44& m);
+
+ void SetOrtho(float _left, float _right, float _bottom, float _top, float _near, float _far);
+
+ Matrix44 operator * (const Matrix44 & m) const;
+
+ void operator *= (const Matrix44 & m);
+
+ const float* GetElements() const;
+
+ void SetIdentity();
+
+ void SetTranslation(float x, float y);
+
+ void SetRotation(float r);
+
+ void SetScale(float sx, float sy);
+
+ void SetShear(float kx, float ky);
+
+ void SetTransformation(float x, float y, float angle, float sx, float sy, float ox, float oy);
+
+ void Translate(float x, float y);
+
+ void Rotate(float r);
+
+ void Scale(float sx, float sy);
+
+ void Transform(float x, float y, float angle, float sx, float sy, float ox, float oy);
+
+ ///
+ /// Multiplies this Matrix44 with a shear transformation.
+ /// @param kx Shear along the x-axis.
+ /// @param ky Shear along the y-axis.
+ ///
+ void Shear(float kx, float ky);
+
+ void Ortho(float left, float right, float bottom, float top, float near, float far);
+
+ /////
+ ///// Transforms an array of vertices by this Matrix44. The sources and
+ ///// destination arrays may be the same.
+ /////
+ ///// @param dst Storage for the transformed vertices.
+ ///// @param src The source vertices.
+ ///// @param size The number of vertices.
+ /////
+ //void transform(Graphics::Vertex* dst, const Graphics::Vertex * src, int size) const;
+
+ ///
+ /// ʽ
+ ///
+ float Calculate();
+
+private:
+
+ ///
+ /// | e0 e4 e8 e12 |
+ /// | e1 e5 e9 e13 |
+ /// | e2 e6 e10 e14 |
+ /// | e3 e7 e11 e15 |
+ ///
+ float e[16];
+
+};
+
+namespace_end
+namespace_end
+
+namespace AEMath = AsuraEngine::Math;
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-base/Math/Quaternion.cpp b/Source/modules/asura-base/Math/Quaternion.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-base/Math/Quaternion.cpp
diff --git a/Source/modules/asura-base/Math/Quaternion.h b/Source/modules/asura-base/Math/Quaternion.h
new file mode 100644
index 0000000..c1e19be
--- /dev/null
+++ b/Source/modules/asura-base/Math/Quaternion.h
@@ -0,0 +1,18 @@
+#ifndef _ASURA_QUATERNION_H_
+#define _ASURA_QUATERNION_H_
+
+#include <asura-base/Classes.h>
+
+namespace_begin(AsruaEngine)
+namespace_begin(Math)
+
+class Quaternion
+{
+
+};
+
+
+namespace_end
+namespace_end
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-base/Math/Random.h b/Source/modules/asura-base/Math/Random.h
new file mode 100644
index 0000000..7d3b976
--- /dev/null
+++ b/Source/modules/asura-base/Math/Random.h
@@ -0,0 +1,88 @@
+#ifndef _ASURA_RANDOM_H_
+#define _ASURA_RANDOM_H_
+
+#include "../Type.h"
+#include "../Classes.h"
+
+namespace_begin(AsuraEngine)
+namespace_begin(Math)
+
+/*
+Some random generator timings:
+MacBook Pro w/ Core 2 Duo 2.4GHz. Times are for gcc 4.0.1 (OS X 10.6.2) / VS2008 SP1 (Win XP SP3),
+in milliseconds for this loop (4915200 calls):
+
+for (int j = 0; j < 100; ++j)
+for (int i = 0; i < 128*128*3; ++i)
+data[i] = (rnd.get() & 0x3) << 6;
+
+gcc vs2008 Size
+C's rand(): 57.0 109.3 ms 1
+Mersenne Twister: 56.0 37.4 ms 2500
+Unity 2.x LCG: 11.1 9.2 ms 4
+Xorshift 128: 15.0 17.8 ms 16
+Xorshift 32: 20.6 10.7 ms 4
+WELL 512: 43.6 55.1 ms 68
+*/
+
+// Xorshift 128 implementation
+// Xorshift paper: http://www.jstatsoft.org/v08/i14/paper
+// Wikipedia: http://en.wikipedia.org/wiki/Xorshift
+class Rand {
+public:
+
+ Rand(uint32 seed = 0)
+ {
+ SetSeed(seed);
+ }
+
+ uint32 Get()
+ {
+ uint32 t;
+ t = x ^ (x << 11);
+ x = y; y = z; z = w;
+ return w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));
+ }
+
+ inline static float GetFloatFromInt(uint32 value)
+ {
+ // take 23 bits of integer, and divide by 2^23-1
+ return float(value & 0x007FFFFF) * (1.0f / 8388607.0f);
+ }
+
+ inline static uint8 GetByteFromInt(uint32 value)
+ {
+ // take the most significant byte from the 23-bit value
+ return uint8(value >> (23 - 8));
+ }
+
+ // random number between 0.0 and 1.0
+ float GetFloat()
+ {
+ return GetFloatFromInt(Get());
+ }
+
+ // random number between -1.0 and 1.0
+ float GetSignedFloat()
+ {
+ return GetFloat() * 2.0f - 1.0f;
+ }
+
+ void SetSeed(uint32 seed)
+ {
+ x = seed;
+ y = x * 1812433253U + 1;
+ z = y * 1812433253U + 1;
+ w = z * 1812433253U + 1;
+ }
+
+ uint32 GetSeed() const { return x; }
+
+private:
+ uint32 x, y, z, w;
+};
+
+namespace_end
+namespace_end
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-base/Math/RangedValue.cpp b/Source/modules/asura-base/Math/RangedValue.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-base/Math/RangedValue.cpp
diff --git a/Source/modules/asura-base/Math/RangedValue.h b/Source/modules/asura-base/Math/RangedValue.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-base/Math/RangedValue.h
diff --git a/Source/modules/asura-base/Math/Rect.hpp b/Source/modules/asura-base/Math/Rect.hpp
new file mode 100644
index 0000000..af4fa78
--- /dev/null
+++ b/Source/modules/asura-base/Math/Rect.hpp
@@ -0,0 +1,50 @@
+#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);
+ ~Rect() {};
+
+ ///
+ /// 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);
+
+ void Set(T x, T y, T w, T h);
+
+ T x, y, w, h;
+};
+
+#include "Rect.inc"
+
+// 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/modules/asura-base/Math/Rect.inc b/Source/modules/asura-base/Math/Rect.inc
new file mode 100644
index 0000000..efafbf9
--- /dev/null
+++ b/Source/modules/asura-base/Math/Rect.inc
@@ -0,0 +1,28 @@
+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)
+{
+
+}
+
+template <typename T>
+void Rect<T>::Set(T X, T Y, T W, T H)
+{
+ x = X;
+ y = Y;
+ w = W;
+ h = H;
+} \ No newline at end of file
diff --git a/Source/modules/asura-base/Math/Transform.cpp b/Source/modules/asura-base/Math/Transform.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-base/Math/Transform.cpp
diff --git a/Source/modules/asura-base/Math/Transform.h b/Source/modules/asura-base/Math/Transform.h
new file mode 100644
index 0000000..5dcfdcf
--- /dev/null
+++ b/Source/modules/asura-base/Math/Transform.h
@@ -0,0 +1,30 @@
+#ifndef _ASURA_ENGINE_TRANSFORM_H_
+#define _ASURA_ENGINE_TRANSFORM_H_
+
+#include "../scripting/Scripting.h"
+
+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/modules/asura-base/Math/Vector2.hpp b/Source/modules/asura-base/Math/Vector2.hpp
new file mode 100644
index 0000000..e141017
--- /dev/null
+++ b/Source/modules/asura-base/Math/Vector2.hpp
@@ -0,0 +1,72 @@
+#ifndef _ASURA_ENGINE_VECTOR2_H__
+#define _ASURA_ENGINE_VECTOR2_H__
+
+#include <asura-base/Classes.h>
+
+namespace_begin(AsuraEngine)
+namespace_begin(Math)
+
+template <typename T>
+class Vector2
+{
+public:
+ Vector2();
+ Vector2(T X, T Y);
+
+ template <typename U>
+ explicit Vector2(const Vector2<U>& vector);
+
+ void 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.inc"
+
+typedef Vector2<int> Vector2i;
+typedef Vector2<unsigned int> Vector2u;
+typedef Vector2<float> Vector2f;
+
+namespace_end
+namespace_end
+
+namespace AEMath = AsuraEngine::Math;
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-base/Math/Vector2.inc b/Source/modules/asura-base/Math/Vector2.inc
new file mode 100644
index 0000000..155432a
--- /dev/null
+++ b/Source/modules/asura-base/Math/Vector2.inc
@@ -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 void 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/modules/asura-base/Math/Vector3.hpp b/Source/modules/asura-base/Math/Vector3.hpp
new file mode 100644
index 0000000..c526ace
--- /dev/null
+++ b/Source/modules/asura-base/Math/Vector3.hpp
@@ -0,0 +1,235 @@
+#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.inc"
+
+ // Define the most common types
+ typedef Vector3<int> Vector3i;
+ typedef Vector3<float> Vector3f;
+
+ }
+}
+
+namespace AEMath = AsuraEngine::Math;
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-base/Math/Vector3.inc b/Source/modules/asura-base/Math/Vector3.inc
new file mode 100644
index 0000000..3a2aa93
--- /dev/null
+++ b/Source/modules/asura-base/Math/Vector3.inc
@@ -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/modules/asura-base/Math/Vector4.h b/Source/modules/asura-base/Math/Vector4.h
new file mode 100644
index 0000000..a5bf549
--- /dev/null
+++ b/Source/modules/asura-base/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.inc"
+
+ // Define the most common types
+ typedef Vector4<int> Vector4i;
+ typedef Vector4<float> Vector4f;
+
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-base/Math/Vector4.inc b/Source/modules/asura-base/Math/Vector4.inc
new file mode 100644
index 0000000..4b043a1
--- /dev/null
+++ b/Source/modules/asura-base/Math/Vector4.inc
@@ -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, T W) :
+ x(X),
+ y(Y),
+ z(Z),
+ w(W)
+{
+
+}
+
+
+////////////////////////////////////////////////////////////
+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/modules/asura-base/Module.h b/Source/modules/asura-base/Module.h
new file mode 100644
index 0000000..5ecb7c7
--- /dev/null
+++ b/Source/modules/asura-base/Module.h
@@ -0,0 +1,32 @@
+#ifndef _ASURA_MODULE_H_
+#define _ASURA_MODULE_H_
+
+#include "Type.h"
+#include "Scripting/Scripting.h"
+
+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/modules/asura-base/Scripting/Scripting.h b/Source/modules/asura-base/Scripting/Scripting.h
new file mode 100644
index 0000000..350a409
--- /dev/null
+++ b/Source/modules/asura-base/Scripting/Scripting.h
@@ -0,0 +1,30 @@
+#ifndef _ASURA_ENGINE_PORTABLE_H_
+#define _ASURA_ENGINE_PORTABLE_H_
+
+extern "C" {
+#include <lua51/lua.h>
+#include <lua51/lualib.h>
+#include <lua51/lauxlib.h>
+}
+
+#include <luax/luax.h>
+
+#include "../Type.h"
+#include "../Classes.h"
+
+namespace_begin(AsuraEngine)
+namespace_begin(Scripting)
+
+// ҪΪ࣬userdatamember ref̳д࣬ע̳С
+using Object = Luax::LuaxObject;
+
+// ҪעluanativeҪ̳дģ塣BASEָ࣬ĬLuaxObjectָLuaxObjectࡢ
+template<typename TYPE, typename BASE = Luax::LuaxObject>
+using Portable = Luax::LuaxNativeClass<TYPE, BASE>;
+
+namespace_end
+namespace_end
+
+namespace AEScripting = AsuraEngine::Scripting;
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-base/Singleton.hpp b/Source/modules/asura-base/Singleton.hpp
new file mode 100644
index 0000000..9bb7336
--- /dev/null
+++ b/Source/modules/asura-base/Singleton.hpp
@@ -0,0 +1,59 @@
+#ifndef _ASURA_SINGLETON_H_
+#define _ASURA_SINGLETON_H_
+
+#include "UtilsConfig.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/modules/asura-base/Threads/Conditional.cpp b/Source/modules/asura-base/Threads/Conditional.cpp
new file mode 100644
index 0000000..f86a81e
--- /dev/null
+++ b/Source/modules/asura-base/Threads/Conditional.cpp
@@ -0,0 +1,84 @@
+#include "Conditional.h"
+
+namespace_begin(AsuraEngine)
+namespace_begin(Threads)
+
+Conditional::Conditional()
+ : m_Waiting(0)
+ , m_Signals(0)
+{
+}
+
+Conditional::~Conditional()
+{
+}
+
+void Conditional::Signal()
+{
+ m_Mutex.Lock();
+ if (m_Waiting > m_Signals)
+ {
+ ++m_Signals;
+ signal(m_WaitSem);
+ m_Mutex.Unlock();
+ wait(m_DoneSem);
+ }
+ else
+ {
+ m_Mutex.Unlock();
+ }
+}
+
+void Conditional::Broadcast()
+{
+ m_Mutex.Lock();
+ if (m_Waiting> m_Signals) {
+ int i, num_waiting;
+
+ num_waiting = (m_Waiting - m_Signals);
+ m_Signals = m_Waiting;
+ for (i = 0; i < num_waiting; ++i) {
+ signal(m_WaitSem);
+ }
+ m_Mutex.Unlock();
+ for (i = 0; i < num_waiting; ++i) {
+ wait(m_DoneSem);
+ }
+ }
+ else {
+ m_Mutex.Unlock();
+ }
+
+}
+
+bool Conditional::Wait(Mutex* mutex, int timeout /*= ASURA_MUTEX_MAXWAIT*/)
+{
+ bool retval;
+
+ m_Mutex.Lock();
+ ++m_Waiting;
+ m_Mutex.Unlock();
+
+ mutex->Unlock();
+
+ retval = wait(m_WaitSem, timeout);
+
+ m_Mutex.Lock();
+ if (m_Signals > 0) {
+ if (!retval) {
+ wait(m_WaitSem);
+ }
+ signal(m_DoneSem);
+
+ --m_Signals;
+ }
+ --m_Waiting;
+ m_Mutex.Unlock();
+
+ m_Mutex.Lock();
+
+ return retval;
+}
+
+namespace_end
+namespace_end \ No newline at end of file
diff --git a/Source/modules/asura-base/Threads/Conditional.h b/Source/modules/asura-base/Threads/Conditional.h
new file mode 100644
index 0000000..ee818ca
--- /dev/null
+++ b/Source/modules/asura-base/Threads/Conditional.h
@@ -0,0 +1,41 @@
+#ifndef _ASURA_CONDITIONAL_H_
+#define _ASURA_CONDITIONAL_H_
+
+#include <asura-base/Classes.h>
+
+#include "Mutex.h"
+#include "Semaphore.h"
+
+namespace_begin(AsuraEngine)
+namespace_begin(Threads)
+
+///
+///
+///
+class Conditional
+{
+public:
+
+ Conditional();
+ ~Conditional();
+
+ void Signal();
+ void Broadcast();
+ bool Wait(Mutex* mutex, int timeout = ASURA_MUTEX_MAXWAIT);
+
+private:
+
+ Mutex m_Mutex;
+
+ Semaphore m_WaitSem;
+ Semaphore m_DoneSem;
+
+ int m_Waiting;
+ int m_Signals;
+
+};
+
+namespace_end
+namespace_end
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-base/Threads/Coroutine.cpp b/Source/modules/asura-base/Threads/Coroutine.cpp
new file mode 100644
index 0000000..5c4ab68
--- /dev/null
+++ b/Source/modules/asura-base/Threads/Coroutine.cpp
@@ -0,0 +1,15 @@
+#include "coroutine.h"
+
+namespace_begin(AsuraEngine)
+namespace_begin(Threads)
+
+/*
+Coroutine::Coroutine()
+{
+
+}
+*/
+
+
+namespace_end
+namespace_end
diff --git a/Source/modules/asura-base/Threads/Coroutine.h b/Source/modules/asura-base/Threads/Coroutine.h
new file mode 100644
index 0000000..d1d3a57
--- /dev/null
+++ b/Source/modules/asura-base/Threads/Coroutine.h
@@ -0,0 +1,40 @@
+#ifndef _ASURA_COROUTINE_H_
+#define _ASURA_COROUTINE_H_
+
+#include <asura-base/Classes.h>
+
+#include "../Scripting/Scripting.h"
+
+namespace_begin(AsuraEngine)
+namespace_begin(Threads)
+
+///
+/// luaЭ̣һЩ߼
+///
+class Coroutine ASURA_FINAL
+ : public AEScripting::Portable<Coroutine>
+{
+public:
+
+ LUAX_DECL_FACTORY(Coroutine);
+
+
+
+private:
+
+ ///
+ /// ǰЭ̵state
+ ///
+ lua_State* m_ThreadState;
+
+ LUAX_DECL_METHOD(_New);
+ LUAX_DECL_METHOD(_Run);
+
+};
+
+namespace_end
+namespace_end
+
+namespace AEThreading = AsuraEngine::Threads;
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-base/Threads/Mutex.cpp b/Source/modules/asura-base/Threads/Mutex.cpp
new file mode 100644
index 0000000..91db3b5
--- /dev/null
+++ b/Source/modules/asura-base/Threads/Mutex.cpp
@@ -0,0 +1,105 @@
+#include <asura-base/Exception.h>
+
+#include "Mutex.h"
+
+namespace_begin(AsuraEngine)
+namespace_begin(Threads)
+
+#define try_create_mutex(impl)\
+if (!m_Impl) \
+{ \
+try \
+{ \
+ m_Impl = new impl(); \
+} \
+catch (Exception& e) \
+{ \
+ m_Impl = nullptr; \
+} \
+}
+
+Mutex::Mutex()
+ : m_Impl(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(m_Impl);
+}
+
+Mutex::~Mutex()
+{
+ if(m_Impl)
+ delete m_Impl;
+}
+
+void Mutex::Lock()
+{
+ ASSERT(m_Impl);
+
+ m_Impl->Lock();
+}
+
+void Mutex::Unlock()
+{
+ ASSERT(m_Impl);
+
+ m_Impl->Unlock();
+}
+
+#if ASURA_MUTEX_WIN32_CRITICLE_SECTION
+
+MutexImplWin32_CS::MutexImplWin32_CS()
+{
+ ::InitializeCriticalSection(&m_Mutex);
+}
+
+MutexImplWin32_CS::~MutexImplWin32_CS()
+{
+ ::DeleteCriticalSection(&m_Mutex);
+}
+
+void MutexImplWin32_CS::Lock()
+{
+ ::EnterCriticalSection(&m_Mutex);
+}
+
+void MutexImplWin32_CS::Unlock()
+{
+ ::LeaveCriticalSection(&m_Mutex);
+}
+
+#endif // ASURA_MUTEX_WIN32_CRITICLE_SECTION
+
+#if ASURA_MUTEX_WIN32_KERNAL_MUTEX
+
+MutexImplWin32_KM::MutexImplWin32_KM()
+{
+ m_Handle = ::CreateMutex(NULL, FALSE, NULL);
+ if (!m_Handle)
+ throw Exception("Cant use win32 mutex.");
+}
+
+MutexImplWin32_KM::~MutexImplWin32_KM()
+{
+ ::CloseHandle(m_Handle);
+ m_Handle = NULL;
+}
+
+void MutexImplWin32_KM::Lock()
+{
+ ::WaitForSingleObject(m_Handle, ASURA_MUTEX_MAXWAIT);
+}
+
+void MutexImplWin32_KM::Unlock()
+{
+ ::ReleaseMutex(m_Handle);
+}
+
+#endif // ASURA_MUTEX_WIN32_KERNAL_MUTEX
+
+namespace_end
+namespace_end \ No newline at end of file
diff --git a/Source/modules/asura-base/Threads/Mutex.h b/Source/modules/asura-base/Threads/Mutex.h
new file mode 100644
index 0000000..5f2e1bf
--- /dev/null
+++ b/Source/modules/asura-base/Threads/Mutex.h
@@ -0,0 +1,128 @@
+#ifndef _ASURA_MUTEX_H_
+#define _ASURA_MUTEX_H_
+
+#include <asura-base/Type.h>
+#include <asura-base/Classes.h>
+
+#include "../UtilsConfig.h"
+
+#if ASURA_THREAD_WIN32
+#include <windows.h>
+#endif
+
+namespace_begin(AsuraEngine)
+namespace_begin(Threads)
+
+#define ASURA_MUTEX_MAXWAIT (~(uint32)0)
+
+class MutexImpl;
+
+class Mutex
+{
+public:
+
+ Mutex();
+ ~Mutex();
+
+ void Lock();
+ void Unlock();
+
+private:
+
+ // ֹ
+ Mutex(const Mutex&);
+ Mutex& operator=(const Mutex&);
+
+ MutexImpl* m_Impl;
+
+};
+
+class _mutex_locker
+{
+public:
+ _mutex_locker(Mutex& mutex)
+ : m(mutex)
+ {
+ m.Lock();
+ };
+ ~_mutex_locker()
+ {
+ m.Unlock();
+ }
+ operator bool() { return false; };
+private:
+ void* operator new(size_t);
+ Mutex& m;
+};
+
+#define lock(m) \
+if(_mutex_locker _asura_mutex_locker = m){} else
+
+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 m_Handle;
+ CRITICAL_SECTION m_Mutex;
+
+};
+
+#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 m_Handle;
+
+};
+
+#endif // ASURA_MUTEX_WIN32_KERNAL_MUTEX
+
+#if ASURA_THREAD_STD
+
+class MutexImplSTD ASURA_FINAL : public MutexImpl
+{
+};
+
+#endif // ASURA_THREAD_STD
+
+namespace_end
+namespace_end
+
+namespace AEThreading = AsuraEngine::Threads;
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-base/Threads/Semaphore.cpp b/Source/modules/asura-base/Threads/Semaphore.cpp
new file mode 100644
index 0000000..024961e
--- /dev/null
+++ b/Source/modules/asura-base/Threads/Semaphore.cpp
@@ -0,0 +1,99 @@
+#include "../Exception.h"
+#include "../Type.h"
+
+#include "Mutex.h"
+#include "Semaphore.h"
+
+namespace_begin(AsuraEngine)
+namespace_begin(Threads)
+
+#define try_create_semaphore(impl) \
+if (!m_Impl) \
+{ \
+ try \
+ { \
+ m_Impl = new impl(init_count); \
+ } \
+ catch (Exception& e) \
+ { \
+ m_Impl = nullptr; \
+ } \
+}
+
+Semaphore::Semaphore(unsigned int init_count)
+ : m_Impl(nullptr)
+{
+#ifdef ASURA_THREAD_WIN32
+ try_create_semaphore(SemaphoreWin32);
+#endif
+ //ASSERT(m_Impl);
+}
+
+Semaphore::~Semaphore()
+{
+ if (m_Impl) delete m_Impl;
+}
+
+void Semaphore::Signal()
+{
+ ASSERT(m_Impl);
+ m_Impl->Signal();
+}
+
+bool Semaphore::Wait(int timeout /*= ASURA_MUTEX_MAXWAIT*/)
+{
+ ASSERT(m_Impl);
+ return m_Impl->Wait(timeout);
+}
+
+#if ASURA_THREAD_WIN32
+
+SemaphoreWin32::SemaphoreWin32(unsigned int init_value)
+ : SemaphoreImpl(init_value)
+{
+ // UINT_MAX get error.
+ m_Sem = CreateSemaphore(NULL, init_value, INT_MAX, NULL);
+ if (!m_Sem)
+ {
+ int errorCode = GetLastError();
+ throw Exception("Cant use win32 semaphore. Error code: %d.", errorCode);
+ }
+}
+
+SemaphoreWin32::~SemaphoreWin32()
+{
+ CloseHandle(m_Sem);
+}
+
+void SemaphoreWin32::Signal()
+{
+ InterlockedIncrement(&m_Count);
+ if (ReleaseSemaphore(m_Sem, 1, NULL) == FALSE)
+ InterlockedDecrement(&m_Count);
+}
+
+bool SemaphoreWin32::Wait(int timeout)
+{
+ int result;
+ result = WaitForSingleObject(m_Sem, timeout);
+ if (result == WAIT_OBJECT_0)
+ {
+ InterlockedDecrement(&m_Count);
+ return true;
+ }
+ else if(result == WAIT_TIMEOUT)
+ {
+ // ʱ
+ return false;
+ }
+ else
+ {
+ // δ֪
+ throw Exception("WaitForSingleObject() failed");
+ }
+}
+
+#endif // ASURA_THREAD_WIN32
+
+namespace_end
+namespace_end \ No newline at end of file
diff --git a/Source/modules/asura-base/Threads/Semaphore.h b/Source/modules/asura-base/Threads/Semaphore.h
new file mode 100644
index 0000000..41b1fd2
--- /dev/null
+++ b/Source/modules/asura-base/Threads/Semaphore.h
@@ -0,0 +1,68 @@
+#ifndef _ASURA_SEMAPHORE_H_
+#define _ASURA_SEMAPHORE_H_
+
+#include "../UtilsConfig.h"
+
+#if ASURA_THREAD_WIN32
+#include <windows.h>
+#endif
+
+namespace_begin(AsuraEngine)
+namespace_begin(Threads)
+
+class SemaphoreImpl;
+
+///
+/// ź
+///
+class Semaphore
+{
+public:
+
+ Semaphore(unsigned int init_count = 1);
+ ~Semaphore();
+
+ void Signal();
+ bool Wait(int timeout = ASURA_MUTEX_MAXWAIT);
+
+private:
+ SemaphoreImpl* m_Impl;
+};
+
+class SemaphoreImpl
+{
+public:
+ SemaphoreImpl(unsigned int init_value)
+ : m_Count(init_value)
+ {
+ };
+ virtual ~SemaphoreImpl() {};
+ virtual void Signal() = 0;
+ virtual bool Wait(int timeout) = 0;
+ inline int Current() { return m_Count; }
+protected:
+ unsigned int m_Count;
+};
+
+#define wait(sem, ...) sem.Wait(__VA_ARGS__)
+#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 m_Sem;
+};
+
+#endif // ASURA_THREAD_WIN32
+
+namespace_end
+namespace_end
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-base/Threads/Task.cpp b/Source/modules/asura-base/Threads/Task.cpp
new file mode 100644
index 0000000..926b491
--- /dev/null
+++ b/Source/modules/asura-base/Threads/Task.cpp
@@ -0,0 +1,10 @@
+#include "task.h"
+#include "../scripting/Scripting.h"
+
+using namespace AEScripting;
+
+namespace_begin(AsuraEngine)
+namespace_begin(Threads)
+
+namespace_end
+namespace_end
diff --git a/Source/modules/asura-base/Threads/Task.h b/Source/modules/asura-base/Threads/Task.h
new file mode 100644
index 0000000..2e9977a
--- /dev/null
+++ b/Source/modules/asura-base/Threads/Task.h
@@ -0,0 +1,43 @@
+#ifndef _ASURA_THRAD_TASK_H_
+#define _ASURA_THRAD_TASK_H_
+
+#include <asura-base/Type.h>
+#include <asura-base/Scripting/Scripting.h>
+#include <asura-base/Classes.h>
+
+namespace_begin(AsuraEngine)
+namespace_begin(Threads)
+
+///
+/// ϣһ̴߳񣬼̳TaskдExecute
+///
+ASURA_ABSTRACT class Task : public AEScripting::Object
+{
+public:
+
+ Task() {};
+ virtual ~Task() {};
+
+ ///
+ /// ִɺ󷵻trueûص
+ ///
+ virtual bool Execute() = 0;
+
+ ///
+ /// ûصinvoke threadص
+ ///
+ virtual void Invoke(lua_State* invokeThreaad) = 0;
+
+protected:
+
+ // ȡص
+ Luax::LuaxMemberRef m_Callback;
+
+};
+
+namespace_end
+namespace_end
+
+namespace AEThreading = AsuraEngine::Threads;
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-base/Threads/Thread.cpp b/Source/modules/asura-base/Threads/Thread.cpp
new file mode 100644
index 0000000..1153912
--- /dev/null
+++ b/Source/modules/asura-base/Threads/Thread.cpp
@@ -0,0 +1,287 @@
+#include "Thread.h"
+
+#include "ThreadImplWin32.h"
+#include "ThreadImplPosix.h"
+#include "ThreadImplSdl.h"
+#include "ThreadImplStd.h"
+
+namespace_begin(AsuraEngine)
+namespace_begin(Threads)
+
+Thread::Thread(lua_State* luaThread, ThreadType type /*= THREAD_TYPE_DEFERRED*/, uint sleepTime /*= 0*/, const std::string& name /*= ""*/)
+ : m_Name(name)
+ , m_State(THREAD_STATE_IDLE)
+ , m_Type(type)
+ , m_LuaThread(luaThread)
+ , m_CallbackThread(nullptr)
+ , m_SleepTime(sleepTime)
+{
+ LUAX_STATE(luaThread);
+ if (type == THREAD_TYPE_IMMEDIATE)
+ {
+ Luax::LuaxVM* vm = state.GetVM();
+ ASSERT(vm);
+ m_CallbackThread = vm->CreateThread();
+ ASSERT(m_CallbackThread);
+ SetLuaxMemberRef(state, m_CallbackThreadRef, -1);
+ state.Pop(); // callback thread
+ }
+}
+
+Thread::~Thread()
+{
+ if (m_Impl)
+ {
+ delete m_Impl;
+ m_Impl = nullptr;
+ }
+}
+
+bool Thread::AddTask(Task* task)
+{
+ lock(m_TaskQueueMutex)
+ {
+ task->Retain();
+ m_TaskQueue.push(task);
+ }
+ return true;
+}
+
+uint Thread::GetTaskCount()
+{
+ return m_TaskQueue.size();
+}
+
+void Thread::Idle()
+{
+ m_State = THREAD_STATE_IDLE;
+}
+
+#define try_start_thread(impl)\
+if (!m_Impl) \
+{ \
+m_Impl = new impl(); \
+if (!m_Impl->Start(this, stacksize)) \
+{ \
+ delete m_Impl; \
+ m_Impl = nullptr; \
+} \
+}
+
+bool Thread::Start(bool isDaemon /*= true*/, uint32 stacksize /*= 0*/)
+{
+ if (m_State != THREAD_STATE_IDLE)
+ return false;
+
+ // Ѿһ֮ǰģر
+ if (m_Impl)
+ {
+ delete m_Impl;
+ m_Impl = nullptr;
+ }
+
+#if ASURA_THREAD_WIN32
+ try_start_thread(ThreadImplWin32);
+#endif
+
+ if (!m_Impl)
+ return false;
+
+ m_IsDaemon = isDaemon;
+ m_StateMutex.Lock();
+ m_State = THREAD_STATE_RUNNING;
+ m_StateMutex.Unlock();
+}
+
+void Thread::Pause()
+{
+ ASSERT(m_Impl);
+
+ lock(m_StateMutex)
+ {
+ m_State = THREAD_STATE_PAUSED;
+ }
+}
+
+void Thread::Resume()
+{
+ ASSERT(m_Impl);
+
+ lock(m_StateMutex)
+ {
+ if (m_State == THREAD_STATE_PAUSED)
+ m_State = THREAD_STATE_RUNNING;
+ }
+}
+
+void Thread::Stop()
+{
+ ASSERT(m_Impl);
+
+ lock(m_StateMutex)
+ {
+ m_State = THREAD_STATE_STOPPED;
+ }
+}
+
+void Thread::PauseSync()
+{
+ Pause();
+ wait(m_SemPause);
+}
+
+void Thread::ResumeSync()
+{
+ Resume();
+ wait(m_SemResume);
+}
+
+void Thread::StopSync()
+{
+ Stop();
+ wait(m_SemStop);
+}
+
+void Thread::Join()
+{
+ ASSERT(m_Impl);
+ m_Impl->Join();
+}
+
+ThreadState Thread::GetState()
+{
+ ThreadState state;
+ lock(m_StateMutex)
+ {
+ state = m_State;
+ }
+ return state;
+}
+
+bool Thread::IsRunning()
+{
+ ASSERT(m_Impl);
+
+ return GetState() == THREAD_STATE_RUNNING;
+}
+
+bool Thread::IsPaused()
+{
+ ASSERT(m_Impl);
+
+ return GetState() == THREAD_STATE_PAUSED;
+}
+
+bool Thread::IsStopped()
+{
+ ASSERT(m_Impl);
+
+ return GetState() == THREAD_STATE_STOPPED;
+}
+
+bool Thread::IsCurrent()
+{
+ ASSERT(m_Impl);
+
+ return m_Impl->IsCurrent();
+}
+
+const std::string& Thread::GetName()
+{
+ return m_Name;
+}
+
+int Thread::Process()
+{
+ LUAX_STATE(m_LuaThread);
+
+ do{
+ if (IsRunning())
+ {
+ while (!m_TaskQueue.empty())
+ {
+ Task* task = m_TaskQueue.front();
+ if (task && task->Execute())
+ {
+ if (m_Type == THREAD_TYPE_DEFERRED)
+ {
+ m_FinishedMutex.Lock();
+ task->Retain();
+ m_FinishedTasks.push(task);
+ m_FinishedMutex.Unlock();
+ }
+ else if (m_Type == THREAD_TYPE_IMMEDIATE)
+ {
+ // unsafe
+ task->Invoke(m_CallbackThread);
+ this->LuaxRelease<Task>(state, task);
+ }
+ m_TaskQueueMutex.Lock();
+ m_TaskQueue.pop();
+ task->Release();
+ m_TaskQueueMutex.Unlock();
+ }
+ }
+ }
+
+ // ˳ѭ
+ if (IsStopped())
+ break;
+
+ // CPUʹ
+ Sleep(m_SleepTime);
+
+ } while (m_IsDaemon);
+
+ // ػ̣߳еstop״̬
+ if (!m_IsDaemon)
+ Stop();
+
+ signal(m_SemStop);
+
+ // ״̬ΪIdle
+ Idle();
+
+ return 0;
+}
+
+///
+/// ӳģʽص
+///
+void Thread::Dispatch()
+{
+ if (m_Type != THREAD_TYPE_DEFERRED)
+ return;
+
+ LUAX_STATE(m_LuaThread);
+ while (!m_FinishedTasks.empty())
+ {
+ Task* task = m_FinishedTasks.front();
+ if (task)
+ {
+ task->Invoke(m_LuaThread);
+ this->LuaxRelease<Task>(state, task);
+ m_FinishedMutex.Lock();
+ m_FinishedTasks.pop();
+ task->Release();
+ m_FinishedMutex.Unlock();
+ }
+ }
+}
+
+void Thread::Sleep(uint ms)
+{
+ ASSERT(m_Impl);
+ if (m_Impl)
+ {
+ m_Impl->Sleep(ms);
+ }
+}
+
+void Thread::SetSleepTime(uint ms)
+{
+ m_SleepTime = ms;
+}
+
+namespace_end
+namespace_end \ No newline at end of file
diff --git a/Source/modules/asura-base/Threads/Thread.h b/Source/modules/asura-base/Threads/Thread.h
new file mode 100644
index 0000000..5adba0b
--- /dev/null
+++ b/Source/modules/asura-base/Threads/Thread.h
@@ -0,0 +1,222 @@
+#ifndef _ASURA_THREAD_H_
+#define _ASURA_THREAD_H_
+
+#include <string>
+#include <queue>
+
+#include <asura-base/Scripting/Scripting.h>
+
+#include "Task.h"
+#include "Mutex.h"
+#include "Semaphore.h"
+#include "Threadable.h"
+
+namespace_begin(AsuraEngine)
+namespace_begin(Threads)
+
+class ThreadImpl;
+
+///
+/// ̵߳ļֲͬʵ֣
+/// 1: Deferredӳģʽ߳ϵɺҪ̵ֶ߳Dispatch
+/// ̵߳ص첽Ϊͬlua_Stateͻ⡣
+/// 2: Immediateģʽÿһ߳άһlua_newthreadlua_State
+/// صڲͬlua_Stateеãⲻ̷ͬ߳ͬһlua_State
+///
+enum ThreadType
+{
+ THREAD_TYPE_DEFERRED,
+ THREAD_TYPE_IMMEDIATE, // unsafe
+};
+
+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 Threadable
+{
+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();
+
+ ///
+ /// ִС
+ ///
+ int Process() override;
+
+ const std::string& GetName();
+
+ ///
+ /// ص
+ ///
+ void Dispatch();
+
+ ///
+ /// ߺ
+ ///
+ 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(_Dispatch);
+ LUAX_DECL_METHOD(_GetName);
+ LUAX_DECL_METHOD(_GetType);
+ LUAX_DECL_METHOD(_GetState);
+ LUAX_DECL_METHOD(_SetSleepTime);
+
+ //----------------------------------------------------------------------------//
+
+ ThreadImpl* m_Impl;
+
+ lua_State* m_LuaThread;
+
+ ///
+ /// ˴Ƿػģʽ
+ ///
+ bool m_IsDaemon;
+
+ std::string m_Name;
+ ThreadType m_Type;
+ uint m_SleepTime;
+
+ ThreadState m_State;
+ Mutex m_StateMutex;
+
+ ///
+ /// ͬصź
+ ///
+ Semaphore m_SemPause;
+ Semaphore m_SemResume;
+ Semaphore m_SemStop;
+
+ ///
+ /// С
+ ///
+ std::queue<Task*> m_TaskQueue;
+ Mutex m_TaskQueueMutex;
+
+ ///
+ /// ӳģʽʹ
+ ///
+ std::queue<Task*> m_FinishedTasks;
+ Mutex m_FinishedMutex;
+
+ ///
+ /// ģʽʹãصʹõlua߳
+ ///
+ lua_State* m_CallbackThread;
+ Luax::LuaxMemberRef m_CallbackThreadRef;
+
+};
+
+///
+/// ̵߳ľʵ֣û͸ģһ׼ֲԣ
+/// 1: win32
+/// 2: posix
+/// 3: SDL
+/// 4: std::thread
+///
+ASURA_ABSTRACT class ThreadImpl
+{
+public:
+ ThreadImpl() {};
+ virtual ~ThreadImpl() {};
+
+ virtual bool Start(Threadable* 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;
+
+};
+
+namespace_end
+namespace_end
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-base/Threads/ThreadImplPosix.cpp b/Source/modules/asura-base/Threads/ThreadImplPosix.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-base/Threads/ThreadImplPosix.cpp
diff --git a/Source/modules/asura-base/Threads/ThreadImplPosix.h b/Source/modules/asura-base/Threads/ThreadImplPosix.h
new file mode 100644
index 0000000..ed33807
--- /dev/null
+++ b/Source/modules/asura-base/Threads/ThreadImplPosix.h
@@ -0,0 +1,2 @@
+#include <asura-base/Classes.h>
+
diff --git a/Source/modules/asura-base/Threads/ThreadImplSDL.cpp b/Source/modules/asura-base/Threads/ThreadImplSDL.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-base/Threads/ThreadImplSDL.cpp
diff --git a/Source/modules/asura-base/Threads/ThreadImplSDL.h b/Source/modules/asura-base/Threads/ThreadImplSDL.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-base/Threads/ThreadImplSDL.h
diff --git a/Source/modules/asura-base/Threads/ThreadImplStd.cpp b/Source/modules/asura-base/Threads/ThreadImplStd.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-base/Threads/ThreadImplStd.cpp
diff --git a/Source/modules/asura-base/Threads/ThreadImplStd.h b/Source/modules/asura-base/Threads/ThreadImplStd.h
new file mode 100644
index 0000000..452f569
--- /dev/null
+++ b/Source/modules/asura-base/Threads/ThreadImplStd.h
@@ -0,0 +1,41 @@
+#ifndef _ASURA_THREAD_STD_H_
+#define _ASURA_THREAD_STD_H_
+
+#include "../UtilsConfig.h"
+
+#if ASURA_THREAD_STD
+
+#include <windows.h>
+
+#include "Thread.h"
+
+namespace_begin(AsuraEngine)
+namespace_begin(Threads)
+
+///
+/// Threadstd::threadʵ֡
+///
+class ThreadImplSTD : public ThreadImpl
+{
+public:
+
+ ThreadImplSTD();
+ ~ThreadImplSTD();
+
+ bool Start(Threadable* thread, uint32 stacksize) override;
+ void Join() override;
+ void Kill() override;
+
+ bool IsRunning() override;
+ bool IsCurrent() override;
+
+private:
+
+};
+
+namespace_end
+namespace_end
+
+#endif // #if ASURA_THREAD_STD
+
+#endif // _ASURA_THREAD_STD_H_ \ No newline at end of file
diff --git a/Source/modules/asura-base/Threads/ThreadImplWin32.cpp b/Source/modules/asura-base/Threads/ThreadImplWin32.cpp
new file mode 100644
index 0000000..2467f87
--- /dev/null
+++ b/Source/modules/asura-base/Threads/ThreadImplWin32.cpp
@@ -0,0 +1,77 @@
+#include "ThreadImplWin32.h"
+#include "Thread.h"
+
+#include <iostream>
+
+#if ASURA_THREAD_WIN32
+
+namespace_begin(AsuraEngine)
+namespace_begin(Threads)
+
+static DWORD WINAPI _thread_win32_runner(LPVOID param)
+{
+ Threadable* thread = (Threadable*)param;
+ return thread->Process(); // β
+}
+
+ThreadImplWin32::ThreadImplWin32()
+{
+}
+
+ThreadImplWin32::~ThreadImplWin32()
+{
+ if (!m_Handle) return;
+ ::CloseHandle(m_Handle);
+ m_Handle = 0;
+}
+
+bool ThreadImplWin32::Start(Threadable* thread, uint32 stacksize/*=0*/)
+{
+ assert(!IsRunning());
+ m_Handle = ::CreateThread(
+ NULL
+ , stacksize
+ , _thread_win32_runner
+ , thread
+ , 0 /*е*/
+ , NULL);
+
+ return m_Handle;
+}
+
+void ThreadImplWin32::Join()
+{
+ // ̵߳ȴ̷߳
+ ::WaitForSingleObject(m_Handle, INFINITE);
+}
+
+void ThreadImplWin32::Kill()
+{
+ ::TerminateThread(m_Handle, FALSE);
+}
+
+void ThreadImplWin32::Sleep(uint ms)
+{
+ ::Sleep(ms);
+}
+
+bool ThreadImplWin32::IsRunning()
+{
+ if (m_Handle) {
+ DWORD exitCode = 0;
+ // https://blog.csdn.net/yuanmeng567/article/details/19485719
+ ::GetExitCodeThread(m_Handle, &exitCode);
+ return exitCode == STILL_ACTIVE;
+ }
+ return false;
+}
+
+bool ThreadImplWin32::IsCurrent()
+{
+ return m_Handle == ::GetCurrentThread();
+}
+
+namespace_end
+namespace_end
+
+#endif // ASURA_THREAD_WIN32 \ No newline at end of file
diff --git a/Source/modules/asura-base/Threads/ThreadImplWin32.h b/Source/modules/asura-base/Threads/ThreadImplWin32.h
new file mode 100644
index 0000000..93ca477
--- /dev/null
+++ b/Source/modules/asura-base/Threads/ThreadImplWin32.h
@@ -0,0 +1,44 @@
+#ifndef _ASURA_THREAD_WIN32_H__
+#define _ASURA_THREAD_WIN32_H__
+
+#include "../UtilsConfig.h"
+
+#if ASURA_THREAD_WIN32
+
+#include <windows.h>
+
+#include "thread.h"
+
+namespace_begin(AsuraEngine)
+namespace_begin(Threads)
+
+///
+/// Threadwin32ʵ֡
+///
+class ThreadImplWin32 : public ThreadImpl
+{
+public:
+
+ ThreadImplWin32();
+ ~ThreadImplWin32();
+
+ bool Start(Threadable* thread, uint32 stacksize) override;
+ void Join() override;
+ void Kill() override;
+
+ void Sleep(uint ms) override;
+
+ bool IsRunning() override;
+ bool IsCurrent() override;
+
+private:
+
+ HANDLE m_Handle;
+
+};
+
+namespace_end
+namespace_end
+
+#endif // #if ASURA_THREAD_WIN32
+#endif // _ASURA_THREAD_WIN32_H__ \ No newline at end of file
diff --git a/Source/modules/asura-base/Threads/Threadable.h b/Source/modules/asura-base/Threads/Threadable.h
new file mode 100644
index 0000000..fce7350
--- /dev/null
+++ b/Source/modules/asura-base/Threads/Threadable.h
@@ -0,0 +1,23 @@
+#ifndef _ASURA_THREADABLE_H_
+#define _ASURA_THREADABLE_H_
+
+#include "../Type.h"
+
+namespace_begin(AsuraEngine)
+namespace_begin(Threads)
+
+ASURA_ABSTRACT class Threadable
+{
+public:
+
+ Threadable() {};
+ virtual ~Threadable() {};
+
+ virtual int Process() = 0;
+
+};
+
+namespace_end
+namespace_end
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-base/Threads/binding/_coroutine.cpp b/Source/modules/asura-base/Threads/binding/_coroutine.cpp
new file mode 100644
index 0000000..0656079
--- /dev/null
+++ b/Source/modules/asura-base/Threads/binding/_coroutine.cpp
@@ -0,0 +1,38 @@
+#include "../Coroutine.h"
+
+using namespace std;
+
+namespace_begin(AsuraEngine)
+namespace_begin(Threads)
+
+ 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/modules/asura-base/Threads/binding/_thread.cpp b/Source/modules/asura-base/Threads/binding/_thread.cpp
new file mode 100644
index 0000000..aaa9e8d
--- /dev/null
+++ b/Source/modules/asura-base/Threads/binding/_thread.cpp
@@ -0,0 +1,208 @@
+#include "../Thread.h"
+
+using namespace std;
+
+namespace_begin(AsuraEngine)
+namespace_begin(Threads)
+
+ 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 },
+ { "Dispatch", _Dispatch },
+ { "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",
+ { "IDLE", 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:Dispatch()
+ LUAX_IMPL_METHOD(Thread, _Dispatch)
+ {
+ LUAX_PREPARE(L, Thread);
+ self->Dispatch();
+ 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->m_Type);
+ return 1;
+ }
+
+ // thread:GetState()
+ LUAX_IMPL_METHOD(Thread, _GetState)
+ {
+ LUAX_PREPARE(L, Thread);
+ state.Push(self->m_State);
+ 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/modules/asura-base/Type.h b/Source/modules/asura-base/Type.h
new file mode 100644
index 0000000..5100fa3
--- /dev/null
+++ b/Source/modules/asura-base/Type.h
@@ -0,0 +1,37 @@
+#ifndef _ASURA_UTILS_TYPE_H_
+#define _ASURA_UTILS_TYPE_H_
+
+#include <assert.h>
+#include <cstdlib>
+#include <stdint.h>
+
+#include "asura-base/Configure.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;
+
+#define Assert assert
+
+} // namespace AsuraEngine
+
+#endif // _ASURA_CONFIG_H_ \ No newline at end of file
diff --git a/Source/modules/asura-base/Utilities/Hash128.cpp b/Source/modules/asura-base/Utilities/Hash128.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-base/Utilities/Hash128.cpp
diff --git a/Source/modules/asura-base/Utilities/Hash128.h b/Source/modules/asura-base/Utilities/Hash128.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-base/Utilities/Hash128.h
diff --git a/Source/modules/asura-base/Utilities/LinkedList.cpp b/Source/modules/asura-base/Utilities/LinkedList.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-base/Utilities/LinkedList.cpp
diff --git a/Source/modules/asura-base/Utilities/LinkedList.h b/Source/modules/asura-base/Utilities/LinkedList.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-base/Utilities/LinkedList.h
diff --git a/Source/modules/asura-base/Utilities/StringMap.cpp b/Source/modules/asura-base/Utilities/StringMap.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-base/Utilities/StringMap.cpp
diff --git a/Source/modules/asura-base/Utilities/StringMap.hpp b/Source/modules/asura-base/Utilities/StringMap.hpp
new file mode 100644
index 0000000..15d28ee
--- /dev/null
+++ b/Source/modules/asura-base/Utilities/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 std::string& str);
+
+ std::string GetStringByKey(const key_type& key);
+
+ key_type GetKeyByString(const std::string& str);
+
+ };
+
+}
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-base/Utilities/dynamic_bitset.h b/Source/modules/asura-base/Utilities/dynamic_bitset.h
new file mode 100644
index 0000000..ea4e967
--- /dev/null
+++ b/Source/modules/asura-base/Utilities/dynamic_bitset.h
@@ -0,0 +1,1150 @@
+#ifndef DYNAMIC_BITSET_H
+#define DYNAMIC_BITSET_H
+// (C) Copyright Chuck Allison and Jeremy Siek 2001, 2002.
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all
+// copies. This software is provided "as is" without express or
+// implied warranty, and with no claim as to its suitability for any
+// purpose.
+
+// With optimizations, bug fixes, and improvements by Gennaro Prota.
+
+// See http://www.boost.org/libs/dynamic_bitset for documentation.
+
+// -------------------------------------
+// CHANGE LOG:
+//
+// - corrected workaround for Dinkum lib's allocate() [GP]
+// - changed macro test for old iostreams [GP]
+// - removed #include <vector> for now. [JGS]
+// - Added __GNUC__ to compilers that cannot handle the constructor from basic_string. [JGS]
+// - corrected to_block_range [GP]
+// - corrected from_block_range [GP]
+// - Removed __GNUC__ from compilers that cannot handle the constructor
+// from basic_string and added the workaround suggested by GP. [JGS]
+// - Removed __BORLANDC__ from the #if around the basic_string
+// constructor. Luckily the fix by GP for g++ also fixes Borland. [JGS]
+
+#include <cassert>
+#include <string>
+#include <cstring> // for memset, memcpy, memcmp, etc.
+#include <algorithm> // for std::swap, std::min, std::copy, std::fill
+#include <memory> // for std::swap, std::min, std::copy, std::fill
+#include <stdlib.h>
+
+#include "../Type.h"
+
+namespace std
+{
+ typedef ::size_t size_t;
+}
+// (C) Copyright Chuck Allison and Jeremy Siek 2001, 2002.
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all
+// copies. This software is provided "as is" without express or
+// implied warranty, and with no claim as to its suitability for any
+// purpose.
+
+// With optimizations by Gennaro Prota.
+
+class dynamic_bitset_base
+{
+ typedef std::size_t size_type;
+public:
+#if defined(LINUX) && (defined (__LP64__) || defined(_AMD64_))
+ typedef unsigned int Block;
+#else
+ typedef unsigned long Block;
+#endif
+ enum { bits_per_block = 8 * sizeof(Block) };
+
+ dynamic_bitset_base()
+ : m_bits(0), m_num_bits(0), m_num_blocks(0) { }
+
+ dynamic_bitset_base(size_type num_bits) :
+ m_num_bits(num_bits),
+ m_num_blocks(calc_num_blocks(num_bits))
+ {
+ if (m_num_blocks != 0)
+ {
+ m_bits = new Block[m_num_blocks];
+ memset(m_bits, 0, m_num_blocks * sizeof(Block)); // G.P.S. ask to Jeremy
+ }
+ else
+ m_bits = 0;
+ }
+ ~dynamic_bitset_base() {
+ delete[]m_bits;;
+ }
+
+ Block* m_bits;
+ size_type m_num_bits;
+ size_type m_num_blocks;
+
+ static size_type word(size_type bit) { return bit / bits_per_block; } // [gps]
+ static size_type offset(size_type bit) { return bit % bits_per_block; } // [gps]
+ static Block mask1(size_type bit) { return Block(1) << offset(bit); }
+ static Block mask0(size_type bit) { return ~(Block(1) << offset(bit)); }
+ static size_type calc_num_blocks(size_type num_bits)
+ {
+ return (num_bits + bits_per_block - 1) / bits_per_block;
+ }
+};
+
+
+// ------- count table implementation --------------
+
+typedef unsigned char byte_t;
+
+template <bool bogus = true>
+struct bitcount {
+ typedef byte_t element_type;
+ static const byte_t table[];
+
+};
+//typedef count<true> table_t;
+
+
+// the table: wrapped in a class template, so
+// that it is only instantiated if/when needed
+//
+template <bool bogus>
+const byte_t bitcount<bogus>::table[] =
+{
+ // Automatically generated by GPTableGen.exe v.1.0
+ //
+0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
+};
+
+
+// -------------------------------------------------------
+template <typename BlockInputIterator>
+std::size_t initial_num_blocks(BlockInputIterator first,
+ BlockInputIterator last)
+{
+ std::size_t n = 0;
+ while (first != last)
+ ++first, ++n;
+ return n;
+}
+
+class dynamic_bitset : public dynamic_bitset_base
+{
+public:
+
+ typedef Block block_type;
+ typedef std::size_t size_type;
+ enum { bits_per_block = 8 * sizeof(Block) };
+
+ // reference to a bit
+ class reference
+ {
+ friend class dynamic_bitset;
+ dynamic_bitset* bs;
+ size_type bit;
+ reference(); // intentionally not implemented
+ reference(dynamic_bitset& bs_, size_type bit_) : bs(&bs_), bit(bit_) { }
+ public:
+ reference& operator=(bool value) // for b[i] = x
+ {
+ if (value)
+ bs->set(bit);
+ else
+ bs->reset(bit);
+ return *this;
+ }
+ reference& operator|=(bool value) // for b[i] |= x
+ {
+ if (value)
+ bs->set(bit);
+ return *this;
+ }
+ reference& operator&=(bool value) // for b[i] &= x
+ {
+ if (!(value && bs->test(bit)))
+ bs->reset(bit);
+ return *this;
+ }
+ reference& operator^=(bool value) // for b[i] ^= x
+ {
+ bs->set(bit, bs->test(bit) ^ value);
+ return *this;
+ }
+ reference& operator-=(bool value) // for b[i] -= x
+ {
+ if (!value)
+ bs->reset(bit);
+ return *this;
+ }
+ reference& operator=(const reference& j) // for b[i] = b[j]
+ {
+ if (j.bs->test(j.bit))
+ bs->set(bit);
+ else
+ bs->reset(bit);
+ return *this;
+ }
+ reference& operator|=(const reference& j) // for b[i] |= b[j]
+ {
+ if (j.bs->test(j.bit))
+ bs->set(bit);
+ return *this;
+ }
+ reference& operator&=(const reference& j) // for b[i] &= b[j]
+ {
+ if (!(j.bs->test(j.bit) && bs->test(bit)))
+ bs->reset(bit);
+ return *this;
+ }
+ reference& operator^=(const reference& j) // for b[i] ^= b[j]
+ {
+ bs->set(bit, bs->test(bit) ^ j.bs->test(j.bit));
+ return *this;
+ }
+ reference& operator-=(const reference& j) // for b[i] -= b[j]
+ {
+ if (!j.bs->test(j.bit))
+ bs->reset(bit);
+ return *this;
+ }
+ bool operator~() const // flips the bit
+ {
+ return !bs->test(bit);
+ }
+ operator bool() const // for x = b[i]
+ {
+ return bs->test(bit);
+ }
+ reference& flip() // for b[i].flip();
+ {
+ bs->flip(bit);
+ return *this;
+ }
+ };
+ typedef bool const_reference;
+
+ dynamic_bitset();
+ explicit
+ dynamic_bitset(size_type num_bits, unsigned long value = 0);
+
+ // The parenthesis around std::basic_string<CharT, Traits, Alloc>::npos
+ // in the code below are to avoid a g++ 3.2 bug and a Borland bug. -JGS
+ template <typename String>
+ explicit
+ dynamic_bitset(const String& s,
+ typename String::size_type pos = 0,
+ typename String::size_type n
+ = (String::npos))
+ : dynamic_bitset_base
+ (std::min(n, s.size() - pos))
+ {
+ // Locate sub string
+ Assert(pos > s.length());
+ from_string(s, pos, std::min(n, s.size() - pos));
+ }
+
+ // The first bit in *first is the least significant bit, and the
+ // last bit in the block just before *last is the most significant bit.
+ template <typename BlockInputIterator>
+ dynamic_bitset(BlockInputIterator first, BlockInputIterator last)
+ : dynamic_bitset_base
+ (initial_num_blocks(first, last)
+ * bits_per_block)
+ {
+ if (first != last) {
+ if (this->m_num_bits == 0) { // dealing with input iterators
+ this->append(first, last);
+ }
+ else {
+ // dealing with forward iterators, memory has been allocated
+ for (std::size_t i = 0; first != last; ++first, ++i)
+ set_block_(i, *first);
+ }
+ }
+ }
+
+
+ // copy constructor
+ dynamic_bitset(const dynamic_bitset& b);
+
+ void swap(dynamic_bitset& b);
+
+ dynamic_bitset& operator=(const dynamic_bitset& b);
+
+ // size changing operations
+ void resize(size_type num_bits, bool value = false);
+ void clear();
+ void push_back(bool bit);
+ void append(Block block);
+
+ // This is declared inside the class to avoid compiler bugs.
+ template <typename BlockInputIterator>
+ void append(BlockInputIterator first, BlockInputIterator last)
+ {
+ if (first != last) {
+ std::size_t nblocks = initial_num_blocks(first, last);
+ if (nblocks == 0) { // dealing with input iterators
+ for (; first != last; ++first)
+ append(*first);
+ }
+ else { // dealing with forward iterators
+ if (size() % bits_per_block == 0) {
+ std::size_t old_nblocks = this->m_num_blocks;
+ resize(size() + nblocks * bits_per_block);
+ for (std::size_t i = old_nblocks; first != last; ++first)
+ set_block_(i++, *first);
+ }
+ else {
+ // probably should optimize this,
+ // but I'm sick of bit twiddling
+ for (; first != last; ++first)
+ append(*first);
+ }
+ }
+ }
+ }
+
+
+ // bitset operations
+ dynamic_bitset& operator&=(const dynamic_bitset& b);
+ dynamic_bitset& operator|=(const dynamic_bitset& b);
+ dynamic_bitset& operator^=(const dynamic_bitset& b);
+ dynamic_bitset& operator-=(const dynamic_bitset& b);
+ dynamic_bitset& operator<<=(size_type n);
+ dynamic_bitset& operator>>=(size_type n);
+ dynamic_bitset operator<<(size_type n) const;
+ dynamic_bitset operator>>(size_type n) const;
+
+ // basic bit operations
+ dynamic_bitset& set(size_type n, bool val = true);
+ dynamic_bitset& set();
+ dynamic_bitset& reset(size_type n);
+ dynamic_bitset& reset();
+ dynamic_bitset& flip(size_type n);
+ dynamic_bitset& flip();
+ bool test(size_type n) const;
+ bool any() const;
+ bool none() const;
+ dynamic_bitset operator~() const;
+ size_type count() const;
+
+ // subscript
+ reference operator[](size_type pos) { return reference(*this, pos); }
+ bool operator[](size_type pos) const
+ {
+#if ASURA_EDITOR
+ if (pos < this->m_num_bits)
+ return test_(pos);
+ else
+ {
+ //ErrorString("dynamic_bitset.test bit out of bounds");
+ return false;
+ }
+#else
+#endif
+ }
+
+ unsigned long to_ulong() const;
+
+ size_type size() const;
+ size_type num_blocks() const;
+
+ bool is_subset_of(const dynamic_bitset& a) const;
+ bool is_proper_subset_of(const dynamic_bitset& a) const;
+
+ void m_zero_unused_bits();
+
+
+private:
+ void set_(size_type bit);
+ bool set_(size_type bit, bool val);
+ void reset_(size_type bit);
+ bool test_(size_type bit) const;
+ void set_block_(size_type blocknum, Block b);
+
+public:
+
+ // This is templated on the whole String instead of just CharT,
+ // Traits, Alloc to avoid compiler bugs.
+ template <typename String>
+ void from_string(const String& s, typename String::size_type pos,
+ typename String::size_type rlen)
+ {
+ reset(); // bugfix [gps]
+ size_type const tot = std::min(rlen, s.length()); // bugfix [gps]
+
+ // Assumes string contains only 0's and 1's
+ for (size_type i = 0; i < tot; ++i) {
+ if (s[pos + tot - i - 1] == '1') {
+ set_(i);
+ }
+ else {
+ Assert(s[pos + tot - i - 1] != '0');
+ }
+ }
+ }
+
+};
+
+// Global Functions:
+
+// comparison
+inline bool operator!=(const dynamic_bitset& a,
+ const dynamic_bitset& b);
+
+inline bool operator<=(const dynamic_bitset& a,
+ const dynamic_bitset& b);
+
+inline bool operator>(const dynamic_bitset& a,
+ const dynamic_bitset& b);
+
+inline bool operator>=(const dynamic_bitset& a,
+ const dynamic_bitset& b);
+
+// bitset operations
+inline dynamic_bitset
+operator&(const dynamic_bitset& b1,
+ const dynamic_bitset& b2);
+
+inline dynamic_bitset
+operator|(const dynamic_bitset& b1,
+ const dynamic_bitset& b2);
+
+inline dynamic_bitset
+operator^(const dynamic_bitset& b1,
+ const dynamic_bitset& b2);
+
+inline dynamic_bitset
+operator-(const dynamic_bitset& b1,
+ const dynamic_bitset& b2);
+
+
+template <typename String>
+void
+to_string(const dynamic_bitset& b,
+ String& s);
+
+template <typename BlockOutputIterator>
+void
+to_block_range(const dynamic_bitset& b,
+ BlockOutputIterator result);
+
+template <typename BlockIterator>
+inline void
+from_block_range(BlockIterator first, BlockIterator last,
+ dynamic_bitset& result);
+
+
+//=============================================================================
+// dynamic_bitset implementation
+
+
+//-----------------------------------------------------------------------------
+// constructors, etc.
+
+inline dynamic_bitset::dynamic_bitset()
+ : dynamic_bitset_base(0) { }
+
+inline dynamic_bitset::
+dynamic_bitset(size_type num_bits, unsigned long value)
+ : dynamic_bitset_base(num_bits)
+{
+ const size_type M = std::min(sizeof(unsigned long) * 8, num_bits);
+ for (size_type i = 0; i < M; ++i, value >>= 1) // [G.P.S.] to be optimized
+ if (value & 0x1)
+ set_(i);
+}
+
+// copy constructor
+inline dynamic_bitset::
+dynamic_bitset(const dynamic_bitset& b)
+ : dynamic_bitset_base(b.size())
+{
+ memcpy(this->m_bits, b.m_bits, this->m_num_blocks * sizeof(Block));
+}
+
+inline void dynamic_bitset::
+swap(dynamic_bitset& b)
+{
+ std::swap(this->m_bits, b.m_bits);
+ std::swap(this->m_num_bits, b.m_num_bits);
+ std::swap(this->m_num_blocks, b.m_num_blocks);
+}
+
+inline dynamic_bitset& dynamic_bitset::
+operator=(const dynamic_bitset& b)
+{
+ dynamic_bitset tmp(b);
+ this->swap(tmp);
+ return *this;
+}
+
+//-----------------------------------------------------------------------------
+// size changing operations
+
+inline void dynamic_bitset::
+resize(size_type num_bits, bool value)
+{
+ if (num_bits == size())
+ return;
+ if (num_bits == 0)
+ {
+ this->m_num_bits = 0;
+ this->m_num_blocks = 0;
+ delete this->m_bits;
+ this->m_bits = 0;
+ return;
+ }
+ size_type new_nblocks = this->calc_num_blocks(num_bits);
+ Block* d = new Block[new_nblocks];
+ if (num_bits < size()) { // shrink
+ std::copy(this->m_bits, this->m_bits + new_nblocks, d);
+ std::swap(d, this->m_bits);
+ delete[]d;
+ }
+ else { // grow
+ std::copy(this->m_bits, this->m_bits + this->m_num_blocks, d);
+ Block val = value ? ~static_cast<Block>(0) : static_cast<Block>(0);
+ std::fill(d + this->m_num_blocks, d + new_nblocks, val);
+ std::swap(d, this->m_bits);
+ for (std::size_t i = this->m_num_bits;
+ i < this->m_num_blocks * bits_per_block; ++i)
+ set_(i, value);
+ if (d != 0)
+ delete[]d;
+ }
+ this->m_num_bits = num_bits;
+ this->m_num_blocks = this->calc_num_blocks(num_bits);
+ m_zero_unused_bits();
+}
+
+inline void dynamic_bitset::
+clear()
+{
+ if (this->m_bits != 0) {
+ delete this->m_bits;
+ this->m_bits = 0;
+ this->m_num_bits = 0;
+ this->m_num_blocks = 0;
+ }
+}
+
+
+inline void dynamic_bitset::
+push_back(bool bit)
+{
+ this->resize(this->size() + 1);
+ set_(this->size() - 1, bit);
+}
+
+inline void dynamic_bitset::
+append(Block value)
+{
+ std::size_t old_size = size();
+ resize(old_size + bits_per_block);
+ if (size() % bits_per_block == 0)
+ set_block_(this->m_num_blocks - 1, value);
+ else {
+ // G.P.S. to be optimized
+ for (std::size_t i = old_size; i < size(); ++i, value >>= 1)
+ set_(i, value & 1);
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// bitset operations
+inline dynamic_bitset&
+dynamic_bitset::operator&=(const dynamic_bitset& rhs)
+{
+ Assert(size() != rhs.size());
+ for (size_type i = 0; i < this->m_num_blocks; ++i)
+ this->m_bits[i] &= rhs.m_bits[i];
+ return *this;
+}
+
+inline dynamic_bitset&
+dynamic_bitset::operator|=(const dynamic_bitset& rhs)
+{
+ Assert(size() != rhs.size());
+ for (size_type i = 0; i < this->m_num_blocks; ++i)
+ this->m_bits[i] |= rhs.m_bits[i];
+ m_zero_unused_bits();
+ return *this;
+}
+
+inline dynamic_bitset&
+dynamic_bitset::operator^=(const dynamic_bitset& rhs)
+{
+ Assert(size() != rhs.size());
+ for (size_type i = 0; i < this->m_num_blocks; ++i)
+ this->m_bits[i] ^= rhs.m_bits[i];
+ m_zero_unused_bits();
+ return *this;
+}
+
+inline dynamic_bitset&
+dynamic_bitset::operator-=(const dynamic_bitset& rhs)
+{
+ Assert(size() != rhs.size());
+ for (size_type i = 0; i < this->m_num_blocks; ++i)
+ this->m_bits[i] = this->m_bits[i] & ~rhs.m_bits[i];
+ m_zero_unused_bits();
+ return *this;
+}
+
+inline dynamic_bitset&
+dynamic_bitset::operator<<=(size_type n)
+{
+ if (n >= this->m_num_bits)
+ return reset();
+ //else
+ if (n > 0)
+ {
+ size_type const last = this->m_num_blocks - 1; // m_num_blocks is >= 1
+ size_type const div = n / bits_per_block; // div is <= last
+ size_type const r = n % bits_per_block;
+
+ // PRE: div != 0 or r != 0
+
+ if (r != 0) {
+
+ block_type const rs = bits_per_block - r;
+
+ for (size_type i = last - div; i > 0; --i) {
+ this->m_bits[i + div] = (this->m_bits[i] << r) | (this->m_bits[i - 1] >> rs);
+ }
+ this->m_bits[div] = this->m_bits[0] << r;
+
+ }
+ else {
+ for (size_type i = last - div; i > 0; --i) {
+ this->m_bits[i + div] = this->m_bits[i];
+ }
+ this->m_bits[div] = this->m_bits[0];
+ }
+
+
+ // div blocks are zero filled at the less significant end
+ std::fill(this->m_bits, this->m_bits + div, static_cast<block_type>(0));
+
+
+ }
+
+ return *this;
+
+
+}
+
+
+
+
+
+
+
+// NOTE: this assumes that within a single block bits are
+// numbered from right to left. G.P.S.
+//
+// static Block offset(size_type bit)
+// { return bit % bits_per_block; }
+//
+//
+// In the implementation below the 'if (r != 0)' is logically
+// unnecessary. It's there as an optimization only: in fact
+// for r==0 the first branch becomes the second one with the
+// b[last-div] = b[last] >> r; statement that does the work of
+// the last iteration.
+//
+inline
+dynamic_bitset & dynamic_bitset::operator>>=(size_type n) {
+ if (n >= this->m_num_bits) {
+ return reset();
+ }
+ //else
+ if (n > 0) {
+
+ size_type const last = this->m_num_blocks - 1; // m_num_blocks is >= 1
+ size_type const div = n / bits_per_block; // div is <= last
+ size_type const r = n % bits_per_block;
+
+ // PRE: div != 0 or r != 0
+
+ if (r != 0) {
+
+ block_type const ls = bits_per_block - r;
+
+ for (size_type i = div; i < last; ++i) {
+ this->m_bits[i - div] = (this->m_bits[i] >> r) | (this->m_bits[i + 1] << ls);
+ }
+ // r bits go to zero
+ this->m_bits[last - div] = this->m_bits[last] >> r;
+ }
+
+ else {
+ for (size_type i = div; i <= last; ++i) {
+ this->m_bits[i - div] = this->m_bits[i];
+ }
+ // note the '<=': the last iteration 'absorbs'
+ // this->m_bits[last-div] = this->m_bits[last] >> 0;
+ }
+
+
+
+ // div blocks are zero filled at the most significant end
+ std::fill(this->m_bits + (this->m_num_blocks - div), this->m_bits + this->m_num_blocks, static_cast<block_type>(0));
+ }
+
+ return *this;
+}
+
+
+
+
+
+
+
+inline dynamic_bitset
+dynamic_bitset::operator<<(size_type n) const
+{
+ dynamic_bitset r(*this);
+ return r <<= n;
+}
+
+inline dynamic_bitset
+dynamic_bitset::operator>>(size_type n) const
+{
+ dynamic_bitset r(*this);
+ return r >>= n;
+}
+
+
+//-----------------------------------------------------------------------------
+// basic bit operations
+
+inline dynamic_bitset&
+dynamic_bitset::set(size_type pos, bool val)
+{
+ Assert(pos >= this->m_num_bits);
+ set_(pos, val);
+ return *this;
+}
+
+inline dynamic_bitset&
+dynamic_bitset::set()
+{
+ if (this->m_num_bits > 0) {
+ using namespace std;
+ memset(this->m_bits, ~0u, this->m_num_blocks * sizeof(this->m_bits[0]));
+ m_zero_unused_bits();
+ }
+ return *this;
+}
+
+inline dynamic_bitset&
+dynamic_bitset::reset(size_type pos)
+{
+ Assert(pos >= this->m_num_bits);
+ reset_(pos);
+ return *this;
+}
+
+inline dynamic_bitset&
+dynamic_bitset::reset()
+{
+ if (this->m_num_bits > 0) {
+ using namespace std;
+ memset(this->m_bits, 0, this->m_num_blocks * sizeof(this->m_bits[0]));
+ }
+ return *this;
+}
+
+inline dynamic_bitset&
+dynamic_bitset::flip(size_type pos)
+{
+ Assert(pos >= this->m_num_bits);
+ this->m_bits[this->word(pos)] ^= this->mask1(pos);
+ return *this;
+}
+
+inline dynamic_bitset&
+dynamic_bitset::flip()
+{
+ for (size_type i = 0; i < this->m_num_blocks; ++i)
+ this->m_bits[i] = ~this->m_bits[i];
+ m_zero_unused_bits();
+ return *this;
+}
+
+inline bool dynamic_bitset::test(size_type pos) const
+{
+#if ASURA_EDITOR
+ if (pos < this->m_num_bits)
+ return test_(pos);
+ else
+ {
+ //ErrorString("dynamic_bitset.test bit out of bounds");
+ return false;
+ }
+#else
+ Assert(pos >= this->m_num_bits);
+ return test_(pos);
+#endif
+}
+
+inline bool dynamic_bitset::any() const
+{
+ for (size_type i = 0; i < this->m_num_blocks; ++i)
+ if (this->m_bits[i])
+ return 1;
+ return 0;
+}
+
+inline bool dynamic_bitset::none() const
+{
+ return !any();
+}
+
+inline dynamic_bitset
+dynamic_bitset::operator~() const
+{
+ dynamic_bitset b(*this);
+ b.flip();
+ return b;
+}
+
+
+/* snipped: [gps]
+
+The following is the straightforward implementation of count(), which
+we leave here in a comment for documentation purposes.
+
+template <typename Block, typename Allocator>
+typename dynamic_bitset::size_type
+dynamic_bitset::count() const
+{
+ size_type sum = 0;
+ for (size_type i = 0; i != this->m_num_bits; ++i)
+ if (test_(i))
+ ++sum;
+ return sum;
+}
+
+The actual algorithm used is based on using a lookup
+table.
+
+
+ The basic idea of the method is to pick up X bits at a time
+ from the internal array of blocks and consider those bits as
+ the binary representation of a number N. Then, to use a table
+ of 1<<X elements where table[N] is the number of '1' digits
+ in the binary representation of N (i.e. in our X bits).
+
+ Note that the table can be oversized (i.e. can even have more
+ than 1<<X elements; in that case only the first 1<<X will be
+ actually used) but it cannot be undersized.
+ In this implementation X is 8 (but can be easily changed: you
+ just have to change the definition of count<>::max_bits) and
+ the internal array of blocks is seen as an array of bytes: if
+ a byte has exactly 8 bits then it's enough to sum the value
+ of table[B] for each byte B. Otherwise 8 bits at a time are
+ 'extracted' from each byte by using another loop. As a further
+ efficiency consideration note that even if you have, let's say,
+ 32-bit chars the inner loop will not do 4 (i.e. 32/8) iterations,
+ unless you have at least one bit set in the highest 8 bits of the
+ byte.
+
+ Note also that the outmost if/else is not necessary but is there
+ to help the optimizer (and one of the two branches is always dead
+ code).
+
+ Aras: hardcoded table to be always max_bits=8. To help not so good compilers.
+
+*/
+
+
+inline dynamic_bitset::size_type
+dynamic_bitset::count() const
+{
+ const byte_t * p = reinterpret_cast<const byte_t*>(this->m_bits);
+ const byte_t * past_end = p + this->m_num_blocks * sizeof(Block);
+
+ size_type num = 0;
+
+ while (p < past_end) {
+ num += bitcount<>::table[*p];
+ ++p;
+ }
+
+ return num;
+}
+
+
+//-----------------------------------------------------------------------------
+// conversions
+
+// take as ref param instead?
+template <typename CharT, typename Alloc>
+void
+to_string(const dynamic_bitset& b,
+ std::basic_string<CharT, Alloc>& s)
+{
+ s.assign(b.size(), '0');
+ for (std::size_t i = 0; i < b.size(); ++i)
+ if (b.test(i)) // [G.P.S.]
+ s[b.size() - 1 - i] = '1';
+}
+
+
+// Differently from to_string this function dumps out
+// every bit of the internal representation (useful
+// for debugging purposes)
+//
+template <typename CharT, typename Alloc>
+void
+dump_to_string(const dynamic_bitset& b,
+ std::basic_string<CharT, Alloc>& s)
+{
+ std::size_t const len = b.m_num_blocks * (dynamic_bitset::bits_per_block);
+ s.assign(len, '0');
+ for (std::size_t i = 0; i != len; ++i)
+ if (b[i])// could use test_ here, but we have friend issues.-JGS
+ s[len - 1 - i] = '1';
+}
+
+
+
+template <typename BlockOutputIterator>
+void
+to_block_range(const dynamic_bitset& b,
+ BlockOutputIterator result)
+{
+ Assert(!(b.size() != 0 || b.num_blocks() == 0));
+ std::copy(b.m_bits, b.m_bits + b.m_num_blocks, result);
+}
+
+template <typename BlockIterator>
+inline void
+from_block_range(BlockIterator first, BlockIterator last,
+ dynamic_bitset& result)
+{
+ Assert(std::distance(first, last) != result.num_blocks());
+ std::copy(first, last, result.m_bits);
+ result.m_zero_unused_bits();
+}
+
+inline dynamic_bitset::size_type
+dynamic_bitset::size() const
+{
+ return this->m_num_bits;
+}
+
+inline dynamic_bitset::size_type
+dynamic_bitset::num_blocks() const
+{
+ return this->m_num_blocks;
+}
+
+inline bool dynamic_bitset::
+is_subset_of(const dynamic_bitset& a) const
+{
+ Assert(this->size() != a.size());
+ for (size_type i = 0; i < this->m_num_blocks; ++i)
+ if (this->m_bits[i] & ~a.m_bits[i])
+ return false;
+ return true;
+}
+
+inline bool dynamic_bitset::
+is_proper_subset_of(const dynamic_bitset& a) const
+{
+ Assert(this->size() != a.size());
+ bool proper = false;
+ for (size_type i = 0; i < this->m_num_blocks; ++i) {
+ Block bt = this->m_bits[i], ba = a.m_bits[i];
+ if (ba & ~bt)
+ proper = true;
+ if (bt & ~ba)
+ return false;
+ }
+ return proper;
+}
+
+//-----------------------------------------------------------------------------
+// comparison
+
+inline bool operator==(const dynamic_bitset& a,
+ const dynamic_bitset& b)
+{
+ using namespace std;
+ return (a.m_num_bits == b.m_num_bits) &&
+ ((a.m_num_bits == 0) ||
+ !memcmp(a.m_bits, b.m_bits, a.m_num_blocks * sizeof(a.m_bits[0])));
+}
+
+inline bool operator!=(const dynamic_bitset& a,
+ const dynamic_bitset& b)
+{
+ return !(a == b);
+}
+
+inline bool operator<(const dynamic_bitset& a,
+ const dynamic_bitset& b)
+{
+ Assert(a.size() != b.size());
+ typedef dynamic_bitset::size_type size_type;
+
+ if (a.size() == 0)
+ return false;
+
+ // Since we are storing the most significant bit
+ // at pos == size() - 1, we need to do the memcmp in reverse.
+
+ // Compare a block at a time
+ for (size_type i = a.m_num_blocks - 1; i > 0; --i)
+ if (a.m_bits[i] < b.m_bits[i])
+ return true;
+ else if (a.m_bits[i] > b.m_bits[i])
+ return false;
+
+ if (a.m_bits[0] < b.m_bits[0])
+ return true;
+ else
+ return false;
+}
+
+inline bool operator<=(const dynamic_bitset& a,
+ const dynamic_bitset& b)
+{
+ return !(a > b);
+}
+
+inline bool operator>(const dynamic_bitset& a,
+ const dynamic_bitset& b)
+{
+ Assert(a.size() != b.size());
+ typedef dynamic_bitset::size_type size_type;
+
+ if (a.size() == 0)
+ return false;
+
+ // Since we are storing the most significant bit
+ // at pos == size() - 1, we need to do the memcmp in reverse.
+
+ // Compare a block at a time
+ for (size_type i = a.m_num_blocks - 1; i > 0; --i)
+ if (a.m_bits[i] < b.m_bits[i])
+ return false;
+ else if (a.m_bits[i] > b.m_bits[i])
+ return true;
+
+ if (a.m_bits[0] > b.m_bits[0])
+ return true;
+ else
+ return false;
+}
+
+inline bool operator>=(const dynamic_bitset& a,
+ const dynamic_bitset& b)
+{
+ return !(a < b);
+}
+
+//-----------------------------------------------------------------------------
+// bitset operations
+
+inline dynamic_bitset
+operator&(const dynamic_bitset& x,
+ const dynamic_bitset& y)
+{
+ dynamic_bitset b(x);
+ return b &= y;
+}
+
+inline dynamic_bitset
+operator|(const dynamic_bitset& x,
+ const dynamic_bitset& y)
+{
+ dynamic_bitset b(x);
+ return b |= y;
+}
+
+inline dynamic_bitset
+operator^(const dynamic_bitset& x,
+ const dynamic_bitset& y)
+{
+ dynamic_bitset b(x);
+ return b ^= y;
+}
+
+inline dynamic_bitset
+operator-(const dynamic_bitset& x,
+ const dynamic_bitset& y)
+{
+ dynamic_bitset b(x);
+ return b -= y;
+}
+
+
+//-----------------------------------------------------------------------------
+// private member functions
+
+inline void dynamic_bitset::
+set_(size_type bit)
+{
+ this->m_bits[this->word(bit)] |= this->mask1(bit);
+}
+
+inline void dynamic_bitset::
+set_block_(size_type blocknum, Block value)
+{
+ this->m_bits[blocknum] = value;
+}
+
+inline void dynamic_bitset::
+reset_(size_type b)
+{
+ this->m_bits[this->word(b)] &= this->mask0(b);
+}
+
+inline bool dynamic_bitset::test_(size_type b) const
+{
+ return (this->m_bits[this->word(b)] & this->mask1(b)) != static_cast<Block>(0);
+}
+
+inline bool dynamic_bitset::set_(size_type n, bool value)
+{
+ if (value)
+ set_(n);
+ else
+ reset_(n);
+ return value != static_cast<Block>(0);
+}
+
+
+// If size() is not a multiple of bits_per_block
+// then not all the bits in the last block are used.
+// This function resets the unused bits (convenient
+// for the implementation of many member functions)
+//
+inline void dynamic_bitset::m_zero_unused_bits()
+{
+ Assert(this->m_num_blocks != this->calc_num_blocks(this->m_num_bits));
+
+ // if != 0 this is the number of bits used in the last block
+ const size_type used_bits = this->m_num_bits % bits_per_block;
+
+ if (used_bits != 0)
+ this->m_bits[this->m_num_blocks - 1] &= ~(~static_cast<Block>(0) << used_bits);
+
+}
+
+#endif
diff --git a/Source/modules/asura-base/Utils.h b/Source/modules/asura-base/Utils.h
new file mode 100644
index 0000000..dfcd2a6
--- /dev/null
+++ b/Source/modules/asura-base/Utils.h
@@ -0,0 +1,6 @@
+#ifndef _ASURA_UTILS_H_
+#define _ASURA_UTILS_H_
+
+#include "UtilsModule.h"
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-base/UtilsConfig.h b/Source/modules/asura-base/UtilsConfig.h
new file mode 100644
index 0000000..df52b13
--- /dev/null
+++ b/Source/modules/asura-base/UtilsConfig.h
@@ -0,0 +1,13 @@
+#ifndef _ASURA_UTILS_CONFIG_H_
+#define _ASURA_UTILS_CONFIG_H_
+
+// ı
+#include "asura-base/Configure.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/modules/asura-base/UtilsModule.cpp b/Source/modules/asura-base/UtilsModule.cpp
new file mode 100644
index 0000000..1a40645
--- /dev/null
+++ b/Source/modules/asura-base/UtilsModule.cpp
@@ -0,0 +1,25 @@
+#include "UtilsModule.h"
+
+using namespace AsuraEngine::FileSystem;
+using namespace AsuraEngine::Threads;
+
+namespace AsuraEngine
+{
+
+ void UtilsModule::Initialize(Luax::LuaxState& state)
+ {
+ // IO
+ LUAX_REGISTER_SINGLETON(state, FileManager);
+ LUAX_REGISTER_FACTORY(state, IOTask);
+ LUAX_REGISTER_FACTORY(state, DataBuffer);
+ LUAX_REGISTER_FACTORY(state, FileData);
+ LUAX_REGISTER_FACTORY(state, File);
+ // Threads
+ LUAX_REGISTER_FACTORY(state, Thread);
+ }
+
+ void UtilsModule::Finalize(Luax::LuaxState& state)
+ {
+ }
+
+} \ No newline at end of file
diff --git a/Source/modules/asura-base/UtilsModule.h b/Source/modules/asura-base/UtilsModule.h
new file mode 100644
index 0000000..f9bd875
--- /dev/null
+++ b/Source/modules/asura-base/UtilsModule.h
@@ -0,0 +1,34 @@
+#ifndef _ASURA_LIBS_UTIL_MODULE_H_
+#define _ASURA_LIBS_UTIL_MODULE_H_
+
+#include "FileSystem/FileManager.h"
+#include "FileSystem/DataBuffer.h"
+#include "FileSystem/FileData.h"
+#include "FileSystem/file.h"
+#include "FileSystem/IOTask.h"
+
+#include "Threads/Thread.h"
+
+#include "Module.h"
+
+#include "Classes.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