From 0c391fdbce5a079cf03e483eb6174dd47806163d Mon Sep 17 00:00:00 2001 From: chai Date: Wed, 7 Aug 2019 21:08:47 +0800 Subject: *misc --- Source/modules/asura-base/BuildConfigure.h | 8 + Source/modules/asura-base/Classes.h | 9 + Source/modules/asura-base/Configure.h | 58 + Source/modules/asura-base/Exception.cpp | 40 + Source/modules/asura-base/Exception.h | 30 + .../asura-base/FileSystem/Binding/_compressor.cpp | 0 .../asura-base/FileSystem/Binding/_data_buffer.cpp | 132 +++ .../asura-base/FileSystem/Binding/_file.cpp | 223 ++++ .../asura-base/FileSystem/Binding/_file_data.cpp | 60 + .../FileSystem/Binding/_file_manager.cpp | 265 +++++ .../asura-base/FileSystem/Binding/_io_task.cpp | 46 + .../modules/asura-base/FileSystem/Compressor.cpp | 11 + Source/modules/asura-base/FileSystem/Compressor.h | 28 + .../modules/asura-base/FileSystem/DataBuffer.cpp | 156 +++ Source/modules/asura-base/FileSystem/DataBuffer.h | 87 ++ Source/modules/asura-base/FileSystem/DecodedData.h | 41 + Source/modules/asura-base/FileSystem/File.cpp | 294 +++++ Source/modules/asura-base/FileSystem/File.h | 146 +++ Source/modules/asura-base/FileSystem/FileData.cpp | 59 + Source/modules/asura-base/FileSystem/FileData.h | 69 ++ .../modules/asura-base/FileSystem/FileManager.cpp | 198 ++++ Source/modules/asura-base/FileSystem/FileManager.h | 112 ++ .../modules/asura-base/FileSystem/IOBatchTask.cpp | 0 Source/modules/asura-base/FileSystem/IOBatchTask.h | 31 + Source/modules/asura-base/FileSystem/IOTask.cpp | 61 ++ Source/modules/asura-base/FileSystem/IOTask.h | 56 + Source/modules/asura-base/FileSystem/Renewable.h | 27 + Source/modules/asura-base/Manager.hpp | 14 + Source/modules/asura-base/Math/Curve.cpp | 0 Source/modules/asura-base/Math/Curve.h | 0 Source/modules/asura-base/Math/Functions.cpp | 0 Source/modules/asura-base/Math/Functions.h | 0 Source/modules/asura-base/Math/Matrix44.cpp | 217 ++++ Source/modules/asura-base/Math/Matrix44.h | 96 ++ Source/modules/asura-base/Math/Quaternion.cpp | 0 Source/modules/asura-base/Math/Quaternion.h | 18 + Source/modules/asura-base/Math/Random.h | 88 ++ Source/modules/asura-base/Math/RangedValue.cpp | 0 Source/modules/asura-base/Math/RangedValue.h | 0 Source/modules/asura-base/Math/Rect.hpp | 50 + Source/modules/asura-base/Math/Rect.inc | 28 + Source/modules/asura-base/Math/Transform.cpp | 0 Source/modules/asura-base/Math/Transform.h | 30 + Source/modules/asura-base/Math/Vector2.hpp | 72 ++ Source/modules/asura-base/Math/Vector2.inc | 114 ++ Source/modules/asura-base/Math/Vector3.hpp | 235 ++++ Source/modules/asura-base/Math/Vector3.inc | 145 +++ Source/modules/asura-base/Math/Vector4.h | 234 ++++ Source/modules/asura-base/Math/Vector4.inc | 152 +++ Source/modules/asura-base/Module.h | 32 + Source/modules/asura-base/Scripting/Scripting.h | 30 + Source/modules/asura-base/Singleton.hpp | 59 + Source/modules/asura-base/Threads/Conditional.cpp | 84 ++ Source/modules/asura-base/Threads/Conditional.h | 41 + Source/modules/asura-base/Threads/Coroutine.cpp | 15 + Source/modules/asura-base/Threads/Coroutine.h | 40 + Source/modules/asura-base/Threads/Mutex.cpp | 105 ++ Source/modules/asura-base/Threads/Mutex.h | 128 +++ Source/modules/asura-base/Threads/Semaphore.cpp | 99 ++ Source/modules/asura-base/Threads/Semaphore.h | 68 ++ Source/modules/asura-base/Threads/Task.cpp | 10 + Source/modules/asura-base/Threads/Task.h | 43 + Source/modules/asura-base/Threads/Thread.cpp | 287 +++++ Source/modules/asura-base/Threads/Thread.h | 222 ++++ .../modules/asura-base/Threads/ThreadImplPosix.cpp | 0 .../modules/asura-base/Threads/ThreadImplPosix.h | 2 + .../modules/asura-base/Threads/ThreadImplSDL.cpp | 0 Source/modules/asura-base/Threads/ThreadImplSDL.h | 0 .../modules/asura-base/Threads/ThreadImplStd.cpp | 0 Source/modules/asura-base/Threads/ThreadImplStd.h | 41 + .../modules/asura-base/Threads/ThreadImplWin32.cpp | 77 ++ .../modules/asura-base/Threads/ThreadImplWin32.h | 44 + Source/modules/asura-base/Threads/Threadable.h | 23 + .../asura-base/Threads/binding/_coroutine.cpp | 38 + .../modules/asura-base/Threads/binding/_thread.cpp | 208 ++++ Source/modules/asura-base/Type.h | 37 + Source/modules/asura-base/Utilities/Hash128.cpp | 0 Source/modules/asura-base/Utilities/Hash128.h | 0 Source/modules/asura-base/Utilities/LinkedList.cpp | 0 Source/modules/asura-base/Utilities/LinkedList.h | 0 Source/modules/asura-base/Utilities/StringMap.cpp | 0 Source/modules/asura-base/Utilities/StringMap.hpp | 29 + .../modules/asura-base/Utilities/dynamic_bitset.h | 1150 ++++++++++++++++++++ Source/modules/asura-base/Utils.h | 6 + Source/modules/asura-base/UtilsConfig.h | 13 + Source/modules/asura-base/UtilsModule.cpp | 25 + Source/modules/asura-base/UtilsModule.h | 34 + Source/modules/asura-box2d/Box2DModule.cpp | 0 Source/modules/asura-box2d/Box2DModule.h | 19 + Source/modules/asura-box2d/Physics/Body.h | 64 ++ Source/modules/asura-box2d/Physics/ChainShape.h | 29 + Source/modules/asura-box2d/Physics/CircleShape.h | 0 Source/modules/asura-box2d/Physics/Contact.h | 0 Source/modules/asura-box2d/Physics/DebugDraw.h | 9 + Source/modules/asura-box2d/Physics/DistanceJoint.h | 0 Source/modules/asura-box2d/Physics/EdgeShape.h | 0 Source/modules/asura-box2d/Physics/Fixture.h | 17 + Source/modules/asura-box2d/Physics/FrictionJoint.h | 0 Source/modules/asura-box2d/Physics/GearJoint.h | 0 Source/modules/asura-box2d/Physics/Joint.h | 0 Source/modules/asura-box2d/Physics/MotorJoint.h | 0 Source/modules/asura-box2d/Physics/MouseJoint.h | 0 Source/modules/asura-box2d/Physics/PolygonShape.h | 0 .../modules/asura-box2d/Physics/PrismaticJoint.h | 0 Source/modules/asura-box2d/Physics/PulleyJoint.h | 0 Source/modules/asura-box2d/Physics/RevoluteJoint.h | 0 Source/modules/asura-box2d/Physics/RopeJoint.h | 0 Source/modules/asura-box2d/Physics/Shape.h | 0 Source/modules/asura-box2d/Physics/WeldJoint.h | 0 Source/modules/asura-box2d/Physics/WheelJoint.h | 0 Source/modules/asura-box2d/Physics/World.h | 18 + .../modules/asura-box2d/Physics/binding/_body.cpp | 171 +++ .../modules/asura-box2d/Physics/binding/_world.cpp | 21 + Source/modules/asura-core/Application.cpp | 23 + Source/modules/asura-core/Application.h | 69 ++ Source/modules/asura-core/CoreConfig.h | 13 + Source/modules/asura-core/CoreModule.cpp | 25 + Source/modules/asura-core/CoreModule.h | 26 + Source/modules/asura-core/Font/Glyph.cpp | 0 Source/modules/asura-core/Font/Glyph.h | 0 Source/modules/asura-core/Font/String.cpp | 376 +++++++ Source/modules/asura-core/Font/String.hpp | 595 ++++++++++ Source/modules/asura-core/Font/String.inc | 29 + Source/modules/asura-core/Font/TTF.cpp | 0 Source/modules/asura-core/Font/TTF.h | 17 + Source/modules/asura-core/Font/Utf.hpp | 720 ++++++++++++ Source/modules/asura-core/Font/Utf.inc | 752 +++++++++++++ Source/modules/asura-core/Graphics/BlendMode.h | 17 + Source/modules/asura-core/Graphics/Canvas.cpp | 49 + Source/modules/asura-core/Graphics/Canvas.h | 73 ++ Source/modules/asura-core/Graphics/Color.cpp | 58 + Source/modules/asura-core/Graphics/Color.h | 75 ++ Source/modules/asura-core/Graphics/Color32.cpp | 53 + Source/modules/asura-core/Graphics/Color32.h | 58 + Source/modules/asura-core/Graphics/ColorPalette.h | 0 Source/modules/asura-core/Graphics/DrawInfo.cpp | 10 + Source/modules/asura-core/Graphics/DrawInfo.h | 19 + Source/modules/asura-core/Graphics/DrawUtil.cpp | 0 Source/modules/asura-core/Graphics/DrawUtil.h | 0 Source/modules/asura-core/Graphics/GPUBuffer.cpp | 151 +++ Source/modules/asura-core/Graphics/GPUBuffer.h | 93 ++ Source/modules/asura-core/Graphics/GfxDevice.cpp | 188 ++++ Source/modules/asura-core/Graphics/GfxDevice.h | 141 +++ .../modules/asura-core/Graphics/GraphicsHelper.cpp | 0 .../modules/asura-core/Graphics/GraphicsHelper.h | 15 + Source/modules/asura-core/Graphics/Image.cpp | 103 ++ Source/modules/asura-core/Graphics/Image.h | 63 ++ Source/modules/asura-core/Graphics/IndexBuffer.cpp | 17 + Source/modules/asura-core/Graphics/IndexBuffer.h | 34 + Source/modules/asura-core/Graphics/MatrixStack.cpp | 75 ++ Source/modules/asura-core/Graphics/MatrixStack.h | 58 + Source/modules/asura-core/Graphics/Mesh2D.cpp | 0 Source/modules/asura-core/Graphics/Mesh2D.h | 52 + Source/modules/asura-core/Graphics/Polygon2D.cpp | 0 Source/modules/asura-core/Graphics/Polygon2D.h | 0 Source/modules/asura-core/Graphics/Quad.cpp | 0 Source/modules/asura-core/Graphics/Quad.h | 1 + Source/modules/asura-core/Graphics/RenderState.h | 47 + .../modules/asura-core/Graphics/RenderTarget.cpp | 0 Source/modules/asura-core/Graphics/RenderTarget.h | 52 + Source/modules/asura-core/Graphics/Shader.cpp | 282 +++++ Source/modules/asura-core/Graphics/Shader.h | 117 ++ Source/modules/asura-core/Graphics/Shape.cpp | 0 Source/modules/asura-core/Graphics/Shape.h | 0 Source/modules/asura-core/Graphics/SpriteBatch.cpp | 0 Source/modules/asura-core/Graphics/SpriteBatch.h | 34 + Source/modules/asura-core/Graphics/Texture.cpp | 47 + Source/modules/asura-core/Graphics/Texture.h | 101 ++ Source/modules/asura-core/Graphics/VBO.cpp | 0 Source/modules/asura-core/Graphics/VBO.h | 27 + .../modules/asura-core/Graphics/VertexBuffer.cpp | 16 + Source/modules/asura-core/Graphics/VertexBuffer.h | 34 + .../asura-core/Graphics/binding/_canvas.cpp | 48 + .../modules/asura-core/Graphics/binding/_color.cpp | 130 +++ .../asura-core/Graphics/binding/_color32.cpp | 66 ++ .../asura-core/Graphics/binding/_gfx_device.cpp | 151 +++ .../asura-core/Graphics/binding/_gpu_buffer.cpp | 118 ++ .../modules/asura-core/Graphics/binding/_image.cpp | 71 ++ .../asura-core/Graphics/binding/_index_buffer.cpp | 31 + .../asura-core/Graphics/binding/_mesh2d.cpp | 20 + .../asura-core/Graphics/binding/_shader.cpp | 131 +++ .../asura-core/Graphics/binding/_sprite_batch.cpp | 20 + .../asura-core/Graphics/binding/_texture.cpp | 85 ++ .../asura-core/Graphics/binding/_vertex_buffer.cpp | 38 + Source/modules/asura-core/Image/ImageData.cpp | 62 ++ Source/modules/asura-core/Image/ImageData.h | 81 ++ .../modules/asura-core/Image/ImageDecodeTask.cpp | 17 + Source/modules/asura-core/Image/ImageDecodeTask.h | 35 + Source/modules/asura-core/Image/ImageDecoder.h | 33 + Source/modules/asura-core/Image/PngDecoder.cpp | 17 + Source/modules/asura-core/Image/PngDecoder.h | 25 + Source/modules/asura-core/Image/StbDecoder.cpp | 73 ++ Source/modules/asura-core/Image/StbDecoder.h | 26 + .../asura-core/Image/binding/_image_data.cpp | 108 ++ .../Image/binding/_image_decode_task.cpp | 19 + Source/modules/asura-core/Input/Button.h | 31 + Source/modules/asura-core/Input/ClipBoard.cpp | 0 Source/modules/asura-core/Input/ClipBoard.h | 0 Source/modules/asura-core/Input/InputAxis.cpp | 0 Source/modules/asura-core/Input/InputAxis.h | 15 + Source/modules/asura-core/Input/InputDevice.cpp | 10 + Source/modules/asura-core/Input/InputDevice.h | 82 ++ Source/modules/asura-core/Input/InputEvent.cpp | 0 Source/modules/asura-core/Input/InputEvent.h | 55 + Source/modules/asura-core/Input/InputManager.cpp | 140 +++ Source/modules/asura-core/Input/InputManager.h | 352 ++++++ Source/modules/asura-core/Input/JoystickState.h | 16 + Source/modules/asura-core/Input/KeyboardState.h | 37 + Source/modules/asura-core/Input/MouseState.h | 16 + Source/modules/asura-core/Mesh/Am2Handler.cpp | 34 + Source/modules/asura-core/Mesh/Am2Handler.h | 30 + Source/modules/asura-core/Mesh/Mesh2DData.cpp | 0 Source/modules/asura-core/Mesh/Mesh2DData.h | 78 ++ Source/modules/asura-core/Mesh/Mesh2DHandler.cpp | 0 Source/modules/asura-core/Mesh/Mesh2DHandler.h | 32 + Source/modules/asura-core/Mesh/ObjHandler.cpp | 0 Source/modules/asura-core/Mesh/ObjHandler.h | 0 Source/modules/asura-core/Profiler/GPUProfiler.cpp | 0 Source/modules/asura-core/Profiler/GPUProfiler.h | 0 Source/modules/asura-core/Profiler/Stats.cpp | 0 Source/modules/asura-core/Profiler/Stats.h | 0 Source/modules/asura-core/Threads/Channel.cpp | 0 Source/modules/asura-core/Threads/Channel.h | 18 + Source/modules/asura-core/Threads/ThreadEx.cpp | 20 + Source/modules/asura-core/Threads/ThreadEx.h | 45 + Source/modules/asura-core/Time/Timer.cpp | 0 Source/modules/asura-core/Time/Timer.h | 0 Source/modules/asura-core/Window/Window.cpp | 104 ++ Source/modules/asura-core/Window/Window.h | 138 +++ .../modules/asura-core/Window/WindowImplGlew.cpp | 0 Source/modules/asura-core/Window/WindowImplGlew.h | 0 Source/modules/asura-core/Window/WindowImplGlut.h | 0 Source/modules/asura-core/Window/WindowImplSDL.cpp | 153 +++ Source/modules/asura-core/Window/WindowImplSDL.h | 45 + .../modules/asura-core/Window/WinodwImplGlut.cpp | 0 .../modules/asura-core/Window/binding/_window.cpp | 179 +++ Source/modules/asura-fmod/Audio/Source.h | 20 + Source/modules/asura-fmod/FMODModule.h | 9 + Source/modules/asura-framework/compile.bat | 0 Source/modules/asura-framework/compile.sh | 0 Source/modules/asura-framework/main.cpp | 0 .../asura-framework/scripts/ai/behavior_tree.lua | 0 .../asura-framework/scripts/ai/state_graph.lua | 11 + .../asura-framework/scripts/ai/state_machine.lua | 6 + .../asura-framework/scripts/audio/sound.lua | 9 + .../asura-framework/scripts/audio/source.lua | 22 + Source/modules/asura-framework/scripts/class.lua | 17 + .../modules/asura-framework/scripts/component.lua | 30 + Source/modules/asura-framework/scripts/entity.lua | 114 ++ .../scripts/filesystem/animation_loader.lua | 10 + .../asura-framework/scripts/filesystem/asset.lua | 20 + .../scripts/filesystem/entity_loader.lua | 5 + .../scripts/filesystem/image_loader.lua | 13 + .../asura-framework/scripts/filesystem/loader.lua | 12 + .../scripts/filesystem/material_loader.lua | 7 + .../scripts/filesystem/path_loader.lua | 9 + .../scripts/filesystem/scene_loader.lua | 7 + .../scripts/filesystem/script_loader.lua | 5 + .../scripts/filesystem/shader_loader.lua | 5 + .../scripts/filesystem/statemap_loader.lua | 7 + .../modules/asura-framework/scripts/framework.lua | 21 + .../asura-framework/scripts/graphics/animation.lua | 15 + .../asura-framework/scripts/graphics/animator.lua | 33 + .../asura-framework/scripts/graphics/camera.lua | 21 + .../asura-framework/scripts/graphics/canvas.lua | 34 + .../scripts/graphics/default_shaders.lua | 5 + .../asura-framework/scripts/graphics/image.lua | 40 + .../asura-framework/scripts/graphics/material.lua | 48 + .../scripts/graphics/material_manager.lua | 3 + .../asura-framework/scripts/graphics/mesh2d.lua | 9 + .../scripts/graphics/mesh2d_renderer.lua | 13 + .../scripts/graphics/particle_system.lua | 20 + .../asura-framework/scripts/graphics/renderer.lua | 19 + .../asura-framework/scripts/graphics/shader.lua | 75 ++ .../scripts/graphics/shaderHelper.lua | 14 + .../asura-framework/scripts/graphics/shape.lua | 12 + .../scripts/graphics/shape_renderer.lua | 13 + .../asura-framework/scripts/graphics/sprite.lua | 10 + .../scripts/graphics/sprite_batch_renderer.lua | 9 + .../scripts/graphics/sprite_renderer.lua | 17 + .../modules/asura-framework/scripts/gui/button.lua | 21 + .../modules/asura-framework/scripts/gui/text.lua | 0 .../modules/asura-framework/scripts/gui/widget.lua | 14 + .../scripts/managers/scene_manager.lua | 16 + .../scripts/managers/sprite_manager.lua | 0 .../modules/asura-framework/scripts/math/curve.lua | 0 .../modules/asura-framework/scripts/path/path.lua | 13 + .../scripts/path/path_calculator.lua | 12 + .../asura-framework/scripts/path/path_manager.lua | 0 Source/modules/asura-framework/scripts/scene.lua | 22 + .../modules/asura-framework/scripts/transform.lua | 13 + Source/modules/asura-json/Json/Json.cpp | 0 Source/modules/asura-json/Json/Json.h | 14 + Source/modules/asura-json/JsonModule.cpp | 0 Source/modules/asura-json/JsonModule.h | 0 Source/modules/asura-network/NetworkModule.h | 0 Source/modules/asura-openal/Audio/Audio.cpp | 0 Source/modules/asura-openal/Audio/Audio.h | 18 + .../modules/asura-openal/Audio/MPG123Decoder.cpp | 0 Source/modules/asura-openal/Audio/MPG123Decoder.h | 0 Source/modules/asura-openal/Audio/Sound.cpp | 0 Source/modules/asura-openal/Audio/Sound.h | 31 + Source/modules/asura-openal/Audio/SoundData.cpp | 0 Source/modules/asura-openal/Audio/SoundData.h | 0 .../modules/asura-openal/Audio/SoundDecodeTask.cpp | 0 .../modules/asura-openal/Audio/SoundDecodeTask.h | 0 Source/modules/asura-openal/Audio/SoundDecoder.cpp | 0 Source/modules/asura-openal/Audio/SoundDecoder.h | 30 + Source/modules/asura-openal/Audio/Source.cpp | 0 Source/modules/asura-openal/Audio/Source.h | 0 .../modules/asura-openal/Audio/VorbisDecoder.cpp | 0 Source/modules/asura-openal/Audio/VorbisDecoder.h | 0 312 files changed, 15891 insertions(+) create mode 100644 Source/modules/asura-base/BuildConfigure.h create mode 100644 Source/modules/asura-base/Classes.h create mode 100644 Source/modules/asura-base/Configure.h create mode 100644 Source/modules/asura-base/Exception.cpp create mode 100644 Source/modules/asura-base/Exception.h create mode 100644 Source/modules/asura-base/FileSystem/Binding/_compressor.cpp create mode 100644 Source/modules/asura-base/FileSystem/Binding/_data_buffer.cpp create mode 100644 Source/modules/asura-base/FileSystem/Binding/_file.cpp create mode 100644 Source/modules/asura-base/FileSystem/Binding/_file_data.cpp create mode 100644 Source/modules/asura-base/FileSystem/Binding/_file_manager.cpp create mode 100644 Source/modules/asura-base/FileSystem/Binding/_io_task.cpp create mode 100644 Source/modules/asura-base/FileSystem/Compressor.cpp create mode 100644 Source/modules/asura-base/FileSystem/Compressor.h create mode 100644 Source/modules/asura-base/FileSystem/DataBuffer.cpp create mode 100644 Source/modules/asura-base/FileSystem/DataBuffer.h create mode 100644 Source/modules/asura-base/FileSystem/DecodedData.h create mode 100644 Source/modules/asura-base/FileSystem/File.cpp create mode 100644 Source/modules/asura-base/FileSystem/File.h create mode 100644 Source/modules/asura-base/FileSystem/FileData.cpp create mode 100644 Source/modules/asura-base/FileSystem/FileData.h create mode 100644 Source/modules/asura-base/FileSystem/FileManager.cpp create mode 100644 Source/modules/asura-base/FileSystem/FileManager.h create mode 100644 Source/modules/asura-base/FileSystem/IOBatchTask.cpp create mode 100644 Source/modules/asura-base/FileSystem/IOBatchTask.h create mode 100644 Source/modules/asura-base/FileSystem/IOTask.cpp create mode 100644 Source/modules/asura-base/FileSystem/IOTask.h create mode 100644 Source/modules/asura-base/FileSystem/Renewable.h create mode 100644 Source/modules/asura-base/Manager.hpp create mode 100644 Source/modules/asura-base/Math/Curve.cpp create mode 100644 Source/modules/asura-base/Math/Curve.h create mode 100644 Source/modules/asura-base/Math/Functions.cpp create mode 100644 Source/modules/asura-base/Math/Functions.h create mode 100644 Source/modules/asura-base/Math/Matrix44.cpp create mode 100644 Source/modules/asura-base/Math/Matrix44.h create mode 100644 Source/modules/asura-base/Math/Quaternion.cpp create mode 100644 Source/modules/asura-base/Math/Quaternion.h create mode 100644 Source/modules/asura-base/Math/Random.h create mode 100644 Source/modules/asura-base/Math/RangedValue.cpp create mode 100644 Source/modules/asura-base/Math/RangedValue.h create mode 100644 Source/modules/asura-base/Math/Rect.hpp create mode 100644 Source/modules/asura-base/Math/Rect.inc create mode 100644 Source/modules/asura-base/Math/Transform.cpp create mode 100644 Source/modules/asura-base/Math/Transform.h create mode 100644 Source/modules/asura-base/Math/Vector2.hpp create mode 100644 Source/modules/asura-base/Math/Vector2.inc create mode 100644 Source/modules/asura-base/Math/Vector3.hpp create mode 100644 Source/modules/asura-base/Math/Vector3.inc create mode 100644 Source/modules/asura-base/Math/Vector4.h create mode 100644 Source/modules/asura-base/Math/Vector4.inc create mode 100644 Source/modules/asura-base/Module.h create mode 100644 Source/modules/asura-base/Scripting/Scripting.h create mode 100644 Source/modules/asura-base/Singleton.hpp create mode 100644 Source/modules/asura-base/Threads/Conditional.cpp create mode 100644 Source/modules/asura-base/Threads/Conditional.h create mode 100644 Source/modules/asura-base/Threads/Coroutine.cpp create mode 100644 Source/modules/asura-base/Threads/Coroutine.h create mode 100644 Source/modules/asura-base/Threads/Mutex.cpp create mode 100644 Source/modules/asura-base/Threads/Mutex.h create mode 100644 Source/modules/asura-base/Threads/Semaphore.cpp create mode 100644 Source/modules/asura-base/Threads/Semaphore.h create mode 100644 Source/modules/asura-base/Threads/Task.cpp create mode 100644 Source/modules/asura-base/Threads/Task.h create mode 100644 Source/modules/asura-base/Threads/Thread.cpp create mode 100644 Source/modules/asura-base/Threads/Thread.h create mode 100644 Source/modules/asura-base/Threads/ThreadImplPosix.cpp create mode 100644 Source/modules/asura-base/Threads/ThreadImplPosix.h create mode 100644 Source/modules/asura-base/Threads/ThreadImplSDL.cpp create mode 100644 Source/modules/asura-base/Threads/ThreadImplSDL.h create mode 100644 Source/modules/asura-base/Threads/ThreadImplStd.cpp create mode 100644 Source/modules/asura-base/Threads/ThreadImplStd.h create mode 100644 Source/modules/asura-base/Threads/ThreadImplWin32.cpp create mode 100644 Source/modules/asura-base/Threads/ThreadImplWin32.h create mode 100644 Source/modules/asura-base/Threads/Threadable.h create mode 100644 Source/modules/asura-base/Threads/binding/_coroutine.cpp create mode 100644 Source/modules/asura-base/Threads/binding/_thread.cpp create mode 100644 Source/modules/asura-base/Type.h create mode 100644 Source/modules/asura-base/Utilities/Hash128.cpp create mode 100644 Source/modules/asura-base/Utilities/Hash128.h create mode 100644 Source/modules/asura-base/Utilities/LinkedList.cpp create mode 100644 Source/modules/asura-base/Utilities/LinkedList.h create mode 100644 Source/modules/asura-base/Utilities/StringMap.cpp create mode 100644 Source/modules/asura-base/Utilities/StringMap.hpp create mode 100644 Source/modules/asura-base/Utilities/dynamic_bitset.h create mode 100644 Source/modules/asura-base/Utils.h create mode 100644 Source/modules/asura-base/UtilsConfig.h create mode 100644 Source/modules/asura-base/UtilsModule.cpp create mode 100644 Source/modules/asura-base/UtilsModule.h create mode 100644 Source/modules/asura-box2d/Box2DModule.cpp create mode 100644 Source/modules/asura-box2d/Box2DModule.h create mode 100644 Source/modules/asura-box2d/Physics/Body.h create mode 100644 Source/modules/asura-box2d/Physics/ChainShape.h create mode 100644 Source/modules/asura-box2d/Physics/CircleShape.h create mode 100644 Source/modules/asura-box2d/Physics/Contact.h create mode 100644 Source/modules/asura-box2d/Physics/DebugDraw.h create mode 100644 Source/modules/asura-box2d/Physics/DistanceJoint.h create mode 100644 Source/modules/asura-box2d/Physics/EdgeShape.h create mode 100644 Source/modules/asura-box2d/Physics/Fixture.h create mode 100644 Source/modules/asura-box2d/Physics/FrictionJoint.h create mode 100644 Source/modules/asura-box2d/Physics/GearJoint.h create mode 100644 Source/modules/asura-box2d/Physics/Joint.h create mode 100644 Source/modules/asura-box2d/Physics/MotorJoint.h create mode 100644 Source/modules/asura-box2d/Physics/MouseJoint.h create mode 100644 Source/modules/asura-box2d/Physics/PolygonShape.h create mode 100644 Source/modules/asura-box2d/Physics/PrismaticJoint.h create mode 100644 Source/modules/asura-box2d/Physics/PulleyJoint.h create mode 100644 Source/modules/asura-box2d/Physics/RevoluteJoint.h create mode 100644 Source/modules/asura-box2d/Physics/RopeJoint.h create mode 100644 Source/modules/asura-box2d/Physics/Shape.h create mode 100644 Source/modules/asura-box2d/Physics/WeldJoint.h create mode 100644 Source/modules/asura-box2d/Physics/WheelJoint.h create mode 100644 Source/modules/asura-box2d/Physics/World.h create mode 100644 Source/modules/asura-box2d/Physics/binding/_body.cpp create mode 100644 Source/modules/asura-box2d/Physics/binding/_world.cpp create mode 100644 Source/modules/asura-core/Application.cpp create mode 100644 Source/modules/asura-core/Application.h create mode 100644 Source/modules/asura-core/CoreConfig.h create mode 100644 Source/modules/asura-core/CoreModule.cpp create mode 100644 Source/modules/asura-core/CoreModule.h create mode 100644 Source/modules/asura-core/Font/Glyph.cpp create mode 100644 Source/modules/asura-core/Font/Glyph.h create mode 100644 Source/modules/asura-core/Font/String.cpp create mode 100644 Source/modules/asura-core/Font/String.hpp create mode 100644 Source/modules/asura-core/Font/String.inc create mode 100644 Source/modules/asura-core/Font/TTF.cpp create mode 100644 Source/modules/asura-core/Font/TTF.h create mode 100644 Source/modules/asura-core/Font/Utf.hpp create mode 100644 Source/modules/asura-core/Font/Utf.inc create mode 100644 Source/modules/asura-core/Graphics/BlendMode.h create mode 100644 Source/modules/asura-core/Graphics/Canvas.cpp create mode 100644 Source/modules/asura-core/Graphics/Canvas.h create mode 100644 Source/modules/asura-core/Graphics/Color.cpp create mode 100644 Source/modules/asura-core/Graphics/Color.h create mode 100644 Source/modules/asura-core/Graphics/Color32.cpp create mode 100644 Source/modules/asura-core/Graphics/Color32.h create mode 100644 Source/modules/asura-core/Graphics/ColorPalette.h create mode 100644 Source/modules/asura-core/Graphics/DrawInfo.cpp create mode 100644 Source/modules/asura-core/Graphics/DrawInfo.h create mode 100644 Source/modules/asura-core/Graphics/DrawUtil.cpp create mode 100644 Source/modules/asura-core/Graphics/DrawUtil.h create mode 100644 Source/modules/asura-core/Graphics/GPUBuffer.cpp create mode 100644 Source/modules/asura-core/Graphics/GPUBuffer.h create mode 100644 Source/modules/asura-core/Graphics/GfxDevice.cpp create mode 100644 Source/modules/asura-core/Graphics/GfxDevice.h create mode 100644 Source/modules/asura-core/Graphics/GraphicsHelper.cpp create mode 100644 Source/modules/asura-core/Graphics/GraphicsHelper.h create mode 100644 Source/modules/asura-core/Graphics/Image.cpp create mode 100644 Source/modules/asura-core/Graphics/Image.h create mode 100644 Source/modules/asura-core/Graphics/IndexBuffer.cpp create mode 100644 Source/modules/asura-core/Graphics/IndexBuffer.h create mode 100644 Source/modules/asura-core/Graphics/MatrixStack.cpp create mode 100644 Source/modules/asura-core/Graphics/MatrixStack.h create mode 100644 Source/modules/asura-core/Graphics/Mesh2D.cpp create mode 100644 Source/modules/asura-core/Graphics/Mesh2D.h create mode 100644 Source/modules/asura-core/Graphics/Polygon2D.cpp create mode 100644 Source/modules/asura-core/Graphics/Polygon2D.h create mode 100644 Source/modules/asura-core/Graphics/Quad.cpp create mode 100644 Source/modules/asura-core/Graphics/Quad.h create mode 100644 Source/modules/asura-core/Graphics/RenderState.h create mode 100644 Source/modules/asura-core/Graphics/RenderTarget.cpp create mode 100644 Source/modules/asura-core/Graphics/RenderTarget.h create mode 100644 Source/modules/asura-core/Graphics/Shader.cpp create mode 100644 Source/modules/asura-core/Graphics/Shader.h create mode 100644 Source/modules/asura-core/Graphics/Shape.cpp create mode 100644 Source/modules/asura-core/Graphics/Shape.h create mode 100644 Source/modules/asura-core/Graphics/SpriteBatch.cpp create mode 100644 Source/modules/asura-core/Graphics/SpriteBatch.h create mode 100644 Source/modules/asura-core/Graphics/Texture.cpp create mode 100644 Source/modules/asura-core/Graphics/Texture.h create mode 100644 Source/modules/asura-core/Graphics/VBO.cpp create mode 100644 Source/modules/asura-core/Graphics/VBO.h create mode 100644 Source/modules/asura-core/Graphics/VertexBuffer.cpp create mode 100644 Source/modules/asura-core/Graphics/VertexBuffer.h create mode 100644 Source/modules/asura-core/Graphics/binding/_canvas.cpp create mode 100644 Source/modules/asura-core/Graphics/binding/_color.cpp create mode 100644 Source/modules/asura-core/Graphics/binding/_color32.cpp create mode 100644 Source/modules/asura-core/Graphics/binding/_gfx_device.cpp create mode 100644 Source/modules/asura-core/Graphics/binding/_gpu_buffer.cpp create mode 100644 Source/modules/asura-core/Graphics/binding/_image.cpp create mode 100644 Source/modules/asura-core/Graphics/binding/_index_buffer.cpp create mode 100644 Source/modules/asura-core/Graphics/binding/_mesh2d.cpp create mode 100644 Source/modules/asura-core/Graphics/binding/_shader.cpp create mode 100644 Source/modules/asura-core/Graphics/binding/_sprite_batch.cpp create mode 100644 Source/modules/asura-core/Graphics/binding/_texture.cpp create mode 100644 Source/modules/asura-core/Graphics/binding/_vertex_buffer.cpp create mode 100644 Source/modules/asura-core/Image/ImageData.cpp create mode 100644 Source/modules/asura-core/Image/ImageData.h create mode 100644 Source/modules/asura-core/Image/ImageDecodeTask.cpp create mode 100644 Source/modules/asura-core/Image/ImageDecodeTask.h create mode 100644 Source/modules/asura-core/Image/ImageDecoder.h create mode 100644 Source/modules/asura-core/Image/PngDecoder.cpp create mode 100644 Source/modules/asura-core/Image/PngDecoder.h create mode 100644 Source/modules/asura-core/Image/StbDecoder.cpp create mode 100644 Source/modules/asura-core/Image/StbDecoder.h create mode 100644 Source/modules/asura-core/Image/binding/_image_data.cpp create mode 100644 Source/modules/asura-core/Image/binding/_image_decode_task.cpp create mode 100644 Source/modules/asura-core/Input/Button.h create mode 100644 Source/modules/asura-core/Input/ClipBoard.cpp create mode 100644 Source/modules/asura-core/Input/ClipBoard.h create mode 100644 Source/modules/asura-core/Input/InputAxis.cpp create mode 100644 Source/modules/asura-core/Input/InputAxis.h create mode 100644 Source/modules/asura-core/Input/InputDevice.cpp create mode 100644 Source/modules/asura-core/Input/InputDevice.h create mode 100644 Source/modules/asura-core/Input/InputEvent.cpp create mode 100644 Source/modules/asura-core/Input/InputEvent.h create mode 100644 Source/modules/asura-core/Input/InputManager.cpp create mode 100644 Source/modules/asura-core/Input/InputManager.h create mode 100644 Source/modules/asura-core/Input/JoystickState.h create mode 100644 Source/modules/asura-core/Input/KeyboardState.h create mode 100644 Source/modules/asura-core/Input/MouseState.h create mode 100644 Source/modules/asura-core/Mesh/Am2Handler.cpp create mode 100644 Source/modules/asura-core/Mesh/Am2Handler.h create mode 100644 Source/modules/asura-core/Mesh/Mesh2DData.cpp create mode 100644 Source/modules/asura-core/Mesh/Mesh2DData.h create mode 100644 Source/modules/asura-core/Mesh/Mesh2DHandler.cpp create mode 100644 Source/modules/asura-core/Mesh/Mesh2DHandler.h create mode 100644 Source/modules/asura-core/Mesh/ObjHandler.cpp create mode 100644 Source/modules/asura-core/Mesh/ObjHandler.h create mode 100644 Source/modules/asura-core/Profiler/GPUProfiler.cpp create mode 100644 Source/modules/asura-core/Profiler/GPUProfiler.h create mode 100644 Source/modules/asura-core/Profiler/Stats.cpp create mode 100644 Source/modules/asura-core/Profiler/Stats.h create mode 100644 Source/modules/asura-core/Threads/Channel.cpp create mode 100644 Source/modules/asura-core/Threads/Channel.h create mode 100644 Source/modules/asura-core/Threads/ThreadEx.cpp create mode 100644 Source/modules/asura-core/Threads/ThreadEx.h create mode 100644 Source/modules/asura-core/Time/Timer.cpp create mode 100644 Source/modules/asura-core/Time/Timer.h create mode 100644 Source/modules/asura-core/Window/Window.cpp create mode 100644 Source/modules/asura-core/Window/Window.h create mode 100644 Source/modules/asura-core/Window/WindowImplGlew.cpp create mode 100644 Source/modules/asura-core/Window/WindowImplGlew.h create mode 100644 Source/modules/asura-core/Window/WindowImplGlut.h create mode 100644 Source/modules/asura-core/Window/WindowImplSDL.cpp create mode 100644 Source/modules/asura-core/Window/WindowImplSDL.h create mode 100644 Source/modules/asura-core/Window/WinodwImplGlut.cpp create mode 100644 Source/modules/asura-core/Window/binding/_window.cpp create mode 100644 Source/modules/asura-fmod/Audio/Source.h create mode 100644 Source/modules/asura-fmod/FMODModule.h create mode 100644 Source/modules/asura-framework/compile.bat create mode 100644 Source/modules/asura-framework/compile.sh create mode 100644 Source/modules/asura-framework/main.cpp create mode 100644 Source/modules/asura-framework/scripts/ai/behavior_tree.lua create mode 100644 Source/modules/asura-framework/scripts/ai/state_graph.lua create mode 100644 Source/modules/asura-framework/scripts/ai/state_machine.lua create mode 100644 Source/modules/asura-framework/scripts/audio/sound.lua create mode 100644 Source/modules/asura-framework/scripts/audio/source.lua create mode 100644 Source/modules/asura-framework/scripts/class.lua create mode 100644 Source/modules/asura-framework/scripts/component.lua create mode 100644 Source/modules/asura-framework/scripts/entity.lua create mode 100644 Source/modules/asura-framework/scripts/filesystem/animation_loader.lua create mode 100644 Source/modules/asura-framework/scripts/filesystem/asset.lua create mode 100644 Source/modules/asura-framework/scripts/filesystem/entity_loader.lua create mode 100644 Source/modules/asura-framework/scripts/filesystem/image_loader.lua create mode 100644 Source/modules/asura-framework/scripts/filesystem/loader.lua create mode 100644 Source/modules/asura-framework/scripts/filesystem/material_loader.lua create mode 100644 Source/modules/asura-framework/scripts/filesystem/path_loader.lua create mode 100644 Source/modules/asura-framework/scripts/filesystem/scene_loader.lua create mode 100644 Source/modules/asura-framework/scripts/filesystem/script_loader.lua create mode 100644 Source/modules/asura-framework/scripts/filesystem/shader_loader.lua create mode 100644 Source/modules/asura-framework/scripts/filesystem/statemap_loader.lua create mode 100644 Source/modules/asura-framework/scripts/framework.lua create mode 100644 Source/modules/asura-framework/scripts/graphics/animation.lua create mode 100644 Source/modules/asura-framework/scripts/graphics/animator.lua create mode 100644 Source/modules/asura-framework/scripts/graphics/camera.lua create mode 100644 Source/modules/asura-framework/scripts/graphics/canvas.lua create mode 100644 Source/modules/asura-framework/scripts/graphics/default_shaders.lua create mode 100644 Source/modules/asura-framework/scripts/graphics/image.lua create mode 100644 Source/modules/asura-framework/scripts/graphics/material.lua create mode 100644 Source/modules/asura-framework/scripts/graphics/material_manager.lua create mode 100644 Source/modules/asura-framework/scripts/graphics/mesh2d.lua create mode 100644 Source/modules/asura-framework/scripts/graphics/mesh2d_renderer.lua create mode 100644 Source/modules/asura-framework/scripts/graphics/particle_system.lua create mode 100644 Source/modules/asura-framework/scripts/graphics/renderer.lua create mode 100644 Source/modules/asura-framework/scripts/graphics/shader.lua create mode 100644 Source/modules/asura-framework/scripts/graphics/shaderHelper.lua create mode 100644 Source/modules/asura-framework/scripts/graphics/shape.lua create mode 100644 Source/modules/asura-framework/scripts/graphics/shape_renderer.lua create mode 100644 Source/modules/asura-framework/scripts/graphics/sprite.lua create mode 100644 Source/modules/asura-framework/scripts/graphics/sprite_batch_renderer.lua create mode 100644 Source/modules/asura-framework/scripts/graphics/sprite_renderer.lua create mode 100644 Source/modules/asura-framework/scripts/gui/button.lua create mode 100644 Source/modules/asura-framework/scripts/gui/text.lua create mode 100644 Source/modules/asura-framework/scripts/gui/widget.lua create mode 100644 Source/modules/asura-framework/scripts/managers/scene_manager.lua create mode 100644 Source/modules/asura-framework/scripts/managers/sprite_manager.lua create mode 100644 Source/modules/asura-framework/scripts/math/curve.lua create mode 100644 Source/modules/asura-framework/scripts/path/path.lua create mode 100644 Source/modules/asura-framework/scripts/path/path_calculator.lua create mode 100644 Source/modules/asura-framework/scripts/path/path_manager.lua create mode 100644 Source/modules/asura-framework/scripts/scene.lua create mode 100644 Source/modules/asura-framework/scripts/transform.lua create mode 100644 Source/modules/asura-json/Json/Json.cpp create mode 100644 Source/modules/asura-json/Json/Json.h create mode 100644 Source/modules/asura-json/JsonModule.cpp create mode 100644 Source/modules/asura-json/JsonModule.h create mode 100644 Source/modules/asura-network/NetworkModule.h create mode 100644 Source/modules/asura-openal/Audio/Audio.cpp create mode 100644 Source/modules/asura-openal/Audio/Audio.h create mode 100644 Source/modules/asura-openal/Audio/MPG123Decoder.cpp create mode 100644 Source/modules/asura-openal/Audio/MPG123Decoder.h create mode 100644 Source/modules/asura-openal/Audio/Sound.cpp create mode 100644 Source/modules/asura-openal/Audio/Sound.h create mode 100644 Source/modules/asura-openal/Audio/SoundData.cpp create mode 100644 Source/modules/asura-openal/Audio/SoundData.h create mode 100644 Source/modules/asura-openal/Audio/SoundDecodeTask.cpp create mode 100644 Source/modules/asura-openal/Audio/SoundDecodeTask.h create mode 100644 Source/modules/asura-openal/Audio/SoundDecoder.cpp create mode 100644 Source/modules/asura-openal/Audio/SoundDecoder.h create mode 100644 Source/modules/asura-openal/Audio/Source.cpp create mode 100644 Source/modules/asura-openal/Audio/Source.h create mode 100644 Source/modules/asura-openal/Audio/VorbisDecoder.cpp create mode 100644 Source/modules/asura-openal/Audio/VorbisDecoder.h (limited to 'Source/modules') 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 +#include + +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 +#include + +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 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(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(1); + lua_pushinteger(L, self->GetSize()); + return 1; + } + + // capacity = databuffer:GetCapacity() + LUAX_IMPL_METHOD(DataBuffer, _GetCapacity) + { + LUAX_SETUP(L, "U"); + + DataBuffer* self = state.GetUserdata(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(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(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(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(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(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(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(2); + if (!db) return state.ErrorType(2, "DataBuffer"); + int len = state.CheckValue(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(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(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(2); + int size = state.CheckValue(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(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(1, ""); + cc8* moutpoint = state.GetValue(2, "/"); + bool prepend = state.GetValue(3, false); + mounted = fs->Mount(path, moutpoint, prepend); + } + else if (state.IsType(1, LUA_TUSERDATA)) + { + DataBuffer* db = state.CheckUserdata(1); + if (!db) + return state.ErrorType(1, "Data Buffer"); + cc8* arcname = state.GetValue(2, ""); + cc8* mountpoint = state.GetValue(3, "/"); + bool prepend = state.GetValue(4, false); + mounted = fs->Mount(db, arcname, mountpoint, prepend); + // retain + fs->LuaxRetain(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(1, ""); + unmounted = fs->Unmount(path); + } + else if (state.IsType(1, LUA_TUSERDATA)) + { + DataBuffer* db = state.CheckUserdata(1); + if (!db) + return state.ErrorType(1, "Data Buffer"); + unmounted = fs->Unmount(db); + if (unmounted) + fs->LuaxRelease(state, db); + } + state.Push(unmounted); + return 1; + } + + // moutpoint = FileManager.GetMountPoint(path) + LUAX_IMPL_METHOD(FileManager, _GetMountPoint) + { + PREPARE(L); + + cc8* path = state.CheckValue(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(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(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(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(1); + DataBuffer* db = state.CheckUserdata(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(1); + DataBuffer* db = state.CheckUserdata(2); + state.Push(fs->Append(path, db)); + return 1; + } + + // successed = FileManager.Remove(path) + LUAX_IMPL_METHOD(FileManager, _Remove) + { + PREPARE(L); + + cc8* path = state.CheckValue(1); + state.Push(fs->Remove(path)); + return 1; + } + + // filedata = FileManager.Read(path) + LUAX_IMPL_METHOD(FileManager, _Read) + { + PREPARE(L); + + cc8* path = state.CheckValue(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(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(1); + std::vector 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(1); + DataBuffer* db = state.CheckUserdata(2); + IOTaskType type = (IOTaskType)state.CheckValue(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 + { + 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 +#include +#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 + +#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 + { + 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首地址和里面数据的长度 + /// + 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 + +#include + +#include "../Scripting/Scripting.h" + +#include "DataBuffer.h" + +namespace AsuraEngine +{ + namespace FileSystem + { + + /// + /// 可以在另一个线程构建的data继承此类。如图片数据、音频数据等,可以在另一个线程中解析原 + /// 文件,生成内部数据格式,如像素等。 + /// + ASURA_ABSTRACT class DecodedData + { + public: + + /// + /// 从内存中构建data,可以放在另一个线程里面,从资源管理系统里面加载。 + /// + DecodedData() {}; + virtual ~DecodedData() {}; + + /// + /// 解码内存中的数据并以某种格式保存。 + /// + 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 + +#include + +#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 + { + 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); + + /// + /// 异步写文件,将写文件task加入thread的队列。 + /// + 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 + +#include + +#include "DataBuffer.h" + +namespace AsuraEngine +{ + namespace FileSystem + { + + class Filesystem; + + /// + /// 当从filesystem直接读取整个文件时,返回FileData对象描述文件内容和其他信息。由Filesystem创建。 + /// + class FileData ASURA_FINAL + : public AEScripting::Portable + { + 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 buffer不会再filedata析构时销毁,当lua引用计数为0时由lua调用GC销毁。创建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 + +#include "../Exception.h" + +#include "File.h" +#include "FileData.h" +#include "FileManager.h" + +using namespace std; + +namespace AsuraEngine +{ + namespace FileSystem + { + +#ifdef ASURA_WINDOWS + #include + #include +#else + #include + #include +#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 +#include + +#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; + }; + + /// + /// 资源管理,负责加载、存储资源,指定根目录等。无论编辑器还是运行时,都需要限制访问的机制,将用户的操作限制在游戏目录 + /// 下,file system就是做这件事的。FileManager是运行时和编辑器共用的类,AssetDatabase是用来管理资源的类,在framework + /// 里实现,单纯是逻辑处理,读写还是用FileManager实现,AssetDatabase提供根据文件内容创建对应资源的方法。 + /// + class FileManager ASURA_FINAL + : public Singleton + , public AEScripting::Portable + { + 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& items) { return false; }; + + private: + + typedef std::map 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 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 + +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 + +#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 + { + 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 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 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 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 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 // memcpy +#include + +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 + +#include "../Scripting/Scripting.h" + +namespace_begin(AsuraEngine) +namespace_begin(Math) + +/// 不需要转置的OpenGL矩阵,类似glm::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 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 + +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 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 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 +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& src1, const Rect& src2, Rect& 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 Recti; +typedef Rect Rectu; +typedef Rect Rectf; +typedef Rect 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 +inline Rect::Rect() + : x(0) + , y(0) + , w(0) + , h(0) +{ + +} + +template +inline Rect::Rect(T X, T Y, T W, T H) + : x(X) + , y(Y) + , w(W) + , h(H) +{ + +} + +template +void Rect::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 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 + +namespace_begin(AsuraEngine) +namespace_begin(Math) + +template +class Vector2 +{ +public: + Vector2(); + Vector2(T X, T Y); + + template + explicit Vector2(const Vector2& vector); + + void Set(T X, T Y); + + T x; ///< X coordinate of the vector + T y; ///< Y coordinate of the vector +}; + +template +Vector2 operator -(const Vector2& right); + +template +Vector2& operator +=(Vector2& left, const Vector2& right); + +template +Vector2& operator -=(Vector2& left, const Vector2& right); + +template +Vector2 operator +(const Vector2& left, const Vector2& right); + +template +Vector2 operator -(const Vector2& left, const Vector2& right); + +template +Vector2 operator *(const Vector2& left, T right); + +template +Vector2 operator *(T left, const Vector2& right); + +template +Vector2& operator *=(Vector2& left, T right); + +template +Vector2 operator /(const Vector2& left, T right); + +template +Vector2& operator /=(Vector2& left, T right); + +template +bool operator ==(const Vector2& left, const Vector2& right); + +template +bool operator !=(const Vector2& left, const Vector2& right); + +#include "Vector2.inc" + +typedef Vector2 Vector2i; +typedef Vector2 Vector2u; +typedef Vector2 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 +inline Vector2::Vector2() : + x(0), + y(0) +{ + +} + +template +inline Vector2::Vector2(T X, T Y) : + x(X), + y(Y) +{ + +} + +template +template +inline Vector2::Vector2(const Vector2& vector) : + x(static_cast(vector.x)), + y(static_cast(vector.y)) +{ +} + +template +inline void Vector2::Set(T X, T Y) +{ + x = X; + y = Y; +} + +template +inline Vector2 operator -(const Vector2& right) +{ + return Vector2(-right.x, -right.y); +} + +template +inline Vector2& operator +=(Vector2& left, const Vector2& right) +{ + left.x += right.x; + left.y += right.y; + + return left; +} + +template +inline Vector2& operator -=(Vector2& left, const Vector2& right) +{ + left.x -= right.x; + left.y -= right.y; + + return left; +} + +template +inline Vector2 operator +(const Vector2& left, const Vector2& right) +{ + return Vector2(left.x + right.x, left.y + right.y); +} + +template +inline Vector2 operator -(const Vector2& left, const Vector2& right) +{ + return Vector2(left.x - right.x, left.y - right.y); +} + +template +inline Vector2 operator *(const Vector2& left, T right) +{ + return Vector2(left.x * right, left.y * right); +} + +template +inline Vector2 operator *(T left, const Vector2& right) +{ + return Vector2(right.x * left, right.y * left); +} + +template +inline Vector2& operator *=(Vector2& left, T right) +{ + left.x *= right; + left.y *= right; + + return left; +} + +template +inline Vector2 operator /(const Vector2& left, T right) +{ + return Vector2(left.x / right, left.y / right); +} + +template +inline Vector2& operator /=(Vector2& left, T right) +{ + left.x /= right; + left.y /= right; + + return left; +} + +template +inline bool operator ==(const Vector2& left, const Vector2& right) +{ + return (left.x == right.x) && (left.y == right.y); +} + +template +inline bool operator !=(const Vector2& left, const Vector2& 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 + 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 + explicit Vector3(const Vector3& 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 + Vector3 operator -(const Vector3& 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 + Vector3& operator +=(Vector3& left, const Vector3& 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 + Vector3& operator -=(Vector3& left, const Vector3& 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 + Vector3 operator +(const Vector3& left, const Vector3& 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 + Vector3 operator -(const Vector3& left, const Vector3& 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 + Vector3 operator *(const Vector3& 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 + Vector3 operator *(T left, const Vector3& 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 + Vector3& operator *=(Vector3& 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 + Vector3 operator /(const Vector3& 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 + Vector3& operator /=(Vector3& 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 + bool operator ==(const Vector3& left, const Vector3& 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 + bool operator !=(const Vector3& left, const Vector3& right); + +#include "Vector3.inc" + + // Define the most common types + typedef Vector3 Vector3i; + typedef Vector3 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 +inline Vector3::Vector3() : + x(0), + y(0), + z(0) +{ + +} + + +//////////////////////////////////////////////////////////// +template +inline Vector3::Vector3(T X, T Y, T Z) : + x(X), + y(Y), + z(Z) +{ + +} + + +//////////////////////////////////////////////////////////// +template +template +inline Vector3::Vector3(const Vector3& vector) : + x(static_cast(vector.x)), + y(static_cast(vector.y)), + z(static_cast(vector.z)) +{ +} + + +//////////////////////////////////////////////////////////// +template +inline Vector3 operator -(const Vector3& left) +{ + return Vector3(-left.x, -left.y, -left.z); +} + + +//////////////////////////////////////////////////////////// +template +inline Vector3& operator +=(Vector3& left, const Vector3& right) +{ + left.x += right.x; + left.y += right.y; + left.z += right.z; + + return left; +} + + +//////////////////////////////////////////////////////////// +template +inline Vector3& operator -=(Vector3& left, const Vector3& right) +{ + left.x -= right.x; + left.y -= right.y; + left.z -= right.z; + + return left; +} + + +//////////////////////////////////////////////////////////// +template +inline Vector3 operator +(const Vector3& left, const Vector3& right) +{ + return Vector3(left.x + right.x, left.y + right.y, left.z + right.z); +} + + +//////////////////////////////////////////////////////////// +template +inline Vector3 operator -(const Vector3& left, const Vector3& right) +{ + return Vector3(left.x - right.x, left.y - right.y, left.z - right.z); +} + + +//////////////////////////////////////////////////////////// +template +inline Vector3 operator *(const Vector3& left, T right) +{ + return Vector3(left.x * right, left.y * right, left.z * right); +} + + +//////////////////////////////////////////////////////////// +template +inline Vector3 operator *(T left, const Vector3& right) +{ + return Vector3(right.x * left, right.y * left, right.z * left); +} + + +//////////////////////////////////////////////////////////// +template +inline Vector3& operator *=(Vector3& left, T right) +{ + left.x *= right; + left.y *= right; + left.z *= right; + + return left; +} + + +//////////////////////////////////////////////////////////// +template +inline Vector3 operator /(const Vector3& left, T right) +{ + return Vector3(left.x / right, left.y / right, left.z / right); +} + + +//////////////////////////////////////////////////////////// +template +inline Vector3& operator /=(Vector3& left, T right) +{ + left.x /= right; + left.y /= right; + left.z /= right; + + return left; +} + + +//////////////////////////////////////////////////////////// +template +inline bool operator ==(const Vector3& left, const Vector3& right) +{ + return (left.x == right.x) && (left.y == right.y) && (left.z == right.z); +} + + +//////////////////////////////////////////////////////////// +template +inline bool operator !=(const Vector3& left, const Vector3& 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 + 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 + explicit Vector4(const Vector4& 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 + Vector4 operator -(const Vector4& 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 + Vector4& operator +=(Vector4& left, const Vector4& 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 + Vector4& operator -=(Vector4& left, const Vector4& 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 + Vector4 operator +(const Vector4& left, const Vector4& 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 + Vector4 operator -(const Vector4& left, const Vector4& 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 + Vector4 operator *(const Vector4& 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 + Vector4 operator *(T left, const Vector4& 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 + Vector4& operator *=(Vector4& 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 + Vector4 operator /(const Vector4& 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 + Vector4& operator /=(Vector4& 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 + bool operator ==(const Vector4& left, const Vector4& 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 + bool operator !=(const Vector4& left, const Vector4& right); + +#include "Vector4.inc" + + // Define the most common types + typedef Vector4 Vector4i; + typedef Vector4 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 +inline Vector4::Vector4() : + x(0), + y(0), + z(0), + w(0) +{ + +} + + +//////////////////////////////////////////////////////////// +template +inline Vector4::Vector4(T X, T Y, T Z, T W) : + x(X), + y(Y), + z(Z), + w(W) +{ + +} + + +//////////////////////////////////////////////////////////// +template +template +inline Vector4::Vector4(const Vector4& vector) : + x(static_cast(vector.x)), + y(static_cast(vector.y)), + z(static_cast(vector.z)), + w(static_cast(vector.w)) +{ +} + + +//////////////////////////////////////////////////////////// +template +inline Vector4 operator -(const Vector4& left) +{ + return Vector4(-left.x, -left.y, -left.z, -left.w); +} + + +//////////////////////////////////////////////////////////// +template +inline Vector4& operator +=(Vector4& left, const Vector4& right) +{ + left.x += right.x; + left.y += right.y; + left.z += right.z; + left.w += right.w; + + return left; +} + + +//////////////////////////////////////////////////////////// +template +inline Vector4& operator -=(Vector4& left, const Vector4& right) +{ + left.x -= right.x; + left.y -= right.y; + left.z -= right.z; + left.w -= right.w; + + return left; +} + + +//////////////////////////////////////////////////////////// +template +inline Vector4 operator +(const Vector4& left, const Vector4& right) +{ + return Vector4(left.x + right.x, left.y + right.y, left.z + right.z, left.w + right.w); +} + + +//////////////////////////////////////////////////////////// +template +inline Vector4 operator -(const Vector4& left, const Vector4& right) +{ + return Vector4(left.x - right.x, left.y - right.y, left.z - right.z, left.w - right.w); +} + + +//////////////////////////////////////////////////////////// +template +inline Vector4 operator *(const Vector4& left, T right) +{ + return Vector4(left.x * right, left.y * right, left.z * right, left.w * right); +} + + +//////////////////////////////////////////////////////////// +template +inline Vector4 operator *(T left, const Vector4& right) +{ + return Vector4(right.x * left, right.y * left, right.z * left, right.w * left); +} + + +//////////////////////////////////////////////////////////// +template +inline Vector4& operator *=(Vector4& left, T right) +{ + left.x *= right; + left.y *= right; + left.z *= right; + left.w *= right; + + return left; +} + + +//////////////////////////////////////////////////////////// +template +inline Vector4 operator /(const Vector4& left, T right) +{ + return Vector4(left.x / right, left.y / right, left.z / right, left.w / right); +} + + +//////////////////////////////////////////////////////////// +template +inline Vector4& operator /=(Vector4& left, T right) +{ + left.x /= right; + left.y /= right; + left.z /= right; + left.w /= right; + + return left; +} + + +//////////////////////////////////////////////////////////// +template +inline bool operator ==(const Vector4& left, const Vector4& right) +{ + return (left.x == right.x) && (left.y == right.y) && (left.z == right.z) && (left.w == right.w); +} + + +//////////////////////////////////////////////////////////// +template +inline bool operator !=(const Vector4& left, const Vector4& 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 需要继承此类,以开启注册。在模块队列中按顺序添加这些模块,然后顺序调用Initialize和Finalize方法来初始化和 + /// 关闭这些模块。 + /// + 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 +#include +#include +} + +#include + +#include "../Type.h" +#include "../Classes.h" + +namespace_begin(AsuraEngine) +namespace_begin(Scripting) + +// 需要作为基类,访问userdata和member ref的类继承此类,注意必须是虚继承。 +using Object = Luax::LuaxObject; + +// 要注册给lua的native类需要继承此模板。BASE指定基类,默认是LuaxObject,如果指定基类必须是LuaxObject的派生类、 +template +using Portable = Luax::LuaxNativeClass; + +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 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(this); + }; + + virtual ~Singleton() {}; + + static T* instance; + + private: + + Singleton(const Singleton& singleton); + + Singleton& operator = (const Singleton& singleton); + + }; + + // 实例初始化为空 + template + T* Singleton::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 + +#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 + +#include "../Scripting/Scripting.h" + +namespace_begin(AsuraEngine) +namespace_begin(Threads) + +/// +/// lua协程,用来做一些逻辑并发操作。 +/// +class Coroutine ASURA_FINAL + : public AEScripting::Portable +{ +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 + +#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 +#include + +#include "../UtilsConfig.h" + +#if ASURA_THREAD_WIN32 +#include +#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 +#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 +#include +#include + +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(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(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 +#include + +#include + +#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_newthread创建出来的lua_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 + , 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,会等待手动stop。否则会在某时刻队列完成后自动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 m_TaskQueue; + Mutex m_TaskQueueMutex; + + /// + /// 延迟模式使用 + /// + std::queue 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 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 + 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 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 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 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 + +#include "Thread.h" + +namespace_begin(AsuraEngine) +namespace_begin(Threads) + +/// +/// Thread的std::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 + +#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 + +#include "thread.h" + +namespace_begin(AsuraEngine) +namespace_begin(Threads) + +/// +/// Thread的win32实现。 +/// +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(1, THREAD_TYPE_DEFERRED); + uint sleepTime = state.GetValue(2,1); + cc8* name = state.GetValue(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(2); + self->AddTask(task); + self->LuaxRetain(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(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 +#include +#include + +#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 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 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 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 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 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 + +namespace AsuraEngine +{ + + /// + /// 一个双向一一对应的映射,用来储存shader uniforms、statemathine state parameter的ID。 + /// + template + 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 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 +#include +#include // for memset, memcpy, memcmp, etc. +#include // for std::swap, std::min, std::copy, std::fill +#include // for std::swap, std::min, std::copy, std::fill +#include + +#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 +struct bitcount { + typedef byte_t element_type; + static const byte_t table[]; + +}; +//typedef count table_t; + + +// the table: wrapped in a class template, so +// that it is only instantiated if/when needed +// +template +const byte_t bitcount::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 +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::npos + // in the code below are to avoid a g++ 3.2 bug and a Borland bug. -JGS + template + 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 + 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 + 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 + 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 +void +to_string(const dynamic_bitset& b, + String& s); + +template +void +to_block_range(const dynamic_bitset& b, + BlockOutputIterator result); + +template +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(0) : static_cast(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(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(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 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<::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(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 +void +to_string(const dynamic_bitset& b, + std::basic_string& 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 +void +dump_to_string(const dynamic_bitset& b, + std::basic_string& 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 +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 +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(0); +} + +inline bool dynamic_bitset::set_(size_type n, bool value) +{ + if (value) + set_(n); + else + reset_(n); + return value != static_cast(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(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 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 + +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 + +#include +#include + +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 +{ +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 + +#include +#include + +namespace_begin(AsuraEngine) +namespace_begin(Physics) + +class ChainShape + : AEScripting::Portable +{ +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 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 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 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 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 + +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 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 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 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 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 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 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 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 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 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 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 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 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 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 +#include + +namespace_begin(AsuraEngine) +namespace_begin(Physics) + +class World : public AEScripting::Portable +{ + +}; + +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 +#include +#include +#include + +#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: + + // 添加module,application拥有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 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 +#include + +#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 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 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::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& 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 String::ToUtf8() const +// { +// // Prepare the output string +// std::basic_string output; +// output.reserve(m_String.length()); +// +// // Convert +// Utf32::ToUtf8(m_String.begin(), m_String.end(), std::back_inserter(output)); +// +// return output; +// } +// +// +// //////////////////////////////////////////////////////////// +// std::basic_string String::ToUtf16() const +// { +// // Prepare the output string +// std::basic_string output; +// output.reserve(m_String.length()); +// +// // Convert +// Utf32::ToUtf16(m_String.begin(), m_String.end(), std::back_inserter(output)); +// +// return output; +// } +// +// +// //////////////////////////////////////////////////////////// +// std::basic_string 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 +// +//#include +//#include +//#include +// +//namespace AsuraEngine +//{ +// namespace Text +// { +// +// +// //////////////////////////////////////////////////////////// +// /// \brief Utility string class that automatically handles +// /// conversions between types and encodings +// /// +// //////////////////////////////////////////////////////////// +// class String +// { +// public: +// +// //////////////////////////////////////////////////////////// +// // Types +// //////////////////////////////////////////////////////////// +// typedef std::basic_string::iterator Iterator; ///< Iterator type +// typedef std::basic_string::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& 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 +// 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 +// 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. +// /// +// /// \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 +// 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 ToUtf8() const; +// +// //////////////////////////////////////////////////////////// +// /// \brief Convert the Unicode string to a UTF-16 string +// /// +// /// \return Converted UTF-16 string +// /// +// /// \see toUtf8, toUtf32 +// /// +// //////////////////////////////////////////////////////////// +// std::basic_string 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 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 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 +String String::fromUtf8(T begin, T end) +{ + String string; + Utf8::toUtf32(begin, end, std::back_inserter(string.m_string)); + return string; +} + + +//////////////////////////////////////////////////////////// +template +String String::fromUtf16(T begin, T end) +{ + String string; + Utf16::toUtf32(begin, end, std::back_inserter(string.m_string)); + return string; +} + + +//////////////////////////////////////////////////////////// +template +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 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 +#include +#include +#include + +namespace AsuraEngine +{ + namespace Text + { + + template + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 +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(*begin)]; + if (begin + trailingBytes < end) + { + output = 0; + switch (trailingBytes) + { + case 5: output += static_cast(*begin++); output <<= 6; + case 4: output += static_cast(*begin++); output <<= 6; + case 3: output += static_cast(*begin++); output <<= 6; + case 2: output += static_cast(*begin++); output <<= 6; + case 1: output += static_cast(*begin++); output <<= 6; + case 0: output += static_cast(*begin++); + } + output -= offsets[trailingBytes]; + } + else + { + // Incomplete character + begin = end; + output = replacement; + } + + return begin; +} + + +//////////////////////////////////////////////////////////// +template +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((input | 0x80) & 0xBF); input >>= 6; + case 3: bytes[2] = static_cast((input | 0x80) & 0xBF); input >>= 6; + case 2: bytes[1] = static_cast((input | 0x80) & 0xBF); input >>= 6; + case 1: bytes[0] = static_cast (input | firstBytes[bytestoWrite]); + } + + // Add them to the output + output = std::copy(bytes, bytes + bytestoWrite, output); + } + + return output; +} + + +//////////////////////////////////////////////////////////// +template +In Utf<8>::Next(In begin, In end) +{ + Uint32 codepoint; + return Decode(begin, end, codepoint); +} + + +//////////////////////////////////////////////////////////// +template +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 +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 +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 +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 +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 +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 +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(codepoint) : replacement; + } + + return output; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<8>::ToUtf8(In begin, In end, Out output) +{ + return std::copy(begin, end, output); +} + + +//////////////////////////////////////////////////////////// +template +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 +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 +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 +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(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((input >> 10) + 0xD800); + *output++ = static_cast((input & 0x3FFUL) + 0xDC00); + } + + return output; +} + + +//////////////////////////////////////////////////////////// +template +In Utf<16>::Next(In begin, In end) +{ + Uint32 codepoint; + return Decode(begin, end, codepoint); +} + + +//////////////////////////////////////////////////////////// +template +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 +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 +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 +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 +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 +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 +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(*begin) : replacement; + begin++; + } + + return output; +} + + +//////////////////////////////////////////////////////////// +template +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 +Out Utf<16>::ToUtf16(In begin, In end, Out output) +{ + return std::copy(begin, end, output); +} + + +//////////////////////////////////////////////////////////// +template +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 +In Utf<32>::Decode(In begin, In /*end*/, Uint32& output, Uint32 /*replacement*/) +{ + output = *begin++; + return begin; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<32>::Encode(Uint32 input, Out output, Uint32 /*replacement*/) +{ + *output++ = input; + return output; +} + + +//////////////////////////////////////////////////////////// +template +In Utf<32>::Next(In begin, In /*end*/) +{ + return ++begin; +} + + +//////////////////////////////////////////////////////////// +template +std::size_t Utf<32>::Count(In begin, In end) +{ + return begin - end; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<32>::FromAnsi(In begin, In end, Out output, const std::locale& locale) +{ + while (begin < end) + *output++ = DecodeAnsi(*begin++, locale); + + return output; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<32>::FromWide(In begin, In end, Out output) +{ + while (begin < end) + *output++ = DecodeWide(*begin++); + + return output; +} + + +//////////////////////////////////////////////////////////// +template +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 +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 +Out Utf<32>::ToWide(In begin, In end, Out output, wchar_t replacement) +{ + while (begin < end) + output = EncodeWide(*begin++, output, replacement); + + return output; +} + + +//////////////////////////////////////////////////////////// +template +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(*begin) : replacement; + begin++; + } + + return output; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<32>::ToUtf8(In begin, In end, Out output) +{ + while (begin < end) + output = Utf<8>::Encode(*begin++, output); + + return output; +} + +//////////////////////////////////////////////////////////// +template +Out Utf<32>::ToUtf16(In begin, In end, Out output) +{ + while (begin < end) + output = Utf<16>::Encode(*begin++, output); + + return output; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<32>::ToUtf32(In begin, In end, Out output) +{ + return std::copy(begin, end, output); +} + + +//////////////////////////////////////////////////////////// +template +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(character); + + #else + + // Get the facet of the locale which deals with character conversion + const std::ctype& facet = std::use_facet< std::ctype >(locale); + + // Use the facet to convert each character of the input string + return static_cast(facet.widen(input)); + + #endif +} + + +//////////////////////////////////////////////////////////// +template +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 +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(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& facet = std::use_facet< std::ctype >(locale); + + // Use the facet to convert each character of the input string + *output++ = facet.narrow(static_cast(codepoint), replacement); + + return output; + + #endif +} + + +//////////////////////////////////////////////////////////// +template +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(codepoint); + break; + } + + default: + { + if ((codepoint <= 0xFFFF) && ((codepoint < 0xD800) || (codepoint > 0xDFFF))) + { + *output++ = static_cast(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 + +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, ¤t_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, ¤t_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, ¤t_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 +#include +#include +#include + +#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 +{ +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 +#include + +#include "../CoreConfig.h" + +namespace_begin(AsuraEngine) +namespace_begin(Graphics) + +class Color32; + +/// +/// 规范化颜色,相比Color32有更大的操作性。 +/// +class Color ASURA_FINAL + : public Scripting::Portable +{ +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 +#include + +#include "../CoreConfig.h" + +namespace_begin(AsuraEngine) +namespace_begin(Graphics) + +class Color; + +/// +/// 32bits颜色 +/// +class Color32 ASURA_FINAL + : public Scripting::Portable +{ +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 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 + +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 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 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 +#include +#include + +#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缓冲,分顶点缓冲vbo和索引缓冲ebo两种,避免每次都从内存向显存上传数据。在framework的renderers中构建。 +/// +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 + +#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 + +#include + +#include +#include +#include +#include + +#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 +{ +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 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 + +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 + +#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 +#include +#include +#include +#include +#include + +// 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 +{ +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 + +#include "GPUBuffer.h" + +namespace_begin(AsuraEngine) +namespace_begin(Graphics) + +/// +/// 顶点数据 +/// +class IndexBuffer ASURA_FINAL + : public AEScripting::Portable + , 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 +#include +#include + +namespace_begin(AsuraEngine) +namespace_begin(Graphics) + +/// +/// 栈的矩阵深度。 +/// +#define ASURA_MAX_MATRIX_STACK_DEPTH 32 // 2KB + +/// +/// 保存栈状态,用来恢复之前的状态。栈中的一个矩阵stack[i]的值是stack[0]*..*stack[i-1] +/// 的值,并附加一系列transform。 +/// +/// TODO: template 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 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 + +// asura modules +#include +#include + +// 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 +{ +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 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 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 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 @@ +// Quad和rect的区别在于,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 +#include + +#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 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 +#include +#include + +#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() {}; + + /// + /// 用颜色col清空整个RT + /// + virtual void Clear(const Color& col = Color::Black) = 0; + + /// + /// 用颜色col清空部分RT + /// + virtual void Clear(const Math::Recti& quad, const Color& col = Color::Black) = 0; + + /// + /// 绘制texture到本RT上 + /// + virtual void Draw(const Drawable* texture, const RenderState& state) = 0; + + /// + /// 绘制一部分texture到本RT上 + /// + 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 + +#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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "GfxDevice.h" +#include "Color.h" +#include "Texture.h" +#include "VertexBuffer.h" +#include "IndexBuffer.h" + +namespace_begin(AsuraEngine) +namespace_begin(Graphics) + +/// +/// 一个shader是一个在材质间共享的程序。Shader本身不保存uniforms和顶点数据,只提供设置 uniforms和use着色 +/// 器的方法。编辑器针对每个shader,会通过shader代码找到声明的uniforms变量,并暴露给framework的material +/// 设置。 +/// +class Shader ASURA_FINAL + : public Scripting::Portable + , 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 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 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 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 + +#include "GPUBuffer.h" + +namespace_begin(AsuraEngine) +namespace_begin(Graphics) + +/// +/// Sprite batch用在批量渲染单个图片的地方,比如粒子系统。 +/// +class SpriteBatch ASURA_FINAL + : public Scripting::Portable +{ +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 + +#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 +#include + +#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, ///< RGBA都是8bits int + COLOR_FORMAT_RGBA32F, ///< RGBA都是32bits float +}; + +/// 纹理格式,GPU内部和CPU外部格式 +struct TextureFormat +{ + GLenum internalformat; ///< GPU内部格式 + GLenum externalformat; ///< CPU外部格式 + GLenum type; ///< 外部格式每个channel数值类型 +}; + +/// +/// 2D纹理抽象类,在2d mesh和render 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(); + + /// 如果设置U或V方向filter为 + 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 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 + +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 + +#include "GPUBuffer.h" + +namespace_begin(AsuraEngine) +namespace_begin(Graphics) + +/// +/// 向framework提供了创建显存缓冲的功能,可以直接设置缓冲,绝大多数功能都可以通过此类直接设置顶点数据。 +/// +class VertexBuffer ASURA_FINAL + : public AEScripting::Portable + , 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 + +#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(-1); + memcpy(data + (i - 1)*unit, &n, unit); + break; + } + case GL_FLOAT: + { + float n = state.CheckValue(-1); + memcpy(data + (i - 1)*unit, &n, unit); + break; + } + case GL_UNSIGNED_BYTE: + { + unsigned char n = state.CheckValue(-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(2); + FilterMode mag = (FilterMode)state.CheckValue(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(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(1); + BufferDataType datatype = (BufferDataType)state.CheckValue(2); + uint count = state.CheckValue(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) + +// 解析image的decoder,用来作为解析策略。 +list 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 + +#include +#include +#include +#include +#include + +#include "../Graphics/Texture.h" +#include "../Graphics/Color.h" + +namespace_begin(AsuraEngine) +namespace_begin(Image) + +class ImageDecoder; + +class ImageData ASURA_FINAL + : public Scripting::Portable + , 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 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 +#include +#include + +namespace_begin(AsuraEngine) +namespace_begin(Image) + +class ImageDecodeTask + : public AEScripting::Portable +{ +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 + +#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 + +#include "StbDecoder.h" + +#define STB_IMAGE_IMPLEMENTATION +#include + +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)) + { + // 4个channel都是float + 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解压JPEG、TGA、BMP文件 +/// +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 +#include + +#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(2); + DataBuffer* buffer = state.CheckUserdata(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 + +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 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 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 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 + +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 +#include +#include + +#include + +#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 &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 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 +#include +#include + +#include +#include + +namespace_begin(AsuraEngine) +namespace_begin(Input) + +// 所有的客户端事件,如键盘、重绘、鼠标 +struct InputEvent +{ + InputEvent(); + ~InputEvent(); + +#if ASURA_EDITOR + + bool Open(HWND window); + void Close(void); + + bool GetJoystickNames(std::vector &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 +#include +#include +#include +#include + +#include +#include + +#include "InputAxis.h" + +namespace_begin(AsuraEngine) +namespace_begin(Input) + +class InputManager : public Singleton +{ +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 m_Axis; + + AEMath::Vector2f m_MouseDelta; + AEMath::Vector2f m_MousePos; + + bool m_MousePresent; + + std::vector> 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 + +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 + +#include "Button.h" + +namespace_begin(AsuraEngine) +namespace_begin(Input) + +typedef std::vector