summaryrefslogtreecommitdiff
path: root/Source/modules
diff options
context:
space:
mode:
authorchai <chaifix@163.com>2019-08-07 21:08:47 +0800
committerchai <chaifix@163.com>2019-08-07 21:08:47 +0800
commit0c391fdbce5a079cf03e483eb6174dd47806163d (patch)
treeb06cd7a9d0ae0d9bb9e82f3dcb786dfce11f8628 /Source/modules
parent9686368e58e25cbd6dc37d686bdd2be3f80486d6 (diff)
*misc
Diffstat (limited to 'Source/modules')
-rw-r--r--Source/modules/asura-base/BuildConfigure.h8
-rw-r--r--Source/modules/asura-base/Classes.h9
-rw-r--r--Source/modules/asura-base/Configure.h58
-rw-r--r--Source/modules/asura-base/Exception.cpp40
-rw-r--r--Source/modules/asura-base/Exception.h30
-rw-r--r--Source/modules/asura-base/FileSystem/Binding/_compressor.cpp0
-rw-r--r--Source/modules/asura-base/FileSystem/Binding/_data_buffer.cpp132
-rw-r--r--Source/modules/asura-base/FileSystem/Binding/_file.cpp223
-rw-r--r--Source/modules/asura-base/FileSystem/Binding/_file_data.cpp60
-rw-r--r--Source/modules/asura-base/FileSystem/Binding/_file_manager.cpp265
-rw-r--r--Source/modules/asura-base/FileSystem/Binding/_io_task.cpp46
-rw-r--r--Source/modules/asura-base/FileSystem/Compressor.cpp11
-rw-r--r--Source/modules/asura-base/FileSystem/Compressor.h28
-rw-r--r--Source/modules/asura-base/FileSystem/DataBuffer.cpp156
-rw-r--r--Source/modules/asura-base/FileSystem/DataBuffer.h87
-rw-r--r--Source/modules/asura-base/FileSystem/DecodedData.h41
-rw-r--r--Source/modules/asura-base/FileSystem/File.cpp294
-rw-r--r--Source/modules/asura-base/FileSystem/File.h146
-rw-r--r--Source/modules/asura-base/FileSystem/FileData.cpp59
-rw-r--r--Source/modules/asura-base/FileSystem/FileData.h69
-rw-r--r--Source/modules/asura-base/FileSystem/FileManager.cpp198
-rw-r--r--Source/modules/asura-base/FileSystem/FileManager.h112
-rw-r--r--Source/modules/asura-base/FileSystem/IOBatchTask.cpp0
-rw-r--r--Source/modules/asura-base/FileSystem/IOBatchTask.h31
-rw-r--r--Source/modules/asura-base/FileSystem/IOTask.cpp61
-rw-r--r--Source/modules/asura-base/FileSystem/IOTask.h56
-rw-r--r--Source/modules/asura-base/FileSystem/Renewable.h27
-rw-r--r--Source/modules/asura-base/Manager.hpp14
-rw-r--r--Source/modules/asura-base/Math/Curve.cpp0
-rw-r--r--Source/modules/asura-base/Math/Curve.h0
-rw-r--r--Source/modules/asura-base/Math/Functions.cpp0
-rw-r--r--Source/modules/asura-base/Math/Functions.h0
-rw-r--r--Source/modules/asura-base/Math/Matrix44.cpp217
-rw-r--r--Source/modules/asura-base/Math/Matrix44.h96
-rw-r--r--Source/modules/asura-base/Math/Quaternion.cpp0
-rw-r--r--Source/modules/asura-base/Math/Quaternion.h18
-rw-r--r--Source/modules/asura-base/Math/Random.h88
-rw-r--r--Source/modules/asura-base/Math/RangedValue.cpp0
-rw-r--r--Source/modules/asura-base/Math/RangedValue.h0
-rw-r--r--Source/modules/asura-base/Math/Rect.hpp50
-rw-r--r--Source/modules/asura-base/Math/Rect.inc28
-rw-r--r--Source/modules/asura-base/Math/Transform.cpp0
-rw-r--r--Source/modules/asura-base/Math/Transform.h30
-rw-r--r--Source/modules/asura-base/Math/Vector2.hpp72
-rw-r--r--Source/modules/asura-base/Math/Vector2.inc114
-rw-r--r--Source/modules/asura-base/Math/Vector3.hpp235
-rw-r--r--Source/modules/asura-base/Math/Vector3.inc145
-rw-r--r--Source/modules/asura-base/Math/Vector4.h234
-rw-r--r--Source/modules/asura-base/Math/Vector4.inc152
-rw-r--r--Source/modules/asura-base/Module.h32
-rw-r--r--Source/modules/asura-base/Scripting/Scripting.h30
-rw-r--r--Source/modules/asura-base/Singleton.hpp59
-rw-r--r--Source/modules/asura-base/Threads/Conditional.cpp84
-rw-r--r--Source/modules/asura-base/Threads/Conditional.h41
-rw-r--r--Source/modules/asura-base/Threads/Coroutine.cpp15
-rw-r--r--Source/modules/asura-base/Threads/Coroutine.h40
-rw-r--r--Source/modules/asura-base/Threads/Mutex.cpp105
-rw-r--r--Source/modules/asura-base/Threads/Mutex.h128
-rw-r--r--Source/modules/asura-base/Threads/Semaphore.cpp99
-rw-r--r--Source/modules/asura-base/Threads/Semaphore.h68
-rw-r--r--Source/modules/asura-base/Threads/Task.cpp10
-rw-r--r--Source/modules/asura-base/Threads/Task.h43
-rw-r--r--Source/modules/asura-base/Threads/Thread.cpp287
-rw-r--r--Source/modules/asura-base/Threads/Thread.h222
-rw-r--r--Source/modules/asura-base/Threads/ThreadImplPosix.cpp0
-rw-r--r--Source/modules/asura-base/Threads/ThreadImplPosix.h2
-rw-r--r--Source/modules/asura-base/Threads/ThreadImplSDL.cpp0
-rw-r--r--Source/modules/asura-base/Threads/ThreadImplSDL.h0
-rw-r--r--Source/modules/asura-base/Threads/ThreadImplStd.cpp0
-rw-r--r--Source/modules/asura-base/Threads/ThreadImplStd.h41
-rw-r--r--Source/modules/asura-base/Threads/ThreadImplWin32.cpp77
-rw-r--r--Source/modules/asura-base/Threads/ThreadImplWin32.h44
-rw-r--r--Source/modules/asura-base/Threads/Threadable.h23
-rw-r--r--Source/modules/asura-base/Threads/binding/_coroutine.cpp38
-rw-r--r--Source/modules/asura-base/Threads/binding/_thread.cpp208
-rw-r--r--Source/modules/asura-base/Type.h37
-rw-r--r--Source/modules/asura-base/Utilities/Hash128.cpp0
-rw-r--r--Source/modules/asura-base/Utilities/Hash128.h0
-rw-r--r--Source/modules/asura-base/Utilities/LinkedList.cpp0
-rw-r--r--Source/modules/asura-base/Utilities/LinkedList.h0
-rw-r--r--Source/modules/asura-base/Utilities/StringMap.cpp0
-rw-r--r--Source/modules/asura-base/Utilities/StringMap.hpp29
-rw-r--r--Source/modules/asura-base/Utilities/dynamic_bitset.h1150
-rw-r--r--Source/modules/asura-base/Utils.h6
-rw-r--r--Source/modules/asura-base/UtilsConfig.h13
-rw-r--r--Source/modules/asura-base/UtilsModule.cpp25
-rw-r--r--Source/modules/asura-base/UtilsModule.h34
-rw-r--r--Source/modules/asura-box2d/Box2DModule.cpp0
-rw-r--r--Source/modules/asura-box2d/Box2DModule.h19
-rw-r--r--Source/modules/asura-box2d/Physics/Body.h64
-rw-r--r--Source/modules/asura-box2d/Physics/ChainShape.h29
-rw-r--r--Source/modules/asura-box2d/Physics/CircleShape.h0
-rw-r--r--Source/modules/asura-box2d/Physics/Contact.h0
-rw-r--r--Source/modules/asura-box2d/Physics/DebugDraw.h9
-rw-r--r--Source/modules/asura-box2d/Physics/DistanceJoint.h0
-rw-r--r--Source/modules/asura-box2d/Physics/EdgeShape.h0
-rw-r--r--Source/modules/asura-box2d/Physics/Fixture.h17
-rw-r--r--Source/modules/asura-box2d/Physics/FrictionJoint.h0
-rw-r--r--Source/modules/asura-box2d/Physics/GearJoint.h0
-rw-r--r--Source/modules/asura-box2d/Physics/Joint.h0
-rw-r--r--Source/modules/asura-box2d/Physics/MotorJoint.h0
-rw-r--r--Source/modules/asura-box2d/Physics/MouseJoint.h0
-rw-r--r--Source/modules/asura-box2d/Physics/PolygonShape.h0
-rw-r--r--Source/modules/asura-box2d/Physics/PrismaticJoint.h0
-rw-r--r--Source/modules/asura-box2d/Physics/PulleyJoint.h0
-rw-r--r--Source/modules/asura-box2d/Physics/RevoluteJoint.h0
-rw-r--r--Source/modules/asura-box2d/Physics/RopeJoint.h0
-rw-r--r--Source/modules/asura-box2d/Physics/Shape.h0
-rw-r--r--Source/modules/asura-box2d/Physics/WeldJoint.h0
-rw-r--r--Source/modules/asura-box2d/Physics/WheelJoint.h0
-rw-r--r--Source/modules/asura-box2d/Physics/World.h18
-rw-r--r--Source/modules/asura-box2d/Physics/binding/_body.cpp171
-rw-r--r--Source/modules/asura-box2d/Physics/binding/_world.cpp21
-rw-r--r--Source/modules/asura-core/Application.cpp23
-rw-r--r--Source/modules/asura-core/Application.h69
-rw-r--r--Source/modules/asura-core/CoreConfig.h13
-rw-r--r--Source/modules/asura-core/CoreModule.cpp25
-rw-r--r--Source/modules/asura-core/CoreModule.h26
-rw-r--r--Source/modules/asura-core/Font/Glyph.cpp0
-rw-r--r--Source/modules/asura-core/Font/Glyph.h0
-rw-r--r--Source/modules/asura-core/Font/String.cpp376
-rw-r--r--Source/modules/asura-core/Font/String.hpp595
-rw-r--r--Source/modules/asura-core/Font/String.inc29
-rw-r--r--Source/modules/asura-core/Font/TTF.cpp0
-rw-r--r--Source/modules/asura-core/Font/TTF.h17
-rw-r--r--Source/modules/asura-core/Font/Utf.hpp720
-rw-r--r--Source/modules/asura-core/Font/Utf.inc752
-rw-r--r--Source/modules/asura-core/Graphics/BlendMode.h17
-rw-r--r--Source/modules/asura-core/Graphics/Canvas.cpp49
-rw-r--r--Source/modules/asura-core/Graphics/Canvas.h73
-rw-r--r--Source/modules/asura-core/Graphics/Color.cpp58
-rw-r--r--Source/modules/asura-core/Graphics/Color.h75
-rw-r--r--Source/modules/asura-core/Graphics/Color32.cpp53
-rw-r--r--Source/modules/asura-core/Graphics/Color32.h58
-rw-r--r--Source/modules/asura-core/Graphics/ColorPalette.h0
-rw-r--r--Source/modules/asura-core/Graphics/DrawInfo.cpp10
-rw-r--r--Source/modules/asura-core/Graphics/DrawInfo.h19
-rw-r--r--Source/modules/asura-core/Graphics/DrawUtil.cpp0
-rw-r--r--Source/modules/asura-core/Graphics/DrawUtil.h0
-rw-r--r--Source/modules/asura-core/Graphics/GPUBuffer.cpp151
-rw-r--r--Source/modules/asura-core/Graphics/GPUBuffer.h93
-rw-r--r--Source/modules/asura-core/Graphics/GfxDevice.cpp188
-rw-r--r--Source/modules/asura-core/Graphics/GfxDevice.h141
-rw-r--r--Source/modules/asura-core/Graphics/GraphicsHelper.cpp0
-rw-r--r--Source/modules/asura-core/Graphics/GraphicsHelper.h15
-rw-r--r--Source/modules/asura-core/Graphics/Image.cpp103
-rw-r--r--Source/modules/asura-core/Graphics/Image.h63
-rw-r--r--Source/modules/asura-core/Graphics/IndexBuffer.cpp17
-rw-r--r--Source/modules/asura-core/Graphics/IndexBuffer.h34
-rw-r--r--Source/modules/asura-core/Graphics/MatrixStack.cpp75
-rw-r--r--Source/modules/asura-core/Graphics/MatrixStack.h58
-rw-r--r--Source/modules/asura-core/Graphics/Mesh2D.cpp0
-rw-r--r--Source/modules/asura-core/Graphics/Mesh2D.h52
-rw-r--r--Source/modules/asura-core/Graphics/Polygon2D.cpp0
-rw-r--r--Source/modules/asura-core/Graphics/Polygon2D.h0
-rw-r--r--Source/modules/asura-core/Graphics/Quad.cpp0
-rw-r--r--Source/modules/asura-core/Graphics/Quad.h1
-rw-r--r--Source/modules/asura-core/Graphics/RenderState.h47
-rw-r--r--Source/modules/asura-core/Graphics/RenderTarget.cpp0
-rw-r--r--Source/modules/asura-core/Graphics/RenderTarget.h52
-rw-r--r--Source/modules/asura-core/Graphics/Shader.cpp282
-rw-r--r--Source/modules/asura-core/Graphics/Shader.h117
-rw-r--r--Source/modules/asura-core/Graphics/Shape.cpp0
-rw-r--r--Source/modules/asura-core/Graphics/Shape.h0
-rw-r--r--Source/modules/asura-core/Graphics/SpriteBatch.cpp0
-rw-r--r--Source/modules/asura-core/Graphics/SpriteBatch.h34
-rw-r--r--Source/modules/asura-core/Graphics/Texture.cpp47
-rw-r--r--Source/modules/asura-core/Graphics/Texture.h101
-rw-r--r--Source/modules/asura-core/Graphics/VBO.cpp0
-rw-r--r--Source/modules/asura-core/Graphics/VBO.h27
-rw-r--r--Source/modules/asura-core/Graphics/VertexBuffer.cpp16
-rw-r--r--Source/modules/asura-core/Graphics/VertexBuffer.h34
-rw-r--r--Source/modules/asura-core/Graphics/binding/_canvas.cpp48
-rw-r--r--Source/modules/asura-core/Graphics/binding/_color.cpp130
-rw-r--r--Source/modules/asura-core/Graphics/binding/_color32.cpp66
-rw-r--r--Source/modules/asura-core/Graphics/binding/_gfx_device.cpp151
-rw-r--r--Source/modules/asura-core/Graphics/binding/_gpu_buffer.cpp118
-rw-r--r--Source/modules/asura-core/Graphics/binding/_image.cpp71
-rw-r--r--Source/modules/asura-core/Graphics/binding/_index_buffer.cpp31
-rw-r--r--Source/modules/asura-core/Graphics/binding/_mesh2d.cpp20
-rw-r--r--Source/modules/asura-core/Graphics/binding/_shader.cpp131
-rw-r--r--Source/modules/asura-core/Graphics/binding/_sprite_batch.cpp20
-rw-r--r--Source/modules/asura-core/Graphics/binding/_texture.cpp85
-rw-r--r--Source/modules/asura-core/Graphics/binding/_vertex_buffer.cpp38
-rw-r--r--Source/modules/asura-core/Image/ImageData.cpp62
-rw-r--r--Source/modules/asura-core/Image/ImageData.h81
-rw-r--r--Source/modules/asura-core/Image/ImageDecodeTask.cpp17
-rw-r--r--Source/modules/asura-core/Image/ImageDecodeTask.h35
-rw-r--r--Source/modules/asura-core/Image/ImageDecoder.h33
-rw-r--r--Source/modules/asura-core/Image/PngDecoder.cpp17
-rw-r--r--Source/modules/asura-core/Image/PngDecoder.h25
-rw-r--r--Source/modules/asura-core/Image/StbDecoder.cpp73
-rw-r--r--Source/modules/asura-core/Image/StbDecoder.h26
-rw-r--r--Source/modules/asura-core/Image/binding/_image_data.cpp108
-rw-r--r--Source/modules/asura-core/Image/binding/_image_decode_task.cpp19
-rw-r--r--Source/modules/asura-core/Input/Button.h31
-rw-r--r--Source/modules/asura-core/Input/ClipBoard.cpp0
-rw-r--r--Source/modules/asura-core/Input/ClipBoard.h0
-rw-r--r--Source/modules/asura-core/Input/InputAxis.cpp0
-rw-r--r--Source/modules/asura-core/Input/InputAxis.h15
-rw-r--r--Source/modules/asura-core/Input/InputDevice.cpp10
-rw-r--r--Source/modules/asura-core/Input/InputDevice.h82
-rw-r--r--Source/modules/asura-core/Input/InputEvent.cpp0
-rw-r--r--Source/modules/asura-core/Input/InputEvent.h55
-rw-r--r--Source/modules/asura-core/Input/InputManager.cpp140
-rw-r--r--Source/modules/asura-core/Input/InputManager.h352
-rw-r--r--Source/modules/asura-core/Input/JoystickState.h16
-rw-r--r--Source/modules/asura-core/Input/KeyboardState.h37
-rw-r--r--Source/modules/asura-core/Input/MouseState.h16
-rw-r--r--Source/modules/asura-core/Mesh/Am2Handler.cpp34
-rw-r--r--Source/modules/asura-core/Mesh/Am2Handler.h30
-rw-r--r--Source/modules/asura-core/Mesh/Mesh2DData.cpp0
-rw-r--r--Source/modules/asura-core/Mesh/Mesh2DData.h78
-rw-r--r--Source/modules/asura-core/Mesh/Mesh2DHandler.cpp0
-rw-r--r--Source/modules/asura-core/Mesh/Mesh2DHandler.h32
-rw-r--r--Source/modules/asura-core/Mesh/ObjHandler.cpp0
-rw-r--r--Source/modules/asura-core/Mesh/ObjHandler.h0
-rw-r--r--Source/modules/asura-core/Profiler/GPUProfiler.cpp0
-rw-r--r--Source/modules/asura-core/Profiler/GPUProfiler.h0
-rw-r--r--Source/modules/asura-core/Profiler/Stats.cpp0
-rw-r--r--Source/modules/asura-core/Profiler/Stats.h0
-rw-r--r--Source/modules/asura-core/Threads/Channel.cpp0
-rw-r--r--Source/modules/asura-core/Threads/Channel.h18
-rw-r--r--Source/modules/asura-core/Threads/ThreadEx.cpp20
-rw-r--r--Source/modules/asura-core/Threads/ThreadEx.h45
-rw-r--r--Source/modules/asura-core/Time/Timer.cpp0
-rw-r--r--Source/modules/asura-core/Time/Timer.h0
-rw-r--r--Source/modules/asura-core/Window/Window.cpp104
-rw-r--r--Source/modules/asura-core/Window/Window.h138
-rw-r--r--Source/modules/asura-core/Window/WindowImplGlew.cpp0
-rw-r--r--Source/modules/asura-core/Window/WindowImplGlew.h0
-rw-r--r--Source/modules/asura-core/Window/WindowImplGlut.h0
-rw-r--r--Source/modules/asura-core/Window/WindowImplSDL.cpp153
-rw-r--r--Source/modules/asura-core/Window/WindowImplSDL.h45
-rw-r--r--Source/modules/asura-core/Window/WinodwImplGlut.cpp0
-rw-r--r--Source/modules/asura-core/Window/binding/_window.cpp179
-rw-r--r--Source/modules/asura-fmod/Audio/Source.h20
-rw-r--r--Source/modules/asura-fmod/FMODModule.h9
-rw-r--r--Source/modules/asura-framework/compile.bat0
-rw-r--r--Source/modules/asura-framework/compile.sh0
-rw-r--r--Source/modules/asura-framework/main.cpp0
-rw-r--r--Source/modules/asura-framework/scripts/ai/behavior_tree.lua0
-rw-r--r--Source/modules/asura-framework/scripts/ai/state_graph.lua11
-rw-r--r--Source/modules/asura-framework/scripts/ai/state_machine.lua6
-rw-r--r--Source/modules/asura-framework/scripts/audio/sound.lua9
-rw-r--r--Source/modules/asura-framework/scripts/audio/source.lua22
-rw-r--r--Source/modules/asura-framework/scripts/class.lua17
-rw-r--r--Source/modules/asura-framework/scripts/component.lua30
-rw-r--r--Source/modules/asura-framework/scripts/entity.lua114
-rw-r--r--Source/modules/asura-framework/scripts/filesystem/animation_loader.lua10
-rw-r--r--Source/modules/asura-framework/scripts/filesystem/asset.lua20
-rw-r--r--Source/modules/asura-framework/scripts/filesystem/entity_loader.lua5
-rw-r--r--Source/modules/asura-framework/scripts/filesystem/image_loader.lua13
-rw-r--r--Source/modules/asura-framework/scripts/filesystem/loader.lua12
-rw-r--r--Source/modules/asura-framework/scripts/filesystem/material_loader.lua7
-rw-r--r--Source/modules/asura-framework/scripts/filesystem/path_loader.lua9
-rw-r--r--Source/modules/asura-framework/scripts/filesystem/scene_loader.lua7
-rw-r--r--Source/modules/asura-framework/scripts/filesystem/script_loader.lua5
-rw-r--r--Source/modules/asura-framework/scripts/filesystem/shader_loader.lua5
-rw-r--r--Source/modules/asura-framework/scripts/filesystem/statemap_loader.lua7
-rw-r--r--Source/modules/asura-framework/scripts/framework.lua21
-rw-r--r--Source/modules/asura-framework/scripts/graphics/animation.lua15
-rw-r--r--Source/modules/asura-framework/scripts/graphics/animator.lua33
-rw-r--r--Source/modules/asura-framework/scripts/graphics/camera.lua21
-rw-r--r--Source/modules/asura-framework/scripts/graphics/canvas.lua34
-rw-r--r--Source/modules/asura-framework/scripts/graphics/default_shaders.lua5
-rw-r--r--Source/modules/asura-framework/scripts/graphics/image.lua40
-rw-r--r--Source/modules/asura-framework/scripts/graphics/material.lua48
-rw-r--r--Source/modules/asura-framework/scripts/graphics/material_manager.lua3
-rw-r--r--Source/modules/asura-framework/scripts/graphics/mesh2d.lua9
-rw-r--r--Source/modules/asura-framework/scripts/graphics/mesh2d_renderer.lua13
-rw-r--r--Source/modules/asura-framework/scripts/graphics/particle_system.lua20
-rw-r--r--Source/modules/asura-framework/scripts/graphics/renderer.lua19
-rw-r--r--Source/modules/asura-framework/scripts/graphics/shader.lua75
-rw-r--r--Source/modules/asura-framework/scripts/graphics/shaderHelper.lua14
-rw-r--r--Source/modules/asura-framework/scripts/graphics/shape.lua12
-rw-r--r--Source/modules/asura-framework/scripts/graphics/shape_renderer.lua13
-rw-r--r--Source/modules/asura-framework/scripts/graphics/sprite.lua10
-rw-r--r--Source/modules/asura-framework/scripts/graphics/sprite_batch_renderer.lua9
-rw-r--r--Source/modules/asura-framework/scripts/graphics/sprite_renderer.lua17
-rw-r--r--Source/modules/asura-framework/scripts/gui/button.lua21
-rw-r--r--Source/modules/asura-framework/scripts/gui/text.lua0
-rw-r--r--Source/modules/asura-framework/scripts/gui/widget.lua14
-rw-r--r--Source/modules/asura-framework/scripts/managers/scene_manager.lua16
-rw-r--r--Source/modules/asura-framework/scripts/managers/sprite_manager.lua0
-rw-r--r--Source/modules/asura-framework/scripts/math/curve.lua0
-rw-r--r--Source/modules/asura-framework/scripts/path/path.lua13
-rw-r--r--Source/modules/asura-framework/scripts/path/path_calculator.lua12
-rw-r--r--Source/modules/asura-framework/scripts/path/path_manager.lua0
-rw-r--r--Source/modules/asura-framework/scripts/scene.lua22
-rw-r--r--Source/modules/asura-framework/scripts/transform.lua13
-rw-r--r--Source/modules/asura-json/Json/Json.cpp0
-rw-r--r--Source/modules/asura-json/Json/Json.h14
-rw-r--r--Source/modules/asura-json/JsonModule.cpp0
-rw-r--r--Source/modules/asura-json/JsonModule.h0
-rw-r--r--Source/modules/asura-network/NetworkModule.h0
-rw-r--r--Source/modules/asura-openal/Audio/Audio.cpp0
-rw-r--r--Source/modules/asura-openal/Audio/Audio.h18
-rw-r--r--Source/modules/asura-openal/Audio/MPG123Decoder.cpp0
-rw-r--r--Source/modules/asura-openal/Audio/MPG123Decoder.h0
-rw-r--r--Source/modules/asura-openal/Audio/Sound.cpp0
-rw-r--r--Source/modules/asura-openal/Audio/Sound.h31
-rw-r--r--Source/modules/asura-openal/Audio/SoundData.cpp0
-rw-r--r--Source/modules/asura-openal/Audio/SoundData.h0
-rw-r--r--Source/modules/asura-openal/Audio/SoundDecodeTask.cpp0
-rw-r--r--Source/modules/asura-openal/Audio/SoundDecodeTask.h0
-rw-r--r--Source/modules/asura-openal/Audio/SoundDecoder.cpp0
-rw-r--r--Source/modules/asura-openal/Audio/SoundDecoder.h30
-rw-r--r--Source/modules/asura-openal/Audio/Source.cpp0
-rw-r--r--Source/modules/asura-openal/Audio/Source.h0
-rw-r--r--Source/modules/asura-openal/Audio/VorbisDecoder.cpp0
-rw-r--r--Source/modules/asura-openal/Audio/VorbisDecoder.h0
312 files changed, 15891 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
diff --git a/Source/modules/asura-box2d/Box2DModule.cpp b/Source/modules/asura-box2d/Box2DModule.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-box2d/Box2DModule.cpp
diff --git a/Source/modules/asura-box2d/Box2DModule.h b/Source/modules/asura-box2d/Box2DModule.h
new file mode 100644
index 0000000..31a665b
--- /dev/null
+++ b/Source/modules/asura-box2d/Box2DModule.h
@@ -0,0 +1,19 @@
+#ifndef __ASURA_BOX2D_MODULE_H__
+#define __ASURA_BOX2D_MODULE_H__
+
+#include <asura-base/Module.h>
+
+namespace AsuraEngine
+{
+
+ class Box2DModule ASURA_FINAL : public Module
+ {
+ public:
+
+
+
+ };
+
+}
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-box2d/Physics/Body.h b/Source/modules/asura-box2d/Physics/Body.h
new file mode 100644
index 0000000..d7e79d5
--- /dev/null
+++ b/Source/modules/asura-box2d/Physics/Body.h
@@ -0,0 +1,64 @@
+#ifndef __ASURA_BOX2D_BODY_H__
+#define __ASURA_BOX2D_BODY_H__
+
+#include <Box2D/Box2D.h>
+
+#include <asura-base/Classes.h>
+#include <asura-base/Scripting/Scripting.h>
+
+namespace_begin(AsuraEngine)
+namespace_begin(Physics)
+
+class World;
+class Joint;
+
+enum BodyType
+{
+ BODY_TYPE_INVALID,
+ BODY_TYPE_STATIC,
+ BODY_TYPE_DYNAMIC,
+ BODY_TYPE_KINEMATIC
+};
+
+class Body : public AEScripting::Portable<Body>
+{
+public:
+
+private:
+
+ friend class Joint;
+
+ //----------------------------------------------------------------------------//
+
+ LUAX_DECL_FACTORY(Body);
+
+ LUAX_DECL_ENUM(BodyType, 1);
+
+ LUAX_DECL_METHOD(_GetType);
+ LUAX_DECL_METHOD(_GetX);
+ LUAX_DECL_METHOD(_GetY);
+ LUAX_DECL_METHOD(_GetAngle);
+ LUAX_DECL_METHOD(_GetPosition);
+ LUAX_DECL_METHOD(_GetLinearVelocity);
+ LUAX_DECL_METHOD(_GetWorldCenter);
+ LUAX_DECL_METHOD(_GetLocalCenter);
+ LUAX_DECL_METHOD(_GetAngularVelocity);
+ LUAX_DECL_METHOD(_GetMass);
+ LUAX_DECL_METHOD(_GetInertia);
+ LUAX_DECL_METHOD(_GetMassData);
+ LUAX_DECL_METHOD(_GetAngularDamping);
+ LUAX_DECL_METHOD(_GetLinearDamping);
+ LUAX_DECL_METHOD(_GetGravityScale);
+ LUAX_DECL_METHOD(_GetGravityScale);
+
+ //----------------------------------------------------------------------------//
+
+ b2Body* m_Body;
+ World* m_World;
+
+};
+
+namespace_end
+namespace_end
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-box2d/Physics/ChainShape.h b/Source/modules/asura-box2d/Physics/ChainShape.h
new file mode 100644
index 0000000..2403587
--- /dev/null
+++ b/Source/modules/asura-box2d/Physics/ChainShape.h
@@ -0,0 +1,29 @@
+#ifndef __ASURA_CHAIN_SHAPE_H__
+#define __ASURA_CHAIN_SHAPE_H__
+
+#include <Box2D/Collision/Shapes/b2ChainShape.h>
+
+#include <asura-base/Scripting/Scripting.h>
+#include <asura-base/Classes.h>
+
+namespace_begin(AsuraEngine)
+namespace_begin(Physics)
+
+class ChainShape
+ : AEScripting::Portable<ChainShape>
+{
+public:
+
+ ChainShape();
+ ~ChainShape();
+
+private:
+
+ b2ChainShape* m_Shape;
+
+};
+
+namespace_end
+namespace_end
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-box2d/Physics/CircleShape.h b/Source/modules/asura-box2d/Physics/CircleShape.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-box2d/Physics/CircleShape.h
diff --git a/Source/modules/asura-box2d/Physics/Contact.h b/Source/modules/asura-box2d/Physics/Contact.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-box2d/Physics/Contact.h
diff --git a/Source/modules/asura-box2d/Physics/DebugDraw.h b/Source/modules/asura-box2d/Physics/DebugDraw.h
new file mode 100644
index 0000000..a92be43
--- /dev/null
+++ b/Source/modules/asura-box2d/Physics/DebugDraw.h
@@ -0,0 +1,9 @@
+#ifndef _ASURA_BOX2D_DEBUG_DRAW_H_
+#define _ASURA_BOX2D_DEBUG_DRAW_H_
+
+namespace AsuraEngine
+{
+
+}
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-box2d/Physics/DistanceJoint.h b/Source/modules/asura-box2d/Physics/DistanceJoint.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-box2d/Physics/DistanceJoint.h
diff --git a/Source/modules/asura-box2d/Physics/EdgeShape.h b/Source/modules/asura-box2d/Physics/EdgeShape.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-box2d/Physics/EdgeShape.h
diff --git a/Source/modules/asura-box2d/Physics/Fixture.h b/Source/modules/asura-box2d/Physics/Fixture.h
new file mode 100644
index 0000000..69f0153
--- /dev/null
+++ b/Source/modules/asura-box2d/Physics/Fixture.h
@@ -0,0 +1,17 @@
+#ifndef _ASRUA_ENGINE_FIXTURE_H_
+#define _ASRUA_ENGINE_FIXTURE_H_
+
+#include <asura-base/Classes.h>
+
+namespace_begin(AsuraEngine)
+namespace_begin(Physics)
+
+class Fixture
+{
+
+};
+
+namespace_end
+namespace_end
+
+#endif
diff --git a/Source/modules/asura-box2d/Physics/FrictionJoint.h b/Source/modules/asura-box2d/Physics/FrictionJoint.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-box2d/Physics/FrictionJoint.h
diff --git a/Source/modules/asura-box2d/Physics/GearJoint.h b/Source/modules/asura-box2d/Physics/GearJoint.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-box2d/Physics/GearJoint.h
diff --git a/Source/modules/asura-box2d/Physics/Joint.h b/Source/modules/asura-box2d/Physics/Joint.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-box2d/Physics/Joint.h
diff --git a/Source/modules/asura-box2d/Physics/MotorJoint.h b/Source/modules/asura-box2d/Physics/MotorJoint.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-box2d/Physics/MotorJoint.h
diff --git a/Source/modules/asura-box2d/Physics/MouseJoint.h b/Source/modules/asura-box2d/Physics/MouseJoint.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-box2d/Physics/MouseJoint.h
diff --git a/Source/modules/asura-box2d/Physics/PolygonShape.h b/Source/modules/asura-box2d/Physics/PolygonShape.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-box2d/Physics/PolygonShape.h
diff --git a/Source/modules/asura-box2d/Physics/PrismaticJoint.h b/Source/modules/asura-box2d/Physics/PrismaticJoint.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-box2d/Physics/PrismaticJoint.h
diff --git a/Source/modules/asura-box2d/Physics/PulleyJoint.h b/Source/modules/asura-box2d/Physics/PulleyJoint.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-box2d/Physics/PulleyJoint.h
diff --git a/Source/modules/asura-box2d/Physics/RevoluteJoint.h b/Source/modules/asura-box2d/Physics/RevoluteJoint.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-box2d/Physics/RevoluteJoint.h
diff --git a/Source/modules/asura-box2d/Physics/RopeJoint.h b/Source/modules/asura-box2d/Physics/RopeJoint.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-box2d/Physics/RopeJoint.h
diff --git a/Source/modules/asura-box2d/Physics/Shape.h b/Source/modules/asura-box2d/Physics/Shape.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-box2d/Physics/Shape.h
diff --git a/Source/modules/asura-box2d/Physics/WeldJoint.h b/Source/modules/asura-box2d/Physics/WeldJoint.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-box2d/Physics/WeldJoint.h
diff --git a/Source/modules/asura-box2d/Physics/WheelJoint.h b/Source/modules/asura-box2d/Physics/WheelJoint.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-box2d/Physics/WheelJoint.h
diff --git a/Source/modules/asura-box2d/Physics/World.h b/Source/modules/asura-box2d/Physics/World.h
new file mode 100644
index 0000000..a156c79
--- /dev/null
+++ b/Source/modules/asura-box2d/Physics/World.h
@@ -0,0 +1,18 @@
+#ifndef __ASURA_BOX2D_WORLD_H__
+#define __ASURA_BOX2D_WORLD_H__
+
+#include <asura-base/Classes.h>
+#include <asura-base/Scripting/Scripting.h>
+
+namespace_begin(AsuraEngine)
+namespace_begin(Physics)
+
+class World : public AEScripting::Portable<World>
+{
+
+};
+
+namespace_end
+namespace_end
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-box2d/Physics/binding/_body.cpp b/Source/modules/asura-box2d/Physics/binding/_body.cpp
new file mode 100644
index 0000000..0c9e3e8
--- /dev/null
+++ b/Source/modules/asura-box2d/Physics/binding/_body.cpp
@@ -0,0 +1,171 @@
+#include "../Body.h"
+
+using namespace std;
+
+namespace AsuraEngine
+{
+ namespace Physics
+ {
+
+ LUAX_REGISTRY(Body)
+ {
+ LUAX_REGISTER_METHODS(state,
+ { "GetType", _GetType },
+ { "GetX", _GetX },
+ { "GetY", _GetY },
+ { "GetAngle", _GetAngle },
+ { "GetPosition", _GetPosition },
+ { "GetLinearVelocity", _GetLinearVelocity },
+ { "GetWorldCenter", _GetWorldCenter },
+ { "GetLocalCenter", _GetLocalCenter },
+ { "GetAngularVelocity", _GetAngularVelocity },
+ { "GetMass", _GetMass },
+ { "GetInertia", _GetInertia },
+ { "GetMassData", _GetMassData },
+ { "GetAngularDamping", _GetAngularDamping },
+ { "GetLinearDamping", _GetLinearDamping },
+ { "GetGravityScale", _GetGravityScale },
+ { "GetGravityScale", _GetGravityScale }
+ );
+ }
+
+ LUAX_POSTPROCESS(Body)
+ {
+ LUAX_REGISTER_ENUM(state, "EBodyType",
+ { "INVALID", BODY_TYPE_INVALID },
+ { "STATIC", BODY_TYPE_STATIC },
+ { "DYNAMIC", BODY_TYPE_DYNAMIC },
+ { "KINEMATIC", BODY_TYPE_KINEMATIC }
+ );
+
+ }
+
+ // body:GetType()
+ LUAX_IMPL_METHOD(Body, _GetType)
+ {
+ LUAX_PREPARE(L, Body);
+ return 0;
+ }
+
+ // body:GetX()
+ LUAX_IMPL_METHOD(Body, _GetX)
+ {
+ LUAX_PREPARE(L, Body);
+
+ return 0;
+ }
+
+ // body:GetY()
+ LUAX_IMPL_METHOD(Body, _GetY)
+ {
+ LUAX_PREPARE(L, Body);
+
+ return 0;
+ }
+
+ // body:GetAngle()
+ LUAX_IMPL_METHOD(Body, _GetAngle)
+ {
+ LUAX_PREPARE(L, Body);
+
+ return 0;
+ }
+
+ // body:GetPosition()
+ LUAX_IMPL_METHOD(Body, _GetPosition)
+ {
+ LUAX_PREPARE(L, Body);
+
+ return 0;
+ }
+
+ // body:GetLinearVelocity()
+ LUAX_IMPL_METHOD(Body, _GetLinearVelocity)
+ {
+ LUAX_PREPARE(L, Body);
+
+ return 0;
+ }
+
+ // body:GetWorldCenter()
+ LUAX_IMPL_METHOD(Body, _GetWorldCenter)
+ {
+ LUAX_PREPARE(L, Body);
+
+ return 0;
+ }
+
+ // body:GetLocalCenter()
+ LUAX_IMPL_METHOD(Body, _GetLocalCenter)
+ {
+ LUAX_PREPARE(L, Body);
+
+ return 0;
+ }
+
+ // body:GetAngularVelocity()
+ LUAX_IMPL_METHOD(Body, _GetAngularVelocity)
+ {
+ LUAX_PREPARE(L, Body);
+
+ return 0;
+ }
+
+ // body:GetMass()
+ LUAX_IMPL_METHOD(Body, _GetMass)
+ {
+ LUAX_PREPARE(L, Body);
+
+ return 0;
+ }
+
+ // body:GetInertia()
+ LUAX_IMPL_METHOD(Body, _GetInertia)
+ {
+ LUAX_PREPARE(L, Body);
+
+ return 0;
+ }
+
+ // body:GetMassData()
+ LUAX_IMPL_METHOD(Body, _GetMassData)
+ {
+ LUAX_PREPARE(L, Body);
+
+ return 0;
+ }
+
+ // body:GetAngularDamping()
+ LUAX_IMPL_METHOD(Body, _GetAngularDamping)
+ {
+ LUAX_PREPARE(L, Body);
+
+ return 0;
+ }
+
+ // body:GetLinearDamping()
+ LUAX_IMPL_METHOD(Body, _GetLinearDamping)
+ {
+ LUAX_PREPARE(L, Body);
+
+ return 0;
+ }
+
+ // body:GetGravityScale()
+ LUAX_IMPL_METHOD(Body, _GetGravityScale)
+ {
+ LUAX_PREPARE(L, Body);
+
+ return 0;
+ }
+
+ // body:GetGravityScale()
+ LUAX_IMPL_METHOD(Body, _GetGravityScale)
+ {
+ LUAX_PREPARE(L, Body);
+
+ return 0;
+ }
+
+ }
+}
diff --git a/Source/modules/asura-box2d/Physics/binding/_world.cpp b/Source/modules/asura-box2d/Physics/binding/_world.cpp
new file mode 100644
index 0000000..0940959
--- /dev/null
+++ b/Source/modules/asura-box2d/Physics/binding/_world.cpp
@@ -0,0 +1,21 @@
+#include "../World.h"
+
+using namespace std;
+
+namespace AsuraEngine
+{
+ namespace Physics
+ {
+ /*
+ LUAX_REGISTRY(World)
+ {
+
+ }
+
+ LUAX_POSTPROCESS(World)
+ {
+
+ }
+*/
+ }
+}
diff --git a/Source/modules/asura-core/Application.cpp b/Source/modules/asura-core/Application.cpp
new file mode 100644
index 0000000..2f20e45
--- /dev/null
+++ b/Source/modules/asura-core/Application.cpp
@@ -0,0 +1,23 @@
+#include "Application.h"
+
+using namespace Luax;
+
+namespace AsuraEngine
+{
+
+Application::Application()
+{
+
+}
+
+Application::~Application()
+{
+
+}
+
+bool Application::InitSubModules(uint flag)
+{
+ return false;
+}
+
+} \ No newline at end of file
diff --git a/Source/modules/asura-core/Application.h b/Source/modules/asura-core/Application.h
new file mode 100644
index 0000000..cccd6f7
--- /dev/null
+++ b/Source/modules/asura-core/Application.h
@@ -0,0 +1,69 @@
+#ifndef _ASURA_ENGINE_APPLICATION_H_
+#define _ASURA_ENGINE_APPLICATION_H_
+
+#include <asura-base/Scripting/Scripting.h>
+#include <asura-base/Module.h>
+#include <asura-base/Classes.h>
+#include <queue>
+
+#include "CoreConfig.h"
+
+namespace_begin(AsuraEngine)
+
+/// ģ
+enum SubModules
+{
+ ASURA_MODULE_NONE = 0X00000000U,
+
+ ASURA_MODULE_GRAPHICS = 1 << 1,
+ ASURA_MODULE_AUDIO = 1 << 2,
+ ASURA_MODULE_FONT = 1 << 3,
+ ASURA_MODULE_INPUT = 1 << 4,
+ ASURA_MODULE_MATH = 1 << 5,
+ ASURA_MODULE_PHYSICS = 1 << 6,
+ ASURA_MODULE_TIME = 1 << 7,
+ ASURA_MODULE_WINDOW = 1 << 8,
+
+ ASURA_MODULE_ALL = 0XFFFFFFFFU
+};
+
+///
+/// ѭ
+///
+class Application
+{
+public:
+
+ Application();
+
+ virtual ~Application();
+
+ // ʼǰϵͳ
+ bool InitSubModules(uint flag = ASURA_MODULE_ALL);
+
+ //
+ virtual void Run(int argc, char* args[]);
+
+ // ˳runʱĴ
+ virtual void OnExit();
+
+protected:
+
+ // moduleapplicationӵmoduleȨ
+ void EnqueueModule(Module* module);
+
+private:
+
+ /// ̵߳lua state handleӦѭСһ˵ֻҪ߳һlua_State̲߳Ҫ̼߳
+ /// lua̫ʹˡC++дȻעһصһ̴߳lua_Stateעắִк󷢻
+ /// ̵߳lua_Stateֻ֤һnativeʵ֮һlua_State󶨡
+ Luax::LuaxVM* m_VM;
+
+ // Asura libsᰴն˳ʼ˳ʱִ˳
+ std::queue<Module*> m_Modules;
+
+};
+
+namespace_end
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-core/CoreConfig.h b/Source/modules/asura-core/CoreConfig.h
new file mode 100644
index 0000000..2dd0b03
--- /dev/null
+++ b/Source/modules/asura-core/CoreConfig.h
@@ -0,0 +1,13 @@
+#ifndef _ASURA_CORE_CONFIG_H_
+#define _ASURA_CORE_CONFIG_H_
+
+#define ASURA_WINDOW_SDL 1
+
+#define ASURA_OPENGL_GLAD (1 << 1)
+#define ASURA_OPENGL_GLEE (1 << 2)
+#define ASURA_OPENGL_GLUT (1 << 3)
+#define ASURA_OPENGL_LOADER (ASURA_OPENGL_GLAD|ASURA_OPENGL_GLEE|ASURA_OPENGL_GLUT)
+
+#define ASURA_GL_PROFILE 1
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-core/CoreModule.cpp b/Source/modules/asura-core/CoreModule.cpp
new file mode 100644
index 0000000..93f8ca0
--- /dev/null
+++ b/Source/modules/asura-core/CoreModule.cpp
@@ -0,0 +1,25 @@
+#include "CoreModule.h"
+
+using namespace AEThreading;
+using namespace AEGraphics;
+
+namespace AsuraEngine
+{
+
+ void CoreModule::Initialize(Luax::LuaxState& state)
+ {
+ // Graphics
+ LUAX_REGISTER_ABSTRACT_FACTORY(state, Texture);
+ LUAX_REGISTER_FACTORY(state, AEGraphics::Image);
+ // Wnd
+ LUAX_REGISTER_SINGLETON(state, AEWindow::Window);
+ // Threads
+ //LUAX_REGISTER_FACTORY(state, ThreadEx);
+ }
+
+ void CoreModule::Finalize(Luax::LuaxState& state)
+ {
+
+ }
+
+} \ No newline at end of file
diff --git a/Source/modules/asura-core/CoreModule.h b/Source/modules/asura-core/CoreModule.h
new file mode 100644
index 0000000..d592f42
--- /dev/null
+++ b/Source/modules/asura-core/CoreModule.h
@@ -0,0 +1,26 @@
+#ifndef _ASURA_CORE_MODULE_H_
+#define _ASURA_CORE_MODULE_H_
+
+#include <asura-base/Module.h>
+#include <asura-base/Classes.h>
+
+#include "graphics/image.h"
+#include "graphics/texture.h"
+#include "window/window.h"
+#include "Threads/ThreadEx.h"
+
+namespace_begin(AsuraEngine)
+
+class CoreModule : public Module
+{
+public:
+
+ void Initialize(Luax::LuaxState& state) override;
+
+ void Finalize(Luax::LuaxState& state) override;
+
+};
+
+namespace_end
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-core/Font/Glyph.cpp b/Source/modules/asura-core/Font/Glyph.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-core/Font/Glyph.cpp
diff --git a/Source/modules/asura-core/Font/Glyph.h b/Source/modules/asura-core/Font/Glyph.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-core/Font/Glyph.h
diff --git a/Source/modules/asura-core/Font/String.cpp b/Source/modules/asura-core/Font/String.cpp
new file mode 100644
index 0000000..1731338
--- /dev/null
+++ b/Source/modules/asura-core/Font/String.cpp
@@ -0,0 +1,376 @@
+//#include "String.hpp"
+//#include "Utf.hpp"
+//
+//namespace AsuraEngine
+//{
+// namespace Text
+// {
+//
+//
+// ////////////////////////////////////////////////////////////
+// const std::size_t String::InvalidPos = std::basic_string<uint32>::npos;
+//
+//
+// ////////////////////////////////////////////////////////////
+// String::String()
+// {
+// }
+//
+//
+// ////////////////////////////////////////////////////////////
+// String::String(char ansiChar, const std::locale& locale)
+// {
+// m_String += Utf32::DecodeAnsi(ansiChar, locale);
+// }
+//
+//
+// ////////////////////////////////////////////////////////////
+// String::String(wchar_t wideChar)
+// {
+// m_String += Utf32::DecodeWide(wideChar);
+// }
+//
+//
+// ////////////////////////////////////////////////////////////
+// String::String(uint32 utf32Char)
+// {
+// m_String += utf32Char;
+// }
+//
+//
+// ////////////////////////////////////////////////////////////
+// String::String(const char* ansiString, const std::locale& locale)
+// {
+// if (ansiString)
+// {
+// std::size_t length = strlen(ansiString);
+// if (length > 0)
+// {
+// m_String.reserve(length + 1);
+// Utf32::FromAnsi(ansiString, ansiString + length, std::back_inserter(m_String), locale);
+// }
+// }
+// }
+//
+//
+// ////////////////////////////////////////////////////////////
+// String::String(const std::string& ansiString, const std::locale& locale)
+// {
+// m_String.reserve(ansiString.length() + 1);
+// Utf32::FromAnsi(ansiString.begin(), ansiString.end(), std::back_inserter(m_String), locale);
+// }
+//
+//
+// ////////////////////////////////////////////////////////////
+// String::String(const wchar_t* wideString)
+// {
+// if (wideString)
+// {
+// std::size_t length = std::wcslen(wideString);
+// if (length > 0)
+// {
+// m_String.reserve(length + 1);
+// Utf32::FromWide(wideString, wideString + length, std::back_inserter(m_String));
+// }
+// }
+// }
+//
+//
+// ////////////////////////////////////////////////////////////
+// String::String(const std::wstring& wideString)
+// {
+// m_String.reserve(wideString.length() + 1);
+// Utf32::FromWide(wideString.begin(), wideString.end(), std::back_inserter(m_String));
+// }
+//
+//
+// ////////////////////////////////////////////////////////////
+// String::String(const uint32* utf32String)
+// {
+// if (utf32String)
+// m_String = utf32String;
+// }
+//
+//
+// ////////////////////////////////////////////////////////////
+// String::String(const std::basic_string<uint32>& utf32String) :
+// m_String(utf32String)
+// {
+// }
+//
+//
+// ////////////////////////////////////////////////////////////
+// String::String(const String& copy) :
+// m_String(copy.mString)
+// {
+// }
+//
+//
+// ////////////////////////////////////////////////////////////
+// String::operator std::string() const
+// {
+// return ToAnsiString();
+// }
+//
+//
+// ////////////////////////////////////////////////////////////
+// String::operator std::wstring() const
+// {
+// return ToWideString();
+// }
+//
+//
+// ////////////////////////////////////////////////////////////
+// std::string String::ToAnsiString(const std::locale& locale) const
+// {
+// // Prepare the output string
+// std::string output;
+// output.reserve(m_String.length() + 1);
+//
+// // Convert
+// Utf32::ToAnsi(m_String.begin(), m_String.end(), std::back_inserter(output), 0, locale);
+//
+// return output;
+// }
+//
+//
+// ////////////////////////////////////////////////////////////
+// std::wstring String::ToWideString() const
+// {
+// // Prepare the output string
+// std::wstring output;
+// output.reserve(m_String.length() + 1);
+//
+// // Convert
+// Utf32::ToWide(m_String.begin(), m_String.end(), std::back_inserter(output), 0);
+//
+// return output;
+// }
+//
+//
+// ////////////////////////////////////////////////////////////
+// std::basic_string<uint8> String::ToUtf8() const
+// {
+// // Prepare the output string
+// std::basic_string<uint8> output;
+// output.reserve(m_String.length());
+//
+// // Convert
+// Utf32::ToUtf8(m_String.begin(), m_String.end(), std::back_inserter(output));
+//
+// return output;
+// }
+//
+//
+// ////////////////////////////////////////////////////////////
+// std::basic_string<uint16> String::ToUtf16() const
+// {
+// // Prepare the output string
+// std::basic_string<uint16> output;
+// output.reserve(m_String.length());
+//
+// // Convert
+// Utf32::ToUtf16(m_String.begin(), m_String.end(), std::back_inserter(output));
+//
+// return output;
+// }
+//
+//
+// ////////////////////////////////////////////////////////////
+// std::basic_string<uint32> String::ToUtf32() const
+// {
+// return m_String;
+// }
+//
+//
+// ////////////////////////////////////////////////////////////
+// String& String::operator =(const String& right)
+// {
+// m_String = right.mString;
+// return *this;
+// }
+//
+//
+// ////////////////////////////////////////////////////////////
+// String& String::operator +=(const String& right)
+// {
+// m_String += right.mString;
+// return *this;
+// }
+//
+//
+// ////////////////////////////////////////////////////////////
+// uint32 String::operator [](std::size_t index) const
+// {
+// return m_String[index];
+// }
+//
+//
+// ////////////////////////////////////////////////////////////
+// uint32& String::operator [](std::size_t index)
+// {
+// return m_String[index];
+// }
+//
+//
+// ////////////////////////////////////////////////////////////
+// void String::Clear()
+// {
+// m_String.clear();
+// }
+//
+//
+// ////////////////////////////////////////////////////////////
+// std::size_t String::GetSize() const
+// {
+// return m_String.size();
+// }
+//
+//
+// ////////////////////////////////////////////////////////////
+// bool String::IsEmpty() const
+// {
+// return m_String.empty();
+// }
+//
+//
+// ////////////////////////////////////////////////////////////
+// void String::Erase(std::size_t position, std::size_t count)
+// {
+// m_String.erase(position, count);
+// }
+//
+//
+// ////////////////////////////////////////////////////////////
+// void String::Insert(std::size_t position, const String& str)
+// {
+// m_String.insert(position, str.mString);
+// }
+//
+//
+// ////////////////////////////////////////////////////////////
+// std::size_t String::Find(const String& str, std::size_t start) const
+// {
+// return m_String.find(str.mString, start);
+// }
+//
+//
+// ////////////////////////////////////////////////////////////
+// void String::Replace(std::size_t position, std::size_t length, const String& replaceWith)
+// {
+// m_String.replace(position, length, replaceWith.mString);
+// }
+//
+//
+// ////////////////////////////////////////////////////////////
+// void String::Replace(const String& searchFor, const String& replaceWith)
+// {
+// std::size_t step = replaceWith.GetSize();
+// std::size_t len = searchFor.GetSize();
+// std::size_t pos = Find(searchFor);
+//
+// // Replace each occurrence of search
+// while (pos != InvalidPos)
+// {
+// Replace(pos, len, replaceWith);
+// pos = Find(searchFor, pos + step);
+// }
+// }
+//
+//
+// ////////////////////////////////////////////////////////////
+// String String::Substring(std::size_t position, std::size_t length) const
+// {
+// return m_String.substr(position, length);
+// }
+//
+//
+// ////////////////////////////////////////////////////////////
+// const uint32* String::GetData() const
+// {
+// return m_String.c_str();
+// }
+//
+//
+// ////////////////////////////////////////////////////////////
+// String::Iterator String::Begin()
+// {
+// return m_String.begin();
+// }
+//
+//
+// ////////////////////////////////////////////////////////////
+// String::ConstIterator String::Begin() const
+// {
+// return m_String.begin();
+// }
+//
+//
+// ////////////////////////////////////////////////////////////
+// String::Iterator String::End()
+// {
+// return m_String.end();
+// }
+//
+//
+// ////////////////////////////////////////////////////////////
+// String::ConstIterator String::End() const
+// {
+// return m_String.end();
+// }
+//
+//
+// ////////////////////////////////////////////////////////////
+// bool operator ==(const String& left, const String& right)
+// {
+// return left.mString == right.mString;
+// }
+//
+//
+// ////////////////////////////////////////////////////////////
+// bool operator !=(const String& left, const String& right)
+// {
+// return !(left == right);
+// }
+//
+//
+// ////////////////////////////////////////////////////////////
+// bool operator <(const String& left, const String& right)
+// {
+// return left.mString < right.mString;
+// }
+//
+//
+// ////////////////////////////////////////////////////////////
+// bool operator >(const String& left, const String& right)
+// {
+// return right < left;
+// }
+//
+//
+// ////////////////////////////////////////////////////////////
+// bool operator <=(const String& left, const String& right)
+// {
+// return !(right < left);
+// }
+//
+//
+// ////////////////////////////////////////////////////////////
+// bool operator >=(const String& left, const String& right)
+// {
+// return !(left < right);
+// }
+//
+//
+// ////////////////////////////////////////////////////////////
+// String operator +(const String& left, const String& right)
+// {
+// String string = left;
+// string += right;
+//
+// return string;
+// }
+//
+//
+// }
+//}
diff --git a/Source/modules/asura-core/Font/String.hpp b/Source/modules/asura-core/Font/String.hpp
new file mode 100644
index 0000000..845a1d5
--- /dev/null
+++ b/Source/modules/asura-core/Font/String.hpp
@@ -0,0 +1,595 @@
+//#ifndef _ASURA_ENGINE_STRING_H_
+//#define _ASURA_ENGINE_STRING_H_
+//
+//#include <asura-base/type.h>
+//
+//#include <iterator>
+//#include <locale>
+//#include <string>
+//
+//namespace AsuraEngine
+//{
+// namespace Text
+// {
+//
+//
+// ////////////////////////////////////////////////////////////
+// /// \brief Utility string class that automatically handles
+// /// conversions between types and encodings
+// ///
+// ////////////////////////////////////////////////////////////
+// class String
+// {
+// public:
+//
+// ////////////////////////////////////////////////////////////
+// // Types
+// ////////////////////////////////////////////////////////////
+// typedef std::basic_string<uint32>::iterator Iterator; ///< Iterator type
+// typedef std::basic_string<uint32>::const_iterator ConstIterator; ///< Read-only iterator type
+//
+// ////////////////////////////////////////////////////////////
+// // Static member data
+// ////////////////////////////////////////////////////////////
+// static const std::size_t InvalidPos; ///< Represents an invalid position in the string
+//
+// ////////////////////////////////////////////////////////////
+// /// \brief Default constructor
+// ///
+// /// This constructor creates an empty string.
+// ///
+// ////////////////////////////////////////////////////////////
+// String();
+//
+// ////////////////////////////////////////////////////////////
+// /// \brief Construct from a single ANSI character and a locale
+// ///
+// /// The source character is converted to UTF-32 according
+// /// to the given locale.
+// ///
+// /// \param ansiChar ANSI character to convert
+// /// \param locale Locale to use for conversion
+// ///
+// ////////////////////////////////////////////////////////////
+// String(char ansiChar, const std::locale& locale = std::locale());
+//
+// ////////////////////////////////////////////////////////////
+// /// \brief Construct from single wide character
+// ///
+// /// \param wideChar Wide character to convert
+// ///
+// ////////////////////////////////////////////////////////////
+// String(wchar_t wideChar);
+//
+// ////////////////////////////////////////////////////////////
+// /// \brief Construct from single UTF-32 character
+// ///
+// /// \param utf32Char UTF-32 character to convert
+// ///
+// ////////////////////////////////////////////////////////////
+// String(uint utf32Char);
+//
+// ////////////////////////////////////////////////////////////
+// /// \brief Construct from a null-terminated C-style ANSI string and a locale
+// ///
+// /// The source string is converted to UTF-32 according
+// /// to the given locale.
+// ///
+// /// \param ansiString ANSI string to convert
+// /// \param locale Locale to use for conversion
+// ///
+// ////////////////////////////////////////////////////////////
+// String(const char* ansiString, const std::locale& locale = std::locale());
+//
+// ////////////////////////////////////////////////////////////
+// /// \brief Construct from an ANSI string and a locale
+// ///
+// /// The source string is converted to UTF-32 according
+// /// to the given locale.
+// ///
+// /// \param ansiString ANSI string to convert
+// /// \param locale Locale to use for conversion
+// ///
+// ////////////////////////////////////////////////////////////
+// String(const std::string& ansiString, const std::locale& locale = std::locale());
+//
+// ////////////////////////////////////////////////////////////
+// /// \brief Construct from null-terminated C-style wide string
+// ///
+// /// \param wideString Wide string to convert
+// ///
+// ////////////////////////////////////////////////////////////
+// String(const wchar_t* wideString);
+//
+// ////////////////////////////////////////////////////////////
+// /// \brief Construct from a wide string
+// ///
+// /// \param wideString Wide string to convert
+// ///
+// ////////////////////////////////////////////////////////////
+// String(const std::wstring& wideString);
+//
+// ////////////////////////////////////////////////////////////
+// /// \brief Construct from a null-terminated C-style UTF-32 string
+// ///
+// /// \param utf32String UTF-32 string to assign
+// ///
+// ////////////////////////////////////////////////////////////
+// String(const uint* utf32String);
+//
+// ////////////////////////////////////////////////////////////
+// /// \brief Construct from an UTF-32 string
+// ///
+// /// \param utf32String UTF-32 string to assign
+// ///
+// ////////////////////////////////////////////////////////////
+// String(const std::basic_string<uint>& utf32String);
+//
+// ////////////////////////////////////////////////////////////
+// /// \brief Copy constructor
+// ///
+// /// \param copy Instance to copy
+// ///
+// ////////////////////////////////////////////////////////////
+// String(const String& copy);
+//
+// ////////////////////////////////////////////////////////////
+// /// \brief Create a new sf::String from a UTF-8 encoded string
+// ///
+// /// \param begin Forward iterator to the beginning of the UTF-8 sequence
+// /// \param end Forward iterator to the end of the UTF-8 sequence
+// ///
+// /// \return A sf::String containing the source string
+// ///
+// /// \see fromUtf16, fromUtf32
+// ///
+// ////////////////////////////////////////////////////////////
+// template <typename T>
+// static String FromUtf8(T begin, T end);
+//
+// ////////////////////////////////////////////////////////////
+// /// \brief Create a new sf::String from a UTF-16 encoded string
+// ///
+// /// \param begin Forward iterator to the beginning of the UTF-16 sequence
+// /// \param end Forward iterator to the end of the UTF-16 sequence
+// ///
+// /// \return A sf::String containing the source string
+// ///
+// /// \see fromUtf8, fromUtf32
+// ///
+// ////////////////////////////////////////////////////////////
+// template <typename T>
+// static String FromUtf16(T begin, T end);
+//
+// ////////////////////////////////////////////////////////////
+// /// \brief Create a new sf::String from a UTF-32 encoded string
+// ///
+// /// This function is provided for consistency, it is equivalent to
+// /// using the constructors that takes a const sf::uint* or
+// /// a std::basic_string<sf::uint>.
+// ///
+// /// \param begin Forward iterator to the beginning of the UTF-32 sequence
+// /// \param end Forward iterator to the end of the UTF-32 sequence
+// ///
+// /// \return A sf::String containing the source string
+// ///
+// /// \see fromUtf8, fromUtf16
+// ///
+// ////////////////////////////////////////////////////////////
+// template <typename T>
+// static String FromUtf32(T begin, T end);
+//
+// ////////////////////////////////////////////////////////////
+// /// \brief Implicit conversion operator to std::string (ANSI string)
+// ///
+// /// The current global locale is used for conversion. If you
+// /// want to explicitly specify a locale, see toAnsiString.
+// /// Characters that do not fit in the target encoding are
+// /// discarded from the returned string.
+// /// This operator is defined for convenience, and is equivalent
+// /// to calling toAnsiString().
+// ///
+// /// \return Converted ANSI string
+// ///
+// /// \see toAnsiString, operator std::wstring
+// ///
+// ////////////////////////////////////////////////////////////
+// operator std::string() const;
+//
+// ////////////////////////////////////////////////////////////
+// /// \brief Implicit conversion operator to std::wstring (wide string)
+// ///
+// /// Characters that do not fit in the target encoding are
+// /// discarded from the returned string.
+// /// This operator is defined for convenience, and is equivalent
+// /// to calling toWideString().
+// ///
+// /// \return Converted wide string
+// ///
+// /// \see toWideString, operator std::string
+// ///
+// ////////////////////////////////////////////////////////////
+// operator std::wstring() const;
+//
+// ////////////////////////////////////////////////////////////
+// /// \brief Convert the Unicode string to an ANSI string
+// ///
+// /// The UTF-32 string is converted to an ANSI string in
+// /// the encoding defined by \a locale.
+// /// Characters that do not fit in the target encoding are
+// /// discarded from the returned string.
+// ///
+// /// \param locale Locale to use for conversion
+// ///
+// /// \return Converted ANSI string
+// ///
+// /// \see toWideString, operator std::string
+// ///
+// ////////////////////////////////////////////////////////////
+// std::string ToAnsiString(const std::locale& locale = std::locale()) const;
+//
+// ////////////////////////////////////////////////////////////
+// /// \brief Convert the Unicode string to a wide string
+// ///
+// /// Characters that do not fit in the target encoding are
+// /// discarded from the returned string.
+// ///
+// /// \return Converted wide string
+// ///
+// /// \see toAnsiString, operator std::wstring
+// ///
+// ////////////////////////////////////////////////////////////
+// std::wstring ToWideString() const;
+//
+// ////////////////////////////////////////////////////////////
+// /// \brief Convert the Unicode string to a UTF-8 string
+// ///
+// /// \return Converted UTF-8 string
+// ///
+// /// \see toUtf16, toUtf32
+// ///
+// ////////////////////////////////////////////////////////////
+// std::basic_string<uint8> ToUtf8() const;
+//
+// ////////////////////////////////////////////////////////////
+// /// \brief Convert the Unicode string to a UTF-16 string
+// ///
+// /// \return Converted UTF-16 string
+// ///
+// /// \see toUtf8, toUtf32
+// ///
+// ////////////////////////////////////////////////////////////
+// std::basic_string<uint16> ToUtf16() const;
+//
+// ////////////////////////////////////////////////////////////
+// /// \brief Convert the Unicode string to a UTF-32 string
+// ///
+// /// This function doesn't perform any conversion, since the
+// /// string is already stored as UTF-32 internally.
+// ///
+// /// \return Converted UTF-32 string
+// ///
+// /// \see toUtf8, toUtf16
+// ///
+// ////////////////////////////////////////////////////////////
+// std::basic_string<uint> ToUtf32() const;
+//
+// ////////////////////////////////////////////////////////////
+// /// \brief Overload of assignment operator
+// ///
+// /// \param right Instance to assign
+// ///
+// /// \return Reference to self
+// ///
+// ////////////////////////////////////////////////////////////
+// String& operator =(const String& right);
+//
+// ////////////////////////////////////////////////////////////
+// /// \brief Overload of += operator to append an UTF-32 string
+// ///
+// /// \param right String to append
+// ///
+// /// \return Reference to self
+// ///
+// ////////////////////////////////////////////////////////////
+// String& operator +=(const String& right);
+//
+// ////////////////////////////////////////////////////////////
+// /// \brief Overload of [] operator to access a character by its position
+// ///
+// /// This function provides read-only access to characters.
+// /// Note: the behavior is undefined if \a index is out of range.
+// ///
+// /// \param index Index of the character to get
+// ///
+// /// \return Character at position \a index
+// ///
+// ////////////////////////////////////////////////////////////
+// uint operator [](std::size_t index) const;
+//
+// ////////////////////////////////////////////////////////////
+// /// \brief Overload of [] operator to access a character by its position
+// ///
+// /// This function provides read and write access to characters.
+// /// Note: the behavior is undefined if \a index is out of range.
+// ///
+// /// \param index Index of the character to get
+// ///
+// /// \return Reference to the character at position \a index
+// ///
+// ////////////////////////////////////////////////////////////
+// uint& operator [](std::size_t index);
+//
+// ////////////////////////////////////////////////////////////
+// /// \brief Clear the string
+// ///
+// /// This function removes all the characters from the string.
+// ///
+// /// \see isEmpty, erase
+// ///
+// ////////////////////////////////////////////////////////////
+// void Clear();
+//
+// ////////////////////////////////////////////////////////////
+// /// \brief Get the size of the string
+// ///
+// /// \return Number of characters in the string
+// ///
+// /// \see isEmpty
+// ///
+// ////////////////////////////////////////////////////////////
+// std::size_t GetSize() const;
+//
+// ////////////////////////////////////////////////////////////
+// /// \brief Check whether the string is empty or not
+// ///
+// /// \return True if the string is empty (i.e. contains no character)
+// ///
+// /// \see clear, getSize
+// ///
+// ////////////////////////////////////////////////////////////
+// bool IsEmpty() const;
+//
+// ////////////////////////////////////////////////////////////
+// /// \brief Erase one or more characters from the string
+// ///
+// /// This function removes a sequence of \a count characters
+// /// starting from \a position.
+// ///
+// /// \param position Position of the first character to erase
+// /// \param count Number of characters to erase
+// ///
+// ////////////////////////////////////////////////////////////
+// void Erase(std::size_t position, std::size_t count = 1);
+//
+// ////////////////////////////////////////////////////////////
+// /// \brief Insert one or more characters into the string
+// ///
+// /// This function inserts the characters of \a str
+// /// into the string, starting from \a position.
+// ///
+// /// \param position Position of insertion
+// /// \param str Characters to insert
+// ///
+// ////////////////////////////////////////////////////////////
+// void Insert(std::size_t position, const String& str);
+//
+// ////////////////////////////////////////////////////////////
+// /// \brief Find a sequence of one or more characters in the string
+// ///
+// /// This function searches for the characters of \a str
+// /// in the string, starting from \a start.
+// ///
+// /// \param str Characters to find
+// /// \param start Where to begin searching
+// ///
+// /// \return Position of \a str in the string, or String::InvalidPos if not found
+// ///
+// ////////////////////////////////////////////////////////////
+// std::size_t Find(const String& str, std::size_t start = 0) const;
+//
+// ////////////////////////////////////////////////////////////
+// /// \brief Replace a substring with another string
+// ///
+// /// This function replaces the substring that starts at index \a position
+// /// and spans \a length characters with the string \a replaceWith.
+// ///
+// /// \param position Index of the first character to be replaced
+// /// \param length Number of characters to replace. You can pass InvalidPos to
+// /// replace all characters until the end of the string.
+// /// \param replaceWith String that replaces the given substring.
+// ///
+// ////////////////////////////////////////////////////////////
+// void Replace(std::size_t position, std::size_t length, const String& replaceWith);
+//
+// ////////////////////////////////////////////////////////////
+// /// \brief Replace all occurrences of a substring with a replacement string
+// ///
+// /// This function replaces all occurrences of \a searchFor in this string
+// /// with the string \a replaceWith.
+// ///
+// /// \param searchFor The value being searched for
+// /// \param replaceWith The value that replaces found \a searchFor values
+// ///
+// ////////////////////////////////////////////////////////////
+// void Replace(const String& searchFor, const String& replaceWith);
+//
+// ////////////////////////////////////////////////////////////
+// /// \brief Return a part of the string
+// ///
+// /// This function returns the substring that starts at index \a position
+// /// and spans \a length characters.
+// ///
+// /// \param position Index of the first character
+// /// \param length Number of characters to include in the substring (if
+// /// the string is shorter, as many characters as possible
+// /// are included). \ref InvalidPos can be used to include all
+// /// characters until the end of the string.
+// ///
+// /// \return String object containing a substring of this object
+// ///
+// ////////////////////////////////////////////////////////////
+// String Substring(std::size_t position, std::size_t length = InvalidPos) const;
+//
+// ////////////////////////////////////////////////////////////
+// /// \brief Get a pointer to the C-style array of characters
+// ///
+// /// This functions provides a read-only access to a
+// /// null-terminated C-style representation of the string.
+// /// The returned pointer is temporary and is meant only for
+// /// immediate use, thus it is not recommended to store it.
+// ///
+// /// \return Read-only pointer to the array of characters
+// ///
+// ////////////////////////////////////////////////////////////
+// const uint* GetData() const;
+//
+// ////////////////////////////////////////////////////////////
+// /// \brief Return an iterator to the beginning of the string
+// ///
+// /// \return Read-write iterator to the beginning of the string characters
+// ///
+// /// \see end
+// ///
+// ////////////////////////////////////////////////////////////
+// Iterator Begin();
+//
+// ////////////////////////////////////////////////////////////
+// /// \brief Return an iterator to the beginning of the string
+// ///
+// /// \return Read-only iterator to the beginning of the string characters
+// ///
+// /// \see end
+// ///
+// ////////////////////////////////////////////////////////////
+// ConstIterator Begin() const;
+//
+// ////////////////////////////////////////////////////////////
+// /// \brief Return an iterator to the end of the string
+// ///
+// /// The end iterator refers to 1 position past the last character;
+// /// thus it represents an invalid character and should never be
+// /// accessed.
+// ///
+// /// \return Read-write iterator to the end of the string characters
+// ///
+// /// \see begin
+// ///
+// ////////////////////////////////////////////////////////////
+// Iterator End();
+//
+// ////////////////////////////////////////////////////////////
+// /// \brief Return an iterator to the end of the string
+// ///
+// /// The end iterator refers to 1 position past the last character;
+// /// thus it represents an invalid character and should never be
+// /// accessed.
+// ///
+// /// \return Read-only iterator to the end of the string characters
+// ///
+// /// \see begin
+// ///
+// ////////////////////////////////////////////////////////////
+// ConstIterator End() const;
+//
+// private:
+//
+// friend bool operator ==(const String& left, const String& right);
+// friend bool operator <(const String& left, const String& right);
+//
+// ////////////////////////////////////////////////////////////
+// // Member data
+// ////////////////////////////////////////////////////////////
+// std::basic_string<uint> m_String; ///< Internal string of UTF-32 characters
+// };
+//
+// ////////////////////////////////////////////////////////////
+// /// \relates String
+// /// \brief Overload of == operator to compare two UTF-32 strings
+// ///
+// /// \param left Left operand (a string)
+// /// \param right Right operand (a string)
+// ///
+// /// \return True if both strings are equal
+// ///
+// ////////////////////////////////////////////////////////////
+// bool operator ==(const String& left, const String& right);
+//
+// ////////////////////////////////////////////////////////////
+// /// \relates String
+// /// \brief Overload of != operator to compare two UTF-32 strings
+// ///
+// /// \param left Left operand (a string)
+// /// \param right Right operand (a string)
+// ///
+// /// \return True if both strings are different
+// ///
+// ////////////////////////////////////////////////////////////
+// bool operator !=(const String& left, const String& right);
+//
+// ////////////////////////////////////////////////////////////
+// /// \relates String
+// /// \brief Overload of < operator to compare two UTF-32 strings
+// ///
+// /// \param left Left operand (a string)
+// /// \param right Right operand (a string)
+// ///
+// /// \return True if \a left is lexicographically before \a right
+// ///
+// ////////////////////////////////////////////////////////////
+// bool operator <(const String& left, const String& right);
+//
+// ////////////////////////////////////////////////////////////
+// /// \relates String
+// /// \brief Overload of > operator to compare two UTF-32 strings
+// ///
+// /// \param left Left operand (a string)
+// /// \param right Right operand (a string)
+// ///
+// /// \return True if \a left is lexicographically after \a right
+// ///
+// ////////////////////////////////////////////////////////////
+// bool operator >(const String& left, const String& right);
+//
+// ////////////////////////////////////////////////////////////
+// /// \relates String
+// /// \brief Overload of <= operator to compare two UTF-32 strings
+// ///
+// /// \param left Left operand (a string)
+// /// \param right Right operand (a string)
+// ///
+// /// \return True if \a left is lexicographically before or equivalent to \a right
+// ///
+// ////////////////////////////////////////////////////////////
+// bool operator <=(const String& left, const String& right);
+//
+// ////////////////////////////////////////////////////////////
+// /// \relates String
+// /// \brief Overload of >= operator to compare two UTF-32 strings
+// ///
+// /// \param left Left operand (a string)
+// /// \param right Right operand (a string)
+// ///
+// /// \return True if \a left is lexicographically after or equivalent to \a right
+// ///
+// ////////////////////////////////////////////////////////////
+// bool operator >=(const String& left, const String& right);
+//
+// ////////////////////////////////////////////////////////////
+// /// \relates String
+// /// \brief Overload of binary + operator to concatenate two strings
+// ///
+// /// \param left Left operand (a string)
+// /// \param right Right operand (a string)
+// ///
+// /// \return Concatenated string
+// ///
+// ////////////////////////////////////////////////////////////
+// String operator +(const String& left, const String& right);
+//
+// #include "String.inc"
+//
+// }
+//}
+//
+//#endif \ No newline at end of file
diff --git a/Source/modules/asura-core/Font/String.inc b/Source/modules/asura-core/Font/String.inc
new file mode 100644
index 0000000..ef18228
--- /dev/null
+++ b/Source/modules/asura-core/Font/String.inc
@@ -0,0 +1,29 @@
+
+////////////////////////////////////////////////////////////
+template <typename T>
+String String::fromUtf8(T begin, T end)
+{
+ String string;
+ Utf8::toUtf32(begin, end, std::back_inserter(string.m_string));
+ return string;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename T>
+String String::fromUtf16(T begin, T end)
+{
+ String string;
+ Utf16::toUtf32(begin, end, std::back_inserter(string.m_string));
+ return string;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename T>
+String String::fromUtf32(T begin, T end)
+{
+ String string;
+ string.m_string.assign(begin, end);
+ return string;
+}
diff --git a/Source/modules/asura-core/Font/TTF.cpp b/Source/modules/asura-core/Font/TTF.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-core/Font/TTF.cpp
diff --git a/Source/modules/asura-core/Font/TTF.h b/Source/modules/asura-core/Font/TTF.h
new file mode 100644
index 0000000..b83cf76
--- /dev/null
+++ b/Source/modules/asura-core/Font/TTF.h
@@ -0,0 +1,17 @@
+#ifndef _ASURA_TTF_H_
+#define _ASURA_TTF_H_
+
+namespace AsuraEngine
+{
+ namespace Text
+ {
+
+ class TTF
+ {
+
+ };
+
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-core/Font/Utf.hpp b/Source/modules/asura-core/Font/Utf.hpp
new file mode 100644
index 0000000..59f62ed
--- /dev/null
+++ b/Source/modules/asura-core/Font/Utf.hpp
@@ -0,0 +1,720 @@
+#ifndef _ASURA_UTF_HPP_
+#define _ASURA_UTF_HPP_
+
+////////////////////////////////////////////////////////////
+// Headers
+////////////////////////////////////////////////////////////
+#include <algorithm>
+#include <locale>
+#include <string>
+#include <cstdlib>
+
+namespace AsuraEngine
+{
+ namespace Text
+ {
+
+ template <unsigned int N>
+ class Utf;
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Specialization of the Utf template for UTF-8
+ ///
+ ////////////////////////////////////////////////////////////
+ template <>
+ class Utf<8>
+ {
+ public:
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Decode a single UTF-8 character
+ ///
+ /// Decoding a character means finding its unique 32-bits
+ /// code (called the codepoint) in the Unicode standard.
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Codepoint of the decoded UTF-8 character
+ /// \param replacement Replacement character to use in case the UTF-8 sequence is invalid
+ ///
+ /// \return Iterator pointing to one past the last read element of the input sequence
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In>
+ static In Decode(In begin, In end, Uint32& output, Uint32 replacement = 0);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Encode a single UTF-8 character
+ ///
+ /// Encoding a character means converting a unique 32-bits
+ /// code (called the codepoint) in the target encoding, UTF-8.
+ ///
+ /// \param input Codepoint to encode as UTF-8
+ /// \param output Iterator pointing to the beginning of the output sequence
+ /// \param replacement Replacement for characters not convertible to UTF-8 (use 0 to skip them)
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename Out>
+ static Out Encode(Uint32 input, Out output, Uint8 replacement = 0);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Advance to the next UTF-8 character
+ ///
+ /// This function is necessary for multi-elements encodings, as
+ /// a single character may use more than 1 storage element.
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ ///
+ /// \return Iterator pointing to one past the last read element of the input sequence
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In>
+ static In Next(In begin, In end);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Count the number of characters of a UTF-8 sequence
+ ///
+ /// This function is necessary for multi-elements encodings, as
+ /// a single character may use more than 1 storage element, thus the
+ /// total size can be different from (begin - end).
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ ///
+ /// \return Iterator pointing to one past the last read element of the input sequence
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In>
+ static std::size_t Count(In begin, In end);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert an ANSI characters range to UTF-8
+ ///
+ /// The current global locale will be used by default, unless you
+ /// pass a custom one in the \a locale parameter.
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ /// \param locale Locale to use for conversion
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out FromAnsi(In begin, In end, Out output, const std::locale& locale = std::locale());
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert a wide characters range to UTF-8
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out FromWide(In begin, In end, Out output);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert a latin-1 (ISO-5589-1) characters range to UTF-8
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out FromLatin1(In begin, In end, Out output);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert an UTF-8 characters range to ANSI characters
+ ///
+ /// The current global locale will be used by default, unless you
+ /// pass a custom one in the \a locale parameter.
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ /// \param replacement Replacement for characters not convertible to ANSI (use 0 to skip them)
+ /// \param locale Locale to use for conversion
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out ToAnsi(In begin, In end, Out output, char replacement = 0, const std::locale& locale = std::locale());
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert an UTF-8 characters range to wide characters
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them)
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out ToWide(In begin, In end, Out output, wchar_t replacement = 0);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert an UTF-8 characters range to latin-1 (ISO-5589-1) characters
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them)
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out ToLatin1(In begin, In end, Out output, char replacement = 0);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert a UTF-8 characters range to UTF-8
+ ///
+ /// This functions does nothing more than a direct copy;
+ /// it is defined only to provide the same interface as other
+ /// specializations of the sf::Utf<> template, and allow
+ /// generic code to be written on top of it.
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out ToUtf8(In begin, In end, Out output);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert a UTF-8 characters range to UTF-16
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out ToUtf16(In begin, In end, Out output);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert a UTF-8 characters range to UTF-32
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out ToUtf32(In begin, In end, Out output);
+ };
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Specialization of the Utf template for UTF-16
+ ///
+ ////////////////////////////////////////////////////////////
+ template <>
+ class Utf<16>
+ {
+ public:
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Decode a single UTF-16 character
+ ///
+ /// Decoding a character means finding its unique 32-bits
+ /// code (called the codepoint) in the Unicode standard.
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Codepoint of the decoded UTF-16 character
+ /// \param replacement Replacement character to use in case the UTF-8 sequence is invalid
+ ///
+ /// \return Iterator pointing to one past the last read element of the input sequence
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In>
+ static In Decode(In begin, In end, Uint32& output, Uint32 replacement = 0);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Encode a single UTF-16 character
+ ///
+ /// Encoding a character means converting a unique 32-bits
+ /// code (called the codepoint) in the target encoding, UTF-16.
+ ///
+ /// \param input Codepoint to encode as UTF-16
+ /// \param output Iterator pointing to the beginning of the output sequence
+ /// \param replacement Replacement for characters not convertible to UTF-16 (use 0 to skip them)
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename Out>
+ static Out Encode(Uint32 input, Out output, Uint16 replacement = 0);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Advance to the next UTF-16 character
+ ///
+ /// This function is necessary for multi-elements encodings, as
+ /// a single character may use more than 1 storage element.
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ ///
+ /// \return Iterator pointing to one past the last read element of the input sequence
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In>
+ static In Next(In begin, In end);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Count the number of characters of a UTF-16 sequence
+ ///
+ /// This function is necessary for multi-elements encodings, as
+ /// a single character may use more than 1 storage element, thus the
+ /// total size can be different from (begin - end).
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ ///
+ /// \return Iterator pointing to one past the last read element of the input sequence
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In>
+ static std::size_t Count(In begin, In end);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert an ANSI characters range to UTF-16
+ ///
+ /// The current global locale will be used by default, unless you
+ /// pass a custom one in the \a locale parameter.
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ /// \param locale Locale to use for conversion
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out FromAnsi(In begin, In end, Out output, const std::locale& locale = std::locale());
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert a wide characters range to UTF-16
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out FromWide(In begin, In end, Out output);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert a latin-1 (ISO-5589-1) characters range to UTF-16
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out FromLatin1(In begin, In end, Out output);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert an UTF-16 characters range to ANSI characters
+ ///
+ /// The current global locale will be used by default, unless you
+ /// pass a custom one in the \a locale parameter.
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ /// \param replacement Replacement for characters not convertible to ANSI (use 0 to skip them)
+ /// \param locale Locale to use for conversion
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out ToAnsi(In begin, In end, Out output, char replacement = 0, const std::locale& locale = std::locale());
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert an UTF-16 characters range to wide characters
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them)
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out ToWide(In begin, In end, Out output, wchar_t replacement = 0);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert an UTF-16 characters range to latin-1 (ISO-5589-1) characters
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them)
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out ToLatin1(In begin, In end, Out output, char replacement = 0);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert a UTF-16 characters range to UTF-8
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out ToUtf8(In begin, In end, Out output);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert a UTF-16 characters range to UTF-16
+ ///
+ /// This functions does nothing more than a direct copy;
+ /// it is defined only to provide the same interface as other
+ /// specializations of the sf::Utf<> template, and allow
+ /// generic code to be written on top of it.
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out ToUtf16(In begin, In end, Out output);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert a UTF-16 characters range to UTF-32
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out ToUtf32(In begin, In end, Out output);
+ };
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Specialization of the Utf template for UTF-32
+ ///
+ ////////////////////////////////////////////////////////////
+ template <>
+ class Utf<32>
+ {
+ public:
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Decode a single UTF-32 character
+ ///
+ /// Decoding a character means finding its unique 32-bits
+ /// code (called the codepoint) in the Unicode standard.
+ /// For UTF-32, the character value is the same as the codepoint.
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Codepoint of the decoded UTF-32 character
+ /// \param replacement Replacement character to use in case the UTF-8 sequence is invalid
+ ///
+ /// \return Iterator pointing to one past the last read element of the input sequence
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In>
+ static In Decode(In begin, In end, Uint32& output, Uint32 replacement = 0);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Encode a single UTF-32 character
+ ///
+ /// Encoding a character means converting a unique 32-bits
+ /// code (called the codepoint) in the target encoding, UTF-32.
+ /// For UTF-32, the codepoint is the same as the character value.
+ ///
+ /// \param input Codepoint to encode as UTF-32
+ /// \param output Iterator pointing to the beginning of the output sequence
+ /// \param replacement Replacement for characters not convertible to UTF-32 (use 0 to skip them)
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename Out>
+ static Out Encode(Uint32 input, Out output, Uint32 replacement = 0);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Advance to the next UTF-32 character
+ ///
+ /// This function is trivial for UTF-32, which can store
+ /// every character in a single storage element.
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ ///
+ /// \return Iterator pointing to one past the last read element of the input sequence
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In>
+ static In Next(In begin, In end);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Count the number of characters of a UTF-32 sequence
+ ///
+ /// This function is trivial for UTF-32, which can store
+ /// every character in a single storage element.
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ ///
+ /// \return Iterator pointing to one past the last read element of the input sequence
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In>
+ static std::size_t Count(In begin, In end);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert an ANSI characters range to UTF-32
+ ///
+ /// The current global locale will be used by default, unless you
+ /// pass a custom one in the \a locale parameter.
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ /// \param locale Locale to use for conversion
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out FromAnsi(In begin, In end, Out output, const std::locale& locale = std::locale());
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert a wide characters range to UTF-32
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out FromWide(In begin, In end, Out output);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert a latin-1 (ISO-5589-1) characters range to UTF-32
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out FromLatin1(In begin, In end, Out output);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert an UTF-32 characters range to ANSI characters
+ ///
+ /// The current global locale will be used by default, unless you
+ /// pass a custom one in the \a locale parameter.
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ /// \param replacement Replacement for characters not convertible to ANSI (use 0 to skip them)
+ /// \param locale Locale to use for conversion
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out ToAnsi(In begin, In end, Out output, char replacement = 0, const std::locale& locale = std::locale());
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert an UTF-32 characters range to wide characters
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them)
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out ToWide(In begin, In end, Out output, wchar_t replacement = 0);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert an UTF-16 characters range to latin-1 (ISO-5589-1) characters
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them)
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out ToLatin1(In begin, In end, Out output, char replacement = 0);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert a UTF-32 characters range to UTF-8
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out ToUtf8(In begin, In end, Out output);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert a UTF-32 characters range to UTF-16
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out ToUtf16(In begin, In end, Out output);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert a UTF-32 characters range to UTF-32
+ ///
+ /// This functions does nothing more than a direct copy;
+ /// it is defined only to provide the same interface as other
+ /// specializations of the sf::Utf<> template, and allow
+ /// generic code to be written on top of it.
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out ToUtf32(In begin, In end, Out output);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Decode a single ANSI character to UTF-32
+ ///
+ /// This function does not exist in other specializations
+ /// of sf::Utf<>, it is defined for convenience (it is used by
+ /// several other conversion functions).
+ ///
+ /// \param input Input ANSI character
+ /// \param locale Locale to use for conversion
+ ///
+ /// \return Converted character
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In>
+ static Uint32 DecodeAnsi(In input, const std::locale& locale = std::locale());
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Decode a single wide character to UTF-32
+ ///
+ /// This function does not exist in other specializations
+ /// of sf::Utf<>, it is defined for convenience (it is used by
+ /// several other conversion functions).
+ ///
+ /// \param input Input wide character
+ ///
+ /// \return Converted character
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In>
+ static Uint32 DecodeWide(In input);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Encode a single UTF-32 character to ANSI
+ ///
+ /// This function does not exist in other specializations
+ /// of sf::Utf<>, it is defined for convenience (it is used by
+ /// several other conversion functions).
+ ///
+ /// \param codepoint Iterator pointing to the beginning of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ /// \param replacement Replacement if the input character is not convertible to ANSI (use 0 to skip it)
+ /// \param locale Locale to use for conversion
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename Out>
+ static Out EncodeAnsi(Uint32 codepoint, Out output, char replacement = 0, const std::locale& locale = std::locale());
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Encode a single UTF-32 character to wide
+ ///
+ /// This function does not exist in other specializations
+ /// of sf::Utf<>, it is defined for convenience (it is used by
+ /// several other conversion functions).
+ ///
+ /// \param codepoint Iterator pointing to the beginning of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ /// \param replacement Replacement if the input character is not convertible to wide (use 0 to skip it)
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename Out>
+ static Out EncodeWide(Uint32 codepoint, Out output, wchar_t replacement = 0);
+ };
+
+#include "Utf.inc"
+
+ // Make typedefs to get rid of the template syntax
+ typedef Utf<8> Utf8;
+ typedef Utf<16> Utf16;
+ typedef Utf<32> Utf32;
+
+ } // namespace sf
+
+}
+
+
+#endif // SFML_UTF_HPP
diff --git a/Source/modules/asura-core/Font/Utf.inc b/Source/modules/asura-core/Font/Utf.inc
new file mode 100644
index 0000000..69a523b
--- /dev/null
+++ b/Source/modules/asura-core/Font/Utf.inc
@@ -0,0 +1,752 @@
+////////////////////////////////////////////////////////////
+//
+// SFML - Simple and Fast Multimedia Library
+// Copyright (C) 2007-2019 Laurent Gomila (laurent@sfml-dev.org)
+//
+// This software is provided 'as-is', without any express or implied warranty.
+// In no event will the authors be held liable for any damages arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it freely,
+// subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented;
+// you must not claim that you wrote the original software.
+// If you use this software in a product, an acknowledgment
+// in the product documentation would be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such,
+// and must not be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source distribution.
+//
+////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////
+// References:
+//
+// https://www.unicode.org/
+// https://www.unicode.org/Public/PROGRAMS/CVTUTF/ConvertUTF.c
+// https://www.unicode.org/Public/PROGRAMS/CVTUTF/ConvertUTF.h
+// https://people.w3.org/rishida/scripts/uniview/conversion
+//
+////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////
+template <typename In>
+In Utf<8>::Decode(In begin, In end, Uint32& output, Uint32 replacement)
+{
+ // Some useful precomputed data
+ static const int trailing[256] =
+ {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5
+ };
+ static const Uint32 offsets[6] =
+ {
+ 0x00000000, 0x00003080, 0x000E2080, 0x03C82080, 0xFA082080, 0x82082080
+ };
+
+ // decode the character
+ int trailingBytes = trailing[static_cast<Uint8>(*begin)];
+ if (begin + trailingBytes < end)
+ {
+ output = 0;
+ switch (trailingBytes)
+ {
+ case 5: output += static_cast<Uint8>(*begin++); output <<= 6;
+ case 4: output += static_cast<Uint8>(*begin++); output <<= 6;
+ case 3: output += static_cast<Uint8>(*begin++); output <<= 6;
+ case 2: output += static_cast<Uint8>(*begin++); output <<= 6;
+ case 1: output += static_cast<Uint8>(*begin++); output <<= 6;
+ case 0: output += static_cast<Uint8>(*begin++);
+ }
+ output -= offsets[trailingBytes];
+ }
+ else
+ {
+ // Incomplete character
+ begin = end;
+ output = replacement;
+ }
+
+ return begin;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename Out>
+Out Utf<8>::Encode(Uint32 input, Out output, Uint8 replacement)
+{
+ // Some useful precomputed data
+ static const Uint8 firstBytes[7] =
+ {
+ 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC
+ };
+
+ // encode the character
+ if ((input > 0x0010FFFF) || ((input >= 0xD800) && (input <= 0xDBFF)))
+ {
+ // Invalid character
+ if (replacement)
+ *output++ = replacement;
+ }
+ else
+ {
+ // Valid character
+
+ // Get the number of bytes to write
+ std::size_t bytestoWrite = 1;
+ if (input < 0x80) bytestoWrite = 1;
+ else if (input < 0x800) bytestoWrite = 2;
+ else if (input < 0x10000) bytestoWrite = 3;
+ else if (input <= 0x0010FFFF) bytestoWrite = 4;
+
+ // Extract the bytes to write
+ Uint8 bytes[4];
+ switch (bytestoWrite)
+ {
+ case 4: bytes[3] = static_cast<Uint8>((input | 0x80) & 0xBF); input >>= 6;
+ case 3: bytes[2] = static_cast<Uint8>((input | 0x80) & 0xBF); input >>= 6;
+ case 2: bytes[1] = static_cast<Uint8>((input | 0x80) & 0xBF); input >>= 6;
+ case 1: bytes[0] = static_cast<Uint8> (input | firstBytes[bytestoWrite]);
+ }
+
+ // Add them to the output
+ output = std::copy(bytes, bytes + bytestoWrite, output);
+ }
+
+ return output;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In>
+In Utf<8>::Next(In begin, In end)
+{
+ Uint32 codepoint;
+ return Decode(begin, end, codepoint);
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In>
+std::size_t Utf<8>::Count(In begin, In end)
+{
+ std::size_t length = 0;
+ while (begin < end)
+ {
+ begin = Next(begin, end);
+ ++length;
+ }
+
+ return length;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In, typename Out>
+Out Utf<8>::FromAnsi(In begin, In end, Out output, const std::locale& locale)
+{
+ while (begin < end)
+ {
+ Uint32 codepoint = Utf<32>::DecodeAnsi(*begin++, locale);
+ output = Encode(codepoint, output);
+ }
+
+ return output;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In, typename Out>
+Out Utf<8>::FromWide(In begin, In end, Out output)
+{
+ while (begin < end)
+ {
+ Uint32 codepoint = Utf<32>::DecodeWide(*begin++);
+ output = Encode(codepoint, output);
+ }
+
+ return output;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In, typename Out>
+Out Utf<8>::FromLatin1(In begin, In end, Out output)
+{
+ // Latin-1 is directly compatible with Unicode encodings,
+ // and can thus be treated as (a sub-range of) UTF-32
+ while (begin < end)
+ output = Encode(*begin++, output);
+
+ return output;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In, typename Out>
+Out Utf<8>::ToAnsi(In begin, In end, Out output, char replacement, const std::locale& locale)
+{
+ while (begin < end)
+ {
+ Uint32 codepoint;
+ begin = Decode(begin, end, codepoint);
+ output = Utf<32>::EncodeAnsi(codepoint, output, replacement, locale);
+ }
+
+ return output;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In, typename Out>
+Out Utf<8>::ToWide(In begin, In end, Out output, wchar_t replacement)
+{
+ while (begin < end)
+ {
+ Uint32 codepoint;
+ begin = Decode(begin, end, codepoint);
+ output = Utf<32>::EncodeWide(codepoint, output, replacement);
+ }
+
+ return output;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In, typename Out>
+Out Utf<8>::ToLatin1(In begin, In end, Out output, char replacement)
+{
+ // Latin-1 is directly compatible with Unicode encodings,
+ // and can thus be treated as (a sub-range of) UTF-32
+ while (begin < end)
+ {
+ Uint32 codepoint;
+ begin = Decode(begin, end, codepoint);
+ *output++ = codepoint < 256 ? static_cast<char>(codepoint) : replacement;
+ }
+
+ return output;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In, typename Out>
+Out Utf<8>::ToUtf8(In begin, In end, Out output)
+{
+ return std::copy(begin, end, output);
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In, typename Out>
+Out Utf<8>::ToUtf16(In begin, In end, Out output)
+{
+ while (begin < end)
+ {
+ Uint32 codepoint;
+ begin = Decode(begin, end, codepoint);
+ output = Utf<16>::Encode(codepoint, output);
+ }
+
+ return output;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In, typename Out>
+Out Utf<8>::ToUtf32(In begin, In end, Out output)
+{
+ while (begin < end)
+ {
+ Uint32 codepoint;
+ begin = Decode(begin, end, codepoint);
+ *output++ = codepoint;
+ }
+
+ return output;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In>
+In Utf<16>::Decode(In begin, In end, Uint32& output, Uint32 replacement)
+{
+ Uint16 first = *begin++;
+
+ // If it's a surrogate pair, first convert to a single UTF-32 character
+ if ((first >= 0xD800) && (first <= 0xDBFF))
+ {
+ if (begin < end)
+ {
+ Uint32 second = *begin++;
+ if ((second >= 0xDC00) && (second <= 0xDFFF))
+ {
+ // The second element is valid: convert the two elements to a UTF-32 character
+ output = ((first - 0xD800) << 10) + (second - 0xDC00) + 0x0010000;
+ }
+ else
+ {
+ // Invalid character
+ output = replacement;
+ }
+ }
+ else
+ {
+ // Invalid character
+ begin = end;
+ output = replacement;
+ }
+ }
+ else
+ {
+ // We can make a direct copy
+ output = first;
+ }
+
+ return begin;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename Out>
+Out Utf<16>::Encode(Uint32 input, Out output, Uint16 replacement)
+{
+ if (input <= 0xFFFF)
+ {
+ // The character can be copied directly, we just need to check if it's in the valid range
+ if ((input >= 0xD800) && (input <= 0xDFFF))
+ {
+ // Invalid character (this range is reserved)
+ if (replacement)
+ *output++ = replacement;
+ }
+ else
+ {
+ // Valid character directly convertible to a single UTF-16 character
+ *output++ = static_cast<Uint16>(input);
+ }
+ }
+ else if (input > 0x0010FFFF)
+ {
+ // Invalid character (greater than the maximum Unicode value)
+ if (replacement)
+ *output++ = replacement;
+ }
+ else
+ {
+ // The input character will be converted to two UTF-16 elements
+ input -= 0x0010000;
+ *output++ = static_cast<Uint16>((input >> 10) + 0xD800);
+ *output++ = static_cast<Uint16>((input & 0x3FFUL) + 0xDC00);
+ }
+
+ return output;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In>
+In Utf<16>::Next(In begin, In end)
+{
+ Uint32 codepoint;
+ return Decode(begin, end, codepoint);
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In>
+std::size_t Utf<16>::Count(In begin, In end)
+{
+ std::size_t length = 0;
+ while (begin < end)
+ {
+ begin = Next(begin, end);
+ ++length;
+ }
+
+ return length;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In, typename Out>
+Out Utf<16>::FromAnsi(In begin, In end, Out output, const std::locale& locale)
+{
+ while (begin < end)
+ {
+ Uint32 codepoint = Utf<32>::DecodeAnsi(*begin++, locale);
+ output = Encode(codepoint, output);
+ }
+
+ return output;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In, typename Out>
+Out Utf<16>::FromWide(In begin, In end, Out output)
+{
+ while (begin < end)
+ {
+ Uint32 codepoint = Utf<32>::DecodeWide(*begin++);
+ output = Encode(codepoint, output);
+ }
+
+ return output;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In, typename Out>
+Out Utf<16>::FromLatin1(In begin, In end, Out output)
+{
+ // Latin-1 is directly compatible with Unicode encodings,
+ // and can thus be treated as (a sub-range of) UTF-32
+ return std::copy(begin, end, output);
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In, typename Out>
+Out Utf<16>::ToAnsi(In begin, In end, Out output, char replacement, const std::locale& locale)
+{
+ while (begin < end)
+ {
+ Uint32 codepoint;
+ begin = Decode(begin, end, codepoint);
+ output = Utf<32>::EncodeAnsi(codepoint, output, replacement, locale);
+ }
+
+ return output;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In, typename Out>
+Out Utf<16>::ToWide(In begin, In end, Out output, wchar_t replacement)
+{
+ while (begin < end)
+ {
+ Uint32 codepoint;
+ begin = Decode(begin, end, codepoint);
+ output = Utf<32>::EncodeWide(codepoint, output, replacement);
+ }
+
+ return output;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In, typename Out>
+Out Utf<16>::ToLatin1(In begin, In end, Out output, char replacement)
+{
+ // Latin-1 is directly compatible with Unicode encodings,
+ // and can thus be treated as (a sub-range of) UTF-32
+ while (begin < end)
+ {
+ *output++ = *begin < 256 ? static_cast<char>(*begin) : replacement;
+ begin++;
+ }
+
+ return output;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In, typename Out>
+Out Utf<16>::ToUtf8(In begin, In end, Out output)
+{
+ while (begin < end)
+ {
+ Uint32 codepoint;
+ begin = Decode(begin, end, codepoint);
+ output = Utf<8>::Encode(codepoint, output);
+ }
+
+ return output;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In, typename Out>
+Out Utf<16>::ToUtf16(In begin, In end, Out output)
+{
+ return std::copy(begin, end, output);
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In, typename Out>
+Out Utf<16>::ToUtf32(In begin, In end, Out output)
+{
+ while (begin < end)
+ {
+ Uint32 codepoint;
+ begin = Decode(begin, end, codepoint);
+ *output++ = codepoint;
+ }
+
+ return output;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In>
+In Utf<32>::Decode(In begin, In /*end*/, Uint32& output, Uint32 /*replacement*/)
+{
+ output = *begin++;
+ return begin;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename Out>
+Out Utf<32>::Encode(Uint32 input, Out output, Uint32 /*replacement*/)
+{
+ *output++ = input;
+ return output;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In>
+In Utf<32>::Next(In begin, In /*end*/)
+{
+ return ++begin;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In>
+std::size_t Utf<32>::Count(In begin, In end)
+{
+ return begin - end;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In, typename Out>
+Out Utf<32>::FromAnsi(In begin, In end, Out output, const std::locale& locale)
+{
+ while (begin < end)
+ *output++ = DecodeAnsi(*begin++, locale);
+
+ return output;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In, typename Out>
+Out Utf<32>::FromWide(In begin, In end, Out output)
+{
+ while (begin < end)
+ *output++ = DecodeWide(*begin++);
+
+ return output;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In, typename Out>
+Out Utf<32>::FromLatin1(In begin, In end, Out output)
+{
+ // Latin-1 is directly compatible with Unicode encodings,
+ // and can thus be treated as (a sub-range of) UTF-32
+ return std::copy(begin, end, output);
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In, typename Out>
+Out Utf<32>::ToAnsi(In begin, In end, Out output, char replacement, const std::locale& locale)
+{
+ while (begin < end)
+ output = EncodeAnsi(*begin++, output, replacement, locale);
+
+ return output;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In, typename Out>
+Out Utf<32>::ToWide(In begin, In end, Out output, wchar_t replacement)
+{
+ while (begin < end)
+ output = EncodeWide(*begin++, output, replacement);
+
+ return output;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In, typename Out>
+Out Utf<32>::ToLatin1(In begin, In end, Out output, char replacement)
+{
+ // Latin-1 is directly compatible with Unicode encodings,
+ // and can thus be treated as (a sub-range of) UTF-32
+ while (begin < end)
+ {
+ *output++ = *begin < 256 ? static_cast<char>(*begin) : replacement;
+ begin++;
+ }
+
+ return output;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In, typename Out>
+Out Utf<32>::ToUtf8(In begin, In end, Out output)
+{
+ while (begin < end)
+ output = Utf<8>::Encode(*begin++, output);
+
+ return output;
+}
+
+////////////////////////////////////////////////////////////
+template <typename In, typename Out>
+Out Utf<32>::ToUtf16(In begin, In end, Out output)
+{
+ while (begin < end)
+ output = Utf<16>::Encode(*begin++, output);
+
+ return output;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In, typename Out>
+Out Utf<32>::ToUtf32(In begin, In end, Out output)
+{
+ return std::copy(begin, end, output);
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In>
+Uint32 Utf<32>::DecodeAnsi(In input, const std::locale& locale)
+{
+ // On Windows, GCC's standard library (glibc++) has almost
+ // no support for Unicode stuff. As a consequence, in this
+ // context we can only use the default locale and ignore
+ // the one passed as parameter.
+
+ #if defined(SFML_SYSTEM_WINDOWS) && /* if Windows ... */ \
+ (defined(__GLIBCPP__) || defined (__GLIBCXX__)) && /* ... and standard library is glibc++ ... */ \
+ !(defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)) /* ... and STLPort is not used on top of it */
+
+ (void)locale; // to avoid warnings
+
+ wchar_t character = 0;
+ mbtowc(&character, &input, 1);
+ return static_cast<Uint32>(character);
+
+ #else
+
+ // Get the facet of the locale which deals with character conversion
+ const std::ctype<wchar_t>& facet = std::use_facet< std::ctype<wchar_t> >(locale);
+
+ // Use the facet to convert each character of the input string
+ return static_cast<Uint32>(facet.widen(input));
+
+ #endif
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename In>
+Uint32 Utf<32>::DecodeWide(In input)
+{
+ // The encoding of wide characters is not well defined and is left to the system;
+ // however we can safely assume that it is UCS-2 on Windows and
+ // UCS-4 on Unix systems.
+ // In both cases, a simple copy is enough (UCS-2 is a subset of UCS-4,
+ // and UCS-4 *is* UTF-32).
+
+ return input;
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename Out>
+Out Utf<32>::EncodeAnsi(Uint32 codepoint, Out output, char replacement, const std::locale& locale)
+{
+ // On Windows, gcc's standard library (glibc++) has almost
+ // no support for Unicode stuff. As a consequence, in this
+ // context we can only use the default locale and ignore
+ // the one passed as parameter.
+
+ #if defined(SFML_SYSTEM_WINDOWS) && /* if Windows ... */ \
+ (defined(__GLIBCPP__) || defined (__GLIBCXX__)) && /* ... and standard library is glibc++ ... */ \
+ !(defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)) /* ... and STLPort is not used on top of it */
+
+ (void)locale; // to avoid warnings
+
+ char character = 0;
+ if (wctomb(&character, static_cast<wchar_t>(codepoint)) >= 0)
+ *output++ = character;
+ else if (replacement)
+ *output++ = replacement;
+
+ return output;
+
+ #else
+
+ // Get the facet of the locale which deals with character conversion
+ const std::ctype<wchar_t>& facet = std::use_facet< std::ctype<wchar_t> >(locale);
+
+ // Use the facet to convert each character of the input string
+ *output++ = facet.narrow(static_cast<wchar_t>(codepoint), replacement);
+
+ return output;
+
+ #endif
+}
+
+
+////////////////////////////////////////////////////////////
+template <typename Out>
+Out Utf<32>::EncodeWide(Uint32 codepoint, Out output, wchar_t replacement)
+{
+ // The encoding of wide characters is not well defined and is left to the system;
+ // however we can safely assume that it is UCS-2 on Windows and
+ // UCS-4 on Unix systems.
+ // For UCS-2 we need to check if the source characters fits in (UCS-2 is a subset of UCS-4).
+ // For UCS-4 we can do a direct copy (UCS-4 *is* UTF-32).
+
+ switch (sizeof(wchar_t))
+ {
+ case 4:
+ {
+ *output++ = static_cast<wchar_t>(codepoint);
+ break;
+ }
+
+ default:
+ {
+ if ((codepoint <= 0xFFFF) && ((codepoint < 0xD800) || (codepoint > 0xDFFF)))
+ {
+ *output++ = static_cast<wchar_t>(codepoint);
+ }
+ else if (replacement)
+ {
+ *output++ = replacement;
+ }
+ break;
+ }
+ }
+
+ return output;
+}
diff --git a/Source/modules/asura-core/Graphics/BlendMode.h b/Source/modules/asura-core/Graphics/BlendMode.h
new file mode 100644
index 0000000..fb17b45
--- /dev/null
+++ b/Source/modules/asura-core/Graphics/BlendMode.h
@@ -0,0 +1,17 @@
+#ifndef _ASURA_ENGINE_BLEND_MODE_H_
+#define _ASURA_ENGINE_BLEND_MODE_H_
+
+#include <asura-base/Classes.h>
+
+namespace_begin(AsuraEngine)
+namespace_begin(Graphics)
+
+enum BlendMode
+{
+
+};
+
+namespace_end
+namespace_end
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-core/Graphics/Canvas.cpp b/Source/modules/asura-core/Graphics/Canvas.cpp
new file mode 100644
index 0000000..60c8f87
--- /dev/null
+++ b/Source/modules/asura-core/Graphics/Canvas.cpp
@@ -0,0 +1,49 @@
+#include "Canvas.h"
+
+namespace_begin(AsuraEngine)
+namespace_begin(Graphics)
+
+Canvas::Canvas()
+ : m_Width(0)
+ , m_Height(0)
+ , m_FBO(0)
+{
+ // Fix: ôСʼʱframebufferԴ
+ //glGenFramebuffers(1, &m_FBO);
+ //GLint current_fbo;
+ //glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &current_fbo);
+ //glBindFramebuffer(GL_FRAMEBUFFER, m_FBO);
+ //glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_TexID, 0);
+ //glBindFramebuffer(GL_FRAMEBUFFER, current_fbo);
+}
+
+void Canvas::SetSize(uint w, uint h)
+{
+ if (m_FBO == 0)
+ {
+ glGenFramebuffers(1, &m_FBO);
+ if (m_FBO == 0)
+ throw Exception("OpenGL glGenFramebuffers cannot generate frame buffer object.");
+ //
+ if (m_TexID == 0)
+ {
+ glGenTextures(1, &m_TexID);
+ if (m_TexID == 0)
+ throw Exception("OpenGL glGenTextures cannot generate texture.");
+ }
+ GLint current_fbo;
+ glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &current_fbo);
+ glBindFramebuffer(GL_FRAMEBUFFER, m_FBO);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_TexID, 0);
+ glBindFramebuffer(GL_FRAMEBUFFER, current_fbo);
+ }
+ GLint current_tex;
+ glGetIntegerv(GL_TEXTURE_BINDING_2D, &current_tex);
+ glBindTexture(GL_TEXTURE_2D, m_TexID);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+ glBindTexture(GL_TEXTURE_2D, current_tex);
+}
+
+namespace_end
+
+namespace_end \ No newline at end of file
diff --git a/Source/modules/asura-core/Graphics/Canvas.h b/Source/modules/asura-core/Graphics/Canvas.h
new file mode 100644
index 0000000..de02b9d
--- /dev/null
+++ b/Source/modules/asura-core/Graphics/Canvas.h
@@ -0,0 +1,73 @@
+#ifndef _ASURA_ENGINE_CANVAS_H_
+#define _ASURA_ENGINE_CANVAS_H_
+
+#include <asura-base/Scripting/Scripting.h>
+#include <asura-base/Math/Rect.hpp>
+#include <asura-base/Math/Vector2.hpp>
+#include <asura-base/Exception.h>
+
+#include "GfxDevice.h"
+#include "Texture.h"
+#include "RenderTarget.h"
+#include "RenderState.h"
+
+namespace_begin(AsuraEngine)
+namespace_begin(Graphics)
+
+
+///
+/// CanvasҲԳΪrender textureҲΪtextureȾ
+///
+class Canvas ASURA_FINAL
+ : public Scripting::Portable<Canvas, RenderTarget>
+{
+public:
+
+ Canvas();
+
+ ~Canvas();
+
+ ///
+ /// render textureĴС
+ ///
+ void SetSize(uint w, uint h) ASURA_THROW(Exception);
+
+ void Clear(const Color& col = Color::Black) override;
+/*
+ void Clear(const Math::Recti& quad, const Color& col = Color::Black) override;
+*/
+ void Render(const RenderTarget* rt, const Math::Vector2i& pos, const Math::Vector2i& scale, const Math::Vector2i& center, float rot);
+
+ void Render(const RenderTarget* rt, const Math::Rectf& quad, const Math::Vector2i& pos, const Math::Vector2i& scale, const Math::Vector2i& center, float rot);
+
+ void Draw(const Drawable* texture, const RenderState& state);
+
+ void Draw(const Drawable* texture, const Math::Recti& quad, const RenderState& state);
+
+private:
+
+ GLuint m_FBO;
+
+ GLuint m_TexID;
+
+ uint m_Width, m_Height;
+
+luaxport:
+
+ LUAX_DECL_FACTORY(Canvas, RenderTarget);
+
+ LUAX_DECL_METHOD(_SetSize);
+ LUAX_DECL_METHOD(_Bind);
+ LUAX_DECL_METHOD(_Unbind);
+
+};
+
+///
+/// CanvasΪRenderTexture
+///
+typedef Canvas RenderTexture;
+
+} // Graphics
+} // AsuraEngine
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-core/Graphics/Color.cpp b/Source/modules/asura-core/Graphics/Color.cpp
new file mode 100644
index 0000000..5a66291
--- /dev/null
+++ b/Source/modules/asura-core/Graphics/Color.cpp
@@ -0,0 +1,58 @@
+#include "Color.h"
+#include "Color32.h"
+
+namespace_begin(AsuraEngine)
+namespace_begin(Graphics)
+
+Color::Color()
+{
+ r = g = b = a = 0;
+}
+
+Color::Color(const Color& c)
+{
+ r = c.r;
+ g = c.g;
+ b = c.b;
+ a = c.a;
+}
+
+Color::Color(float r, float g, float b, float a)
+{
+ this->r = r;
+ this->g = g;
+ this->b = b;
+ this->a = a;
+}
+
+Color::Color(const Color32& c)
+{
+ r = c.r / 255.f;
+ g = c.g / 255.f;
+ b = c.b / 255.f;
+ a = c.a / 255.f;
+}
+
+Color::~Color()
+{
+}
+
+void Color::Set(float r, float g, float b, float a)
+{
+ this->r = r;
+ this->g = g;
+ this->b = b;
+ this->a = a;
+}
+
+//Color Color::operator *(const Color& c)
+//{
+// r *= c.r;
+// g *= c.g;
+// b *= c.b;
+// a *= c.a;
+
+//}
+
+namespace_end
+namespace_end
diff --git a/Source/modules/asura-core/Graphics/Color.h b/Source/modules/asura-core/Graphics/Color.h
new file mode 100644
index 0000000..c81b601
--- /dev/null
+++ b/Source/modules/asura-core/Graphics/Color.h
@@ -0,0 +1,75 @@
+#ifndef _ASURA_ENGINE_COLOR_H_
+#define _ASURA_ENGINE_COLOR_H_
+
+#include <asura-base/Scripting/Scripting.h>
+#include <asura-base/Classes.h>
+
+#include "../CoreConfig.h"
+
+namespace_begin(AsuraEngine)
+namespace_begin(Graphics)
+
+class Color32;
+
+///
+/// 淶ɫColor32иIJԡ
+///
+class Color ASURA_FINAL
+ : public Scripting::Portable<Color>
+{
+public:
+
+ static Color Black;
+ static Color White;
+ static Color Red;
+ static Color Green;
+ static Color Blue;
+
+ Color();
+
+ Color(const Color& c);
+
+ Color(float r, float g, float b, float a);
+
+ Color(const Color32& c);
+
+ ~Color();
+
+ Color operator *(const Color& c);
+
+ void Set(float r, float g, float b, float a);
+
+ GET_SET(float, Red, r);
+ GET_SET(float, Green, g);
+ GET_SET(float, Blue, b);
+ GET_SET(float, Alpha, a);
+
+ float r, g, b, a;
+
+luaxport:
+
+ LUAX_DECL_FACTORY(Color);
+
+ LUAX_DECL_METHOD(_ToColor32);
+ LUAX_DECL_METHOD(_SetColor);
+ LUAX_DECL_METHOD(_GetColor);
+ LUAX_DECL_METHOD(_GetR);
+ LUAX_DECL_METHOD(_GetG);
+ LUAX_DECL_METHOD(_GetB);
+ LUAX_DECL_METHOD(_GetA);
+
+ // Ԫ
+ LUAX_DECL_METHOD(___eq); // __eq
+ LUAX_DECL_METHOD(___add); // __add
+ LUAX_DECL_METHOD(___sub); // __sub
+ LUAX_DECL_METHOD(___mul); // __mul
+ LUAX_DECL_METHOD(___div); // __div
+
+};
+
+namespace_end
+namespace_end
+
+namespace AEGraphics = AsuraEngine::Graphics;
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-core/Graphics/Color32.cpp b/Source/modules/asura-core/Graphics/Color32.cpp
new file mode 100644
index 0000000..f1f0b74
--- /dev/null
+++ b/Source/modules/asura-core/Graphics/Color32.cpp
@@ -0,0 +1,53 @@
+#include "Color.h"
+#include "Color32.h"
+
+namespace_begin(AsuraEngine)
+namespace_begin(Graphics)
+
+#if ASURA_LITTLE_ENDIAN
+// СˣֽڵAlphaڸߵַ
+const uint32 Color32::RMASK = 0x000000ff;
+const uint32 Color32::GMASK = 0x0000ff00;
+const uint32 Color32::BMASK = 0x00ff0000;
+const uint32 Color32::AMASK = 0xff000000;
+#endif
+
+Color32::Color32()
+{
+ r = g = b = a = 0;
+}
+
+Color32::Color32(const Color32& c)
+{
+ r = c.r;
+ g = c.g;
+ b = c.b;
+ a = c.a;
+}
+
+Color32::Color32(const Color& c)
+{
+ r = 255.f * c.r;
+ g = 255.f * c.g;
+ b = 255.f * c.b;
+ a = 255.f * c.a;
+}
+
+Color32::Color32(byte r, byte g, byte b, byte a)
+{
+ this->r = r;
+ this->g = g;
+ this->b = b;
+ this->a = a;
+}
+
+void Color32::Set(const Color32& c32)
+{
+ r = c32.r;
+ g = c32.g;
+ b = c32.b;
+ a = c32.a;
+}
+
+namespace_end
+namespace_end \ No newline at end of file
diff --git a/Source/modules/asura-core/Graphics/Color32.h b/Source/modules/asura-core/Graphics/Color32.h
new file mode 100644
index 0000000..4dbfe2d
--- /dev/null
+++ b/Source/modules/asura-core/Graphics/Color32.h
@@ -0,0 +1,58 @@
+#ifndef _ASURA_ENGINE_COLOR32_H__
+#define _ASURA_ENGINE_COLOR32_H__
+
+#include <asura-base/Classes.h>
+#include <asura-base/Scripting/Scripting.h>
+
+#include "../CoreConfig.h"
+
+namespace_begin(AsuraEngine)
+namespace_begin(Graphics)
+
+class Color;
+
+///
+/// 32bitsɫ
+///
+class Color32 ASURA_FINAL
+ : public Scripting::Portable<Color32>
+{
+public:
+
+ static const uint32 RMASK;
+ static const uint32 GMASK;
+ static const uint32 BMASK;
+ static const uint32 AMASK;
+
+ Color32();
+
+ ~Color32();
+
+ Color32(const Color32& c);
+
+ Color32(const Color& c);
+
+ Color32(byte r, byte g, byte b, byte a);
+
+ void Set(const Color32& c32);
+
+ byte r, g, b, a;
+
+luaxport:
+
+ LUAX_DECL_FACTORY(Color32);
+
+ LUAX_DECL_METHOD(_ToColor);
+ LUAX_DECL_METHOD(_SetColor);
+ LUAX_DECL_METHOD(_GetColor);
+ LUAX_DECL_METHOD(_GetRed);
+ LUAX_DECL_METHOD(_GetGreen);
+ LUAX_DECL_METHOD(_GetBlue);
+ LUAX_DECL_METHOD(_GetAlpha);
+
+};
+
+namespace_end
+namespace_end
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-core/Graphics/ColorPalette.h b/Source/modules/asura-core/Graphics/ColorPalette.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-core/Graphics/ColorPalette.h
diff --git a/Source/modules/asura-core/Graphics/DrawInfo.cpp b/Source/modules/asura-core/Graphics/DrawInfo.cpp
new file mode 100644
index 0000000..c7a6912
--- /dev/null
+++ b/Source/modules/asura-core/Graphics/DrawInfo.cpp
@@ -0,0 +1,10 @@
+#include "DrawInfo.h"
+
+namespace_begin(AsuraEngine)
+namespace_begin(Graphics)
+
+
+
+
+namespace_end
+namespace_end
diff --git a/Source/modules/asura-core/Graphics/DrawInfo.h b/Source/modules/asura-core/Graphics/DrawInfo.h
new file mode 100644
index 0000000..0082102
--- /dev/null
+++ b/Source/modules/asura-core/Graphics/DrawInfo.h
@@ -0,0 +1,19 @@
+#ifndef _ASURA_ENGINE_DRAWINFO_H_
+#define _ASURA_ENGINE_DRAWINFO_H_
+
+#include <asura-base/Classes.h>
+
+namespace_begin(AsuraEngine)
+namespace_begin(Graphics)
+
+///
+struct DrawInfo
+{
+
+};
+
+
+namespace_end
+namespace_end
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-core/Graphics/DrawUtil.cpp b/Source/modules/asura-core/Graphics/DrawUtil.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-core/Graphics/DrawUtil.cpp
diff --git a/Source/modules/asura-core/Graphics/DrawUtil.h b/Source/modules/asura-core/Graphics/DrawUtil.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-core/Graphics/DrawUtil.h
diff --git a/Source/modules/asura-core/Graphics/GPUBuffer.cpp b/Source/modules/asura-core/Graphics/GPUBuffer.cpp
new file mode 100644
index 0000000..f28b914
--- /dev/null
+++ b/Source/modules/asura-core/Graphics/GPUBuffer.cpp
@@ -0,0 +1,151 @@
+#include "GPUBuffer.h"
+
+namespace_begin(AsuraEngine)
+namespace_begin(Graphics)
+
+GPUBuffer::GPUBuffer(BufferType type, BufferUsage usage, BufferDataType dataType, size_t size)
+ : m_Target(GL_ZERO)
+ , m_Buffer(GL_ZERO)
+ , m_Size(0)
+#if ASURA_DEBUG
+ , m_Data(nullptr)
+#endif
+{
+ m_Target = ConvertBufferType(type);
+ m_Usage = ConvertBufferUsage(usage);
+ m_DataType = ConvertBufferDataType(dataType);
+ m_Size = size;
+}
+
+GPUBuffer::~GPUBuffer()
+{
+#if ASURA_DEBUG
+ if (m_Data)
+ free(m_Data);
+#endif
+ glDeleteBuffers(1, &m_Buffer);
+}
+
+GLenum GPUBuffer::ConvertBufferType(BufferType type)
+{
+ switch (type)
+ {
+ case BUFFER_TYPE_VERTEX:
+ return GL_ARRAY_BUFFER;
+ case BUFFER_TYPE_INDEX:
+ return GL_ELEMENT_ARRAY_BUFFER;
+ }
+}
+
+GLenum GPUBuffer::ConvertBufferUsage(BufferUsage usage)
+{
+ switch (usage)
+ {
+ case BUFFER_USAGE_STREAM:
+ return GL_STREAM_DRAW;
+ case BUFFER_USAGE_DYNAMIC:
+ return GL_DYNAMIC_DRAW;
+ case BUFFER_USAGE_STATIC:
+ return GL_STATIC_DRAW;
+ }
+}
+
+GLenum GPUBuffer::ConvertBufferDataType(BufferDataType type)
+{
+ switch (type)
+ {
+ case BUFFER_DATA_TYPE_INT:
+ return GL_INT;
+ case BUFFER_DATA_TYPE_FLOAT:
+ return GL_FLOAT;
+ case BUFFER_DATA_TYPE_UNSIGNED_BYTE:
+ return GL_UNSIGNED_BYTE;
+ }
+}
+
+bool GPUBuffer::Fill(const void * data, size_t size, uint offset)
+{
+ if (data == nullptr)
+ return false;
+ if (m_Buffer == 0)
+ {
+ g_Device.WipeError();
+ glGenBuffers(1, &m_Buffer);
+ if (m_Buffer == 0)
+ throw Exception("OpenGL glGenBuffers failed.");
+ glBindBuffer(m_Target, m_Buffer);
+ glBufferData(m_Target, m_Size, NULL, m_Usage);
+ if (g_Device.HasError())
+ {
+ glBindBuffer(m_Target, 0);
+ throw Exception("OpenGL glBufferData failed. Errorcode=%d.", g_Device.GetError());
+ }
+#if ASURA_DEBUG
+ m_Data = (byte*)malloc(size);
+ memset(m_Data, 0, size);
+#endif
+ }
+ else
+ glBindBuffer(m_Target, m_Buffer);
+ glBufferSubData(m_Target, offset, size, data);
+ if (g_Device.HasError())
+ {
+ glBindBuffer(m_Target, 0);
+ throw Exception("OpenGL glBufferSubData failed. Errorcode=%d.", g_Device.GetError());
+ }
+ glBindBuffer(m_Target, 0);
+#if ASURA_DEBUG
+ memcpy(m_Data + offset, data, size);
+#endif
+ return true;
+}
+
+void GPUBuffer::Bind()
+{
+ glBindBuffer(m_Target, m_Buffer);
+}
+
+void GPUBuffer::UnBind()
+{
+ glBindBuffer(m_Target, 0);
+}
+
+uint GPUBuffer::GetBufferSize()
+{
+ return m_Size;
+}
+
+GLenum GPUBuffer::GetDataType()
+{
+ return m_DataType;
+}
+
+size_t GPUBuffer::GetDataTypeSize()
+{
+ //https://blog.csdn.net/nklinux/article/details/16919017
+ switch (m_DataType)
+ {
+ case GL_UNSIGNED_BYTE:
+ return sizeof(GLbyte);
+ case GL_FLOAT :
+ return sizeof(GLfloat);
+ case GL_INT:
+ return sizeof(GLint);
+ }
+}
+
+size_t GPUBuffer::GetDataTypeSize(GLenum datatype)
+{
+ switch (datatype)
+ {
+ case GL_UNSIGNED_BYTE:
+ return sizeof(GLbyte);
+ case GL_FLOAT:
+ return sizeof(GLfloat);
+ case GL_INT:
+ return sizeof(GLint);
+ }
+}
+
+namespace_end
+namespace_end \ No newline at end of file
diff --git a/Source/modules/asura-core/Graphics/GPUBuffer.h b/Source/modules/asura-core/Graphics/GPUBuffer.h
new file mode 100644
index 0000000..565db17
--- /dev/null
+++ b/Source/modules/asura-core/Graphics/GPUBuffer.h
@@ -0,0 +1,93 @@
+#ifndef _ASURA_GPU_BUFFER_H_
+#define _ASURA_GPU_BUFFER_H_
+
+#include <asura-base/Scripting/Scripting.h>
+#include <asura-base/Exception.h>
+#include <asura-base/type.h>
+
+#include "GfxDevice.h"
+
+namespace_begin(AsuraEngine)
+namespace_begin(Graphics)
+
+enum BufferType
+{
+ BUFFER_TYPE_VERTEX, ///< 㻺壬position\tangent\normal\color\texcoord(n)
+ BUFFER_TYPE_INDEX, ///<
+};
+
+enum BufferUsage
+{
+ BUFFER_USAGE_STREAM, ///< ޸һΣʹô
+ BUFFER_USAGE_DYNAMIC, ///< ޸һΣʹ
+ BUFFER_USAGE_STATIC, ///< ޸ĺʹ
+};
+
+enum BufferDataType
+{
+ BUFFER_DATA_TYPE_INT,
+ BUFFER_DATA_TYPE_FLOAT,
+ BUFFER_DATA_TYPE_UNSIGNED_BYTE,
+};
+
+///
+/// VRAM壬ֶ㻺vboebo֣ÿζڴԴϴݡframeworkrenderersй
+///
+ASURA_ABSTRACT class GPUBuffer
+{
+public:
+
+ GPUBuffer(BufferType type, BufferUsage usage, BufferDataType datatype, size_t size);
+ virtual ~GPUBuffer();
+
+ static size_t GetDataTypeSize(GLenum datatype);
+
+ bool Fill(const void* data, size_t size, uint offset = 0) ASURA_THROW(Exception);
+
+ void Bind();
+ void UnBind();
+
+ uint GetBufferSize();
+ uint GetBufferCount();
+ GLenum GetDataType();
+ size_t GetDataTypeSize();
+
+private:
+
+ GLenum ConvertBufferType(BufferType type);
+ GLenum ConvertBufferUsage(BufferUsage type);
+ GLenum ConvertBufferDataType(BufferDataType type);
+
+ GLenum m_Target;
+ GLuint m_Buffer;
+
+ /// openglԴ滺岢ûж͵ҪֻglVertexAttribPointerʱָdrawcall ʱݸ
+ /// ʼַʹbufferȡඥݣԲͬͿԱһbufferСΪ˱ֽӿڵļ࣬
+ /// ʼbufferʱָͣڱ͵һ£Բͬͷͬbuffer
+
+ GLenum m_DataType;
+ GLuint m_Usage;
+ uint m_Size;
+
+#if ASURA_DEBUG
+ byte* m_Data;
+#endif
+
+luaxport:
+
+ LUAX_DECL_ABSTRACT_FACTORY(GPUBuffer);
+
+ LUAX_DECL_ENUM(BufferType, 1);
+ LUAX_DECL_ENUM(BufferUsage, 1);
+ LUAX_DECL_ENUM(BufferDataType, 2);
+
+ LUAX_DECL_METHOD(_Fill);
+ LUAX_DECL_METHOD(_GetSize);
+ LUAX_DECL_METHOD(_GetCount);
+
+};
+
+namespace_end
+namespace_end
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-core/Graphics/GfxDevice.cpp b/Source/modules/asura-core/Graphics/GfxDevice.cpp
new file mode 100644
index 0000000..529a76c
--- /dev/null
+++ b/Source/modules/asura-core/Graphics/GfxDevice.cpp
@@ -0,0 +1,188 @@
+#include <asura-base/type.h>
+
+#include "../CoreConfig.h"
+
+#include "GfxDevice.h"
+#include "Shader.h"
+#include "MatrixStack.h"
+#include "Color.h"
+
+using namespace AEMath;
+
+namespace_begin(AsuraEngine)
+namespace_begin(Graphics)
+
+#if ASURA_DEBUG
+static bool instantiated = false;
+#endif
+
+GfxDevice g_Device;
+
+GfxDevice::GfxDevice()
+{
+#if ASURA_DEBUG
+ ASSERT(!instantiated);
+ instantiated = true;
+#endif
+}
+
+GfxDevice::~GfxDevice()
+{
+}
+
+GfxDevice& GfxDevice::Get()
+{
+ return g_Device;
+}
+
+static bool inited = false;
+
+bool GfxDevice::Init(const AEMath::Recti& view)
+{
+ bool loaded = false;
+#if ASURA_OPENGL_LOADER & ASURA_OPENGL_GLAD
+ if (!loaded)
+ loaded = gladLoadGL();
+#endif
+ if (!loaded)
+ return false;
+ SetViewport(view);
+
+ inited = true;
+ return true;
+}
+
+bool GfxDevice::Inited()
+{
+ return inited;
+}
+
+void GfxDevice::WipeError()
+{
+ while (glGetError() != GL_NO_ERROR);
+}
+
+bool GfxDevice::HasError()
+{
+ return glGetError() != GL_NO_ERROR;
+}
+
+GLenum GfxDevice::GetError()
+{
+ return glGetError();
+}
+
+void GfxDevice::SetDrawColor(float r, float g, float b, float a)
+{
+ state.drawColor.Set(r, g, b, a);
+}
+
+Color& GfxDevice::GetDrawColor()
+{
+ return state.drawColor;
+}
+
+void GfxDevice::SetViewport(const Recti v)
+{
+ state.viewport = v;
+ glViewport(v.x, v.y, v.w, v.h);
+}
+
+const Recti& GfxDevice::GetViewport()
+{
+ return state.viewport;
+}
+
+void GfxDevice::SetActiveShader(Shader* shader)
+{
+ if (state.shader == shader)
+ return;
+ if (state.shader)
+ state.shader->OnDisable();
+ state.shader = shader;
+ if (shader)
+ {
+ GLint program = shader->GetGLProgram();
+ glUseProgram(program);
+#if ASURA_GL_PROFILE
+ ++stats.shaderSwitch;
+#endif
+ shader->OnEnable();
+ }
+}
+
+Shader* GfxDevice::GetActiveShader() const
+{
+ return state.shader;
+}
+
+void GfxDevice::DrawArrays(GLenum mode, GLint first, GLsizei count)
+{
+ glDrawArrays(mode, first, count);
+#if ASURA_GL_PROFILE
+ ++stats.drawCall;
+#endif
+ if (state.shader)
+ state.shader->OnUsed();
+}
+
+void GfxDevice::PushMatrix ()
+{
+ state.matrix[state.matrixMode].Push ();
+}
+
+void GfxDevice::PopMatrix ()
+{
+ state.matrix[state.matrixMode].Pop();
+}
+
+void GfxDevice::LoadIdentity()
+{
+ state.matrix[state.matrixMode].LoadIdentity();
+}
+
+void GfxDevice::Rotate (float angle)
+{
+ state.matrix[state.matrixMode].Rotate(angle);
+}
+
+void GfxDevice::Translate (float x, float y)
+{
+ state.matrix[state.matrixMode].Translate(x, y);
+}
+
+void GfxDevice::Scale (float x, float y)
+{
+ state.matrix[state.matrixMode].Scale(x, y);
+}
+
+void GfxDevice::Ortho(float l, float r, float b, float t, float n, float f)
+{
+ state.matrix[state.matrixMode].Ortho(l, r, b, t, n, f);
+}
+
+AEMath::Matrix44& GfxDevice::GetMatrix(MatrixMode mode)
+{
+ return state.matrix[mode].GetTop();
+}
+
+AEMath::Matrix44 GfxDevice::GetMVPMatrix()
+{
+ return state.matrix[MATRIX_MODE_PROJECTION].GetTop()
+ * state.matrix[MATRIX_MODE_VIEW].GetTop()
+ * state.matrix[MATRIX_MODE_MODEL].GetTop();
+}
+
+uint GfxDevice::GetMatrixDepth()
+{
+ return state.matrix[state.matrixMode].GetCapacity();
+}
+
+uint GfxDevice::GetMatrixIndex()
+{
+ return state.matrix[state.matrixMode].GetTopIndex();
+}
+
+
+namespace_end
+namespace_end \ No newline at end of file
diff --git a/Source/modules/asura-core/Graphics/GfxDevice.h b/Source/modules/asura-core/Graphics/GfxDevice.h
new file mode 100644
index 0000000..2b105df
--- /dev/null
+++ b/Source/modules/asura-core/Graphics/GfxDevice.h
@@ -0,0 +1,141 @@
+#ifndef _ASURA_ENGINE_GFX_DEVICE_H_
+#define _ASURA_ENGINE_GFX_DEVICE_H_
+
+#include <stack>
+
+#include <glad/glad.h>
+
+#include <asura-base/Scripting/Scripting.h>
+#include <asura-base/Math/Rect.hpp>
+#include <asura-base/Math/matrix44.h>
+#include <asura-base/Math/vector4.h>
+
+#include "Color.h"
+#include "MatrixStack.h"
+
+namespace_begin(AsuraEngine)
+namespace_begin(Graphics)
+
+class Profiler;
+class Shader;
+class GPUBuffer;
+class Canvas;
+
+enum MatrixMode
+{
+ MATRIX_MODE_PROJECTION = 0,
+ MATRIX_MODE_MODEL = 1,
+ MATRIX_MODE_VIEW = 2,
+};
+
+enum GLParams
+{
+ GL_PARAM_MAX_TEXTURE_UNIT = 1,
+};
+
+class GfxDevice : public AEScripting::Portable<GfxDevice>
+{
+public:
+
+ GfxDevice();
+ ~GfxDevice();
+
+ static GfxDevice& Get();
+
+ int GetParam(GLParams param);
+
+ bool Init(const AEMath::Recti& viewport);
+ bool Inited();
+
+ void SetViewport(const AEMath::Recti viewport);
+
+ const AEMath::Recti& GetViewport();
+
+ void PushMatrix();
+ void PopMatrix();
+
+ void LoadIdentity();
+ void Rotate(float angle);
+ void Translate(float x, float y);
+ void Scale(float x, float y);
+ void Ortho(float l, float r, float b, float t, float n, float f);
+
+ uint GetMatrixDepth();
+ uint GetMatrixIndex();
+
+ void DrawArrays(GLenum mode, GLint first, GLsizei count);
+
+ AEMath::Matrix44& GetMatrix(MatrixMode mode);
+ AEMath::Matrix44 GetMVPMatrix();
+
+ void SetDrawColor(float r, float g, float b, float a);
+ Color& GetDrawColor();
+
+ void SetActiveShader(Shader* = NULL);
+ Shader* GetActiveShader() const;
+
+ void WipeError();
+ bool HasError();
+ GLenum GetError();
+
+ GET_SET(MatrixMode, MatrixMode, state.matrixMode);
+ GET_SET(Canvas*, ActiveCanvas, state.canvas);
+
+private:
+
+ friend class Profiler;
+
+ struct
+ {
+ AEMath::Recti viewport; ///< ǰлHDC߱ڴСı߲ˢʱ䶯
+ MatrixStack matrix[3]; ///< model, view, projection
+ MatrixMode matrixMode; ///< ǰľ
+ Color drawColor; ///< Ƶɫ
+ Canvas* canvas; ///< ǰcanvas
+ Shader* shader; ///< ǰʹõshader
+ } state;
+
+#if ASURA_GL_PROFILE
+ struct
+ {
+ uint drawCall; ///< ͳdrawcall
+ uint canvasSwitch; ///< лtextureĴ
+ uint shaderSwitch; ///< лshaderĴ
+ } stats;
+#endif
+
+luaxport:
+
+ LUAX_DECL_SINGLETON(GfxDevice);
+
+ LUAX_DECL_ENUM(MatrixMode, 1);
+ LUAX_DECL_ENUM(GLParams, 1);
+
+ LUAX_DECL_METHOD(_SetMatrixMode);
+ LUAX_DECL_METHOD(_GetMatrixMode);
+ LUAX_DECL_METHOD(_PushMatrix);
+ LUAX_DECL_METHOD(_PopMatrix);
+ LUAX_DECL_METHOD(_LoadIdentity);
+ LUAX_DECL_METHOD(_Rotate);
+ LUAX_DECL_METHOD(_Translate);
+ LUAX_DECL_METHOD(_Scale);
+ LUAX_DECL_METHOD(_Ortho);
+ LUAX_DECL_METHOD(_GetMatrixDepth);
+ LUAX_DECL_METHOD(_GetMatrixIndex);
+ LUAX_DECL_METHOD(_UseShader);
+ LUAX_DECL_METHOD(_UnuseShader);
+
+};
+
+extern GfxDevice g_Device;
+
+
+#define GL_CALL(x) do { x; /*GLAssert(); */} while(0)
+
+
+
+
+namespace_end
+namespace_end
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-core/Graphics/GraphicsHelper.cpp b/Source/modules/asura-core/Graphics/GraphicsHelper.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-core/Graphics/GraphicsHelper.cpp
diff --git a/Source/modules/asura-core/Graphics/GraphicsHelper.h b/Source/modules/asura-core/Graphics/GraphicsHelper.h
new file mode 100644
index 0000000..3125292
--- /dev/null
+++ b/Source/modules/asura-core/Graphics/GraphicsHelper.h
@@ -0,0 +1,15 @@
+#ifndef _ASURA_GRAPHICS_HELPER_H_
+#define _ASURA_GRAPHICS_HELPER_H_
+
+#include <asura-base/Classes.h>
+
+namespace_begin(AsuraEngine)
+namespace_begin(Graphics)
+
+
+
+
+namespace_end
+namespace_end
+
+#endif
diff --git a/Source/modules/asura-core/Graphics/Image.cpp b/Source/modules/asura-core/Graphics/Image.cpp
new file mode 100644
index 0000000..36d2478
--- /dev/null
+++ b/Source/modules/asura-core/Graphics/Image.cpp
@@ -0,0 +1,103 @@
+#include <asura-base/Exception.h>
+
+#include "../CoreConfig.h"
+
+#include "Shader.h"
+#include "Image.h"
+#include "GfxDevice.h"
+
+using namespace AEFileSystem;
+using namespace AEImage;
+
+namespace_begin(AsuraEngine)
+namespace_begin(Graphics)
+
+Image::Image()
+ : m_Width(0)
+ , m_Height(0)
+{
+}
+
+Image::~Image()
+{
+}
+
+bool Image::Load(ImageData* imgData)
+{
+ if (!imgData) return false;
+
+ if (m_TexID == 0)
+ {
+ glGenTextures(1, &m_TexID);
+ if (m_TexID == 0)
+ throw Exception("OpenGL glGenTextures failed.");
+ }
+
+ glBindTexture(GL_TEXTURE_2D, m_TexID);
+ imgData->Lock();
+ int width = imgData->width;
+ int height = imgData->height;
+ TextureFormat tf = ConvertColorFormat(imgData->format);
+ glTexImage2D(
+ GL_TEXTURE_2D
+ , 0
+ , tf.internalformat
+ , width, height
+ , 0
+ , tf.externalformat
+ , tf.type
+ , imgData->pixels
+ );
+
+ m_Width = imgData->width;
+ m_Height = imgData->height;
+ imgData->Unlock();
+ GLenum err = glGetError();
+ if (err != GL_NO_ERROR)
+ throw Exception("OpenGL glTexImage2D cause error, error code=%d", err);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ return true;
+}
+
+bool Image::Load(ImageData* imgData, const AEMath::Vector2i& pos)
+{
+ if (!imgData) return false;
+
+ glBindTexture(GL_TEXTURE_2D, m_TexID);
+ imgData->Lock();
+ int width = imgData->width;
+ int height = imgData->height;
+ TextureFormat tf = ConvertColorFormat(imgData->format);
+ glTexSubImage2D(
+ GL_TEXTURE_2D
+ , 0
+ , pos.x
+ , pos.y
+ , imgData->width
+ , imgData->height
+ , tf.externalformat
+ , tf.type
+ , imgData->pixels
+ );
+ imgData->Unlock();
+ GLenum err = glGetError();
+ if (err != GL_NO_ERROR)
+ throw Exception("OpenGL glTexSubImage2D cause error, error code=%d", err);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ return true;
+}
+
+uint32 Image::GetWidth()
+{
+ return m_Width;
+}
+
+uint32 Image::GetHeight()
+{
+ return m_Height;
+}
+
+namespace_end
+namespace_end \ No newline at end of file
diff --git a/Source/modules/asura-core/Graphics/Image.h b/Source/modules/asura-core/Graphics/Image.h
new file mode 100644
index 0000000..a76d06f
--- /dev/null
+++ b/Source/modules/asura-core/Graphics/Image.h
@@ -0,0 +1,63 @@
+#ifndef _ASURA_ENGINE_IMAGE_H_
+#define _ASURA_ENGINE_IMAGE_H_
+
+// asura modules
+#include <asura-base/Math/Rect.hpp>
+#include <asura-base/Math/Vector2.hpp>
+#include <asura-base/Scripting/Scripting.h>
+#include <asura-base/FileSystem/Renewable.h>
+#include <asura-base/Utilities/Stringmap.hpp>
+#include <asura-base/Manager.hpp>
+
+// module
+#include "../Image/ImageData.h"
+
+// folder
+#include "Color.h"
+#include "Color32.h"
+#include "RenderState.h"
+#include "GPUBuffer.h"
+#include "Texture.h"
+
+namespace_begin(AsuraEngine)
+namespace_begin(Graphics)
+
+class Image ASURA_FINAL : public AEScripting::Portable<Image, Texture>
+{
+public:
+
+ Image();
+ ~Image();
+
+ bool Load(AEImage::ImageData* decodeData);
+ bool Load(AEImage::ImageData* decodeData, const AEMath::Vector2i& pos);
+
+ uint GetWidth();
+ uint GetHeight();
+
+ GPUBuffer* GenGPUBuffer();
+
+private:
+
+ uint32 m_Width, m_Height;
+
+luaxport:
+
+ LUAX_DECL_FACTORY(Image, Texture);
+
+ LUAX_DECL_METHOD(_New);
+ LUAX_DECL_METHOD(_Load);
+ LUAX_DECL_METHOD(_GetWidth);
+ LUAX_DECL_METHOD(_GetHeight);
+ LUAX_DECL_METHOD(_GetSize);
+ LUAX_DECL_METHOD(_GetPixel);
+ LUAX_DECL_METHOD(_Render);
+
+};
+
+namespace_end
+namespace_end
+
+namespace AEGraphics = AsuraEngine::Graphics;
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-core/Graphics/IndexBuffer.cpp b/Source/modules/asura-core/Graphics/IndexBuffer.cpp
new file mode 100644
index 0000000..bb3eea7
--- /dev/null
+++ b/Source/modules/asura-core/Graphics/IndexBuffer.cpp
@@ -0,0 +1,17 @@
+#include "IndexBuffer.h"
+
+namespace_begin(AsuraEngine)
+namespace_begin(Graphics)
+
+
+IndexBuffer::IndexBuffer(BufferUsage usage, BufferDataType datatype, size_t size)
+ : GPUBuffer(BUFFER_TYPE_INDEX, usage, datatype, size)
+{
+}
+
+IndexBuffer::~IndexBuffer()
+{
+}
+
+namespace_end
+namespace_end
diff --git a/Source/modules/asura-core/Graphics/IndexBuffer.h b/Source/modules/asura-core/Graphics/IndexBuffer.h
new file mode 100644
index 0000000..b7886b7
--- /dev/null
+++ b/Source/modules/asura-core/Graphics/IndexBuffer.h
@@ -0,0 +1,34 @@
+#ifndef _ASURA_INDEX_BUFFER_H_
+#define _ASURA_INDEX_BUFFER_H_
+
+#include <asura-base/Scripting/Scripting.h>
+
+#include "GPUBuffer.h"
+
+namespace_begin(AsuraEngine)
+namespace_begin(Graphics)
+
+///
+///
+///
+class IndexBuffer ASURA_FINAL
+ : public AEScripting::Portable<IndexBuffer>
+ , public GPUBuffer
+{
+public:
+
+ IndexBuffer(BufferUsage usage, BufferDataType datatype, size_t size);
+ ~IndexBuffer();
+
+luaxport:
+
+ LUAX_DECL_FACTORY(IndexBuffer);
+
+ LUAX_DECL_METHOD(_New);
+
+};
+
+namespace_end
+namespace_end
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-core/Graphics/MatrixStack.cpp b/Source/modules/asura-core/Graphics/MatrixStack.cpp
new file mode 100644
index 0000000..987d29c
--- /dev/null
+++ b/Source/modules/asura-core/Graphics/MatrixStack.cpp
@@ -0,0 +1,75 @@
+#include "MatrixStack.h"
+
+namespace_begin(AsuraEngine)
+namespace_begin(Graphics)
+
+MatrixStack::MatrixStack()
+ : top(0)
+{
+ // ջʼջô˱֤ջԶǿգȡֵ
+ m_Stack[top].SetIdentity();
+}
+
+MatrixStack::~MatrixStack()
+{
+}
+
+void MatrixStack::LoadIdentity()
+{
+ m_Stack[top].SetIdentity();
+}
+
+bool MatrixStack::Push()
+{
+ if (top == ASURA_MAX_MATRIX_STACK_DEPTH - 1)
+ return false;
+ ++top;
+ m_Stack[top] = m_Stack[top - 1];
+ return true;
+}
+
+bool MatrixStack::Pop()
+{
+ if (top == 0)
+ return false;
+ --top;
+ return true;
+}
+
+AEMath::Matrix44& MatrixStack::GetTop()
+{
+ return m_Stack[top];
+}
+
+uint MatrixStack::GetTopIndex()
+{
+ return top;
+}
+
+uint MatrixStack::GetCapacity()
+{
+ return ASURA_MAX_MATRIX_STACK_DEPTH;
+}
+
+void MatrixStack::Ortho(float left, float right, float bottom, float top, float near, float far)
+{
+ m_Stack[this->top].Ortho(left, right, bottom, top, near, far);
+}
+
+void MatrixStack::Rotate(float angle)
+{
+ m_Stack[top].Rotate(angle);
+}
+
+void MatrixStack::Translate(float x, float y)
+{
+ m_Stack[top].Translate(x, y);
+}
+
+void MatrixStack::Scale(float x, float y)
+{
+ m_Stack[top].Scale(x, y);
+}
+
+namespace_end
+namespace_end \ No newline at end of file
diff --git a/Source/modules/asura-core/Graphics/MatrixStack.h b/Source/modules/asura-core/Graphics/MatrixStack.h
new file mode 100644
index 0000000..8dd56bf
--- /dev/null
+++ b/Source/modules/asura-core/Graphics/MatrixStack.h
@@ -0,0 +1,58 @@
+#ifndef _ASURA_MATRIX_STACK_H_
+#define _ASURA_MATRIX_STACK_H_
+
+#include <asura-base/Type.h>
+#include <asura-base/Math/Matrix44.h>
+#include <asura-base/Classes.h>
+
+namespace_begin(AsuraEngine)
+namespace_begin(Graphics)
+
+///
+/// ջľȡ
+///
+#define ASURA_MAX_MATRIX_STACK_DEPTH 32 // 2KB
+
+///
+/// ջ״ָ̬֮ǰ״̬ջеһstack[i]ֵstack[0]*..*stack[i-1]
+/// ֵһϵtransform
+///
+/// TODO: template<uint _capacity> MatrixStack
+///
+class MatrixStack
+{
+public:
+
+ MatrixStack();
+ ~MatrixStack();
+
+ void LoadIdentity();
+ bool Push();
+ bool Pop();
+
+ AEMath::Matrix44& GetTop();
+ void GetTop(ASURA_OUT AEMath::Matrix44& mat44);
+
+ void LoadMatrix(const AEMath::Matrix44& mat44);
+ void MultMatrix(const AEMath::Matrix44& mat44);
+
+ void Rotate(float angle);
+ void Translate(float x, float y);
+ void Scale(float x, float y);
+
+ void Ortho(float l, float r, float b, float t, float n, float f);
+
+ uint GetTopIndex();
+ uint GetCapacity();
+
+private:
+
+ AEMath::Matrix44 m_Stack[ASURA_MAX_MATRIX_STACK_DEPTH];
+ uint8 top;
+
+};
+
+namespace_end
+namespace_end
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-core/Graphics/Mesh2D.cpp b/Source/modules/asura-core/Graphics/Mesh2D.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-core/Graphics/Mesh2D.cpp
diff --git a/Source/modules/asura-core/Graphics/Mesh2D.h b/Source/modules/asura-core/Graphics/Mesh2D.h
new file mode 100644
index 0000000..7a0f62e
--- /dev/null
+++ b/Source/modules/asura-core/Graphics/Mesh2D.h
@@ -0,0 +1,52 @@
+#ifndef _ASURA_ENGINE_MESH2D_H__
+#define _ASURA_ENGINE_MESH2D_H__
+
+// cpp
+#include <vector>
+
+// asura modules
+#include <asura-base/Scripting/Scripting.h>
+#include <asura-base/Math/Vector2.hpp>
+
+// module
+#include "../Mesh/Mesh2dData.h"
+
+// folder
+#include "Color.h"
+#include "VertexBuffer.h"
+#include "IndexBuffer.h"
+
+namespace_begin(AsuraEngine)
+namespace_begin(Graphics)
+
+///
+/// 2D meshһЩ㶯
+/// https://en.wikipedia.org/wiki/Polygon_mesh
+///
+class Mesh2D ASURA_FINAL
+ : public Scripting::Portable<Mesh2D>
+{
+public:
+
+ Mesh2D();
+ ~Mesh2D();
+
+ bool Load(AEMesh::Mesh2DData* data);
+
+private:
+
+ VertexBuffer* m_VBO; ///< vertex buffer
+ IndexBuffer* m_IBO; ///< index buffer
+
+luaxport:
+
+ LUAX_DECL_FACTORY(Mesh2D);
+
+ LUAX_DECL_METHOD(_SetVertex);
+
+};
+
+namespace_end
+namespace_end
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-core/Graphics/Polygon2D.cpp b/Source/modules/asura-core/Graphics/Polygon2D.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-core/Graphics/Polygon2D.cpp
diff --git a/Source/modules/asura-core/Graphics/Polygon2D.h b/Source/modules/asura-core/Graphics/Polygon2D.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-core/Graphics/Polygon2D.h
diff --git a/Source/modules/asura-core/Graphics/Quad.cpp b/Source/modules/asura-core/Graphics/Quad.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-core/Graphics/Quad.cpp
diff --git a/Source/modules/asura-core/Graphics/Quad.h b/Source/modules/asura-core/Graphics/Quad.h
new file mode 100644
index 0000000..b7dd3d9
--- /dev/null
+++ b/Source/modules/asura-core/Graphics/Quad.h
@@ -0,0 +1 @@
+// Quadrectڣrectǵıƫᣬquadһ
diff --git a/Source/modules/asura-core/Graphics/RenderState.h b/Source/modules/asura-core/Graphics/RenderState.h
new file mode 100644
index 0000000..23804d8
--- /dev/null
+++ b/Source/modules/asura-core/Graphics/RenderState.h
@@ -0,0 +1,47 @@
+#ifndef _ASURA_ENGINE_RENDER_STATE_H_
+#define _ASURA_ENGINE_RENDER_STATE_H_
+
+#include <asura-base/Math/Vector2.hpp>
+#include <asura-base/Math/Transform.h>
+
+#include "BlendMode.h"
+
+namespace_begin(AsuraEngine)
+namespace_begin(Graphics)
+
+class Shader;
+
+///
+/// Ⱦǰķʽ
+///
+struct RenderState ASURA_FINAL
+{
+ ///
+ /// Ĭϵrender state
+ ///
+ static RenderState Default;
+
+ RenderState();
+ ~RenderState();
+
+ ///
+ /// λášλúת
+ ///
+ Math::Transform transform;
+
+ ///
+ /// ɫ
+ ///
+ Shader* shader;
+
+ ///
+ /// Ϸʽ
+ ///
+ BlendMode blendMode;
+
+};
+
+namespace_end
+namespace_end
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-core/Graphics/RenderTarget.cpp b/Source/modules/asura-core/Graphics/RenderTarget.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-core/Graphics/RenderTarget.cpp
diff --git a/Source/modules/asura-core/Graphics/RenderTarget.h b/Source/modules/asura-core/Graphics/RenderTarget.h
new file mode 100644
index 0000000..ab09e35
--- /dev/null
+++ b/Source/modules/asura-core/Graphics/RenderTarget.h
@@ -0,0 +1,52 @@
+#ifndef _ASURA_ENGINE_RENDERTARGET_H_
+#define _ASURA_ENGINE_RENDERTARGET_H_
+
+#include <asura-base/Math/Vector2.hpp>
+#include <asura-base/Math/Rect.hpp>
+#include <asura-base/Scripting/Scripting.h>
+
+#include "Texture.h"
+#include "Color.h"
+
+namespace_begin(AsuraEngine)
+namespace_begin(Graphics)
+
+///
+/// ɱΪȾĿ࣬
+/// Canvas(RenderTexture)
+/// Window(RenderWindow)
+///
+class RenderTarget : public AEScripting::Object
+{
+public:
+
+ RenderTarget() {};
+
+ virtual ~RenderTarget() {};
+
+ ///
+ /// ɫcolRT
+ ///
+ virtual void Clear(const Color& col = Color::Black) = 0;
+
+ ///
+ /// ɫcolղRT
+ ///
+ virtual void Clear(const Math::Recti& quad, const Color& col = Color::Black) = 0;
+
+ ///
+ /// textureRT
+ ///
+ virtual void Draw(const Drawable* texture, const RenderState& state) = 0;
+
+ ///
+ /// һtextureRT
+ ///
+ virtual void Draw(const Drawable* texture, const Math::Recti& quad, const RenderState& state) = 0;
+
+};
+
+namespace_end
+namespace_end
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-core/Graphics/Shader.cpp b/Source/modules/asura-core/Graphics/Shader.cpp
new file mode 100644
index 0000000..329b3f1
--- /dev/null
+++ b/Source/modules/asura-core/Graphics/Shader.cpp
@@ -0,0 +1,282 @@
+#include <asura-base/Exception.h>
+
+#include "GfxDevice.h"
+#include "Shader.h"
+
+using namespace std;
+
+namespace_begin(AsuraEngine)
+namespace_begin(Graphics)
+
+// texture unit
+static uint8 texUnit = 0;
+
+Shader::Shader()
+{
+}
+
+Shader::~Shader()
+{
+ if(m_VertShader) glDeleteShader(m_VertShader);
+ if(m_FragShader) glDeleteShader(m_FragShader);
+ if(m_Program) glDeleteProgram(m_Program);
+}
+
+void Shader::SetActive(Shader* shader)
+{
+ g_Device.SetActiveShader(shader);
+}
+
+Shader* Shader::GetActive()
+{
+ return g_Device.GetActiveShader();
+}
+
+bool Shader::Load(const string& vert, const string& frag)
+{
+ string warnning = "";
+
+ if (!m_Program)
+ {
+ m_Program = glCreateProgram();
+ if (!m_Program)
+ throw Exception("Cannot create OpenGL shader program.");
+ }
+
+ if (!CompileVertexShader(vert, warnning))
+ {
+ throw Exception("Compile vertex shader failed:%s", warnning);
+ }
+
+ if (!CompileFragementShader(frag, warnning))
+ {
+ throw Exception("Compile fragment shader failed:%s", warnning);
+ }
+
+ glAttachShader(m_Program, m_VertShader);
+ glAttachShader(m_Program, m_FragShader);
+
+ glLinkProgram(m_Program);
+ GLint success;
+ glGetProgramiv(m_Program, GL_LINK_STATUS, &success);
+ if (success == GL_FALSE)
+ {
+ warnning = GetProgramWarnings();
+ throw Exception("Link shader program failed:\n%s", warnning.c_str());
+ }
+
+ return true;
+}
+
+bool Shader::CompileVertexShader(const string& vert, string& outError)
+{
+ if (!m_VertShader)
+ {
+ m_VertShader = glCreateShader(GL_VERTEX_SHADER);
+ if (!m_VertShader)
+ {
+ outError = "Cannot create OpenGL Vertex shader.";
+ return false;
+ }
+ }
+
+ const GLchar* source = vert.c_str();
+ GLint success;
+
+ glShaderSource(m_VertShader, 1, &source, NULL);
+ glCompileShader(m_VertShader);
+ glGetShaderiv(m_VertShader, GL_COMPILE_STATUS, &success);
+ if (success == GL_FALSE)
+ {
+ outError = GetShaderWarnings(m_VertShader);
+ return false;
+ }
+
+ return true;
+}
+
+bool Shader::CompileFragementShader(const string& frag, string& outError)
+{
+ if (!m_FragShader)
+ {
+ m_FragShader = glCreateShader(GL_FRAGMENT_SHADER);
+ if (!m_FragShader)
+ {
+ outError = "Cannot create OpenGL fragment shader.";
+ return false;
+ }
+ }
+
+ const GLchar* source = frag.c_str();
+ GLint success;
+
+ source = frag.c_str();
+ glShaderSource(m_FragShader, 1, &source, NULL);
+ glCompileShader(m_FragShader);
+ glGetShaderiv(m_FragShader, GL_COMPILE_STATUS, &success);
+ if (success == GL_FALSE)
+ {
+ outError = GetShaderWarnings(m_FragShader);
+ return false;
+ }
+
+ return true;
+}
+
+void Shader::OnEnable()
+{
+ texUnit = 0;
+}
+
+void Shader::OnDisable()
+{
+ texUnit = 0;
+}
+
+void Shader::OnUsed()
+{
+ texUnit = 0;
+}
+
+uint Shader::GetUniformLocation(const std::string& uniform)
+{
+ GLint loc = glGetUniformLocation(m_Program, uniform.c_str());
+ return loc;
+}
+
+bool Shader::HasUniform(const std::string& uniform)
+{
+ GLint loc = glGetUniformLocation(m_Program, uniform.c_str());
+ return loc != -1;
+}
+
+GLuint Shader::GetGLProgram()
+{
+ return m_Program;
+}
+
+void Shader::SetUniformFloat(uint loc, float value)
+{
+ if(g_Device.GetActiveShader() == this)
+ glUniform1f(loc, value);
+}
+
+bool Shader::SetUniformTexture(uint loc, const Texture& texture)
+{
+ if (g_Device.GetActiveShader() != this)
+ return false;
+
+ g_Device.WipeError();
+ glActiveTexture(GL_TEXTURE0 + texUnit);
+ if (g_Device.HasError())
+ return false;
+ GLint tex = texture.GetGLTexture();
+ glBindTexture(GL_TEXTURE_2D, tex);
+ if (g_Device.HasError())
+ return false;
+ glUniform1i(loc, texUnit);
+ if (g_Device.HasError())
+ return false;
+ ++texUnit;
+}
+
+void Shader::SetUniformVector2(uint loc, const Math::Vector2f& vec2)
+{
+ if (g_Device.GetActiveShader() == this)
+ glUniform2f(loc, vec2.x, vec2.y);
+}
+
+void Shader::SetUniformVector3(uint loc, const Math::Vector3f& vec3)
+{
+ if (g_Device.GetActiveShader() == this)
+ glUniform3f(loc, vec3.x, vec3.y, vec3.z);
+}
+
+void Shader::SetUniformVector4(uint loc, const Math::Vector4f& vec4)
+{
+ if (g_Device.GetActiveShader() == this)
+ glUniform4f(loc, vec4.x, vec4.y, vec4.z, vec4.w);
+}
+
+void Shader::SetUniformMatrix44(uint loc, const Math::Matrix44& mat)
+{
+ if (g_Device.GetActiveShader() == this)
+ glUniformMatrix4fv(loc, 1, GL_FALSE, mat.GetElements());
+}
+
+void Shader::SetUniformColor(uint loc, const Color& color)
+{
+ if (g_Device.GetActiveShader() == this)
+ glUniform4f(loc, color.r, color.g, color.b, color.a);
+}
+
+uint Shader::GetGLTextureUnitCount()
+{
+ GLint maxTextureUnits;
+ glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
+ return (uint)maxTextureUnits;
+}
+
+std::string Shader::GetProgramWarnings()
+{
+ GLint strsize, nullpos;
+ glGetProgramiv(m_Program, GL_INFO_LOG_LENGTH, &strsize);
+
+ if (strsize == 0)
+ return "";
+
+ char *tempstr = new char[strsize];
+
+ memset(tempstr, '\0', strsize);
+ glGetProgramInfoLog(m_Program, strsize, &nullpos, tempstr);
+ tempstr[nullpos] = '\0';
+
+ std::string warnings(tempstr);
+ delete[] tempstr;
+
+ return warnings;
+}
+
+std::string Shader::GetShaderWarnings(GLuint shader)
+{
+ GLint strsize, nullpos;
+ glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &strsize);
+
+ if (strsize == 0)
+ return "";
+
+ char *tempstr = new char[strsize];
+
+ memset(tempstr, '\0', strsize);
+ glGetShaderInfoLog(shader, strsize, &nullpos, tempstr);
+ tempstr[nullpos] = '\0';
+
+ std::string warnings(tempstr);
+ delete[] tempstr;
+
+ return warnings;
+}
+
+void Shader::SetAttribute(int loc, VertexBuffer* vbo, uint offseti, uint stridei, bool normalized)
+{
+ GLsizei offset = offseti * vbo->GetDataTypeSize();
+ GLsizei stride = stridei * vbo->GetDataTypeSize();
+ glEnableVertexAttribArray(loc);
+ vbo->Bind();
+ glVertexAttribPointer(loc, 2, vbo->GetDataType(), normalized, stride, (GLvoid*)offset);
+ vbo->UnBind();
+}
+
+int Shader::GetAttributeLocation(const std::string& attribute)
+{
+ int loc = glGetAttribLocation(m_Program, attribute.c_str());
+ return loc;
+}
+
+void Shader::DisableAttribute(int loc)
+{
+ glDisableVertexAttribArray(loc);
+}
+
+namespace_end
+namespace_end \ No newline at end of file
diff --git a/Source/modules/asura-core/Graphics/Shader.h b/Source/modules/asura-core/Graphics/Shader.h
new file mode 100644
index 0000000..615b028
--- /dev/null
+++ b/Source/modules/asura-core/Graphics/Shader.h
@@ -0,0 +1,117 @@
+#ifndef _ASURA_ENGINE_SHADER_H_
+#define _ASURA_ENGINE_SHADER_H_
+
+#include <map>
+#include <string>
+
+#include <asura-base/Exception.h>
+#include <asura-base/Scripting/Scripting.h>
+#include <asura-base/FileSystem/Renewable.h>
+#include <asura-base/Math/Vector2.hpp>
+#include <asura-base/Math/vector3.hpp>
+#include <asura-base/Math/vector4.h>
+#include <asura-base/Math/matrix44.h>
+#include <asura-base/Utilities/Stringmap.hpp>
+#include <asura-base/Manager.hpp>
+
+#include "GfxDevice.h"
+#include "Color.h"
+#include "Texture.h"
+#include "VertexBuffer.h"
+#include "IndexBuffer.h"
+
+namespace_begin(AsuraEngine)
+namespace_begin(Graphics)
+
+///
+/// һshaderһڲʼ乲ijShaderuniformsͶݣֻṩ uniformsuseɫ
+/// ķ༭ÿshaderͨshaderҵuniforms¶frameworkmaterial
+/// á
+///
+class Shader ASURA_FINAL
+ : public Scripting::Portable<Shader>
+ , public AEFileSystem::Renewable
+{
+public:
+
+ Shader();
+
+ ~Shader();
+
+ static void SetActive(Shader* shader);
+ static Shader* GetActive();
+
+ bool Load(const std::string& vert, const std::string& frag) ASURA_THROW(Exception);
+
+ // ʹSetActiveлshaderʱ
+ void OnEnable();
+ void OnDisable();
+ // Draw call֮
+ void OnUsed();
+
+ void SetAttribute(int loc, VertexBuffer* vbo, uint offseti = 0, uint stridei = 0, bool normalized = false);
+ int GetAttributeLocation(const std::string& attribute);
+ void DisableAttribute(int loc);
+
+ bool HasUniform(const std::string& uniform);
+ uint GetUniformLocation(const std::string& uniform);
+ void SetUniformFloat(uint loc, float value);
+ void SetUniformVector2(uint loc, const Math::Vector2f& vec2);
+ void SetUniformVector3(uint loc, const Math::Vector3f& vec3);
+ void SetUniformVector4(uint loc, const Math::Vector4f& vec4);
+ void SetUniformColor(uint loc, const Color& color);
+ void SetUniformMatrix44(uint loc, const Math::Matrix44& mat44);
+ bool SetUniformTexture(uint loc, const Texture& texture);
+
+ float GetUniformFloat(uint loc);
+ AEMath::Vector2f GetUniformVector2(uint loc);
+ AEMath::Vector3f GetUniformVector3(uint loc);
+ AEMath::Vector4f GetUniformVector4s(uint loc);
+ AEMath::Matrix44 GetUniformMatrix44(uint loc);
+
+ GLuint GetGLProgram();
+
+ static uint GetGLTextureUnitCount();
+
+private:
+
+ bool CompileVertexShader(const std::string& vert, std::string& outError);
+ bool CompileFragementShader(const std::string& frag, std::string& outError);
+
+ std::string GetProgramWarnings();
+ std::string GetShaderWarnings(GLuint shader);
+
+ GLuint m_Program;
+ GLuint m_VertShader;
+ GLuint m_FragShader;
+
+luaxport:
+
+ LUAX_DECL_FACTORY(Shader);
+
+ LUAX_DECL_METHOD(_New);
+ LUAX_DECL_METHOD(_Load);
+ LUAX_DECL_METHOD(_Update);
+ LUAX_DECL_METHOD(_HasUniform);
+ LUAX_DECL_METHOD(_GetUniformLocation);
+ LUAX_DECL_METHOD(_SetUniformFloat);
+ LUAX_DECL_METHOD(_SetUniformTexture);
+ LUAX_DECL_METHOD(_SetUniformVector2);
+ LUAX_DECL_METHOD(_SetUniformVector3);
+ LUAX_DECL_METHOD(_SetUniformVector4);
+ LUAX_DECL_METHOD(_SetUniformColor);
+
+ LUAX_DECL_METHOD(_GetAttributeLocation);
+ LUAX_DECL_METHOD(_SetAttribute);
+ LUAX_DECL_METHOD(_DisableAttribute);
+
+ LUAX_DECL_METHOD(_SetBuiltInUniforms);
+
+};
+
+typedef Shader GpuProgram;
+
+namespace_end
+namespace_end
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-core/Graphics/Shape.cpp b/Source/modules/asura-core/Graphics/Shape.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-core/Graphics/Shape.cpp
diff --git a/Source/modules/asura-core/Graphics/Shape.h b/Source/modules/asura-core/Graphics/Shape.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-core/Graphics/Shape.h
diff --git a/Source/modules/asura-core/Graphics/SpriteBatch.cpp b/Source/modules/asura-core/Graphics/SpriteBatch.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-core/Graphics/SpriteBatch.cpp
diff --git a/Source/modules/asura-core/Graphics/SpriteBatch.h b/Source/modules/asura-core/Graphics/SpriteBatch.h
new file mode 100644
index 0000000..30cb56c
--- /dev/null
+++ b/Source/modules/asura-core/Graphics/SpriteBatch.h
@@ -0,0 +1,34 @@
+#ifndef _ASURA_ENGINE_SPRITE_BATCH_H_
+#define _ASURA_ENGINE_SPRITE_BATCH_H_
+
+#include <asura-base/Scripting/Scripting.h>
+
+#include "GPUBuffer.h"
+
+namespace_begin(AsuraEngine)
+namespace_begin(Graphics)
+
+///
+/// Sprite batchȾͼƬĵطϵͳ
+///
+class SpriteBatch ASURA_FINAL
+ : public Scripting::Portable<SpriteBatch>
+{
+public:
+
+ SpriteBatch();
+
+ ~SpriteBatch();
+
+private:
+
+luaxport:
+
+ LUAX_DECL_FACTORY(SpriteBatch);
+
+};
+
+namespace_end
+namespace_end
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-core/Graphics/Texture.cpp b/Source/modules/asura-core/Graphics/Texture.cpp
new file mode 100644
index 0000000..03f005d
--- /dev/null
+++ b/Source/modules/asura-core/Graphics/Texture.cpp
@@ -0,0 +1,47 @@
+#include <asura-base/Exception.h>
+
+#include "Texture.h"
+
+namespace_begin(AsuraEngine)
+namespace_begin(Graphics)
+
+Texture::Texture()
+ : m_TexID(0)
+{
+}
+
+Texture::~Texture()
+{
+ // ͷԴ
+ if(m_TexID != 0)
+ glDeleteTextures(1, &m_TexID);
+}
+
+GLuint Texture::GetGLTexture() const
+{
+ return m_TexID;
+}
+
+TextureFormat Texture::ConvertColorFormat(const ColorFormat& colorformat)
+{
+ TextureFormat t;
+ switch (colorformat)
+ {
+ case COLOR_FORMAT_RGBA8:
+ t.internalformat = GL_RGBA8; // 4*sizeof(byte) ~= 4 bytes
+ t.externalformat = GL_RGBA;
+ t.type = GL_UNSIGNED_BYTE;
+ break;
+ case COLOR_FORMAT_RGBA32F:
+ t.internalformat = GL_RGBA32F; // 4*sizeof(float) = 16 bytes
+ t.externalformat = GL_RGBA;
+ t.type = GL_FLOAT;
+ break;
+ default:
+ ASSERT(false);
+ }
+ return t;
+}
+
+namespace_end
+namespace_end \ No newline at end of file
diff --git a/Source/modules/asura-core/Graphics/Texture.h b/Source/modules/asura-core/Graphics/Texture.h
new file mode 100644
index 0000000..76b9a8f
--- /dev/null
+++ b/Source/modules/asura-core/Graphics/Texture.h
@@ -0,0 +1,101 @@
+#ifndef _ASURA_TEXTURE_H_
+#define _ASURA_TEXTURE_H_
+
+#include <asura-base/Math/Vector2.hpp>
+#include <asura-base/Math/Rect.hpp>
+
+#include "../CoreConfig.h"
+
+#include "RenderState.h"
+#include "GfxDevice.h"
+
+namespace_begin(AsuraEngine)
+namespace_begin(Graphics)
+
+class RenderTarget;
+
+/// UVʽ
+enum WrapMode
+{
+ WRAP_MODE_REPEAT,
+ WRAP_MODE_MIRROR,
+ WRAP_MODE_CLAMPTOEDGE,
+ WRAP_MODE_CLAMPTOBORDER,
+};
+
+/// ˲ģʽ
+enum FilterMode
+{
+ FILTER_MODE_NEAREST,
+ FILTER_MODE_LINEAR,
+};
+
+/// ͼݵɫʽ
+enum ColorFormat
+{
+ COLOR_FORMAT_UNKNOWN,
+ COLOR_FORMAT_RGBA8, ///< RGBA8bits int
+ COLOR_FORMAT_RGBA32F, ///< RGBA32bits float
+};
+
+/// ʽGPUڲCPUⲿʽ
+struct TextureFormat
+{
+ GLenum internalformat; ///< GPUڲʽ
+ GLenum externalformat; ///< CPUⲿʽ
+ GLenum type; ///< ⲿʽÿchannelֵ
+};
+
+///
+/// 2D࣬2d meshrender targetбʹáTextureȾԭϽǣϷϲԵѿ
+/// ϵΪ׼EditorҲϽΪԭ㣬Ϊ˷㡣
+///
+ASURA_ABSTRACT class Texture : public AEScripting::Object
+{
+public:
+
+ LUAX_DECL_ABSTRACT_FACTORY(Texture);
+
+ Texture();
+ virtual ~Texture();
+
+ GLuint GetGLTexture() const;
+
+ void SetFilterMode(FilterMode min, FilterMode mag);
+ void SetWrapMode(WrapMode wrapMode);
+
+ void GetFilterMode();
+ void GetWrapMode();
+
+ /// UVfilterΪ
+ bool IsGenMipmap();
+
+protected:
+
+ /// תcolor formatΪtexture format
+ TextureFormat ConvertColorFormat(const ColorFormat& colorformat);
+
+ GLuint m_TexID;
+ FilterMode m_MinFilter;
+ FilterMode m_MagFilter;
+ WrapMode m_WrapMode;
+ bool m_IsGenMipmap;
+
+ LUAX_DECL_ENUM(ColorFormat, 1);
+ LUAX_DECL_ENUM(FilterMode, 1);
+ LUAX_DECL_ENUM(WrapMode, 1);
+
+ LUAX_DECL_METHOD(_SetFilterMode);
+ LUAX_DECL_METHOD(_SetWrapMode);
+ LUAX_DECL_METHOD(_GetFilterMode);
+ LUAX_DECL_METHOD(_GetWrapMode);
+ LUAX_DECL_METHOD(_IsGenMipmap);
+
+};
+
+typedef Texture Drawable;
+
+namespace_end
+namespace_end
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-core/Graphics/VBO.cpp b/Source/modules/asura-core/Graphics/VBO.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-core/Graphics/VBO.cpp
diff --git a/Source/modules/asura-core/Graphics/VBO.h b/Source/modules/asura-core/Graphics/VBO.h
new file mode 100644
index 0000000..f80991e
--- /dev/null
+++ b/Source/modules/asura-core/Graphics/VBO.h
@@ -0,0 +1,27 @@
+#ifndef _ASURA_ENGINE_VBO_H_
+#define _ASURA_ENGINE_VBO_H_
+
+#include <asura-base/Classes.h>
+
+namespace_begin(AsuraEngine)
+namespace_begin(Graphics)
+
+struct VertexBufferData
+{
+
+};
+
+struct IndexBufferData
+{
+
+};
+
+class VBO
+{
+
+};
+
+namespace_end
+namespace_end
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-core/Graphics/VertexBuffer.cpp b/Source/modules/asura-core/Graphics/VertexBuffer.cpp
new file mode 100644
index 0000000..c44e9be
--- /dev/null
+++ b/Source/modules/asura-core/Graphics/VertexBuffer.cpp
@@ -0,0 +1,16 @@
+#include "VertexBuffer.h"
+
+namespace_begin(AsuraEngine)
+namespace_begin(Graphics)
+
+VertexBuffer::VertexBuffer(BufferUsage usage, BufferDataType datatype, size_t size)
+ : GPUBuffer(BUFFER_TYPE_VERTEX, usage, datatype, size)
+{
+}
+
+VertexBuffer::~VertexBuffer()
+{
+}
+
+namespace_end
+namespace_end
diff --git a/Source/modules/asura-core/Graphics/VertexBuffer.h b/Source/modules/asura-core/Graphics/VertexBuffer.h
new file mode 100644
index 0000000..0622388
--- /dev/null
+++ b/Source/modules/asura-core/Graphics/VertexBuffer.h
@@ -0,0 +1,34 @@
+#ifndef _ASURA_VERTEX_BUFFER_H_
+#define _ASURA_VERTEX_BUFFER_H_
+
+#include <asura-base/Scripting/Scripting.h>
+
+#include "GPUBuffer.h"
+
+namespace_begin(AsuraEngine)
+namespace_begin(Graphics)
+
+///
+/// frameworkṩ˴Դ滺Ĺܣֱû壬ֱܶͨöݡ
+///
+class VertexBuffer ASURA_FINAL
+ : public AEScripting::Portable<VertexBuffer>
+ , public GPUBuffer
+{
+public:
+
+ VertexBuffer(BufferUsage usage, BufferDataType datatype, size_t size);
+ ~VertexBuffer();
+
+luaxport:
+
+ LUAX_DECL_FACTORY(VertexBuffer);
+
+ LUAX_DECL_METHOD(_New);
+
+};
+
+namespace_end
+namespace_end
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-core/Graphics/binding/_canvas.cpp b/Source/modules/asura-core/Graphics/binding/_canvas.cpp
new file mode 100644
index 0000000..44841f5
--- /dev/null
+++ b/Source/modules/asura-core/Graphics/binding/_canvas.cpp
@@ -0,0 +1,48 @@
+#include "../Canvas.h"
+
+using namespace std;
+
+namespace_begin(AsuraEngine)
+namespace_begin(Graphics)
+
+
+ LUAX_REGISTRY(Canvas)
+ {
+ LUAX_REGISTER_METHODS(state,
+ { "SetSize", _SetSize },
+ { "Bind", _Bind },
+ { "Unbind", _Unbind }
+ );
+ }
+
+ LUAX_POSTPROCESS(Canvas)
+ {
+
+ }
+
+ // canvas:SetSize()
+ LUAX_IMPL_METHOD(Canvas, _SetSize)
+ {
+ LUAX_PREPARE(L, Canvas);
+ return 0;
+
+ }
+
+ // canvas:Bind()
+ LUAX_IMPL_METHOD(Canvas, _Bind)
+ {
+ LUAX_PREPARE(L, Canvas);
+
+ return 0;
+ }
+
+ // canvas:Unbind()
+ LUAX_IMPL_METHOD(Canvas, _Unbind)
+ {
+ LUAX_PREPARE(L, Canvas);
+ return 0;
+
+ }
+
+ }
+}
diff --git a/Source/modules/asura-core/Graphics/binding/_color.cpp b/Source/modules/asura-core/Graphics/binding/_color.cpp
new file mode 100644
index 0000000..008d9c2
--- /dev/null
+++ b/Source/modules/asura-core/Graphics/binding/_color.cpp
@@ -0,0 +1,130 @@
+#include "../Color.h"
+
+using namespace std;
+using namespace Luax;
+
+namespace_begin(AsuraEngine)
+namespace_begin(Graphics)
+
+
+LUAX_REGISTRY(Color)
+{
+ LUAX_REGISTER_METHODS(state,
+ { "ToColor32", _ToColor32 },
+ { "SetColor", _SetColor },
+ { "GetColor", _GetColor },
+ { "GetR", _GetR },
+ { "GetG", _GetG },
+ { "GetB", _GetB },
+ { "GetA", _GetA },
+ { "__eq", ___eq },
+ { "__add", ___add },
+ { "__sub", ___sub },
+ { "__mul", ___mul },
+ { "__div", ___div }
+ );
+}
+
+LUAX_POSTPROCESS(Color)
+{
+
+}
+
+// color:ToColor32()
+LUAX_IMPL_METHOD(Color, _ToColor32)
+{
+ LUAX_PREPARE(L, Color);
+
+ return 0;
+}
+
+// color:SetColor()
+LUAX_IMPL_METHOD(Color, _SetColor)
+{
+ LUAX_PREPARE(L, Color);
+
+ return 0;
+}
+
+// color:GetColor()
+LUAX_IMPL_METHOD(Color, _GetColor)
+{
+ LUAX_PREPARE(L, Color);
+
+ return 0;
+}
+
+// color:GetR()
+LUAX_IMPL_METHOD(Color, _GetR)
+{
+ LUAX_PREPARE(L, Color);
+
+ return 0;
+}
+
+// color:GetG()
+LUAX_IMPL_METHOD(Color, _GetG)
+{
+ LUAX_PREPARE(L, Color);
+
+ return 0;
+}
+
+// color:GetB()
+LUAX_IMPL_METHOD(Color, _GetB)
+{
+ LUAX_PREPARE(L, Color);
+
+ return 0;
+}
+
+// color:GetA()
+LUAX_IMPL_METHOD(Color, _GetA)
+{
+ LUAX_PREPARE(L, Color);
+
+ return 0;
+}
+
+// color:__eq()
+LUAX_IMPL_METHOD(Color, ___eq)
+{
+ LUAX_PREPARE(L, Color);
+
+ return 0;
+}
+
+// color:__add()
+LUAX_IMPL_METHOD(Color, ___add)
+{
+ LUAX_PREPARE(L, Color);
+
+ return 0;
+}
+
+// color:__sub()
+LUAX_IMPL_METHOD(Color, ___sub)
+{
+ LUAX_PREPARE(L, Color);
+
+ return 0;
+}
+
+// color:__mul()
+LUAX_IMPL_METHOD(Color, ___mul)
+{
+ LUAX_PREPARE(L, Color);
+
+ return 0;
+}
+
+// color:__div()
+LUAX_IMPL_METHOD(Color, ___div)
+{
+ LUAX_PREPARE(L, Color);
+
+ return 0;
+}
+
+}
+} \ No newline at end of file
diff --git a/Source/modules/asura-core/Graphics/binding/_color32.cpp b/Source/modules/asura-core/Graphics/binding/_color32.cpp
new file mode 100644
index 0000000..7613361
--- /dev/null
+++ b/Source/modules/asura-core/Graphics/binding/_color32.cpp
@@ -0,0 +1,66 @@
+#include "../Color32.h"
+
+using namespace std;
+
+namespace_begin(AsuraEngine)
+namespace_begin(Graphics)
+
+
+ LUAX_REGISTRY(Color32)
+ {
+ LUAX_REGISTER_METHODS(state,
+ { "ToColor", _ToColor },
+ { "GetRed", _GetRed },
+ { "GetGreen", _GetGreen },
+ { "GetBlue", _GetBlue },
+ { "GetAlpha", _GetAlpha }
+ );
+ }
+
+ LUAX_POSTPROCESS(Color32)
+ {
+
+ }
+
+ // color32:ToColor()
+ LUAX_IMPL_METHOD(Color32, _ToColor)
+ {
+ LUAX_PREPARE(L, Color32);
+ return 0;
+
+ }
+
+ // color32:GetRed()
+ LUAX_IMPL_METHOD(Color32, _GetRed)
+ {
+ LUAX_PREPARE(L, Color32);
+ return 0;
+ }
+
+ // color32:GetGreen()
+ LUAX_IMPL_METHOD(Color32, _GetGreen)
+ {
+ LUAX_PREPARE(L, Color32);
+
+ return 0;
+ }
+
+ // color32:GetBlue()
+ LUAX_IMPL_METHOD(Color32, _GetBlue)
+ {
+ LUAX_PREPARE(L, Color32);
+
+ return 0;
+ }
+
+ // color32:GetAlpha()
+ LUAX_IMPL_METHOD(Color32, _GetAlpha)
+ {
+ LUAX_PREPARE(L, Color32);
+
+ return 0;
+ }
+
+ }
+}
+ \ No newline at end of file
diff --git a/Source/modules/asura-core/Graphics/binding/_gfx_device.cpp b/Source/modules/asura-core/Graphics/binding/_gfx_device.cpp
new file mode 100644
index 0000000..f6c2004
--- /dev/null
+++ b/Source/modules/asura-core/Graphics/binding/_gfx_device.cpp
@@ -0,0 +1,151 @@
+#include "../GfxDevice.h"
+
+using namespace std;
+using namespace Luax;
+
+namespace_begin(AsuraEngine)
+namespace_begin(Graphics)
+
+
+ LUAX_REGISTRY(GfxDevice)
+ {
+ LUAX_REGISTER_METHODS(state,
+ { "SetMatrixMode", _SetMatrixMode },
+ { "GetMatrixMode", _GetMatrixMode },
+ { "PushMatrix", _PushMatrix },
+ { "PopMatrix", _PopMatrix },
+ { "LoadIdentity", _LoadIdentity },
+ { "Rotate", _Rotate },
+ { "Translate", _Translate },
+ { "Scale", _Scale },
+ { "Ortho", _Ortho },
+ { "GetMatrixDepth", _GetMatrixDepth },
+ { "GetMatrixIndex", _GetMatrixIndex },
+ { "UseShader", _UseShader },
+ { "UnuseShader", _UnuseShader }
+ );
+ }
+
+ LUAX_POSTPROCESS(GfxDevice)
+ {
+ LUAX_REGISTER_ENUM(state, "EMatrixMode",
+ { "PROJECTION", MATRIX_MODE_PROJECTION },
+ { "0", 0 },
+ { "MODEL", MATRIX_MODE_MODEL },
+ { "1", 1 },
+ { "VIEW", MATRIX_MODE_VIEW },
+ { "2", 2 }
+ );
+ LUAX_REGISTER_ENUM(state, "EGLParams",
+ { "MAX_TEXTURE_UNIT", GL_PARAM_MAX_TEXTURE_UNIT },
+ { "1", 1 }
+ );
+
+ }
+
+ // gfxdevice:SetMatrixMode()
+ LUAX_IMPL_METHOD(GfxDevice, _SetMatrixMode)
+ {
+ LUAX_PREPARE(L, GfxDevice);
+
+ return 0;
+ }
+
+ // gfxdevice:GetMatrixMode()
+ LUAX_IMPL_METHOD(GfxDevice, _GetMatrixMode)
+ {
+ LUAX_PREPARE(L, GfxDevice);
+
+ return 0;
+ }
+
+ // gfxdevice:PushMatrix()
+ LUAX_IMPL_METHOD(GfxDevice, _PushMatrix)
+ {
+ LUAX_PREPARE(L, GfxDevice);
+
+ return 0;
+ }
+
+ // gfxdevice:PopMatrix()
+ LUAX_IMPL_METHOD(GfxDevice, _PopMatrix)
+ {
+ LUAX_PREPARE(L, GfxDevice);
+
+ return 0;
+ }
+
+ // gfxdevice:LoadIdentity()
+ LUAX_IMPL_METHOD(GfxDevice, _LoadIdentity)
+ {
+ LUAX_PREPARE(L, GfxDevice);
+
+ return 0;
+ }
+
+ // gfxdevice:Rotate()
+ LUAX_IMPL_METHOD(GfxDevice, _Rotate)
+ {
+ LUAX_PREPARE(L, GfxDevice);
+
+ return 0;
+ }
+
+ // gfxdevice:Translate()
+ LUAX_IMPL_METHOD(GfxDevice, _Translate)
+ {
+ LUAX_PREPARE(L, GfxDevice);
+
+ return 0;
+ }
+
+ // gfxdevice:Scale()
+ LUAX_IMPL_METHOD(GfxDevice, _Scale)
+ {
+ LUAX_PREPARE(L, GfxDevice);
+
+ return 0;
+ }
+
+ // gfxdevice:Ortho()
+ LUAX_IMPL_METHOD(GfxDevice, _Ortho)
+ {
+ LUAX_PREPARE(L, GfxDevice);
+
+ return 0;
+ }
+
+ // gfxdevice:GetMatrixDepth()
+ LUAX_IMPL_METHOD(GfxDevice, _GetMatrixDepth)
+ {
+ LUAX_PREPARE(L, GfxDevice);
+
+ return 0;
+ }
+
+ // gfxdevice:GetMatrixIndex()
+ LUAX_IMPL_METHOD(GfxDevice, _GetMatrixIndex)
+ {
+ LUAX_PREPARE(L, GfxDevice);
+
+ return 0;
+ }
+
+ // gfxdevice:UseShader()
+ LUAX_IMPL_METHOD(GfxDevice, _UseShader)
+ {
+ LUAX_PREPARE(L, GfxDevice);
+
+ return 0;
+ }
+
+ // gfxdevice:UnuseShader()
+ LUAX_IMPL_METHOD(GfxDevice, _UnuseShader)
+ {
+ LUAX_PREPARE(L, GfxDevice);
+
+ return 0;
+ }
+
+ }
+}
diff --git a/Source/modules/asura-core/Graphics/binding/_gpu_buffer.cpp b/Source/modules/asura-core/Graphics/binding/_gpu_buffer.cpp
new file mode 100644
index 0000000..8c39a59
--- /dev/null
+++ b/Source/modules/asura-core/Graphics/binding/_gpu_buffer.cpp
@@ -0,0 +1,118 @@
+#include <stdlib.h>
+
+#include "../image.h"
+#include "../GPUBuffer.h"
+
+using namespace std;
+using namespace Luax;
+
+namespace_begin(AsuraEngine)
+namespace_begin(Graphics)
+
+
+ LUAX_REGISTRY(GPUBuffer)
+ {
+ LUAX_REGISTER_METHODS(state,
+ { "Fill", _Fill },
+ { "GetSize", _GetSize },
+ { "GetCount", _GetCount }
+ );
+ }
+
+ LUAX_POSTPROCESS(GPUBuffer)
+ {
+ LUAX_REGISTER_ENUM(state, "EBufferType",
+ { "VERTEX", BUFFER_TYPE_VERTEX },
+ { "INDEX", BUFFER_TYPE_INDEX }
+ );
+ LUAX_REGISTER_ENUM(state, "EBufferUsage",
+ { "STREAM", BUFFER_USAGE_STREAM },
+ { "DYNAMIC", BUFFER_USAGE_DYNAMIC },
+ { "STATIC", BUFFER_USAGE_STATIC }
+ );
+ LUAX_REGISTER_ENUM(state, "EBufferDataType",
+ { "INT", BUFFER_DATA_TYPE_INT },
+ { "FLOAT", BUFFER_DATA_TYPE_FLOAT },
+ { "UNSIGNED_BYTE", BUFFER_DATA_TYPE_UNSIGNED_BYTE }
+ );
+
+ }
+
+ // buffer = GPUBuffer.New(bufferType, bufferUsage, bufferDataType, size)
+ // buffer = GPUBuffer.New(image)
+ // buffer = GPUBuffer.New(mesh2d)
+ // buffer = GPUBuffer.New(canvas)
+ // buffer = GPUBuffer.New(shape)
+ //LUAX_IMPL_METHOD(GPUBuffer, _New)
+ //{
+ // LUAX_STATE(L);
+
+ // return 0;
+ //}
+
+ // gpubuffer:Fill({data_unit_list}, offseti)
+ // data_unit_list ݵtable
+ // offseti : ʼǵĵطڵ(0ʼ
+ LUAX_IMPL_METHOD(GPUBuffer, _Fill)
+ {
+ LUAX_PREPARE(L, GPUBuffer);
+
+ // ʹbufferӦ޸bufferڵһεʱʼsizeСbufferȻ䡣
+ int offset = state.GetValue(3, 0);
+ int count = lua_objlen(L, 2);
+ int size = count * self->GetDataTypeSize();
+ byte* data = (byte*)malloc(size);
+ int unit = self->GetDataTypeSize();
+ int i = 1;
+ lua_rawgeti(L, 2, i);
+ while (!lua_isnil(L, -1))
+ {
+ switch (self->m_DataType)
+ {
+ case GL_INT:
+ {
+ int n = state.CheckValue<int>(-1);
+ memcpy(data + (i - 1)*unit, &n, unit);
+ break;
+ }
+ case GL_FLOAT:
+ {
+ float n = state.CheckValue<float>(-1);
+ memcpy(data + (i - 1)*unit, &n, unit);
+ break;
+ }
+ case GL_UNSIGNED_BYTE:
+ {
+ unsigned char n = state.CheckValue<unsigned char>(-1);
+ memcpy(data + (i - 1)*unit, &n, unit);
+ break;
+ }
+ }
+ state.Pop(1); // value
+ lua_rawgeti(L, 2, ++i);
+ }
+ state.Pop(); // nil
+
+ self->Fill(data, size, offset * unit);
+
+ free(data);
+ return 0;
+ }
+
+ // gpubuffer:GetSize()
+ LUAX_IMPL_METHOD(GPUBuffer, _GetSize)
+ {
+ LUAX_PREPARE(L, GPUBuffer);
+ state.Push(self->m_Size);
+ return 0;
+ }
+
+ LUAX_IMPL_METHOD(GPUBuffer, _GetCount)
+ {
+ LUAX_PREPARE(L, GPUBuffer);
+ state.Push(self->m_Size / self->GetDataTypeSize());
+ return 0;
+ }
+
+ }
+}
diff --git a/Source/modules/asura-core/Graphics/binding/_image.cpp b/Source/modules/asura-core/Graphics/binding/_image.cpp
new file mode 100644
index 0000000..0e4cb16
--- /dev/null
+++ b/Source/modules/asura-core/Graphics/binding/_image.cpp
@@ -0,0 +1,71 @@
+#include "../image.h"
+
+using namespace std;
+
+namespace_begin(AsuraEngine)
+namespace_begin(Graphics)
+
+
+ LUAX_REGISTRY(Image)
+ {
+ LUAX_INHERIT(state, Texture);
+
+ LUAX_REGISTER_METHODS(state,
+ { "New", _New },
+ { "GetWidth", _GetWidth },
+ { "GetHeight", _GetHeight },
+ { "GetSize", _GetSize },
+ { "Render", _Render }
+ );
+ }
+
+ LUAX_POSTPROCESS(Image)
+ {
+ }
+
+ // image = Image.New()
+ LUAX_IMPL_METHOD(Image, _New)
+ {
+ LUAX_STATE(L);
+ Image* img = new Image();
+ img->PushLuaxUserdata(state);
+ return 1;
+ }
+
+ // width = image:GetWidth()
+ LUAX_IMPL_METHOD(Image, _GetWidth)
+ {
+ LUAX_PREPARE(L, Image);
+ state.Push(self->GetWidth());
+ return 1;
+ }
+
+ // height = image:GetHeight()
+ LUAX_IMPL_METHOD(Image, _GetHeight)
+ {
+ LUAX_PREPARE(L, Image);
+ state.Push(self->GetHeight());
+ return 1;
+ }
+
+ // width, height = image:GetSize()
+ LUAX_IMPL_METHOD(Image, _GetSize)
+ {
+ LUAX_PREPARE(L, Image);
+ int width = self->GetWidth();
+ int height = self->GetHeight();
+ state.Push(width);
+ state.Push(height);
+ return 2;
+ }
+
+ // image:Render()
+ LUAX_IMPL_METHOD(Image, _Render)
+ {
+ LUAX_PREPARE(L, Image);
+
+ return 0;
+ }
+
+ }
+}
diff --git a/Source/modules/asura-core/Graphics/binding/_index_buffer.cpp b/Source/modules/asura-core/Graphics/binding/_index_buffer.cpp
new file mode 100644
index 0000000..151dc98
--- /dev/null
+++ b/Source/modules/asura-core/Graphics/binding/_index_buffer.cpp
@@ -0,0 +1,31 @@
+#include "../IndexBuffer.h"
+
+using namespace std;
+using namespace Luax;
+
+namespace_begin(AsuraEngine)
+namespace_begin(Graphics)
+
+
+ LUAX_REGISTRY(IndexBuffer)
+ {
+ LUAX_REGISTER_METHODS(state,
+ { "New", _New }
+ );
+ }
+
+ LUAX_POSTPROCESS(IndexBuffer)
+ {
+
+ }
+
+ // IndexBuffer.New()
+ LUAX_IMPL_METHOD(IndexBuffer, _New)
+ {
+ LUAX_STATE(L);
+
+ return 0;
+ }
+
+ }
+}
diff --git a/Source/modules/asura-core/Graphics/binding/_mesh2d.cpp b/Source/modules/asura-core/Graphics/binding/_mesh2d.cpp
new file mode 100644
index 0000000..4e3f426
--- /dev/null
+++ b/Source/modules/asura-core/Graphics/binding/_mesh2d.cpp
@@ -0,0 +1,20 @@
+#include "../mesh2d.h"
+
+using namespace std;
+
+namespace_begin(AsuraEngine)
+namespace_begin(Graphics)
+
+
+ LUAX_REGISTRY(Mesh2D)
+ {
+
+ }
+
+ LUAX_POSTPROCESS(Mesh2D)
+ {
+
+ }
+
+ }
+}
diff --git a/Source/modules/asura-core/Graphics/binding/_shader.cpp b/Source/modules/asura-core/Graphics/binding/_shader.cpp
new file mode 100644
index 0000000..85fd388
--- /dev/null
+++ b/Source/modules/asura-core/Graphics/binding/_shader.cpp
@@ -0,0 +1,131 @@
+#include "../shader.h"
+
+using namespace std;
+using namespace Luax;
+
+namespace_begin(AsuraEngine)
+namespace_begin(Graphics)
+
+
+ LUAX_REGISTRY(Shader)
+ {
+ LUAX_REGISTER_METHODS(state,
+ { "New", _New },
+ { "Load", _Load },
+ { "Update", _Update },
+ { "HasUniform", _HasUniform },
+ { "GetUniformLocation", _GetUniformLocation },
+ { "SetBuiltInUniforms", _SetBuiltInUniforms },
+ { "SetUniformFloat", _SetUniformFloat },
+ { "SetUniformTexture", _SetUniformTexture },
+ { "SetUniformVector2", _SetUniformVector2 },
+ { "SetUniformVector3", _SetUniformVector3 },
+ { "SetUniformVector4", _SetUniformVector4 },
+ { "SetUniformColor", _SetUniformColor },
+ { "SetBuiltInUniforms", _SetBuiltInUniforms }
+ );
+ }
+
+ LUAX_POSTPROCESS(Shader)
+ {
+
+ }
+
+ // Shader.New()
+ LUAX_IMPL_METHOD(Shader, _New)
+ {
+ LUAX_STATE(L);
+
+ return 0;
+ }
+
+ // shader:Load()
+ LUAX_IMPL_METHOD(Shader, _Load)
+ {
+ LUAX_PREPARE(L, Shader);
+
+ return 0;
+ }
+
+ // shader:Update()
+ LUAX_IMPL_METHOD(Shader, _Update)
+ {
+ LUAX_PREPARE(L, Shader);
+
+ return 0;
+ }
+
+ // shader:HasUniform()
+ LUAX_IMPL_METHOD(Shader, _HasUniform)
+ {
+ LUAX_PREPARE(L, Shader);
+
+ return 0;
+ }
+
+ // shader:GetUniformLocation()
+ LUAX_IMPL_METHOD(Shader, _GetUniformLocation)
+ {
+ LUAX_PREPARE(L, Shader);
+
+ return 0;
+ }
+
+ // shader:SetBuiltInUniforms()
+ LUAX_IMPL_METHOD(Shader, _SetBuiltInUniforms)
+ {
+ LUAX_PREPARE(L, Shader);
+
+ return 0;
+ }
+
+ // shader:SetUniformFloat()
+ LUAX_IMPL_METHOD(Shader, _SetUniformFloat)
+ {
+ LUAX_PREPARE(L, Shader);
+
+ return 0;
+ }
+
+ // shader:SetUniformTexture()
+ LUAX_IMPL_METHOD(Shader, _SetUniformTexture)
+ {
+ LUAX_PREPARE(L, Shader);
+
+ return 0;
+ }
+
+ // shader:SetUniformVector2()
+ LUAX_IMPL_METHOD(Shader, _SetUniformVector2)
+ {
+ LUAX_PREPARE(L, Shader);
+
+ return 0;
+ }
+
+ // shader:SetUniformVector3()
+ LUAX_IMPL_METHOD(Shader, _SetUniformVector3)
+ {
+ LUAX_PREPARE(L, Shader);
+
+ return 0;
+ }
+
+ // shader:SetUniformVector4()
+ LUAX_IMPL_METHOD(Shader, _SetUniformVector4)
+ {
+ LUAX_PREPARE(L, Shader);
+
+ return 0;
+ }
+
+ // shader:SetUniformColor()
+ LUAX_IMPL_METHOD(Shader, _SetUniformColor)
+ {
+ LUAX_PREPARE(L, Shader);
+
+ return 0;
+ }
+
+ }
+}
diff --git a/Source/modules/asura-core/Graphics/binding/_sprite_batch.cpp b/Source/modules/asura-core/Graphics/binding/_sprite_batch.cpp
new file mode 100644
index 0000000..6b7d25c
--- /dev/null
+++ b/Source/modules/asura-core/Graphics/binding/_sprite_batch.cpp
@@ -0,0 +1,20 @@
+#include "../SpriteBatch.h"
+
+using namespace std;
+
+namespace_begin(AsuraEngine)
+namespace_begin(Graphics)
+
+
+ LUAX_REGISTRY(SpriteBatch)
+ {
+
+ }
+
+ LUAX_POSTPROCESS(SpriteBatch)
+ {
+
+ }
+
+ }
+}
diff --git a/Source/modules/asura-core/Graphics/binding/_texture.cpp b/Source/modules/asura-core/Graphics/binding/_texture.cpp
new file mode 100644
index 0000000..f5e5f17
--- /dev/null
+++ b/Source/modules/asura-core/Graphics/binding/_texture.cpp
@@ -0,0 +1,85 @@
+#include "../texture.h"
+
+using namespace std;
+
+namespace_begin(AsuraEngine)
+namespace_begin(Graphics)
+
+
+ LUAX_REGISTRY(Texture)
+ {
+ LUAX_REGISTER_METHODS(state,
+ { "SetFilterMode", _SetFilterMode },
+ { "SetWrapMode", _SetWrapMode },
+ { "GetFilterMode", _GetFilterMode },
+ { "GetWrapMode", _GetWrapMode },
+ { "IsGenMipmap", _IsGenMipmap }
+ );
+ }
+
+ LUAX_POSTPROCESS(Texture)
+ {
+ LUAX_REGISTER_ENUM(state, "EColorFormat",
+ { "UNKNOWN", COLOR_FORMAT_UNKNOWN },
+ { "RGBA8", COLOR_FORMAT_RGBA8 },
+ { "RGBA32F", COLOR_FORMAT_RGBA32F }
+ );
+ LUAX_REGISTER_ENUM(state, "EFilterMode",
+ { "NEAREST", FILTER_MODE_NEAREST },
+ { "LINEAR", FILTER_MODE_LINEAR }
+ );
+ LUAX_REGISTER_ENUM(state, "EWrapMode",
+ { "REPEAT", WRAP_MODE_REPEAT },
+ { "MIRROR", WRAP_MODE_MIRROR },
+ { "CLAMPTOEDGE", WRAP_MODE_CLAMPTOEDGE },
+ { "CLAMPTOBORDER", WRAP_MODE_CLAMPTOBORDER }
+ );
+
+ }
+
+ // texture:SetFilterMode(minFilter, magFilter)
+ LUAX_IMPL_METHOD(Texture, _SetFilterMode)
+ {
+ LUAX_PREPARE(L, Texture);
+ FilterMode min = (FilterMode)state.CheckValue<int>(2);
+ FilterMode mag = (FilterMode)state.CheckValue<int>(3);
+ self->SetFilterMode(min, mag);
+ return 0;
+ }
+
+ // texture:SetWrapMode(wrap_mode)
+ LUAX_IMPL_METHOD(Texture, _SetWrapMode)
+ {
+ LUAX_PREPARE(L, Texture);
+ WrapMode wrap_mode = (WrapMode)state.CheckValue<int>(2);
+ self->SetWrapMode(wrap_mode);
+ return 0;
+ }
+
+ // min, mag = texture:GetFilterMode()
+ LUAX_IMPL_METHOD(Texture, _GetFilterMode)
+ {
+ LUAX_PREPARE(L, Texture);
+ state.Push((int)self->m_MinFilter);
+ state.Push((int)self->m_MagFilter);
+ return 2;
+ }
+
+ // wrapmode= texture:GetWrapMode()
+ LUAX_IMPL_METHOD(Texture, _GetWrapMode)
+ {
+ LUAX_PREPARE(L, Texture);
+ state.Push((int)self->m_WrapMode);
+ return 1;
+ }
+
+ // texture:IsGenMipmap()
+ LUAX_IMPL_METHOD(Texture, _IsGenMipmap)
+ {
+ LUAX_PREPARE(L, Texture);
+ state.Push(self->IsGenMipmap());
+ return 1;
+ }
+
+ }
+} \ No newline at end of file
diff --git a/Source/modules/asura-core/Graphics/binding/_vertex_buffer.cpp b/Source/modules/asura-core/Graphics/binding/_vertex_buffer.cpp
new file mode 100644
index 0000000..8ed487b
--- /dev/null
+++ b/Source/modules/asura-core/Graphics/binding/_vertex_buffer.cpp
@@ -0,0 +1,38 @@
+#include "../VertexBuffer.h"
+
+using namespace std;
+using namespace Luax;
+
+namespace_begin(AsuraEngine)
+namespace_begin(Graphics)
+
+
+ LUAX_REGISTRY(VertexBuffer)
+ {
+ LUAX_REGISTER_METHODS(state,
+ { "New", _New }
+ );
+ }
+
+ LUAX_POSTPROCESS(VertexBuffer)
+ {
+
+ }
+
+ // vbo = VertexBuffer.New(usage, data_type, count)
+ LUAX_IMPL_METHOD(VertexBuffer, _New)
+ {
+ LUAX_STATE(L);
+
+ BufferUsage usage = (BufferUsage)state.CheckValue<uint>(1);
+ BufferDataType datatype = (BufferDataType)state.CheckValue<uint>(2);
+ uint count = state.CheckValue<uint>(3);
+
+ VertexBuffer* vbo = new VertexBuffer(usage, datatype, count * GPUBuffer::GetDataTypeSize(datatype));
+ vbo->PushLuaxUserdata(state);
+
+ return 1;
+ }
+
+ }
+}
diff --git a/Source/modules/asura-core/Image/ImageData.cpp b/Source/modules/asura-core/Image/ImageData.cpp
new file mode 100644
index 0000000..bbfd177
--- /dev/null
+++ b/Source/modules/asura-core/Image/ImageData.cpp
@@ -0,0 +1,62 @@
+#include "ImageData.h"
+#include "PngDecoder.h"
+#include "StbDecoder.h"
+#include "ImageDecoder.h"
+
+using namespace std;
+
+using namespace AEGraphics;
+
+namespace_begin(AsuraEngine)
+namespace_begin(Image)
+
+// imagedecoderΪԡ
+list<ImageDecoder*> ImageData::ImageDecoders = {
+ new PNGDecoder(), // png
+ new STBDecoder() // jpeg, tga, bmp
+};
+
+ImageData::ImageData()
+ : pixels(nullptr)
+ , size(0)
+ , width(0)
+ , height(0)
+ , format(COLOR_FORMAT_UNKNOWN)
+{
+}
+
+ImageData::~ImageData()
+{
+ if (pixels)
+ delete[] pixels;
+}
+
+void ImageData::Decode(FileSystem::DataBuffer& buffer)
+{
+ for (ImageDecoder* decoder : ImageDecoders)
+ {
+ if (decoder->CanDecode(buffer))
+ {
+ decoder->Decode(buffer, *this);
+ return;
+ }
+ }
+}
+
+Color ImageData::GetPixel(uint x, uint y)
+{
+ return Color();
+}
+
+void ImageData::Lock()
+{
+ m_Mutex.Lock();
+}
+
+void ImageData::Unlock()
+{
+ m_Mutex.Unlock();
+}
+
+namespace_end
+namespace_end \ No newline at end of file
diff --git a/Source/modules/asura-core/Image/ImageData.h b/Source/modules/asura-core/Image/ImageData.h
new file mode 100644
index 0000000..2d70edc
--- /dev/null
+++ b/Source/modules/asura-core/Image/ImageData.h
@@ -0,0 +1,81 @@
+#ifndef _ASURA_ENGINE_IMAGEDATA_H_
+#define _ASURA_ENGINE_IMAGEDATA_H_
+
+#include <list>
+
+#include <asura-base/Scripting/Scripting.h>
+#include <asura-base/FileSystem/DecodedData.h>
+#include <asura-base/FileSystem/DataBuffer.h>
+#include <asura-base/Threads/Thread.h>
+#include <asura-base/Threads/Mutex.h>
+
+#include "../Graphics/Texture.h"
+#include "../Graphics/Color.h"
+
+namespace_begin(AsuraEngine)
+namespace_begin(Image)
+
+class ImageDecoder;
+
+class ImageData ASURA_FINAL
+ : public Scripting::Portable<ImageData>
+ , public AEFileSystem::DecodedData
+{
+public:
+
+ ///
+ /// ͼƬļϢʧܣ׳쳣
+ ///
+ ImageData();
+ ~ImageData();
+
+ void Decode(AEFileSystem::DataBuffer& buffer) override;
+
+ void Lock();
+ void Unlock();
+
+ AEGraphics::Color GetPixel(uint x, uint y);
+
+ //----------------------------------------------------------------------------//
+
+ uint width, height; // سߴ
+ AEGraphics::ColorFormat format; // ʽ
+ byte* pixels; //
+ std::size_t size; // ݳ
+
+ //----------------------------------------------------------------------------//
+
+private:
+
+ ///
+ /// ڵһ׼image dataʱṩdecoderڼdecodersмѡԡ
+ ///
+ static std::list<ImageDecoder*> ImageDecoders;
+
+ ///
+ /// дݵ
+ ///
+ AEThreading::Mutex m_Mutex;
+
+luaxport:
+
+ LUAX_DECL_FACTORY(ImageData);
+
+ LUAX_DECL_METHOD(_New);
+ LUAX_DECL_METHOD(_GetPixel);
+ LUAX_DECL_METHOD(_GetSize);
+ LUAX_DECL_METHOD(_GetWidth);
+ LUAX_DECL_METHOD(_GetHeight);
+ LUAX_DECL_METHOD(_GetPixelFormat);
+ LUAX_DECL_METHOD(_Decode);
+ LUAX_DECL_METHOD(_DecodeAsync);
+ LUAX_DECL_METHOD(_IsAvailable);
+
+};
+
+namespace_end
+namespace_end
+
+namespace AEImage = AsuraEngine::Image;
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-core/Image/ImageDecodeTask.cpp b/Source/modules/asura-core/Image/ImageDecodeTask.cpp
new file mode 100644
index 0000000..16c166e
--- /dev/null
+++ b/Source/modules/asura-core/Image/ImageDecodeTask.cpp
@@ -0,0 +1,17 @@
+#include "ImageDecodeTask.h"
+
+namespace_begin(AsuraEngine)
+namespace_begin(Image)
+
+bool ImageDecodeTask::Execute()
+{
+ return false;
+}
+
+void ImageDecodeTask::Invoke(lua_State* invokeThreaad)
+{
+
+}
+
+namespace_end
+namespace_end \ No newline at end of file
diff --git a/Source/modules/asura-core/Image/ImageDecodeTask.h b/Source/modules/asura-core/Image/ImageDecodeTask.h
new file mode 100644
index 0000000..194ac3e
--- /dev/null
+++ b/Source/modules/asura-core/Image/ImageDecodeTask.h
@@ -0,0 +1,35 @@
+#ifndef _ASURA_IMAGE_DECODE_TASK_H_
+#define _ASURA_IMAGE_DECODE_TASK_H_
+
+#include <asura-base/Threads/task.h>
+#include <asura-base/Scripting/Scripting.h>
+#include <asura-base/Classes.h>
+
+namespace_begin(AsuraEngine)
+namespace_begin(Image)
+
+class ImageDecodeTask
+ : public AEScripting::Portable<ImageDecodeTask, AEThreading::Task>
+{
+public:
+
+ ///
+ /// ִɺ󷵻trueûص
+ ///
+ bool Execute() override;
+
+ ///
+ /// ûصinvoke threadص
+ ///
+ void Invoke(lua_State* invokeThreaad) override;
+
+luaxport:
+
+ LUAX_DECL_FACTORY(ImageDecodeTask, AEThreading::Task);
+
+};
+
+namespace_end
+namespace_end
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-core/Image/ImageDecoder.h b/Source/modules/asura-core/Image/ImageDecoder.h
new file mode 100644
index 0000000..6cea8fd
--- /dev/null
+++ b/Source/modules/asura-core/Image/ImageDecoder.h
@@ -0,0 +1,33 @@
+#ifndef _ASURA_ENGINE_IMAGE_DECODER_H_
+#define _ASURA_ENGINE_IMAGE_DECODER_H_
+
+#include <asura-base/FileSystem/DataBuffer.h>
+
+#include "ImageData.h"
+
+namespace_begin(AsuraEngine)
+namespace_begin(Image)
+
+ASURA_ABSTRACT class ImageDecoder
+{
+public:
+
+ ImageDecoder() {};
+ virtual ~ImageDecoder() {};
+
+ ///
+ /// жڴǷñdecoderѹ
+ ///
+ virtual bool CanDecode(AEFileSystem::DataBuffer& input) = 0;
+
+ ///
+ /// һڴ棬һѹImage dataѹʧܷnullptr
+ ///
+ virtual void Decode(AEFileSystem::DataBuffer& input, ImageData& target) = 0;
+
+};
+
+namespace_end
+namespace_end
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-core/Image/PngDecoder.cpp b/Source/modules/asura-core/Image/PngDecoder.cpp
new file mode 100644
index 0000000..b314561
--- /dev/null
+++ b/Source/modules/asura-core/Image/PngDecoder.cpp
@@ -0,0 +1,17 @@
+#include "PngDecoder.h"
+
+namespace_begin(AsuraEngine)
+namespace_begin(Image)
+
+bool PNGDecoder::CanDecode(AEFileSystem::DataBuffer& buffer)
+{
+ return false;
+}
+
+void PNGDecoder::Decode(AEFileSystem::DataBuffer& buffer, ImageData& data)
+{
+
+}
+
+namespace_end
+namespace_end
diff --git a/Source/modules/asura-core/Image/PngDecoder.h b/Source/modules/asura-core/Image/PngDecoder.h
new file mode 100644
index 0000000..3b2a39c
--- /dev/null
+++ b/Source/modules/asura-core/Image/PngDecoder.h
@@ -0,0 +1,25 @@
+#ifndef _ASURA_ENGINE_PNGDECODER_H_
+#define _ASURA_ENGINE_PNGDECODER_H_
+
+#include "ImageDecoder.h"
+
+namespace_begin(AsuraEngine)
+namespace_begin(Image)
+
+///
+/// ʹlodepngѹpngļ
+///
+class PNGDecoder ASURA_FINAL: public ImageDecoder
+{
+public:
+
+ bool CanDecode(AEFileSystem::DataBuffer& buffer) override;
+
+ void Decode(AEFileSystem::DataBuffer& buffer, ImageData& data) override;
+
+};
+
+namespace_end
+namespace_end
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-core/Image/StbDecoder.cpp b/Source/modules/asura-core/Image/StbDecoder.cpp
new file mode 100644
index 0000000..101b148
--- /dev/null
+++ b/Source/modules/asura-core/Image/StbDecoder.cpp
@@ -0,0 +1,73 @@
+#include <asura-base/Exception.h>
+
+#include "StbDecoder.h"
+
+#define STB_IMAGE_IMPLEMENTATION
+#include <stb/stb_image.h>
+
+using namespace AEGraphics;
+
+namespace_begin(AsuraEngine)
+namespace_begin(Image)
+
+bool STBDecoder::CanDecode(FileSystem::DataBuffer& buffer)
+{
+ int w = 0;
+ int h = 0;
+ int comp = 0;
+
+ int status = stbi_info_from_memory((const stbi_uc*)buffer.GetData(), buffer.GetSize(), &w, &h, &comp);
+
+ return status == 1 && w > 0 && h > 0;
+}
+
+void STBDecoder::Decode(FileSystem::DataBuffer& db, ImageData& imageData)
+{
+ const stbi_uc *buffer = (const stbi_uc *)db.GetData();
+ // databufferݳ
+ int bufferlen = db.GetSize();
+
+ int width, height;
+ int comp = 0;
+ byte* data = nullptr;
+ ColorFormat format = COLOR_FORMAT_UNKNOWN;
+ std::size_t size = 0;
+
+ if (stbi_is_hdr_from_memory(buffer, bufferlen))
+ {
+ // 4channelfloat
+ data = (byte*)stbi_loadf_from_memory(buffer, bufferlen, &width, &height, &comp, STBI_rgb_alpha);
+ format = COLOR_FORMAT_RGBA32F;
+ size = width * height * 4 * sizeof(float);
+ }
+ else
+ {
+ data = (byte*)stbi_load_from_memory(buffer, bufferlen, &width, &height, &comp, STBI_rgb_alpha);
+ format = COLOR_FORMAT_RGBA8;
+ size = width * height * 4;
+ }
+ if (data)
+ {
+ imageData.Lock();
+
+ if (imageData.pixels)
+ free(imageData.pixels);
+ imageData.pixels = (byte*)data;
+ imageData.format = format;
+ imageData.width = width;
+ imageData.height = height;
+ imageData.size = size;
+
+ imageData.Unlock();
+ }
+ else
+ {
+ const char *err = stbi_failure_reason();
+ if (err == nullptr)
+ err = "unknown error";
+ throw Exception("Could not decode image with stb_image (%s).", err);
+ }
+}
+
+namespace_end
+namespace_end \ No newline at end of file
diff --git a/Source/modules/asura-core/Image/StbDecoder.h b/Source/modules/asura-core/Image/StbDecoder.h
new file mode 100644
index 0000000..23e8c38
--- /dev/null
+++ b/Source/modules/asura-core/Image/StbDecoder.h
@@ -0,0 +1,26 @@
+#ifndef _ASURA_ENGINE_STBDECODER_H_
+#define _ASURA_ENGINE_STBDECODER_H_
+
+#include "ImageDecoder.h"
+
+namespace_begin(AsuraEngine)
+namespace_begin(Image)
+
+///
+/// ʹstb_imageѹJPEGTGABMPļ
+///
+class STBDecoder ASURA_FINAL
+ : public ImageDecoder
+{
+public:
+
+ bool CanDecode(AEFileSystem::DataBuffer& buffer) override;
+
+ void Decode(AEFileSystem::DataBuffer& buffer, ImageData& data) override;
+
+};
+
+namespace_end
+namespace_end
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-core/Image/binding/_image_data.cpp b/Source/modules/asura-core/Image/binding/_image_data.cpp
new file mode 100644
index 0000000..375f854
--- /dev/null
+++ b/Source/modules/asura-core/Image/binding/_image_data.cpp
@@ -0,0 +1,108 @@
+#include <asura-base/Threads/Thread.h>
+#include <asura-base/FileSystem/DataBuffer.h>
+
+#include "../ImageData.h"
+
+using namespace std;
+using namespace AEThreading;
+using namespace AEFileSystem;
+
+namespace_begin(AsuraEngine)
+namespace_begin(Image)
+LUAX_REGISTRY(ImageData)
+ {
+ LUAX_REGISTER_METHODS(state,
+ { "New", _New },
+ { "GetPixel", _GetPixel },
+ { "GetSize", _GetSize },
+ { "GetWidth", _GetWidth },
+ { "GetHeight", _GetHeight },
+ { "GetPixelFormat", _GetPixelFormat },
+ { "Decode", _Decode },
+ { "DecodeAsync", _DecodeAsync },
+ { "IsAvailable", _IsAvailable }
+ );
+ }
+
+ LUAX_POSTPROCESS(ImageData)
+ {
+
+ }
+
+ // ImageData.New()
+ LUAX_IMPL_METHOD(ImageData, _New)
+ {
+ LUAX_STATE(L);
+
+ return 0;
+ }
+
+ // imagedata:GetPixel()
+ LUAX_IMPL_METHOD(ImageData, _GetPixel)
+ {
+ LUAX_PREPARE(L, ImageData);
+
+ return 0;
+ }
+
+ // imagedata:GetSize()
+ LUAX_IMPL_METHOD(ImageData, _GetSize)
+ {
+ LUAX_PREPARE(L, ImageData);
+
+ return 0;
+ }
+
+ // imagedata:GetWidth()
+ LUAX_IMPL_METHOD(ImageData, _GetWidth)
+ {
+ LUAX_PREPARE(L, ImageData);
+
+ return 0;
+ }
+
+ // imagedata:GetHeight()
+ LUAX_IMPL_METHOD(ImageData, _GetHeight)
+ {
+ LUAX_PREPARE(L, ImageData);
+
+ return 0;
+ }
+
+ // imagedata:GetPixelFormat()
+ LUAX_IMPL_METHOD(ImageData, _GetPixelFormat)
+ {
+ LUAX_PREPARE(L, ImageData);
+
+ return 0;
+ }
+
+ // imagedata:Decode()
+ LUAX_IMPL_METHOD(ImageData, _Decode)
+ {
+ LUAX_PREPARE(L, ImageData);
+
+ return 0;
+ }
+
+ // imagedata:DecodeAsync(thread, databuffer, callback)
+ LUAX_IMPL_METHOD(ImageData, _DecodeAsync)
+ {
+ LUAX_PREPARE(L, ImageData);
+
+ Thread* thread = state.CheckUserdata<Thread>(2);
+ DataBuffer* buffer = state.CheckUserdata<DataBuffer>(3);
+
+ return 0;
+ }
+
+ // imagedata:IsAvailable()
+ LUAX_IMPL_METHOD(ImageData, _IsAvailable)
+ {
+ LUAX_PREPARE(L, ImageData);
+
+ return 0;
+ }
+
+ }
+}
diff --git a/Source/modules/asura-core/Image/binding/_image_decode_task.cpp b/Source/modules/asura-core/Image/binding/_image_decode_task.cpp
new file mode 100644
index 0000000..3c8ed4b
--- /dev/null
+++ b/Source/modules/asura-core/Image/binding/_image_decode_task.cpp
@@ -0,0 +1,19 @@
+#include "../ImageDecodeTask.h"
+
+using namespace std;
+
+namespace_begin(AsuraEngine)
+namespace_begin(Image)
+
+LUAX_REGISTRY(ImageDecodeTask)
+{
+
+}
+
+LUAX_POSTPROCESS(ImageDecodeTask)
+{
+
+}
+
+}
+}
diff --git a/Source/modules/asura-core/Input/Button.h b/Source/modules/asura-core/Input/Button.h
new file mode 100644
index 0000000..528063d
--- /dev/null
+++ b/Source/modules/asura-core/Input/Button.h
@@ -0,0 +1,31 @@
+#ifndef __BUTTON_H__
+#define __BUTTON_H__
+
+#include <asura-base/Classes.h>
+
+namespace_begin(AsuraEngine)
+namespace_begin(Input)
+
+/// keyboard button \ mouse button \ joystick button
+class Button
+{
+public:
+ inline Button(int key, bool state) :
+ key(key),
+ state(state)
+ {
+ }
+
+ inline int GetKey(void) const { return this->key; }
+ inline bool GetState(void) const { return this->state; }
+
+private:
+ int key;
+ bool state;
+
+};
+
+namespace_end
+namespace_end
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-core/Input/ClipBoard.cpp b/Source/modules/asura-core/Input/ClipBoard.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-core/Input/ClipBoard.cpp
diff --git a/Source/modules/asura-core/Input/ClipBoard.h b/Source/modules/asura-core/Input/ClipBoard.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-core/Input/ClipBoard.h
diff --git a/Source/modules/asura-core/Input/InputAxis.cpp b/Source/modules/asura-core/Input/InputAxis.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-core/Input/InputAxis.cpp
diff --git a/Source/modules/asura-core/Input/InputAxis.h b/Source/modules/asura-core/Input/InputAxis.h
new file mode 100644
index 0000000..9f721d7
--- /dev/null
+++ b/Source/modules/asura-core/Input/InputAxis.h
@@ -0,0 +1,15 @@
+#ifndef _ASURA_ENGINE_INPUT_AXIS_H_
+#define _ASURA_ENGINE_INPUT_AXIS_H_
+
+#include <asura-base/Classes.h>
+
+namespace_begin(AsuraEngine)
+namespace_begin(Input)
+
+class InputAxis {};
+
+
+namespace_end
+namespace_end
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-core/Input/InputDevice.cpp b/Source/modules/asura-core/Input/InputDevice.cpp
new file mode 100644
index 0000000..0c9c42f
--- /dev/null
+++ b/Source/modules/asura-core/Input/InputDevice.cpp
@@ -0,0 +1,10 @@
+#include "InputDevice.h"
+
+namespace_begin(AsuraEngine)
+namespace_begin(Input)
+
+
+
+
+namespace_end
+namespace_end \ No newline at end of file
diff --git a/Source/modules/asura-core/Input/InputDevice.h b/Source/modules/asura-core/Input/InputDevice.h
new file mode 100644
index 0000000..2b3ff9b
--- /dev/null
+++ b/Source/modules/asura-core/Input/InputDevice.h
@@ -0,0 +1,82 @@
+#ifndef _ASURA_ENGINE_INPUT_BASE_H_
+#define _ASURA_ENGINE_INPUT_BASE_H_
+
+#include <asura-base/Math/Vector2.hpp>
+#include <asura-base/Scripting/Scripting.h>
+#include <asura-base/Singleton.hpp>
+
+#include <windows.h>
+
+#include "../CoreConfig.h"
+
+#include "KeyboardState.h"
+#include "MouseState.h"
+#include "JoystickState.h"
+
+namespace_begin(AsuraEngine)
+namespace_begin(Input)
+
+class InputDevice ASURA_FINAL
+{
+public:
+
+ InputDevice();
+ ~InputDevice();
+
+#if ASURA_EDITOR
+
+ bool Open(HWND window);
+ void Close();
+
+ bool ToggleFullscreen(bool fullscreen, HWND window);
+
+ bool Process(bool discard);
+ LRESULT OnKey(HWND window, UINT message, WPARAM wParam, LPARAM lParam);
+ LRESULT OnInput(HWND window, UINT message, WPARAM wParam, LPARAM lParam);
+ LRESULT OnDeviceChange(LPCWSTR name, bool add);
+
+ static bool ConvertPositionToClientAreaCoord(HWND activeWindow, POINT position, AEMath::Vector2f& newPos);
+
+#elif ASURA_RUNNER
+
+ bool Open();
+ void Close();
+
+#endif
+
+ bool Activate(bool active);
+
+ bool GetJoystickNames(std::vector<std::string> &names);
+
+protected:
+
+ bool UpdateState();
+
+ MouseState m_Mouse;
+ KeyboardState m_Keyboard;
+ JoystickState m_Joysticks;
+
+private:
+
+ bool UpdateMousePosition();
+
+};
+
+extern InputDevice g_InputDevice;
+
+#if ASURA_EDITOR
+
+bool ConvertPositionToClientAreaCoord();
+
+#elif ASURA_RUNNER
+
+bool ConvertPositionToClientAreaCoord();
+
+#endif
+
+namespace_end
+namespace_end
+
+namespace AEInput = AsuraEngine::Input;
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-core/Input/InputEvent.cpp b/Source/modules/asura-core/Input/InputEvent.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-core/Input/InputEvent.cpp
diff --git a/Source/modules/asura-core/Input/InputEvent.h b/Source/modules/asura-core/Input/InputEvent.h
new file mode 100644
index 0000000..c643b75
--- /dev/null
+++ b/Source/modules/asura-core/Input/InputEvent.h
@@ -0,0 +1,55 @@
+#ifndef _ASURA_ENGINE_INPUT_EVENT_H_
+#define _ASURA_ENGINE_INPUT_EVENT_H_
+
+#include <asura-base/Configure.h>
+#include <asura-base/Classes.h>
+#include <asura-base/Math/Vector2.hpp>
+
+#include <windows.h>
+#include <vector>
+
+namespace_begin(AsuraEngine)
+namespace_begin(Input)
+
+// еĿͻ¼̡ػ桢
+struct InputEvent
+{
+ InputEvent();
+ ~InputEvent();
+
+#if ASURA_EDITOR
+
+ bool Open(HWND window);
+ void Close(void);
+
+ bool GetJoystickNames(std::vector<std::string> &names);
+
+ bool Activate(bool active);
+ bool ToggleFullscreen(bool fullscreen, HWND window);
+
+ bool Process(bool discard);
+ LRESULT OnKey(HWND window, UINT message, WPARAM wParam, LPARAM lParam);
+ LRESULT OnInput(HWND window, UINT message, WPARAM wParam, LPARAM lParam);
+ LRESULT OnDeviceChange(LPCWSTR name, bool add);
+
+ static bool ConvertPositionToClientAreaCoord(HWND activeWindow, POINT position, AEMath::Vector2f& newPos);
+
+#elif ASURA_RUNNER
+
+ bool Open();
+
+#endif
+
+ enum
+ {
+
+ };
+
+};
+
+//InputEvent ConvertInputEvent();
+
+namespace_end
+namespace_end
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-core/Input/InputManager.cpp b/Source/modules/asura-core/Input/InputManager.cpp
new file mode 100644
index 0000000..cec1b36
--- /dev/null
+++ b/Source/modules/asura-core/Input/InputManager.cpp
@@ -0,0 +1,140 @@
+#include "InputManager.h"
+
+namespace_begin(AsuraEngine)
+namespace_begin(Input)
+
+InputManager::InputManager()
+{
+}
+
+InputManager::~InputManager()
+{
+}
+
+void InputManager::Reset()
+{
+}
+
+bool InputManager::GetButton(const std::string& name)
+{
+ return 0;
+}
+
+bool InputManager::GetButtonDown(const std::string& name)
+{
+ return 0;
+}
+
+bool InputManager::GetButtonUp(const std::string& name)
+{
+ return 0;
+}
+
+bool InputManager::HasAxisOrButton(const std::string& name)
+{
+ return 0;
+}
+
+float InputManager::GetAxis(const std::string& name)
+{
+ return 0;
+}
+
+float InputManager::GetAxisRaw(const std::string& name)
+{
+ return 0;
+}
+
+bool InputManager::GetMouseButton(int mouseBut)
+{
+ return 0;
+}
+
+bool InputManager::GetMouseButtonState(int mouseBut)
+{
+ return 0;
+}
+
+bool InputManager::GetMouseButtonDown(int mouseBut)
+{
+ return 0;
+}
+
+bool InputManager::GetMouseButtonUp(int mouseBut)
+{
+ return 0;
+}
+
+
+bool InputManager::GetKey(int key)
+{
+ return 0;
+}
+
+bool InputManager::GetKeyDown(int key)
+{
+ return 0;
+}
+
+bool InputManager::GetKeyUp(int key)
+{
+ return 0;
+}
+
+
+const AEMath::Vector2f& InputManager::GetMouseDelta()
+{
+ return m_MouseDelta;
+}
+
+const AEMath::Vector2f& InputManager::GetMousePosition()
+{
+ return m_MousePos;
+}
+
+
+float InputManager::GetJoystickPosition()
+{
+ return 0;
+}
+
+void InputManager::setJoystickPosition()
+{
+}
+
+
+void InputManager::SetKeyState(int key, bool state)
+{
+ // This ignores keyRepeats (multiple keydown without a keyup event between)
+ if (state && !m_CurrentKeyState[key])
+ m_ThisFrameKeyDown[key] = true;
+ if (!state && m_CurrentKeyState[key])
+ m_ThisFrameKeyUp[key] = true;
+
+ m_CurrentKeyState[key] = state;
+}
+
+void InputManager::SetMouseDelta(const AEMath::Vector2f& delta)
+{
+}
+
+void InputManager::SetMousePosition(const AEMath::Vector2f& pos)
+{
+}
+
+void InputManager::SetMouseButton(int button, bool enabled)
+{
+}
+
+
+void InputManager::ProcessInput()
+{
+}
+
+void InputManager::SendInputEvents()
+{
+}
+
+
+namespace_end
+namespace_end \ No newline at end of file
diff --git a/Source/modules/asura-core/Input/InputManager.h b/Source/modules/asura-core/Input/InputManager.h
new file mode 100644
index 0000000..3c44745
--- /dev/null
+++ b/Source/modules/asura-core/Input/InputManager.h
@@ -0,0 +1,352 @@
+#ifndef _ASURA_INPUT_MAMANGER_H_
+#define _ASURA_INPUT_MAMANGER_H_
+
+#include <asura-base/Math/Vector2.hpp>
+#include <asura-base/Scripting/Scripting.h>
+#include <asura-base/Singleton.hpp>
+#include <asura-base/Classes.h>
+#include <asura-base/Utilities/dynamic_bitset.h>
+
+#include <string>
+#include <vector>
+
+#include "InputAxis.h"
+
+namespace_begin(AsuraEngine)
+namespace_begin(Input)
+
+class InputManager : public Singleton<InputManager>
+{
+public:
+
+ InputManager();
+ ~InputManager();
+
+ void Reset();
+
+ bool GetButton(const std::string& name);
+ bool GetButtonDown(const std::string& name);
+ bool GetButtonUp(const std::string& name);
+ bool HasAxisOrButton(const std::string& name);
+ float GetAxis(const std::string& name);
+ float GetAxisRaw(const std::string& name);
+
+ bool GetMouseButton(int mouseBut);
+ bool GetMouseButtonState(int mouseBut);
+ bool GetMouseButtonDown(int mouseBut);
+ bool GetMouseButtonUp(int mouseBut);
+
+ bool GetKey(int key);
+ bool GetKeyDown(int key);
+ bool GetKeyUp(int key);
+
+ const AEMath::Vector2f& GetMouseDelta();
+ const AEMath::Vector2f& GetMousePosition();
+
+ float GetJoystickPosition();
+ void setJoystickPosition();
+
+ void SetKeyState(int key, bool state);
+ void SetMouseDelta(const AEMath::Vector2f& delta);
+ void SetMousePosition(const AEMath::Vector2f& pos);
+ void SetMouseButton(int button, bool enabled);
+
+ void ProcessInput();
+ void SendInputEvents();
+
+private:
+
+ dynamic_bitset m_CurrentKeyState;
+ dynamic_bitset m_ThisFrameKeyDown;
+ dynamic_bitset m_ThisFrameKeyUp;
+
+ std::vector<InputAxis> m_Axis;
+
+ AEMath::Vector2f m_MouseDelta;
+ AEMath::Vector2f m_MousePos;
+
+ bool m_MousePresent;
+
+ std::vector<std::vector<float>> m_JoystickPos;
+
+ std::string m_InputString;
+ std::string m_CompositionString;
+
+ AEMath::Vector2f m_TextFieldCursorPos;
+ bool m_TextFieldInput;
+
+ bool m_EatKeyPressOnTextFieldFocus;
+ int m_IMECompositionMode;
+ bool m_IMEIsSelected;
+
+ int m_LastJoyNum, m_LastJoyAxis;
+ bool m_ShouldQuit;
+ bool m_SimulateMouseWithTouches;
+
+};
+
+// keyboard keys
+enum {
+ /* The keyboard syms have been cleverly chosen to map to ASCII */
+ SDLK_UNKNOWN = 0,
+ SDLK_FIRST = 0,
+ SDLK_BACKSPACE = 8,
+ SDLK_TAB = 9,
+ SDLK_CLEAR = 12,
+ SDLK_RETURN = 13,
+ SDLK_PAUSE = 19,
+ SDLK_ESCAPE = 27,
+ SDLK_SPACE = 32,
+ SDLK_EXCLAIM = 33,
+ SDLK_QUOTEDBL = 34,
+ SDLK_HASH = 35,
+ SDLK_DOLLAR = 36,
+ SDLK_AMPERSAND = 38,
+ SDLK_QUOTE = 39,
+ SDLK_LEFTPAREN = 40,
+ SDLK_RIGHTPAREN = 41,
+ SDLK_ASTERISK = 42,
+ SDLK_PLUS = 43,
+ SDLK_COMMA = 44,
+ SDLK_MINUS = 45,
+ SDLK_PERIOD = 46,
+ SDLK_SLASH = 47,
+ SDLK_0 = 48,
+ SDLK_1 = 49,
+ SDLK_2 = 50,
+ SDLK_3 = 51,
+ SDLK_4 = 52,
+ SDLK_5 = 53,
+ SDLK_6 = 54,
+ SDLK_7 = 55,
+ SDLK_8 = 56,
+ SDLK_9 = 57,
+ SDLK_COLON = 58,
+ SDLK_SEMICOLON = 59,
+ SDLK_LESS = 60,
+ SDLK_EQUALS = 61,
+ SDLK_GREATER = 62,
+ SDLK_QUESTION = 63,
+ SDLK_AT = 64,
+ /*
+ Skip uppercase letters
+ */
+ SDLK_LEFTBRACKET = 91,
+ SDLK_BACKSLASH = 92,
+ SDLK_RIGHTBRACKET = 93,
+ SDLK_CARET = 94,
+ SDLK_UNDERSCORE = 95,
+ SDLK_BACKQUOTE = 96,
+ SDLK_a = 97,
+ SDLK_b = 98,
+ SDLK_c = 99,
+ SDLK_d = 100,
+ SDLK_e = 101,
+ SDLK_f = 102,
+ SDLK_g = 103,
+ SDLK_h = 104,
+ SDLK_i = 105,
+ SDLK_j = 106,
+ SDLK_k = 107,
+ SDLK_l = 108,
+ SDLK_m = 109,
+ SDLK_n = 110,
+ SDLK_o = 111,
+ SDLK_p = 112,
+ SDLK_q = 113,
+ SDLK_r = 114,
+ SDLK_s = 115,
+ SDLK_t = 116,
+ SDLK_u = 117,
+ SDLK_v = 118,
+ SDLK_w = 119,
+ SDLK_x = 120,
+ SDLK_y = 121,
+ SDLK_z = 122,
+ SDLK_DELETE = 127,
+ /* End of ASCII mapped keysyms */
+
+ /* International keyboard syms */
+ SDLK_WORLD_0 = 160, /* 0xA0 */
+ SDLK_WORLD_1 = 161,
+ SDLK_WORLD_2 = 162,
+ SDLK_WORLD_3 = 163,
+ SDLK_WORLD_4 = 164,
+ SDLK_WORLD_5 = 165,
+ SDLK_WORLD_6 = 166,
+ SDLK_WORLD_7 = 167,
+ SDLK_WORLD_8 = 168,
+ SDLK_WORLD_9 = 169,
+ SDLK_WORLD_10 = 170,
+ SDLK_WORLD_11 = 171,
+ SDLK_WORLD_12 = 172,
+ SDLK_WORLD_13 = 173,
+ SDLK_WORLD_14 = 174,
+ SDLK_WORLD_15 = 175,
+ SDLK_WORLD_16 = 176,
+ SDLK_WORLD_17 = 177,
+ SDLK_WORLD_18 = 178,
+ SDLK_WORLD_19 = 179,
+ SDLK_WORLD_20 = 180,
+ SDLK_WORLD_21 = 181,
+ SDLK_WORLD_22 = 182,
+ SDLK_WORLD_23 = 183,
+ SDLK_WORLD_24 = 184,
+ SDLK_WORLD_25 = 185,
+ SDLK_WORLD_26 = 186,
+ SDLK_WORLD_27 = 187,
+ SDLK_WORLD_28 = 188,
+ SDLK_WORLD_29 = 189,
+ SDLK_WORLD_30 = 190,
+ SDLK_WORLD_31 = 191,
+ SDLK_WORLD_32 = 192,
+ SDLK_WORLD_33 = 193,
+ SDLK_WORLD_34 = 194,
+ SDLK_WORLD_35 = 195,
+ SDLK_WORLD_36 = 196,
+ SDLK_WORLD_37 = 197,
+ SDLK_WORLD_38 = 198,
+ SDLK_WORLD_39 = 199,
+ SDLK_WORLD_40 = 200,
+ SDLK_WORLD_41 = 201,
+ SDLK_WORLD_42 = 202,
+ SDLK_WORLD_43 = 203,
+ SDLK_WORLD_44 = 204,
+ SDLK_WORLD_45 = 205,
+ SDLK_WORLD_46 = 206,
+ SDLK_WORLD_47 = 207,
+ SDLK_WORLD_48 = 208,
+ SDLK_WORLD_49 = 209,
+ SDLK_WORLD_50 = 210,
+ SDLK_WORLD_51 = 211,
+ SDLK_WORLD_52 = 212,
+ SDLK_WORLD_53 = 213,
+ SDLK_WORLD_54 = 214,
+ SDLK_WORLD_55 = 215,
+ SDLK_WORLD_56 = 216,
+ SDLK_WORLD_57 = 217,
+ SDLK_WORLD_58 = 218,
+ SDLK_WORLD_59 = 219,
+ SDLK_WORLD_60 = 220,
+ SDLK_WORLD_61 = 221,
+ SDLK_WORLD_62 = 222,
+ SDLK_WORLD_63 = 223,
+ SDLK_WORLD_64 = 224,
+ SDLK_WORLD_65 = 225,
+ SDLK_WORLD_66 = 226,
+ SDLK_WORLD_67 = 227,
+ SDLK_WORLD_68 = 228,
+ SDLK_WORLD_69 = 229,
+ SDLK_WORLD_70 = 230,
+ SDLK_WORLD_71 = 231,
+ SDLK_WORLD_72 = 232,
+ SDLK_WORLD_73 = 233,
+ SDLK_WORLD_74 = 234,
+ SDLK_WORLD_75 = 235,
+ SDLK_WORLD_76 = 236,
+ SDLK_WORLD_77 = 237,
+ SDLK_WORLD_78 = 238,
+ SDLK_WORLD_79 = 239,
+ SDLK_WORLD_80 = 240,
+ SDLK_WORLD_81 = 241,
+ SDLK_WORLD_82 = 242,
+ SDLK_WORLD_83 = 243,
+ SDLK_WORLD_84 = 244,
+ SDLK_WORLD_85 = 245,
+ SDLK_WORLD_86 = 246,
+ SDLK_WORLD_87 = 247,
+ SDLK_WORLD_88 = 248,
+ SDLK_WORLD_89 = 249,
+ SDLK_WORLD_90 = 250,
+ SDLK_WORLD_91 = 251,
+ SDLK_WORLD_92 = 252,
+ SDLK_WORLD_93 = 253,
+ SDLK_WORLD_94 = 254,
+ SDLK_WORLD_95 = 255, /* 0xFF */
+
+ /* Numeric keypad */
+ SDLK_KP0 = 256,
+ SDLK_KP1 = 257,
+ SDLK_KP2 = 258,
+ SDLK_KP3 = 259,
+ SDLK_KP4 = 260,
+ SDLK_KP5 = 261,
+ SDLK_KP6 = 262,
+ SDLK_KP7 = 263,
+ SDLK_KP8 = 264,
+ SDLK_KP9 = 265,
+ SDLK_KP_PERIOD = 266,
+ SDLK_KP_DIVIDE = 267,
+ SDLK_KP_MULTIPLY = 268,
+ SDLK_KP_MINUS = 269,
+ SDLK_KP_PLUS = 270,
+ SDLK_KP_ENTER = 271,
+ SDLK_KP_EQUALS = 272,
+
+ /* Arrows + Home/End pad */
+ SDLK_UP = 273,
+ SDLK_DOWN = 274,
+ SDLK_RIGHT = 275,
+ SDLK_LEFT = 276,
+ SDLK_INSERT = 277,
+ SDLK_HOME = 278,
+ SDLK_END = 279,
+ SDLK_PAGEUP = 280,
+ SDLK_PAGEDOWN = 281,
+
+ /* Function keys */
+ SDLK_F1 = 282,
+ SDLK_F2 = 283,
+ SDLK_F3 = 284,
+ SDLK_F4 = 285,
+ SDLK_F5 = 286,
+ SDLK_F6 = 287,
+ SDLK_F7 = 288,
+ SDLK_F8 = 289,
+ SDLK_F9 = 290,
+ SDLK_F10 = 291,
+ SDLK_F11 = 292,
+ SDLK_F12 = 293,
+ SDLK_F13 = 294,
+ SDLK_F14 = 295,
+ SDLK_F15 = 296,
+
+ /* Key state modifier keys */
+ SDLK_NUMLOCK = 300,
+ SDLK_CAPSLOCK = 301,
+ SDLK_SCROLLOCK = 302,
+ SDLK_RSHIFT = 303,
+ SDLK_LSHIFT = 304,
+ SDLK_RCTRL = 305,
+ SDLK_LCTRL = 306,
+ SDLK_RALT = 307,
+ SDLK_LALT = 308,
+ SDLK_RMETA = 309,
+ SDLK_LMETA = 310,
+ SDLK_RGUI = 309,
+ SDLK_LGUI = 310,
+ SDLK_LSUPER = 311, /* Left "Windows" key */
+ SDLK_RSUPER = 312, /* Right "Windows" key */
+ SDLK_MODE = 313, /* "Alt Gr" key */
+ SDLK_COMPOSE = 314, /* Multi-key compose key */
+
+ /* Miscellaneous function keys */
+ SDLK_HELP = 315,
+ SDLK_PRINT = 316,
+ SDLK_SYSREQ = 317,
+ SDLK_BREAK = 318,
+ SDLK_MENU = 319,
+ SDLK_POWER = 320, /* Power Macintosh power key */
+ SDLK_EURO = 321, /* Some european keyboards */
+ SDLK_UNDO = 322, /* Atari keyboard has Undo */
+
+ /* Add any other keys here */
+
+ SDLK_LAST
+};
+
+
+namespace_end
+namespace_end
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-core/Input/JoystickState.h b/Source/modules/asura-core/Input/JoystickState.h
new file mode 100644
index 0000000..e97e235
--- /dev/null
+++ b/Source/modules/asura-core/Input/JoystickState.h
@@ -0,0 +1,16 @@
+#ifndef _ASURA_JOYSTICKSTATE_H_
+#define _ASURA_JOYSTICKSTATE_H_
+
+#include <asura-base/Classes.h>
+
+namespace_begin(AsuraEngine)
+namespace_begin(Input)
+
+class JoystickState {};
+
+
+namespace_end
+namespace_end
+
+#endif
+
diff --git a/Source/modules/asura-core/Input/KeyboardState.h b/Source/modules/asura-core/Input/KeyboardState.h
new file mode 100644
index 0000000..96d22e7
--- /dev/null
+++ b/Source/modules/asura-core/Input/KeyboardState.h
@@ -0,0 +1,37 @@
+#ifndef __KEYBOARD_STATE_H__
+#define __KEYBOARD_STATE_H__
+
+#include <vector>
+
+#include "Button.h"
+
+namespace_begin(AsuraEngine)
+namespace_begin(Input)
+
+typedef std::vector<Button> Buttons;
+
+class KeyboardState
+{
+private:
+ Buttons buttons;
+
+public:
+ inline KeyboardState(void)
+ {
+ this->buttons.reserve(256);
+ }
+
+ inline const Buttons &GetButtons(void) const { return this->buttons; }
+ inline void AddButton(int key, bool state) { this->buttons.push_back(Button(key, state)); }
+
+ void Reset(bool full)
+ {
+ this->buttons.clear();
+ }
+
+};
+
+namespace_end
+namespace_end
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-core/Input/MouseState.h b/Source/modules/asura-core/Input/MouseState.h
new file mode 100644
index 0000000..6b44070
--- /dev/null
+++ b/Source/modules/asura-core/Input/MouseState.h
@@ -0,0 +1,16 @@
+#ifndef _ASURA_MOUSESTATE_H_
+#define _ASURA_MOUSESTATE_H_
+
+#include <asura-base/Classes.h>
+
+namespace_begin(AsuraEngine)
+namespace_begin(Input)
+
+class MouseState {};
+
+
+namespace_end
+namespace_end
+
+#endif
+
diff --git a/Source/modules/asura-core/Mesh/Am2Handler.cpp b/Source/modules/asura-core/Mesh/Am2Handler.cpp
new file mode 100644
index 0000000..115797f
--- /dev/null
+++ b/Source/modules/asura-core/Mesh/Am2Handler.cpp
@@ -0,0 +1,34 @@
+#include "Am2Handler.h"
+
+namespace_begin(AsuraEngine)
+namespace_begin(Mesh)
+/*
+Asuramesh2DʽΪ.am2ʽ¡
+ͷ11ֽڱһAsuraMesh2Dļ
+ASURAMESH2D
+v position
+t tangent
+n normal
+[c color]
+[u texcoord0]
+[u texcoord1]
+[u texcoord2]
+[u texcoord3]
+
+f surface
+
+
+ASURAMESH2D
+p 0
+v 0, 0
+t -0.2, 0.45
+n -0.3, 0.6
+p 1
+
+f 0, 1, 2
+*/
+
+
+
+namespace_end
+namespace_end
diff --git a/Source/modules/asura-core/Mesh/Am2Handler.h b/Source/modules/asura-core/Mesh/Am2Handler.h
new file mode 100644
index 0000000..ff5dbfa
--- /dev/null
+++ b/Source/modules/asura-core/Mesh/Am2Handler.h
@@ -0,0 +1,30 @@
+#ifndef _ASURA_MESH2D_AM2_HANDLER_H__
+#define _ASURA_MESH2D_AM2_HANDLER_H__
+
+#include "Mesh2dHandler.h"
+
+namespace_begin(AsuraEngine)
+namespace_begin(Mesh)
+
+///
+/// Asura Mesh Format handler͹Asura.am2ʽmeshļ
+///
+class AM2Handler ASURA_FINAL : public Mesh2DHandler
+{
+public:
+
+ AM2Handler();
+ ~AM2Handler();
+
+ bool CanDecode(AEFileSystem::DataBuffer& input) override;
+
+ void Decode(AEFileSystem::DataBuffer& input, Mesh2DData& target) override;
+
+ void Encode(Mesh2DData& input, AEFileSystem::DataBuffer& target) override;
+
+};
+
+namespace_end
+namespace_end
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-core/Mesh/Mesh2DData.cpp b/Source/modules/asura-core/Mesh/Mesh2DData.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-core/Mesh/Mesh2DData.cpp
diff --git a/Source/modules/asura-core/Mesh/Mesh2DData.h b/Source/modules/asura-core/Mesh/Mesh2DData.h
new file mode 100644
index 0000000..3e30a06
--- /dev/null
+++ b/Source/modules/asura-core/Mesh/Mesh2DData.h
@@ -0,0 +1,78 @@
+#ifndef _ASURA_MESH2D_DATA_H__
+#define _ASURA_MESH2D_DATA_H__
+
+// cpp
+#include <vector>
+
+// asura modules
+#include <asura-base/Scripting/Scripting.h>
+#include <asura-base/Math/Vector2.hpp>
+#include <asura-base/FileSystem/DecodedData.h>
+
+// module
+#include "../Graphics/Color.h"
+#include "../Graphics/GPUBuffer.h"
+
+namespace_begin(AsuraEngine)
+namespace_begin(Mesh)
+
+///
+/// Mesh2DĶݣindexʹáAsura 2D mesh֧4UVһϡ
+///
+struct Vertex
+{
+ AEMath::Vector2f position; ///<
+ AEGraphics::Color color; ///< ɫ
+ AEMath::Vector2f texCoord[4]; ///< UVs
+};
+
+///
+/// meshĶݺ
+///
+class Mesh2DData
+ : AEFileSystem::DecodedData
+ , AEScripting::Portable<Mesh2DData>
+{
+public:
+
+ enum Mesh2DComponent
+ {
+ MESH2D_COMPONENT_POSITION,
+ MESH2D_COMPONENT_COLOR,
+ MESH2D_COMPONENT_TEXCOORD0,
+ MESH2D_COMPONENT_TEXCOORD1,
+ MESH2D_COMPONENT_TEXCOORD2,
+ MESH2D_COMPONENT_TEXCOORD3,
+ };
+
+ void Decode(AEFileSystem::DataBuffer& buffer) override;
+
+private:
+
+ LUAX_DECL_FACTORY(Mesh2DData);
+
+ LUAX_DECL_ENUM(Mesh2DComponent, 1);
+
+ LUAX_DECL_METHOD(_GetVertices);
+ LUAX_DECL_METHOD(_GetVertex);
+
+ ///
+ /// meshж㡣
+ ///
+ std::vector<Vertex*> m_Vertices;
+
+ ///
+ /// ebo
+ ///
+ std::vector<int> m_Indices;
+
+ int m_Components;
+
+};
+
+namespace_end
+namespace_end
+
+namespace AEMesh = AsuraEngine::Mesh;
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-core/Mesh/Mesh2DHandler.cpp b/Source/modules/asura-core/Mesh/Mesh2DHandler.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-core/Mesh/Mesh2DHandler.cpp
diff --git a/Source/modules/asura-core/Mesh/Mesh2DHandler.h b/Source/modules/asura-core/Mesh/Mesh2DHandler.h
new file mode 100644
index 0000000..9ddb724
--- /dev/null
+++ b/Source/modules/asura-core/Mesh/Mesh2DHandler.h
@@ -0,0 +1,32 @@
+#ifndef _ASURA_MESH2D_HANDLER_H__
+#define _ASURA_MESH2D_HANDLER_H__
+
+#include <asura-base/FileSystem/DataBuffer.h>
+#include <asura-base/Type.h>
+
+#include "Mesh2dData.h"
+
+namespace_begin(AsuraEngine)
+namespace_begin(Mesh)
+
+///
+/// ͱmesh
+///
+ASURA_ABSTRACT class Mesh2DHandler
+{
+public:
+ Mesh2DHandler() {};
+ virtual ~Mesh2DHandler() {};
+
+ virtual bool CanDecode(AEFileSystem::DataBuffer& input) = 0;
+
+ virtual void Decode(AEFileSystem::DataBuffer& input, Mesh2DData& target) = 0;
+
+ virtual void Encode(Mesh2DData& input, AEFileSystem::DataBuffer& target) = 0;
+
+};
+
+namespace_end
+namespace_end
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-core/Mesh/ObjHandler.cpp b/Source/modules/asura-core/Mesh/ObjHandler.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-core/Mesh/ObjHandler.cpp
diff --git a/Source/modules/asura-core/Mesh/ObjHandler.h b/Source/modules/asura-core/Mesh/ObjHandler.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-core/Mesh/ObjHandler.h
diff --git a/Source/modules/asura-core/Profiler/GPUProfiler.cpp b/Source/modules/asura-core/Profiler/GPUProfiler.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-core/Profiler/GPUProfiler.cpp
diff --git a/Source/modules/asura-core/Profiler/GPUProfiler.h b/Source/modules/asura-core/Profiler/GPUProfiler.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-core/Profiler/GPUProfiler.h
diff --git a/Source/modules/asura-core/Profiler/Stats.cpp b/Source/modules/asura-core/Profiler/Stats.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-core/Profiler/Stats.cpp
diff --git a/Source/modules/asura-core/Profiler/Stats.h b/Source/modules/asura-core/Profiler/Stats.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-core/Profiler/Stats.h
diff --git a/Source/modules/asura-core/Threads/Channel.cpp b/Source/modules/asura-core/Threads/Channel.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-core/Threads/Channel.cpp
diff --git a/Source/modules/asura-core/Threads/Channel.h b/Source/modules/asura-core/Threads/Channel.h
new file mode 100644
index 0000000..901564f
--- /dev/null
+++ b/Source/modules/asura-core/Threads/Channel.h
@@ -0,0 +1,18 @@
+#ifndef _ASURA_THREAD_CHANNEL_H_
+#define _ASURA_THREAD_CHANNEL_H_
+
+#include <asura-base/Scripting/Scripting.h>
+#include <asura-base/Classes.h>
+
+namespace_begin(AsuraEngine)
+namespace_begin(Threads)
+
+class Channel
+{
+
+};
+
+namespace_end
+namespace_end
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-core/Threads/ThreadEx.cpp b/Source/modules/asura-core/Threads/ThreadEx.cpp
new file mode 100644
index 0000000..cec5ba7
--- /dev/null
+++ b/Source/modules/asura-core/Threads/ThreadEx.cpp
@@ -0,0 +1,20 @@
+#include <asura-base/Classes.h>
+
+#include "ThreadEx.h"
+
+namespace_begin(AsuraEngine)
+namespace_begin(Threads)
+
+int ThreadEx::Process()
+{
+
+ return 0;
+}
+
+void ThreadEx::RegisterModules()
+{
+
+}
+
+namespace_end
+namespace_end \ No newline at end of file
diff --git a/Source/modules/asura-core/Threads/ThreadEx.h b/Source/modules/asura-core/Threads/ThreadEx.h
new file mode 100644
index 0000000..ec597c5
--- /dev/null
+++ b/Source/modules/asura-core/Threads/ThreadEx.h
@@ -0,0 +1,45 @@
+#ifndef _ASURA_THREAD_EX_H_
+#define _ASURA_THREAD_EX_H_
+
+#include <asura-base/Scripting/Scripting.h>
+#include <asura-base/Threads/Thread.h>
+
+namespace_begin(AsuraEngine)
+namespace_begin(Threads)
+
+///
+/// ThreadExеͬͨ˶ͨݡ
+///
+class ThreadEx ASURA_FINAL
+ : public AEScripting::Portable<ThreadEx>
+ , public Threadable
+{
+public:
+
+ LUAX_DECL_FACTORY(ThreadEx);
+
+ ThreadEx();
+ ~ThreadEx();
+
+ int Process() override;
+
+private:
+
+ // ̵߳עAsuraͽӿڣעֻһֶ֮䴫ݡЩ͵Ķ
+ void RegisterModules();
+
+ ThreadImpl* m_Impl;
+
+ // ̴߳
+ Luax::LuaxVM* m_VM;
+
+luaxport:
+
+ LUAX_DECL_METHOD(_New);
+
+};
+
+namespace_end
+namespace_end
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-core/Time/Timer.cpp b/Source/modules/asura-core/Time/Timer.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-core/Time/Timer.cpp
diff --git a/Source/modules/asura-core/Time/Timer.h b/Source/modules/asura-core/Time/Timer.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-core/Time/Timer.h
diff --git a/Source/modules/asura-core/Window/Window.cpp b/Source/modules/asura-core/Window/Window.cpp
new file mode 100644
index 0000000..d75b9a7
--- /dev/null
+++ b/Source/modules/asura-core/Window/Window.cpp
@@ -0,0 +1,104 @@
+#include <asura-base/Exception.h>
+
+#include "window.h"
+
+#include "WindowImplSDL.h"
+#include "WindowImplGlew.h"
+#include "WindowImplGlut.h"
+
+namespace_begin(AsuraEngine)
+namespace_begin(Window)
+
+ Window::Window()
+ : m_Impl(nullptr)
+ {
+ }
+
+ Window::~Window()
+ {
+ if (m_Impl)
+ delete m_Impl;
+ }
+
+#define try_init_window(impl) \
+ if (!m_Impl) \
+ { \
+ m_Impl = new impl(); \
+ if (!m_Impl->Init(config)) \
+ { \
+ delete m_Impl; \
+ m_Impl = nullptr; \
+ } \
+ }
+
+ bool Window::Init(const WindowConfig& config)
+ {
+ ASSERT(!m_Impl);
+#if ASURA_WINDOW_SDL
+ try_init_window(WindowImplSDL);
+#endif
+ return m_Impl != nullptr;
+ }
+
+ void Window::Exit()
+ {
+ if (m_Impl)
+ delete m_Impl;
+ }
+
+ void Window::SetPosition(int x, int y)
+ {
+ ASSERT(m_Impl);
+ m_Impl->SetPosition(x, y);
+ }
+
+ void Window::SetTitle(const std::string& title)
+ {
+ ASSERT(m_Impl);
+ m_Impl->SetTitils(title);
+ }
+
+ void Window::Show()
+ {
+ ASSERT(m_Impl);
+ m_Impl->Show();
+ }
+
+ void Window::Hide()
+ {
+ ASSERT(m_Impl);
+ m_Impl->Hide();
+ }
+
+ void Window::SwapRenderBuffer()
+ {
+ ASSERT(m_Impl);
+ m_Impl->SwapRenderBuffer();
+ }
+
+ void Window::Clear(const AEGraphics::Color& col /*= AEGraphics::Color::Black*/)
+ {
+ ASSERT(m_Impl);
+ glClearColor(col.r, col.g, col.b, col.a);
+ }
+
+ //void Window::Clear(const Math::Recti& quad, const AEGraphics::Color& col /*= AEGraphics::Color::Black*/)
+ //{
+ // ASSERT(m_Impl);
+
+ //}
+
+ void Window::Draw(const AEGraphics::Drawable* texture, const AEGraphics::RenderState& state)
+ {
+ ASSERT(m_Impl);
+
+ }
+/*
+ void Window::Draw(const AEGraphics::Drawable* texture, const Math::Recti& quad, const AEGraphics::RenderState& state)
+ {
+ ASSERT(m_Impl);
+
+ }
+*/
+ }
+}
diff --git a/Source/modules/asura-core/Window/Window.h b/Source/modules/asura-core/Window/Window.h
new file mode 100644
index 0000000..0f2850b
--- /dev/null
+++ b/Source/modules/asura-core/Window/Window.h
@@ -0,0 +1,138 @@
+#ifndef _ASURA_ENGINE_WINDOW_H_
+#define _ASURA_ENGINE_WINDOW_H_
+
+#include <asura-base/Scripting/Scripting.h>
+#include <asura-base/Math/Vector2.hpp>
+#include <asura-base/Singleton.hpp>
+
+#include "../Graphics/Image.h"
+#include "../Graphics/RenderState.h"
+#include "../Graphics/RenderTarget.h"
+
+namespace_begin(AsuraEngine)
+namespace_begin(Window)
+
+class WindowImpl;
+
+///
+/// SDLģһЩõġ
+///
+enum WindowFlag
+{
+ WINDOW_FULLSCREEN = 1 << 1, ///< fullscreen window
+ WINDOW_OPENGL = 1 << 2, ///< window usable with OpenGL context
+ WINDOW_SHOWN = 1 << 3, ///< window is visible
+ WINDOW_HIDDEN = 1 << 4, ///< window is not visible
+ WINDOW_BORDERLESS = 1 << 5, ///< no window decoration
+ WINDOW_RESIZABLE = 1 << 6, ///< window can be resized
+ WINDOW_MINIMIZED = 1 << 7, ///< window is minimized
+ WINDOW_MAXIMIZED = 1 << 8, ///< window is maximized
+ WINDOW_INPUT_GRABBED = 1 << 9, ///< window has grabbed input focus
+ WINDOW_INPUT_FOCUS = 1 << 10, ///< window has input focus
+ WINDOW_MOUSE_FOCUS = 1 << 11, ///< window has mouse focus
+ WINDOW_ALLOW_HIGHDPI = 1 << 12, ///< window should be created in high-DPI mode if supported.
+ ///< On macOS NSHighResolutionCapable must be set true in the
+ ///< application's Info.plist for this to have any effect.
+ WINDOW_MOUSE_CAPTURE = 1 << 13, ///< window has mouse captured (unrelated to INPUT_GRABBED)
+ WINDOW_ALWAYS_ON_TOP = 1 << 14, ///< window should always be above others
+};
+
+/// Windowʼ
+struct WindowConfig
+{
+ uint width, height; ///< ߴ
+ int x, y; ///< ڳʼ
+ std::string title; ///<
+ bool vsync; ///< ֱͬ
+ AEImage::ImageData* icon; ///< ͼ
+ bool show; ///< Ƿʾ
+ int flag; ///< ڱ
+};
+
+///
+/// ϷĵڣrunnerֻҪһڡͬĿͻʵִ˽ӿڲֶעᵽlua༭
+/// ᵼ࣬޽ӵ༭ⴰϡ
+///
+class Window ASURA_FINAL
+ : public AEScripting::Portable<Window, AEGraphics::RenderTarget>
+ , public Singleton<Window>
+{
+public:
+
+ /// ϷʱĴΨһģ༭õࡣ
+ LUAX_DECL_SINGLETON(Window);
+
+ Window();
+ ~Window();
+
+ /// ڡ
+ bool Init(const WindowConfig& config);
+ void Exit();
+
+ void SetSize(uint width, uint height);
+ void SetPosition(int x, int y);
+ void SetTitle(const std::string& title);
+ void SetIcon(AEImage::ImageData* imgData);
+
+ void Show();
+ void Hide();
+
+ /// ǿ˫ĴڣҪչʾǰ̨
+ void SwapRenderBuffer();
+
+ void Clear(const AEGraphics::Color& col = AEGraphics::Color::Black) override;
+ void Clear(const Math::Recti& quad, const AEGraphics::Color& col = AEGraphics::Color::Black) override;
+
+ void Draw(const AEGraphics::Drawable* texture, const AEGraphics::RenderState& state) override;
+ void Draw(const AEGraphics::Drawable* texture, const Math::Recti& quad, const AEGraphics::RenderState& state) override;
+
+private:
+
+ WindowImpl* m_Impl;
+
+luaxport:
+
+ LUAX_DECL_ENUM(WindowFlag, 0);
+
+ LUAX_DECL_METHOD(_Init);
+ LUAX_DECL_METHOD(_Exit);
+ LUAX_DECL_METHOD(_Show);
+ LUAX_DECL_METHOD(_Hide);
+ LUAX_DECL_METHOD(_SetSize);
+ LUAX_DECL_METHOD(_SetPosition);
+ LUAX_DECL_METHOD(_SetTitle);
+ LUAX_DECL_METHOD(_SetIcon);
+ LUAX_DECL_METHOD(_SwapRenderBuffer);
+ LUAX_DECL_METHOD(_Clear);
+ LUAX_DECL_METHOD(_Draw);
+
+};
+
+using RenderWindow = Window;
+
+ASURA_ABSTRACT class WindowImpl
+{
+public:
+
+ WindowImpl() {};
+ virtual ~WindowImpl() {};
+
+ virtual bool Init(const WindowConfig& config);
+
+ virtual void SetSize(uint width, uint height) = 0;
+ virtual void SetPosition(int x, int y) = 0;
+ virtual void SetTitils(const std::string& title) = 0;
+
+ virtual void Show() = 0;
+ virtual void Hide() = 0;
+
+ virtual void SwapRenderBuffer() = 0;
+
+};
+
+namespace_end
+namespace_end
+
+namespace AEWindow = AsuraEngine::Window;
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-core/Window/WindowImplGlew.cpp b/Source/modules/asura-core/Window/WindowImplGlew.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-core/Window/WindowImplGlew.cpp
diff --git a/Source/modules/asura-core/Window/WindowImplGlew.h b/Source/modules/asura-core/Window/WindowImplGlew.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-core/Window/WindowImplGlew.h
diff --git a/Source/modules/asura-core/Window/WindowImplGlut.h b/Source/modules/asura-core/Window/WindowImplGlut.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-core/Window/WindowImplGlut.h
diff --git a/Source/modules/asura-core/Window/WindowImplSDL.cpp b/Source/modules/asura-core/Window/WindowImplSDL.cpp
new file mode 100644
index 0000000..23b2aed
--- /dev/null
+++ b/Source/modules/asura-core/Window/WindowImplSDL.cpp
@@ -0,0 +1,153 @@
+#include "../CoreConfig.h"
+
+#if ASURA_WINDOW_SDL
+
+#include <SDL2/SDL.h>
+
+#include <asura-base/Exception.h>
+
+#include "WindowImplSDL.h"
+
+using namespace AEGraphics;
+using namespace AEImage;
+
+namespace_begin(AsuraEngine)
+namespace_begin(Window)
+
+#define asura_flag_to_sdl_flag(flag, _flag, _sdl_flag) \
+if ((flag & _flag) != 0) \
+ flag |= _sdl_flag
+
+WindowImplSDL::WindowImplSDL()
+ : m_Wnd(nullptr)
+ , m_GLContext(0)
+{
+}
+
+WindowImplSDL::~WindowImplSDL()
+{
+ SDL_GL_DeleteContext(m_GLContext);
+ SDL_DestroyWindow(m_Wnd);
+ SDL_FlushEvent(SDL_WINDOWEVENT);
+}
+
+bool WindowImplSDL::Init(const WindowConfig& config)
+{
+ if (SDL_Init(SDL_INIT_VIDEO) < 0)
+ return false;
+
+ int flag = 0;
+ asura_flag_to_sdl_flag(flag, WINDOW_FULLSCREEN, SDL_WINDOW_FULLSCREEN);
+ asura_flag_to_sdl_flag(flag, WINDOW_OPENGL, SDL_WINDOW_OPENGL);
+ asura_flag_to_sdl_flag(flag, WINDOW_SHOWN, SDL_WINDOW_SHOWN);
+ asura_flag_to_sdl_flag(flag, WINDOW_HIDDEN, SDL_WINDOW_HIDDEN);
+ asura_flag_to_sdl_flag(flag, WINDOW_BORDERLESS, SDL_WINDOW_BORDERLESS);
+ asura_flag_to_sdl_flag(flag, WINDOW_RESIZABLE, SDL_WINDOW_RESIZABLE);
+ asura_flag_to_sdl_flag(flag, WINDOW_MINIMIZED, SDL_WINDOW_MINIMIZED);
+ asura_flag_to_sdl_flag(flag, WINDOW_MAXIMIZED, SDL_WINDOW_MAXIMIZED);
+ asura_flag_to_sdl_flag(flag, WINDOW_INPUT_GRABBED, SDL_WINDOW_INPUT_GRABBED);
+ asura_flag_to_sdl_flag(flag, WINDOW_INPUT_FOCUS, SDL_WINDOW_INPUT_FOCUS);
+ asura_flag_to_sdl_flag(flag, WINDOW_MOUSE_FOCUS, SDL_WINDOW_MOUSE_FOCUS);
+ asura_flag_to_sdl_flag(flag, WINDOW_ALLOW_HIGHDPI, SDL_WINDOW_ALLOW_HIGHDPI);
+ asura_flag_to_sdl_flag(flag, WINDOW_MOUSE_CAPTURE, SDL_WINDOW_MOUSE_CAPTURE);
+ asura_flag_to_sdl_flag(flag, WINDOW_ALWAYS_ON_TOP, SDL_WINDOW_ALWAYS_ON_TOP);
+
+ // Set GL window / framebuffer attributes.
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
+ SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
+ SDL_GL_SetAttribute(SDL_GL_RETAINED_BACKING, 0);
+
+ m_Wnd = SDL_CreateWindow(config.title.c_str(), config.x, config.y, config.width, config.height, flag);
+
+ if (!m_Wnd)
+ return false;
+
+ // ͼ
+ try
+ {
+ if (config.icon)
+ {
+ ImageData* img = config.icon;
+ if (img->format == COLOR_FORMAT_RGBA8)
+ {
+ SDL_Surface *surface;
+
+ img->Lock();
+
+ int w = img->width, h = img->height;
+ surface = SDL_CreateRGBSurfaceFrom(
+ img->pixels,
+ w, h,
+ 32,
+ w * 4,
+ Color32::RMASK,
+ Color32::GMASK,
+ Color32::BMASK,
+ Color32::AMASK
+ );
+
+ img->Unlock();
+
+ SDL_SetWindowIcon(m_Wnd, surface);
+ SDL_FreeSurface(surface);
+ }
+ }
+ }
+ catch (...)
+ {
+ }
+
+ m_GLContext = SDL_GL_CreateContext(m_Wnd);
+
+ if (!m_GLContext)
+ {
+ SDL_DestroyWindow(m_Wnd);
+ return false;
+ }
+
+ SDL_GL_MakeCurrent(m_Wnd, m_GLContext);
+ SDL_GL_SetSwapInterval(config.vsync ? 1 : 0);
+
+ return true;
+}
+
+void WindowImplSDL::SetSize(uint width, uint height)
+{
+ SDL_SetWindowSize(m_Wnd, width, height);
+}
+
+void WindowImplSDL::SetPosition(int x, int y)
+{
+ SDL_SetWindowPosition(m_Wnd, x, y);
+}
+
+void WindowImplSDL::SetTitils(const std::string& title)
+{
+ SDL_SetWindowTitle(m_Wnd, title.c_str());
+}
+
+void WindowImplSDL::Show()
+{
+ SDL_ShowWindow(m_Wnd);
+}
+
+void WindowImplSDL::Hide()
+{
+ SDL_HideWindow(m_Wnd);
+}
+
+void WindowImplSDL::SwapRenderBuffer()
+{
+ SDL_GL_SwapWindow(m_Wnd);
+}
+
+namespace_end
+namespace_end
+
+#endif // ASURA_WINDOW_SDL \ No newline at end of file
diff --git a/Source/modules/asura-core/Window/WindowImplSDL.h b/Source/modules/asura-core/Window/WindowImplSDL.h
new file mode 100644
index 0000000..5971351
--- /dev/null
+++ b/Source/modules/asura-core/Window/WindowImplSDL.h
@@ -0,0 +1,45 @@
+#ifndef _ASURA_WINDOW_SDL_H_
+#define _ASURA_WINDOW_SDL_H_
+
+#include "../CoreConfig.h"
+
+#if ASURA_WINDOW_SDL
+
+#include <SDL2/SDL.h>
+
+#include "Window.h"
+
+namespace_begin(AsuraEngine)
+namespace_begin(Window)
+
+class WindowImplSDL ASURA_FINAL : public WindowImpl
+{
+public:
+
+ WindowImplSDL();
+ ~WindowImplSDL();
+
+ bool Init(const WindowConfig& config);
+
+ void SetSize(uint width, uint height) override;
+ void SetPosition(int x, int y) override;
+ void SetTitils(const std::string& title) override;
+
+ void Show() override;
+ void Hide() override;
+
+ void SwapRenderBuffer() override;
+
+private:
+
+ SDL_Window* m_Wnd;
+ SDL_GLContext m_GLContext;
+
+};
+
+namespace_end
+namespace_end
+
+#endif // ASURA_WINDOW_SDL
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-core/Window/WinodwImplGlut.cpp b/Source/modules/asura-core/Window/WinodwImplGlut.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-core/Window/WinodwImplGlut.cpp
diff --git a/Source/modules/asura-core/Window/binding/_window.cpp b/Source/modules/asura-core/Window/binding/_window.cpp
new file mode 100644
index 0000000..1e14a3a
--- /dev/null
+++ b/Source/modules/asura-core/Window/binding/_window.cpp
@@ -0,0 +1,179 @@
+#include "../../Image/ImageData.h"
+
+#include "../Window.h"
+
+using namespace std;
+using namespace AEGraphics;
+using namespace AEImage;
+
+namespace_begin(AsuraEngine)
+namespace_begin(Window)
+
+ LUAX_REGISTRY(Window)
+ {
+ LUAX_REGISTER_METHODS(state,
+ { "Init", _Init },
+ { "Exit", _Exit },
+ { "Show", _Show },
+ { "Hide", _Hide },
+ { "SetSize", _SetSize },
+ { "SetPosition", _SetPosition },
+ { "SetTitle", _SetTitle },
+ { "SetIcon", _SetIcon },
+ { "SwapRenderBuffer", _SwapRenderBuffer },
+ { "Clear", _Clear },
+ { "Draw", _Draw }
+ );
+ }
+
+ LUAX_POSTPROCESS(Window)
+ {
+ LUAX_REGISTER_ENUM(state, "EWindowFlag",
+ { "FULLSCREEN", WINDOW_FULLSCREEN },
+ { "OPENGL", WINDOW_OPENGL },
+ { "SHOWN", WINDOW_SHOWN },
+ { "HIDDEN", WINDOW_HIDDEN },
+ { "BORDERLESS", WINDOW_BORDERLESS },
+ { "RESIZABLE", WINDOW_RESIZABLE },
+ { "MINIMIZED", WINDOW_MINIMIZED },
+ { "MAXIMIZED", WINDOW_MAXIMIZED },
+ { "INPUT_GRABBED", WINDOW_INPUT_GRABBED },
+ { "INPUT_FOCUS", WINDOW_INPUT_FOCUS },
+ { "MOUSE_FOCUS", WINDOW_MOUSE_FOCUS },
+ { "ALLOW_HIGHDPI", WINDOW_ALLOW_HIGHDPI },
+ { "MOUSE_CAPTURE", WINDOW_MOUSE_CAPTURE },
+ { "ALWAYS_ON_TOP", WINDOW_ALWAYS_ON_TOP }
+ );
+
+ }
+
+ // Window.Init(config_table)
+ LUAX_IMPL_METHOD(Window, _Init)
+ {
+ LUAX_PREPARE(L, Window);
+
+ WindowConfig config;
+
+ if (!state.IsType(1, LUA_TTABLE))
+ return state.ErrorType(1, "window config table");
+
+ config.width = state.GetField(1, "width", 0);
+ config.height = state.GetField(1, "height", 0);
+ config.x = state.GetField(1, "x", 0);
+ config.y = state.GetField(1, "y", 0);
+ config.flag = state.GetField(1, "flag", WINDOW_OPENGL);
+ config.title = state.GetField(1, "title", "");
+ config.vsync = state.GetField(1, "vsync", true);
+ config.show = state.GetField(1, "show", true);
+
+ // try set window icon
+ state.GetField(1, "icon");
+ if (state.IsType(1, LUA_TUSERDATA))
+ {
+ ImageData* data = state.CheckUserdata<ImageData>(-1);
+ if (data)
+ {
+ data->Lock();
+ config.icon = data;
+ Window::Get()->Init(config);
+ data->Unlock();
+ return 0;
+ }
+ }
+ else
+ state.Pop();
+
+ Window::Get()->Init(config);
+
+ return 0;
+ }
+
+ // Window.Exit()
+ LUAX_IMPL_METHOD(Window, _Exit)
+ {
+ LUAX_PREPARE(L, Window);
+ Window::Get()->Exit();
+ return 0;
+ }
+
+ // Window.Show()
+ LUAX_IMPL_METHOD(Window, _Show)
+ {
+ LUAX_PREPARE(L, Window);
+ Window::Get()->Show();
+ return 0;
+ }
+
+ // Window.Hide()
+ LUAX_IMPL_METHOD(Window, _Hide)
+ {
+ LUAX_PREPARE(L, Window);
+ Window::Get()->Hide();
+ return 0;
+ }
+
+ // Window.SetSize(w, h)
+ LUAX_IMPL_METHOD(Window, _SetSize)
+ {
+ LUAX_PREPARE(L, Window);
+ uint w = state.CheckValue<uint>(1);
+ uint h = state.CheckValue<uint>(2);
+ Window::Get()->SetSize(w, h);
+ return 0;
+ }
+
+ // Window.SetPosition(x, y)
+ LUAX_IMPL_METHOD(Window, _SetPosition)
+ {
+ LUAX_PREPARE(L, Window);
+ int x = state.CheckValue<int>(1);
+ int y = state.CheckValue<int>(2);
+ Window::Get()->SetPosition(x, y);
+ return 0;
+ }
+
+ // Window.SetTitle(title)
+ LUAX_IMPL_METHOD(Window, _SetTitle)
+ {
+ LUAX_PREPARE(L, Window);
+ std::string title = state.CheckValue<string>(1);
+ Window::Get()->SetTitle(title);
+ return 0;
+ }
+
+ // Window.SetIcon(imageData)
+ LUAX_IMPL_METHOD(Window, _SetIcon)
+ {
+ LUAX_PREPARE(L, Window);
+ ImageData* imgData = state.CheckUserdata<ImageData>(1);
+ imgData->Lock();
+ Window::Get()->SetIcon(imgData);
+ imgData->Unlock();
+ return 0;
+ }
+
+ // Window.SwapRenderBuffer()
+ LUAX_IMPL_METHOD(Window, _SwapRenderBuffer)
+ {
+ LUAX_PREPARE(L, Window);
+ Window::Get()->SwapRenderBuffer();
+ return 0;
+ }
+
+ // Window.Clear()
+ LUAX_IMPL_METHOD(Window, _Clear)
+ {
+ LUAX_PREPARE(L, Window);
+ Window::Get()->Clear();
+ return 0;
+ }
+
+ // Window.Draw()
+ LUAX_IMPL_METHOD(Window, _Draw)
+ {
+ LUAX_PREPARE(L, Window);
+ return 0;
+ }
+
+ }
+} \ No newline at end of file
diff --git a/Source/modules/asura-fmod/Audio/Source.h b/Source/modules/asura-fmod/Audio/Source.h
new file mode 100644
index 0000000..4585415
--- /dev/null
+++ b/Source/modules/asura-fmod/Audio/Source.h
@@ -0,0 +1,20 @@
+#ifndef __ASURA_FMOD_SOURCE_H__
+#define __ASURA_FMOD_SOURCE_H__
+
+namespace AsruaEngine
+{
+ namespace Audio
+ {
+
+ ///
+ /// fmod
+ ///
+ class Source
+ {
+
+ };
+
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-fmod/FMODModule.h b/Source/modules/asura-fmod/FMODModule.h
new file mode 100644
index 0000000..67b8618
--- /dev/null
+++ b/Source/modules/asura-fmod/FMODModule.h
@@ -0,0 +1,9 @@
+#ifndef __ASURA_FMOD_MODULE_H__
+#define __ASURA_FMOD_MODULE_H__
+
+namespace AsuraEngine
+{
+
+}
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-framework/compile.bat b/Source/modules/asura-framework/compile.bat
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-framework/compile.bat
diff --git a/Source/modules/asura-framework/compile.sh b/Source/modules/asura-framework/compile.sh
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-framework/compile.sh
diff --git a/Source/modules/asura-framework/main.cpp b/Source/modules/asura-framework/main.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-framework/main.cpp
diff --git a/Source/modules/asura-framework/scripts/ai/behavior_tree.lua b/Source/modules/asura-framework/scripts/ai/behavior_tree.lua
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-framework/scripts/ai/behavior_tree.lua
diff --git a/Source/modules/asura-framework/scripts/ai/state_graph.lua b/Source/modules/asura-framework/scripts/ai/state_graph.lua
new file mode 100644
index 0000000..4f563dc
--- /dev/null
+++ b/Source/modules/asura-framework/scripts/ai/state_graph.lua
@@ -0,0 +1,11 @@
+local StateGraph = AsuraEngine.Asset.Extend("StateGraph")
+
+AsuraEngine.StateGraph = StateGraph
+
+function StateGraph.Ctor(self)
+
+end
+
+function StateGraph.ToAsset()
+
+end \ No newline at end of file
diff --git a/Source/modules/asura-framework/scripts/ai/state_machine.lua b/Source/modules/asura-framework/scripts/ai/state_machine.lua
new file mode 100644
index 0000000..6dc5e14
--- /dev/null
+++ b/Source/modules/asura-framework/scripts/ai/state_machine.lua
@@ -0,0 +1,6 @@
+local StateMachine = Class()
+AsuraEngine.StateMachine = StateMachine
+
+function StateMachine.Ctor(self, stategraph)
+ self.stategraph = stategraph
+end \ No newline at end of file
diff --git a/Source/modules/asura-framework/scripts/audio/sound.lua b/Source/modules/asura-framework/scripts/audio/sound.lua
new file mode 100644
index 0000000..d7dea4f
--- /dev/null
+++ b/Source/modules/asura-framework/scripts/audio/sound.lua
@@ -0,0 +1,9 @@
+AsuraEngine.Sound = AsuraEngine.Asset.Extend("Sound")
+
+local Sound = AsuraEngine.Sound
+
+function Sound.Ctor(self)
+
+end
+
+return Sound \ No newline at end of file
diff --git a/Source/modules/asura-framework/scripts/audio/source.lua b/Source/modules/asura-framework/scripts/audio/source.lua
new file mode 100644
index 0000000..7dec511
--- /dev/null
+++ b/Source/modules/asura-framework/scripts/audio/source.lua
@@ -0,0 +1,22 @@
+-- Audio Source
+AsuraEngine.Source = AsuraEngine.Component.Extend("SoundPlayer")
+
+local Source = AsuraEngine.Source
+
+function Source.Ctor(self)
+ self.mSound = nil
+end
+
+function Source.SetSound(sound)
+ self.mSound = sound
+end
+
+function Source.GetSource()
+ return self.mSound
+end
+
+function Source.OnUpdate(dt)
+
+end
+
+return Source \ No newline at end of file
diff --git a/Source/modules/asura-framework/scripts/class.lua b/Source/modules/asura-framework/scripts/class.lua
new file mode 100644
index 0000000..6392483
--- /dev/null
+++ b/Source/modules/asura-framework/scripts/class.lua
@@ -0,0 +1,17 @@
+AsuraEngine.Class = {}
+
+local Class = AsuraEngine.Class
+Class.__index = Class
+
+function Class.Extend(base, classname)
+ local subclass = {}
+ base.__index = base
+ setmetatable(subclass, base)
+ return c
+end
+
+function Class.New(cls)
+ local obj = {}
+ setmetatable(obj, cls)
+ cls.__index = cls
+end \ No newline at end of file
diff --git a/Source/modules/asura-framework/scripts/component.lua b/Source/modules/asura-framework/scripts/component.lua
new file mode 100644
index 0000000..b560bd3
--- /dev/null
+++ b/Source/modules/asura-framework/scripts/component.lua
@@ -0,0 +1,30 @@
+AsuraEngine.Component = AsuraEngine.Class("Component")
+
+local Component = AsuraEngine.Component
+
+-- Component要显示在inspector的变量
+Component.entity = AsuraEngine.Type.Entity
+
+function Component.Extend(cname)
+ self.base(cname)
+ assert(Component.components[cname] == nil)
+
+end
+
+function Component:Ctor(entity)
+ self.entity = entity
+end
+
+function Component:OnEvent(e)
+
+end
+
+function Component:OnUpdate(ms)
+
+end
+
+function Component:OnDraw()
+
+end
+
+return Component \ No newline at end of file
diff --git a/Source/modules/asura-framework/scripts/entity.lua b/Source/modules/asura-framework/scripts/entity.lua
new file mode 100644
index 0000000..ea8e14d
--- /dev/null
+++ b/Source/modules/asura-framework/scripts/entity.lua
@@ -0,0 +1,114 @@
+--
+-- 实体,作为scene中的实体存在。Scene中唯一管理的就是实体entity,游戏里的所有component都依附于entity存在,包括camera组件。
+--
+module "AsuraEngine"
+require "transform"
+
+AsuraEngine.Entity = AsuraEngine.Asset.Extend("Entity")
+
+local Entity = AsuraEngine.Entity
+
+function Entity:Ctor()
+ self.transform = AsuraEngine.Transform.New()
+ self.subentities = {} -- Extend node entities
+end
+
+function Entity:AddChild(entity)
+ table.insert(self.child, entity)
+end
+
+function Entity:AddComponent(type, name)
+ local cname = type
+ if name == nil then
+ cname = name
+ end
+ local component = AsuraEngine.Component.GetComponent(type)
+ self.components[cname] = compoennt
+end
+
+function Entity:GetComponent(name)
+ return self.components[name]
+end
+
+function Entity:GetComponentByType(type)
+
+end
+
+function Entity:OnEnable()
+
+end
+
+function Entity:OnEvent(e)
+ if self.components == nil or type(self.components) ~= "table" then
+ AsuraEditor.LogError("")
+ return
+ end
+ for name, component in self.components do
+ if component.OnEvent ~= nil then
+ component:OnEvent(e)
+ end
+ end
+end
+
+function Entity:OnUpdate(dt)
+ for name, component in self.components do
+ if component.OnUpdate ~= nil then
+ component:OnUpdate(dt)
+ end
+ end
+end
+
+function Entity:OnRender()
+ for name, component in self.components do
+ if component.OnRender ~= nil then
+ component.OnRender()
+ end
+ end
+end
+
+function Entity:OnDisable()
+ for name, component in self.components do
+ if component.OnDisable ~= nil then
+ component.OnDisable()
+ end
+ end
+end
+
+function Entity:GetTrasform()
+ return self.transform
+end
+
+function Entity:GetPosition()
+
+end
+
+function Entity:GetScale()
+
+end
+
+function Entity:GetRotation()
+
+end
+
+function Entity:SetTrasform(transform)
+
+end
+
+function Entity:SetPosition()
+
+end
+
+function Entity:SetScale()
+
+end
+
+function Entity:SetRotation()
+
+end
+
+--写asset
+function Entity:ToAsset()
+
+end
+
+return Entity \ No newline at end of file
diff --git a/Source/modules/asura-framework/scripts/filesystem/animation_loader.lua b/Source/modules/asura-framework/scripts/filesystem/animation_loader.lua
new file mode 100644
index 0000000..9c57c43
--- /dev/null
+++ b/Source/modules/asura-framework/scripts/filesystem/animation_loader.lua
@@ -0,0 +1,10 @@
+require "AnimationManager"
+require "Animation"
+
+local loader = AsuraEngine.Loader.New("animation")
+local manager = AsuraEngine.AnimationManager
+local Animation = AsuraEngine.Animation
+
+function AnimationLoader.OnLoad(asset)
+ local animation = AsuraEngine.Class()
+end \ No newline at end of file
diff --git a/Source/modules/asura-framework/scripts/filesystem/asset.lua b/Source/modules/asura-framework/scripts/filesystem/asset.lua
new file mode 100644
index 0000000..7cf3905
--- /dev/null
+++ b/Source/modules/asura-framework/scripts/filesystem/asset.lua
@@ -0,0 +1,20 @@
+--
+-- 游戏资源类需要继承Asset类,引擎读取.asset文件寻找对应的loader加载进游戏生成对应的Asset派生类对象。对于脚本,不会
+-- 生成对应的对象,而是直接运行脚本将结果保存。
+--
+AsuraEngine.Asset = AsuraEngine.Class("Asset")
+
+local Asset = AsuraEngine.Asset
+
+function Asset.Ctor(self)
+ self.guid = nil
+end
+
+--获得资源编号
+function Asset.GetGUID(self)
+
+end
+
+function Asset.GetAssetByGUID(guid)
+
+end \ No newline at end of file
diff --git a/Source/modules/asura-framework/scripts/filesystem/entity_loader.lua b/Source/modules/asura-framework/scripts/filesystem/entity_loader.lua
new file mode 100644
index 0000000..39ae0d9
--- /dev/null
+++ b/Source/modules/asura-framework/scripts/filesystem/entity_loader.lua
@@ -0,0 +1,5 @@
+local loader = AsuraEngine.Loader.New("entity")
+
+function loader.OnLoad(asset)
+
+end \ No newline at end of file
diff --git a/Source/modules/asura-framework/scripts/filesystem/image_loader.lua b/Source/modules/asura-framework/scripts/filesystem/image_loader.lua
new file mode 100644
index 0000000..6b0bef7
--- /dev/null
+++ b/Source/modules/asura-framework/scripts/filesystem/image_loader.lua
@@ -0,0 +1,13 @@
+require "graphics.image"
+local loader = AsuraEngine.Loader.New("image")
+
+function loader.OnLoad(asset)
+ assert(asset ~= nil)
+ local path = asset.extern
+ local image = AusraEngine.Image.New(path)
+ if image == nil then
+ AsuraEngine.LogError("")
+ return
+ end
+ return image
+end
diff --git a/Source/modules/asura-framework/scripts/filesystem/loader.lua b/Source/modules/asura-framework/scripts/filesystem/loader.lua
new file mode 100644
index 0000000..e192e30
--- /dev/null
+++ b/Source/modules/asura-framework/scripts/filesystem/loader.lua
@@ -0,0 +1,12 @@
+-- Assets loaders
+AsuraEngine.Loader = {}
+local Loader = AsuraEngine.Loader
+Loader.Loaders = {}
+
+function Loader.New(type)
+ assert(Loader.Loaders[type] == nil)
+ local loader = {}
+ Loader[type] = loader
+ return loader
+end
+
diff --git a/Source/modules/asura-framework/scripts/filesystem/material_loader.lua b/Source/modules/asura-framework/scripts/filesystem/material_loader.lua
new file mode 100644
index 0000000..07ca4e9
--- /dev/null
+++ b/Source/modules/asura-framework/scripts/filesystem/material_loader.lua
@@ -0,0 +1,7 @@
+require "MaterialManager"
+
+local loader = AsuraEngine.Loader.New("material")
+
+function loader.OnLoad(asset)
+
+end \ No newline at end of file
diff --git a/Source/modules/asura-framework/scripts/filesystem/path_loader.lua b/Source/modules/asura-framework/scripts/filesystem/path_loader.lua
new file mode 100644
index 0000000..986e42c
--- /dev/null
+++ b/Source/modules/asura-framework/scripts/filesystem/path_loader.lua
@@ -0,0 +1,9 @@
+require "Path/PathManager"
+
+local loader = AsuraEngine.Loader.New("path")
+
+function loader.OnLoad(asset)
+ if asset.type ~= "path" then
+ return nil
+ end
+end \ No newline at end of file
diff --git a/Source/modules/asura-framework/scripts/filesystem/scene_loader.lua b/Source/modules/asura-framework/scripts/filesystem/scene_loader.lua
new file mode 100644
index 0000000..45731f8
--- /dev/null
+++ b/Source/modules/asura-framework/scripts/filesystem/scene_loader.lua
@@ -0,0 +1,7 @@
+local Scene = require "scene"
+
+local loader = AsuraEngine.Loader.New("scene")
+
+function loader.OnLoad(asset)
+
+end \ No newline at end of file
diff --git a/Source/modules/asura-framework/scripts/filesystem/script_loader.lua b/Source/modules/asura-framework/scripts/filesystem/script_loader.lua
new file mode 100644
index 0000000..e93d903
--- /dev/null
+++ b/Source/modules/asura-framework/scripts/filesystem/script_loader.lua
@@ -0,0 +1,5 @@
+local loader = AsuraEngine.Loader.New("script")
+
+function loader.OnLoad(asset)
+
+end \ No newline at end of file
diff --git a/Source/modules/asura-framework/scripts/filesystem/shader_loader.lua b/Source/modules/asura-framework/scripts/filesystem/shader_loader.lua
new file mode 100644
index 0000000..12d88bb
--- /dev/null
+++ b/Source/modules/asura-framework/scripts/filesystem/shader_loader.lua
@@ -0,0 +1,5 @@
+local loader = AsuraEngine.Loader.New("shader")
+
+function loader.OnLoad(asset)
+
+end \ No newline at end of file
diff --git a/Source/modules/asura-framework/scripts/filesystem/statemap_loader.lua b/Source/modules/asura-framework/scripts/filesystem/statemap_loader.lua
new file mode 100644
index 0000000..e52e086
--- /dev/null
+++ b/Source/modules/asura-framework/scripts/filesystem/statemap_loader.lua
@@ -0,0 +1,7 @@
+require "ai/statemap_manager"
+local loader = AsuraEngine.Loader.New("statemap")
+
+--载入statemap
+function loader.OnLoad(asset)
+
+end \ No newline at end of file
diff --git a/Source/modules/asura-framework/scripts/framework.lua b/Source/modules/asura-framework/scripts/framework.lua
new file mode 100644
index 0000000..4643221
--- /dev/null
+++ b/Source/modules/asura-framework/scripts/framework.lua
@@ -0,0 +1,21 @@
+package.path = "scripts\\?.lua"
+
+--loader
+local loadfn = function(modulename)
+ local errmsg = ""
+ local modulepath = string.gsub(modulename, "%.", "/")
+ for path in string.gmatch(package.path, "([^;]+)") do
+ local filename = string.gsub(path, "%?", modulepath)
+ filename = string.gsub(filename, "\\", "/")
+ local result = kleiloadlua(filename)
+ if result then
+ return result
+ end
+ errmsg = errmsg.."\n\tno file '"..filename.."' (checked with custom loader)"
+ end
+ return errmsg
+end
+
+table.insert(package.loaders, 1, loadfn)
+
+require ""
diff --git a/Source/modules/asura-framework/scripts/graphics/animation.lua b/Source/modules/asura-framework/scripts/graphics/animation.lua
new file mode 100644
index 0000000..285adaa
--- /dev/null
+++ b/Source/modules/asura-framework/scripts/graphics/animation.lua
@@ -0,0 +1,15 @@
+AsuraEngine.Animation = AsuraEngine.Asset.Extend("Animation")
+
+local Animation = AsuraEngine.Animation
+
+local Frame = AsuraEngine.Class("Frame")
+
+function Frame.Ctor(self)
+
+end
+
+function Animation.Ctor(self)
+
+end
+
+return Animation \ No newline at end of file
diff --git a/Source/modules/asura-framework/scripts/graphics/animator.lua b/Source/modules/asura-framework/scripts/graphics/animator.lua
new file mode 100644
index 0000000..fd2f979
--- /dev/null
+++ b/Source/modules/asura-framework/scripts/graphics/animator.lua
@@ -0,0 +1,33 @@
+local Component = AsuraEngine.Framework.Require("component")
+
+AsuraEngine.Animator = Component.Extend("Animator")
+
+local Animator = AsuraEngine.Animator
+
+-- Animator inspector variables.
+Animator.spriteRenderer = AsuraEngine.Type.SpriteRenderer
+Animator.animation = AsuraEngine.Type.Animation
+
+function Animator:Ctor(entity, animation)
+ self.base(entity)
+ self.spriteRenderer = entity:GetSpriteRenderer()
+ self.animation = animation
+end
+
+function Animator:SetAnimation(animation)
+ self.animation = animation
+end
+
+function Animator:GetAnimation()
+ return self.animation
+end
+
+function Animator:OnUpdate(dt)
+
+end
+
+function Animator:OnRender()
+
+end
+
+return Animator \ No newline at end of file
diff --git a/Source/modules/asura-framework/scripts/graphics/camera.lua b/Source/modules/asura-framework/scripts/graphics/camera.lua
new file mode 100644
index 0000000..a989de6
--- /dev/null
+++ b/Source/modules/asura-framework/scripts/graphics/camera.lua
@@ -0,0 +1,21 @@
+AsuraEngine.Camera = AsuraEngine.Component.Extend("Camera")
+
+local Camera = AsuraEngine.Camera
+
+Camera.isCulling = AsuraEngine.Type.Bool
+Camera.isOnScreen = AsuraEngine.Type.Bool
+
+function Camera.Ctor(self)
+ self.isCulling = false
+ self.isOnScreen = false
+end
+
+function Camera.OnUpdate(dt)
+
+end
+
+function Camera.OnRender()
+
+end
+
+return Camera \ No newline at end of file
diff --git a/Source/modules/asura-framework/scripts/graphics/canvas.lua b/Source/modules/asura-framework/scripts/graphics/canvas.lua
new file mode 100644
index 0000000..ce2ca20
--- /dev/null
+++ b/Source/modules/asura-framework/scripts/graphics/canvas.lua
@@ -0,0 +1,34 @@
+AsuraEngine.Canvas = AsuraEngine.Component.Extend("Canvas")
+
+local Canvas = AsuraEngine.Canvas
+
+function Canvas.Ctor(self, width, height)
+ self.simCanvas = AsuraEngine.SimCanvas.New(width, height)
+ self.width = width
+ self.height = height
+end
+
+function Canvas.GetWidth(self)
+ return self.width
+end
+
+function Canvas.GetHeight(self)
+ return self.height
+end
+
+function Canvas.GetSize(self)
+ return self.width, self.height
+end
+
+function Canvas.OnEnable(self)
+ if self.simCanvas == nil then
+ return
+ end
+ self.simCanvas:Begin()
+end
+
+function Canvas.OnDisable(self)
+
+end
+
+return Canvas \ No newline at end of file
diff --git a/Source/modules/asura-framework/scripts/graphics/default_shaders.lua b/Source/modules/asura-framework/scripts/graphics/default_shaders.lua
new file mode 100644
index 0000000..bd54cb9
--- /dev/null
+++ b/Source/modules/asura-framework/scripts/graphics/default_shaders.lua
@@ -0,0 +1,5 @@
+--[[
+õshaders.
+]]
+
+
diff --git a/Source/modules/asura-framework/scripts/graphics/image.lua b/Source/modules/asura-framework/scripts/graphics/image.lua
new file mode 100644
index 0000000..f5ebaa2
--- /dev/null
+++ b/Source/modules/asura-framework/scripts/graphics/image.lua
@@ -0,0 +1,40 @@
+-- 图片资源
+AsuraEngine.Image = AsuraEngine.Asset.Extend("Image")
+
+local Image = AsuraEngine.Image
+
+function Image.Ctor(self, path)
+ local simImage = AsuraEngine.SimImage.New(path)
+ local w, h = simImage:GetSize()
+ self.simImage = simImage
+ self.width = w
+ self.height = h
+end
+
+function Image.GetWidth(self)
+ return self.simImage.GetWidth()
+end
+
+function Image.GetHeight(self)
+ return self.simImage.GetHeight()
+end
+
+function Image.GetSize(self)
+ return self.simImage.GetSize()
+end
+
+--获得x,y位置的颜色值
+function Image.GetColor(self, x, y)
+ return self.simImage.GetColor(x, y)
+end
+
+--获得所有像素,返回到一个table里
+function Image.GetPixels(self)
+ return self.simImage:GetPixels()
+end
+
+--image不可再编辑器编辑,所以没有ToAsset方法
+--function Image.ToAsset()
+--end
+
+return Image \ No newline at end of file
diff --git a/Source/modules/asura-framework/scripts/graphics/material.lua b/Source/modules/asura-framework/scripts/graphics/material.lua
new file mode 100644
index 0000000..032c913
--- /dev/null
+++ b/Source/modules/asura-framework/scripts/graphics/material.lua
@@ -0,0 +1,48 @@
+--material是shader的代理啊,保存对shader uniforms的设置
+AsuraEngine.Material = AsuraEngine.Asset.Extend("Material")
+
+local Material = AsuraEngine.Material
+
+function Material.Ctor(self)
+ self.uniforms = {} --uniform变量和值
+ self.shader = nil
+ self.isShared = false
+end
+
+function Material.Clone(self)
+
+end
+
+function Material:ToAsset()
+
+end
+
+function Material:GetUniform(name)
+
+end
+
+function Material:SetFloat(uniform, value)
+
+end
+
+function Material:SetTexture(uniform, tex)
+
+end
+
+function Material:SetInteger(unifrom, value)
+
+end
+
+function Material:SetVec2(uniform, value)
+
+end
+
+function Material:SetMat44(uniform, value)
+
+end
+
+function Material:GetUniformID()
+
+end
+
+return Material \ No newline at end of file
diff --git a/Source/modules/asura-framework/scripts/graphics/material_manager.lua b/Source/modules/asura-framework/scripts/graphics/material_manager.lua
new file mode 100644
index 0000000..086a5db
--- /dev/null
+++ b/Source/modules/asura-framework/scripts/graphics/material_manager.lua
@@ -0,0 +1,3 @@
+local MaterialManager = AsuraEngine.Manager.New()
+
+return MaterialManager \ No newline at end of file
diff --git a/Source/modules/asura-framework/scripts/graphics/mesh2d.lua b/Source/modules/asura-framework/scripts/graphics/mesh2d.lua
new file mode 100644
index 0000000..05b2e2e
--- /dev/null
+++ b/Source/modules/asura-framework/scripts/graphics/mesh2d.lua
@@ -0,0 +1,9 @@
+AsuraEngine.Mesh2D = AsuraEngine.Asset.Extend("Mesh2D")
+
+local Mesh2D = AsuraEngine.Mesh2D
+
+function Mesh2D.Ctor(self)
+
+end
+
+return Mesh2D \ No newline at end of file
diff --git a/Source/modules/asura-framework/scripts/graphics/mesh2d_renderer.lua b/Source/modules/asura-framework/scripts/graphics/mesh2d_renderer.lua
new file mode 100644
index 0000000..09c8c98
--- /dev/null
+++ b/Source/modules/asura-framework/scripts/graphics/mesh2d_renderer.lua
@@ -0,0 +1,13 @@
+AsuraEngine.Mesh2DRenderer = AsuraEngine.Renderer.Extend("Mesh2DRenderer")
+
+local Mesh2DRenderer = AsuraEngine.Mesh2DRenderer
+
+function Mesh2DRenderer.Ctor(self, material)
+ self.base(material)
+end
+
+function Mesh2DRenderer.OnRender(self)
+
+end
+
+return Mesh2DRenderer \ No newline at end of file
diff --git a/Source/modules/asura-framework/scripts/graphics/particle_system.lua b/Source/modules/asura-framework/scripts/graphics/particle_system.lua
new file mode 100644
index 0000000..065a845
--- /dev/null
+++ b/Source/modules/asura-framework/scripts/graphics/particle_system.lua
@@ -0,0 +1,20 @@
+require "graphics.sprite_renderer"
+
+AsuraEngine.ParticleSystem = AsuraEngine.Component.Extend("ParticleSystem")
+
+local ParticleSystem = AsuraEngine.ParticleSystem
+
+function ParticleSystem.Ctor(self, entity, def)
+ self.base(entity)
+ self.spriteRenderer = AsuraEngine.SpriteRenderer.New()
+end
+
+function ParticleSystem.OnRenderer()
+
+end
+
+function ParticleSystem.OnUpdate(dt)
+
+end
+
+return ParticleSystem \ No newline at end of file
diff --git a/Source/modules/asura-framework/scripts/graphics/renderer.lua b/Source/modules/asura-framework/scripts/graphics/renderer.lua
new file mode 100644
index 0000000..92a6409
--- /dev/null
+++ b/Source/modules/asura-framework/scripts/graphics/renderer.lua
@@ -0,0 +1,19 @@
+local Renderer = AsuraEngine.Component.Extend("Renderer")
+AsuraEngine.Renderer = Renderer
+
+function Renderer.Ctor(self)
+ self.materials = {}
+ self.material = nil
+ self.isMultiMaterials = false
+end
+
+--取材质,如果是shared,那么从此材质clone一个
+function Renderer.GetMaterial(self)
+
+end
+
+function Renderer.IsMultiMaterials(self)
+ return self.isMultiMaterials
+end
+
+return Renderer \ No newline at end of file
diff --git a/Source/modules/asura-framework/scripts/graphics/shader.lua b/Source/modules/asura-framework/scripts/graphics/shader.lua
new file mode 100644
index 0000000..c411619
--- /dev/null
+++ b/Source/modules/asura-framework/scripts/graphics/shader.lua
@@ -0,0 +1,75 @@
+AsuraEngine.Shader = AsuraEngine.Asset.Extend("Shader")
+
+local helper = AsuraEngine.Framework.Require("graphics/shaderHelper")
+
+local Shader = AsuraEngine.Shader
+
+function Shader.Ctor(self)
+ self.simShader = nil
+ self.uniforms = {} -- 映射uniform name到location
+end
+
+--编译shader
+function Shader.Load(self, vert, frag)
+ self.uniforms = {}
+ if self.simShader == nil then
+ self.simShader = AsuraEngine.SimShader.New(vert, frag)
+ else
+ self.simShader:Load(vert, frag)
+ end
+ if self.simShader == nil then
+ --shader编译错误
+ return
+ end
+ --在编译的时候就获得所有的uniform和loc
+ local uniforms = helper.GetUniforms(vert, frag)
+ if uniforms == nil then
+ return
+ end
+ for _, uniform in uniforms do
+ self.uniforms[uniform] = self.simShader:GetUniformLocation(uniform)
+ end
+end
+
+function Shader.GetUniformLocation(self, name)
+ if self.uniforms then
+ local id = self.uniforms[name]
+ return id
+ end
+ return 0
+end
+
+function Shader.SendVec2(self, name, vec2)
+ local id = self:GetUniformLocation(name)
+ self.simShader:SendUniformVector2(name, vec2)
+end
+
+function Shader.SendVec3(self, name, vec3)
+
+end
+
+function Shader.SendVec4(self, name, vec4)
+
+end
+
+function Shader.SendTexture(self, name, tex)
+
+end
+
+function Shader.SendFloat(self, name, number)
+
+end
+
+function Shader.SendInteger(self, name, integer)
+
+end
+
+function Shader.SendColor(self, name, color)
+
+end
+
+function Shader.SendMat44(self, name, mat44)
+
+end
+
+return Shader \ No newline at end of file
diff --git a/Source/modules/asura-framework/scripts/graphics/shaderHelper.lua b/Source/modules/asura-framework/scripts/graphics/shaderHelper.lua
new file mode 100644
index 0000000..b1b42a6
--- /dev/null
+++ b/Source/modules/asura-framework/scripts/graphics/shaderHelper.lua
@@ -0,0 +1,14 @@
+--[[
+解析vertex shader和 fragment shader,并取得两个shader里面定义的uniforms
+]]
+local helper = {}
+
+function helper.GetUniforms(vert, frag)
+
+end
+
+function helper.TryCompileShader(vert, frag)
+
+end
+
+return helper \ No newline at end of file
diff --git a/Source/modules/asura-framework/scripts/graphics/shape.lua b/Source/modules/asura-framework/scripts/graphics/shape.lua
new file mode 100644
index 0000000..51ea8c3
--- /dev/null
+++ b/Source/modules/asura-framework/scripts/graphics/shape.lua
@@ -0,0 +1,12 @@
+--
+-- 2D图形
+--
+AsuraEngine.Shape = AsuraEngine.Asset.Extend("Shape")
+
+local Shape = AsuraEngine.Shape
+
+function Shape.Ctor(self)
+
+end
+
+return Shape \ No newline at end of file
diff --git a/Source/modules/asura-framework/scripts/graphics/shape_renderer.lua b/Source/modules/asura-framework/scripts/graphics/shape_renderer.lua
new file mode 100644
index 0000000..80b48b8
--- /dev/null
+++ b/Source/modules/asura-framework/scripts/graphics/shape_renderer.lua
@@ -0,0 +1,13 @@
+AsuraEngine.ShapeRenderer = AsuraEngine.Component.Extend("ShapeRenderer")
+
+local ShapeRenderer = AsuraEngine.ShapeRenderer
+
+function ShapeRenderer.OnRenderer()
+
+end
+
+function ShapeRenderer.OnUpdate(dt)
+
+end
+
+return ShapeRenderer \ No newline at end of file
diff --git a/Source/modules/asura-framework/scripts/graphics/sprite.lua b/Source/modules/asura-framework/scripts/graphics/sprite.lua
new file mode 100644
index 0000000..9bf05f4
--- /dev/null
+++ b/Source/modules/asura-framework/scripts/graphics/sprite.lua
@@ -0,0 +1,10 @@
+local Sprite = AsuraEngine.Asset.Extend("Sprite")
+AsuraEngine.Sprite = Sprite
+
+function Sprite.Ctor(self, image)
+ self.image = image
+end
+
+function Sprite.ToAsset(self)
+
+end \ No newline at end of file
diff --git a/Source/modules/asura-framework/scripts/graphics/sprite_batch_renderer.lua b/Source/modules/asura-framework/scripts/graphics/sprite_batch_renderer.lua
new file mode 100644
index 0000000..9ec73d2
--- /dev/null
+++ b/Source/modules/asura-framework/scripts/graphics/sprite_batch_renderer.lua
@@ -0,0 +1,9 @@
+AsuraEngine.SpriteBatchRenderer = AsuraEngine.Component.Extend("SpriteBatchRenderer")
+
+local SpriteBatchRenderer = AsuraEngine.SpriteBatchRenderer
+
+function SpriteBatchRenderer.Ctor(self)
+
+end
+
+return SpriteBatchRenderer \ No newline at end of file
diff --git a/Source/modules/asura-framework/scripts/graphics/sprite_renderer.lua b/Source/modules/asura-framework/scripts/graphics/sprite_renderer.lua
new file mode 100644
index 0000000..cdf4901
--- /dev/null
+++ b/Source/modules/asura-framework/scripts/graphics/sprite_renderer.lua
@@ -0,0 +1,17 @@
+require "graphics.renderer"
+
+-- ֻrenderersлᴴvertex bufferindex bufferһobject û
+-- rendererûбҪGPU
+
+local SpriteRenderer = AsuraEngine.Renderer.Extend("Spriterenderer")
+AsuraEngine.SpriteRenderer = SpriteRenderer
+
+function SpriteRenderer.Ctor(self)
+ self.materials = {}
+end
+
+function SpriteRenderer:OnRender()
+
+end
+
+return SpriteRenderer \ No newline at end of file
diff --git a/Source/modules/asura-framework/scripts/gui/button.lua b/Source/modules/asura-framework/scripts/gui/button.lua
new file mode 100644
index 0000000..b122931
--- /dev/null
+++ b/Source/modules/asura-framework/scripts/gui/button.lua
@@ -0,0 +1,21 @@
+AsuraEngine.Button = AsuraEngine.Component.Extend("Button")
+
+local Button = AsuraEngine.Button
+
+function Button.Ctor(self)
+
+end
+
+function Button.OnEvent(e)
+
+end
+
+function Button.OnRender()
+
+end
+
+function Button.OnUpdate(dt)
+
+end
+
+return Button \ No newline at end of file
diff --git a/Source/modules/asura-framework/scripts/gui/text.lua b/Source/modules/asura-framework/scripts/gui/text.lua
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-framework/scripts/gui/text.lua
diff --git a/Source/modules/asura-framework/scripts/gui/widget.lua b/Source/modules/asura-framework/scripts/gui/widget.lua
new file mode 100644
index 0000000..430ade0
--- /dev/null
+++ b/Source/modules/asura-framework/scripts/gui/widget.lua
@@ -0,0 +1,14 @@
+--[[
+Imgui,用在游戏里面
+]]
+local Widget = AsuraEngine.Component("Widget")
+
+function Widget.Ctor(self)
+
+end
+
+function Widget.OnEvent(self, e)
+
+end
+
+return Widget \ No newline at end of file
diff --git a/Source/modules/asura-framework/scripts/managers/scene_manager.lua b/Source/modules/asura-framework/scripts/managers/scene_manager.lua
new file mode 100644
index 0000000..7886dc6
--- /dev/null
+++ b/Source/modules/asura-framework/scripts/managers/scene_manager.lua
@@ -0,0 +1,16 @@
+AsuraEngine.SceneManager = AsuraEngine.Class("SceneManager")
+
+local SceneManager = AsuraEngine.SceneManager
+
+--游戏里的所有场景
+SceneManager.scenes = {}
+
+function SceneManager.Ctor()
+
+end
+
+function SceneManager.GetSceneByGUID()
+
+end
+
+return SceneManager \ No newline at end of file
diff --git a/Source/modules/asura-framework/scripts/managers/sprite_manager.lua b/Source/modules/asura-framework/scripts/managers/sprite_manager.lua
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-framework/scripts/managers/sprite_manager.lua
diff --git a/Source/modules/asura-framework/scripts/math/curve.lua b/Source/modules/asura-framework/scripts/math/curve.lua
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-framework/scripts/math/curve.lua
diff --git a/Source/modules/asura-framework/scripts/path/path.lua b/Source/modules/asura-framework/scripts/path/path.lua
new file mode 100644
index 0000000..1fc9b3a
--- /dev/null
+++ b/Source/modules/asura-framework/scripts/path/path.lua
@@ -0,0 +1,13 @@
+local Path = AsuraEngine.Asset.New("path")
+
+function Path:Ctor()
+
+end
+
+-- ToAssetѶpathתΪ.assetļʽ
+function Path.ToAsset(path)
+ local builder = AsuraEngine.AssetBuilder.Get()
+
+end
+
+return Path \ No newline at end of file
diff --git a/Source/modules/asura-framework/scripts/path/path_calculator.lua b/Source/modules/asura-framework/scripts/path/path_calculator.lua
new file mode 100644
index 0000000..d44da08
--- /dev/null
+++ b/Source/modules/asura-framework/scripts/path/path_calculator.lua
@@ -0,0 +1,12 @@
+--[[
+ڱ༭componentsб
+]]
+local PathCalculator = AsuraEngine.Component.New("PathCalculator")
+
+PathCalculator.path = AsuraEngine.Asset.Type("path", "·")
+
+function PathCalculator:ctor(path)
+ self.path = path
+end
+
+return PathCalculator \ No newline at end of file
diff --git a/Source/modules/asura-framework/scripts/path/path_manager.lua b/Source/modules/asura-framework/scripts/path/path_manager.lua
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-framework/scripts/path/path_manager.lua
diff --git a/Source/modules/asura-framework/scripts/scene.lua b/Source/modules/asura-framework/scripts/scene.lua
new file mode 100644
index 0000000..11ac86c
--- /dev/null
+++ b/Source/modules/asura-framework/scripts/scene.lua
@@ -0,0 +1,22 @@
+--
+-- Scene是一系列gameobject的集合。
+--
+AsuraEngine.Scene = AsuraEngine.Asset.Extend("Scene")
+
+local Scene = AsuraEngine.Scene
+
+function Scene.Ctor(self)
+ self.rootGameObjects = {} --当前场景的所有root entity
+ self.super.Ctor(self)
+end
+
+--获取当前的场景
+function Scene.GetCurrent()
+
+end
+
+function Scene.ToAsset()
+
+end
+
+return Scene \ No newline at end of file
diff --git a/Source/modules/asura-framework/scripts/transform.lua b/Source/modules/asura-framework/scripts/transform.lua
new file mode 100644
index 0000000..1d34ae6
--- /dev/null
+++ b/Source/modules/asura-framework/scripts/transform.lua
@@ -0,0 +1,13 @@
+-- transform的起点在左下角,逆时针为正向
+AsuraEngine.Transform = AsuraEngine.Class("Transform")
+local Transform = AsuraEngine.Transform
+
+function Transform.Ctor(self)
+ self.position = {x=0, y=0}
+ self.rotation = 0
+ self.size = {w=0, h=0}
+end
+
+function Transform.Move(self)
+
+end \ No newline at end of file
diff --git a/Source/modules/asura-json/Json/Json.cpp b/Source/modules/asura-json/Json/Json.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-json/Json/Json.cpp
diff --git a/Source/modules/asura-json/Json/Json.h b/Source/modules/asura-json/Json/Json.h
new file mode 100644
index 0000000..2bdaf53
--- /dev/null
+++ b/Source/modules/asura-json/Json/Json.h
@@ -0,0 +1,14 @@
+#ifndef __ASURA_JSON_H__
+#define __ASURA_JSON_H__
+
+namespace AsuraEngine
+{
+ namespace Json
+ {
+
+
+
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-json/JsonModule.cpp b/Source/modules/asura-json/JsonModule.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-json/JsonModule.cpp
diff --git a/Source/modules/asura-json/JsonModule.h b/Source/modules/asura-json/JsonModule.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-json/JsonModule.h
diff --git a/Source/modules/asura-network/NetworkModule.h b/Source/modules/asura-network/NetworkModule.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-network/NetworkModule.h
diff --git a/Source/modules/asura-openal/Audio/Audio.cpp b/Source/modules/asura-openal/Audio/Audio.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-openal/Audio/Audio.cpp
diff --git a/Source/modules/asura-openal/Audio/Audio.h b/Source/modules/asura-openal/Audio/Audio.h
new file mode 100644
index 0000000..a29c448
--- /dev/null
+++ b/Source/modules/asura-openal/Audio/Audio.h
@@ -0,0 +1,18 @@
+#ifndef _ASURA_AUDIO_H_
+#define _ASURA_AUDIO_H_
+
+#include <asura-base/Classes.h>
+
+namespace_begin(AsuraEngine)
+namespace_begin(Audio)
+
+class Audio
+{
+
+};
+
+
+namespace_end
+namespace_end
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-openal/Audio/MPG123Decoder.cpp b/Source/modules/asura-openal/Audio/MPG123Decoder.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-openal/Audio/MPG123Decoder.cpp
diff --git a/Source/modules/asura-openal/Audio/MPG123Decoder.h b/Source/modules/asura-openal/Audio/MPG123Decoder.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-openal/Audio/MPG123Decoder.h
diff --git a/Source/modules/asura-openal/Audio/Sound.cpp b/Source/modules/asura-openal/Audio/Sound.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-openal/Audio/Sound.cpp
diff --git a/Source/modules/asura-openal/Audio/Sound.h b/Source/modules/asura-openal/Audio/Sound.h
new file mode 100644
index 0000000..1a3d280
--- /dev/null
+++ b/Source/modules/asura-openal/Audio/Sound.h
@@ -0,0 +1,31 @@
+#ifndef __ASURA_ENGINE_SOUND_H__
+#define __ASURA_ENGINE_SOUND_H__
+
+#include <asura-base/Scripting/Scripting.h>
+
+namespace AsuraEngine
+{
+ namespace Audio
+ {
+
+ ///
+ /// Ƶļ
+ ///
+ class Sound ASURA_FINAL
+ : public AEScripting::Portable<Sound>
+ {
+ public:
+
+ Sound();
+ ~Sound();
+
+ private:
+
+
+
+ };
+
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-openal/Audio/SoundData.cpp b/Source/modules/asura-openal/Audio/SoundData.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-openal/Audio/SoundData.cpp
diff --git a/Source/modules/asura-openal/Audio/SoundData.h b/Source/modules/asura-openal/Audio/SoundData.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-openal/Audio/SoundData.h
diff --git a/Source/modules/asura-openal/Audio/SoundDecodeTask.cpp b/Source/modules/asura-openal/Audio/SoundDecodeTask.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-openal/Audio/SoundDecodeTask.cpp
diff --git a/Source/modules/asura-openal/Audio/SoundDecodeTask.h b/Source/modules/asura-openal/Audio/SoundDecodeTask.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-openal/Audio/SoundDecodeTask.h
diff --git a/Source/modules/asura-openal/Audio/SoundDecoder.cpp b/Source/modules/asura-openal/Audio/SoundDecoder.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-openal/Audio/SoundDecoder.cpp
diff --git a/Source/modules/asura-openal/Audio/SoundDecoder.h b/Source/modules/asura-openal/Audio/SoundDecoder.h
new file mode 100644
index 0000000..8392a03
--- /dev/null
+++ b/Source/modules/asura-openal/Audio/SoundDecoder.h
@@ -0,0 +1,30 @@
+#ifndef __ASURA_ENGINE_SOUND_DECODER_H__
+#define __ASURA_ENGINE_SOUND_DECODER_H__
+
+#include <asura-base/FileSystem/DataBuffer.h>
+
+#include "sound.h"
+
+namespace AsuraEngine
+{
+ namespace Audio
+ {
+
+ ///
+ /// Ƶļ
+ ///
+ class SoundDecoder
+ {
+ public:
+
+ SoundDecoder();
+ virtual ~SoundDecoder();
+
+ virtual Sound* Decode(const AEFileSystem::DataBuffer* db);
+
+ };
+
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-openal/Audio/Source.cpp b/Source/modules/asura-openal/Audio/Source.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-openal/Audio/Source.cpp
diff --git a/Source/modules/asura-openal/Audio/Source.h b/Source/modules/asura-openal/Audio/Source.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-openal/Audio/Source.h
diff --git a/Source/modules/asura-openal/Audio/VorbisDecoder.cpp b/Source/modules/asura-openal/Audio/VorbisDecoder.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-openal/Audio/VorbisDecoder.cpp
diff --git a/Source/modules/asura-openal/Audio/VorbisDecoder.h b/Source/modules/asura-openal/Audio/VorbisDecoder.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-openal/Audio/VorbisDecoder.h