diff options
Diffstat (limited to 'Source/modules/asura-base')
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 | 
