diff --git a/.gitignore b/.gitignore index 12be364..9727abb 100755 --- a/.gitignore +++ b/.gitignore @@ -25,6 +25,8 @@ StarEngine.v11.suo # Generated Directories bin/ gen/ +build/ +lib/ Debug/ Release/ Obj/ @@ -61,3 +63,4 @@ armeabi/ # starengine files *.star +StarLog.txt diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..6458477 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 3.14) +project(StarEngine + VERSION 0.1.1 + LANGUAGES CXX + DESCRIPTION "A 2D game engine" +) + +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) + +# Build options +option(STAR2D "Enable 2D mode" ON) +option(STARENGINE_BUILD_EXAMPLES "Build example projects" ON) + +# Output directories +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) + +# Add the engine library +add_subdirectory(src) + +# Example / test programs +if(STARENGINE_BUILD_EXAMPLES) + add_subdirectory(test/pong) +endif() \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..30d4e9f --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,276 @@ +# StarEngine static library +# ------------------------- + +# --- Collect source files --- + +# Core engine sources +set(STARENGINE_CORE_SOURCES + StarEngine.cpp + definesCrossPlatform.cpp + Entity.cpp + EventLoop.cpp + Logger.cpp + TimeManager.cpp +) + +# Console is Windows-only (uses WinAPI) +if(WIN32) + list(APPEND STARENGINE_CORE_SOURCES Console.cpp) +endif() + +# Actions +set(STARENGINE_ACTIONS_SOURCES + Actions/Action.cpp + Actions/DelayedAction.cpp + Actions/DelayedFramesAction.cpp + Actions/LoopedAction.cpp + Actions/ScaleAction.cpp + Actions/TimedAction.cpp + Actions/TimedFadeAction.cpp + Actions/TimedMoveAction.cpp + Actions/TimedScaleAction.cpp +) + +# AI +set(STARENGINE_AI_SOURCES + AI/Pathfinding/PathFindManager.cpp + AI/Pathfinding/SearchCell.cpp +) + +# Components +set(STARENGINE_COMPONENTS_SOURCES + Components/BaseComponent.cpp + Components/CameraComponent.cpp + Components/TransformComponent.cpp + Components/AI/PathFindNodeComponent.cpp + Components/Graphics/SpriteComponent.cpp + Components/Graphics/SpritesheetComponent.cpp + Components/Graphics/TextComponent.cpp + Components/Physics/BaseColliderComponent.cpp + Components/Physics/CircleColliderComponent.cpp + Components/Physics/RectangleColliderComponent.cpp +) + +# Graphics +set(STARENGINE_GRAPHICS_SOURCES + Graphics/Color.cpp + Graphics/Font.cpp + Graphics/FontManager.cpp + Graphics/GraphicsManager.cpp + Graphics/ScaleSystem.cpp + Graphics/Shader.cpp + Graphics/SpriteAnimationManager.cpp + Graphics/SpriteBatch.cpp + Graphics/Texture2D.cpp + Graphics/TextureManager.cpp +) + +# Resource.cpp is Android-only (AAsset) +if(ANDROID) + list(APPEND STARENGINE_GRAPHICS_SOURCES Graphics/Resource.cpp) +endif() + +# Graphics UI +set(STARENGINE_UI_SOURCES + Graphics/UI/UIAnimatedButton.cpp + Graphics/UI/UIAnimatedImage.cpp + Graphics/UI/UIAnimatedTextButton.cpp + Graphics/UI/UIBaseCursor.cpp + Graphics/UI/UIButton.cpp + Graphics/UI/UICursor.cpp + Graphics/UI/UIDock.cpp + Graphics/UI/UIImage.cpp + Graphics/UI/UIObject.cpp + Graphics/UI/UISimpleTextButton.cpp + Graphics/UI/UISlider.cpp + Graphics/UI/UIStaticButton.cpp + Graphics/UI/UIStaticTextButton.cpp + Graphics/UI/UITextButton.cpp + Graphics/UI/UITextField.cpp + Graphics/UI/UIUserElement.cpp +) + +# Helpers +set(STARENGINE_HELPERS_SOURCES + Helpers/AARect.cpp + Helpers/Debug/DebugDraw.cpp + Helpers/Filepath.cpp + Helpers/FPS.cpp + Helpers/GameData.cpp + Helpers/HashTag.cpp + Helpers/Helpers.cpp + Helpers/HelpersCrossplatform.cpp + Helpers/Math.cpp + Helpers/Rect.cpp + Helpers/SerializedData.cpp + Helpers/SpriteAnimation.cpp + Helpers/Spritesheet.cpp + Helpers/State.cpp + Helpers/StateManager.cpp + Helpers/Stopwatch.cpp + Helpers/Time.cpp + Helpers/Timer.cpp + Helpers/TimerManager.cpp + Helpers/2D/pos.cpp +) + +# Input +set(STARENGINE_INPUT_SOURCES + Input/InputManager.cpp + Input/XMLContainer.cpp + Input/XMLFileParser.cpp + Input/XMLFileSerializer.cpp + Input/Gestures/BaseGesture.cpp + Input/Gestures/DoubleTapGesture.cpp + Input/Gestures/GestureManager.cpp + Input/Gestures/SwipeGesture.cpp + Input/Gestures/TapGesture.cpp +) + +# Objects +set(STARENGINE_OBJECTS_SOURCES + Objects/BaseCamera.cpp + Objects/FreeCamera.cpp + Objects/Object.cpp +) + +# Physics +set(STARENGINE_PHYSICS_SOURCES + Physics/Collision/CollisionManager.cpp +) + +# Scenes +set(STARENGINE_SCENES_SOURCES + Scenes/BaseScene.cpp + Scenes/SceneManager.cpp + Scenes/SlideScene.cpp + Scenes/SplashScreen.cpp + Scenes/TiledScene.cpp +) + +# Sound +set(STARENGINE_SOUND_SOURCES + Sound/AudioManager.cpp + Sound/BaseSound.cpp + Sound/SoundEffect.cpp + Sound/SoundFile.cpp +) + +# Bundled third-party (PugiXML) +set(STARENGINE_THIRDPARTY_SOURCES + Input/PugiXML/src/pugixml.cpp +) + +# --- Platform-specific sources --- + +if(WIN32) + set(STARENGINE_PLATFORM_SOURCES + Platforms/Windows/Window.cpp + Helpers/glm/core/dummy.cpp + ) +elseif(ANDROID) + set(STARENGINE_PLATFORM_SOURCES + Helpers/HelpersAndroid.cpp + Helpers/glm/core/dummy.cpp + ) +else() + # Linux / other Unix + set(STARENGINE_PLATFORM_SOURCES + Helpers/glm/core/dummy.cpp + ) +endif() + +# --- Combine all sources --- +set(STARENGINE_ALL_SOURCES + ${STARENGINE_CORE_SOURCES} + ${STARENGINE_ACTIONS_SOURCES} + ${STARENGINE_AI_SOURCES} + ${STARENGINE_COMPONENTS_SOURCES} + ${STARENGINE_GRAPHICS_SOURCES} + ${STARENGINE_UI_SOURCES} + ${STARENGINE_HELPERS_SOURCES} + ${STARENGINE_INPUT_SOURCES} + ${STARENGINE_OBJECTS_SOURCES} + ${STARENGINE_PHYSICS_SOURCES} + ${STARENGINE_SCENES_SOURCES} + ${STARENGINE_SOUND_SOURCES} + ${STARENGINE_THIRDPARTY_SOURCES} + ${STARENGINE_PLATFORM_SOURCES} +) + +# --- Create the static library --- +add_library(starengine STATIC ${STARENGINE_ALL_SOURCES}) + +# --- Include directories --- +target_include_directories(starengine + PUBLIC + $ + $ + $ +) + +# --- Compile definitions --- + +# Platform defines +if(WIN32) + target_compile_definitions(starengine PUBLIC DESKTOP) +elseif(ANDROID) + target_compile_definitions(starengine PUBLIC MOBILE) +else() + # Linux: treat as desktop platform + target_compile_definitions(starengine PUBLIC DESKTOP) +endif() + +# Feature defines +if(STAR2D) + target_compile_definitions(starengine PUBLIC STAR2D=1) +endif() + +target_compile_definitions(starengine PUBLIC LOGGER_MIN_LEVEL=1) + +# --- Find and link dependencies --- + +# OpenGL +find_package(OpenGL REQUIRED) +target_link_libraries(starengine PUBLIC OpenGL::GL) + +# GLEW (desktop only) +if(NOT ANDROID) + find_package(GLEW REQUIRED) + target_link_libraries(starengine PUBLIC GLEW::GLEW) +endif() + +# SDL2 +find_package(PkgConfig REQUIRED) +pkg_check_modules(SDL2 REQUIRED IMPORTED_TARGET sdl2) +target_link_libraries(starengine PUBLIC PkgConfig::SDL2) + +# SDL2_mixer +pkg_check_modules(SDL2_MIXER REQUIRED IMPORTED_TARGET SDL2_mixer) +target_link_libraries(starengine PUBLIC PkgConfig::SDL2_MIXER) + +# Freetype +find_package(Freetype REQUIRED) +target_link_libraries(starengine PUBLIC Freetype::Freetype) + +# PNG +find_package(PNG REQUIRED) +target_link_libraries(starengine PUBLIC PNG::PNG) + +# --- Compiler warnings and features --- +target_compile_features(starengine PUBLIC cxx_std_11) + +if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") + target_compile_options(starengine PRIVATE + -Wall + -Wextra + -Wno-unused-parameter + -Wno-reorder + -fexceptions + -frtti + ) +endif() + +if(MSVC) + target_compile_options(starengine PRIVATE /W3 /EHsc) +endif() diff --git a/src/Components/CameraComponent.h b/src/Components/CameraComponent.h index 6a9520d..c01091f 100755 --- a/src/Components/CameraComponent.h +++ b/src/Components/CameraComponent.h @@ -1,5 +1,5 @@ #pragma once -#include "..\defines.h" +#include "../defines.h" #include "BaseComponent.h" namespace star diff --git a/src/Components/Graphics/SpriteComponent.cpp b/src/Components/Graphics/SpriteComponent.cpp index 851dfbd..d031cec 100755 --- a/src/Components/Graphics/SpriteComponent.cpp +++ b/src/Components/Graphics/SpriteComponent.cpp @@ -1,7 +1,7 @@ #include "SpriteComponent.h" #include "../../Objects/Object.h" #include "../../Graphics/SpriteBatch.h" -#include "SpriteSheetComponent.h" +#include "SpritesheetComponent.h" #include "TextComponent.h" namespace star diff --git a/src/Components/Graphics/SpriteComponent.h b/src/Components/Graphics/SpriteComponent.h index 058a3f5..7fda223 100755 --- a/src/Components/Graphics/SpriteComponent.h +++ b/src/Components/Graphics/SpriteComponent.h @@ -2,7 +2,7 @@ #include "../../defines.h" #include "../BaseComponent.h" -#include "../../Helpers/FilePath.h" +#include "../../Helpers/Filepath.h" #include "../../Graphics/Color.h" namespace star diff --git a/src/Components/Graphics/SpritesheetComponent.cpp b/src/Components/Graphics/SpritesheetComponent.cpp index f5e7cb5..79e4d9c 100755 --- a/src/Components/Graphics/SpritesheetComponent.cpp +++ b/src/Components/Graphics/SpritesheetComponent.cpp @@ -1,4 +1,4 @@ -#include "SpriteSheetComponent.h" +#include "SpritesheetComponent.h" #include "../../Graphics/SpriteAnimationManager.h" #include "../../Objects/Object.h" #include "TextComponent.h" diff --git a/src/Components/Graphics/SpritesheetComponent.h b/src/Components/Graphics/SpritesheetComponent.h index 3cef0bb..2df3b5a 100755 --- a/src/Components/Graphics/SpritesheetComponent.h +++ b/src/Components/Graphics/SpritesheetComponent.h @@ -3,7 +3,7 @@ #include "SpriteComponent.h" #include #include "../../Helpers/SpriteAnimation.h" -#include "../../Helpers/SpriteSheet.h" +#include "../../Helpers/Spritesheet.h" namespace star { diff --git a/src/Components/Graphics/TextComponent.cpp b/src/Components/Graphics/TextComponent.cpp index fb9582a..4a50ef4 100755 --- a/src/Components/Graphics/TextComponent.cpp +++ b/src/Components/Graphics/TextComponent.cpp @@ -2,7 +2,7 @@ #include "../../Graphics/FontManager.h" #include "../../Objects/Object.h" #include "SpriteComponent.h" -#include "SpriteSheetComponent.h" +#include "SpritesheetComponent.h" #include "../../Graphics/SpriteBatch.h" namespace star diff --git a/src/Components/Physics/RectangleColliderComponent.h b/src/Components/Physics/RectangleColliderComponent.h index b6bf710..decb863 100755 --- a/src/Components/Physics/RectangleColliderComponent.h +++ b/src/Components/Physics/RectangleColliderComponent.h @@ -1,6 +1,6 @@ #pragma once #include "BaseColliderComponent.h" -#include "../../Helpers\Rect.h" +#include "../../Helpers/Rect.h" namespace star { diff --git a/src/Components/TransformComponent.cpp b/src/Components/TransformComponent.cpp index c4ebc9e..216cadf 100755 --- a/src/Components/TransformComponent.cpp +++ b/src/Components/TransformComponent.cpp @@ -1,9 +1,9 @@ #include "TransformComponent.h" -#include "..\Objects\Object.h" -#include "..\Logger.h" -#include "..\Context.h" -#include "..\Helpers\Math.h" -#include "..\Graphics\GraphicsManager.h" +#include "../Objects/Object.h" +#include "../Logger.h" +#include "../Context.h" +#include "../Helpers/Math.h" +#include "../Graphics/GraphicsManager.h" namespace star { diff --git a/src/Components/TransformComponent.h b/src/Components/TransformComponent.h index 81a5b3e..96c16d7 100755 --- a/src/Components/TransformComponent.h +++ b/src/Components/TransformComponent.h @@ -1,6 +1,6 @@ #pragma once -#include "..\defines.h" +#include "../defines.h" #include "BaseComponent.h" namespace star diff --git a/src/Console.cpp b/src/Console.cpp index 5e6c5aa..9eb0747 100755 --- a/src/Console.cpp +++ b/src/Console.cpp @@ -1,5 +1,5 @@ #include "Console.h" -#include "jni\defines.h" +#include "defines.h" namespace star_w { diff --git a/src/Graphics/Font.cpp b/src/Graphics/Font.cpp index 97ec6ec..0727d94 100755 --- a/src/Graphics/Font.cpp +++ b/src/Graphics/Font.cpp @@ -1,231 +1,231 @@ -#include "Font.h" -#include "../Logger.h" - -#ifndef DESKTOP -#include "Resource.h" -#include "../StarEngine.h" -#endif - -namespace star -{ - Font::Font(): - m_FontPath(EMPTY_STRING), - mFace(0), - mTextures(nullptr), - mMaxLetterHeight(), - mMinLetterHeight(), - mCharacterInfoMap(), - mSize(0) - { - } - - Font::~Font() - { - mCharacterInfoMap.clear(); - } - - bool Font::Init(const tstring& path, uint32 size, FT_Library& library) - { - mSize = size; - mTextures = new GLuint[FONT_TEXTURES]; - m_FontPath = path; - -#ifdef DESKTOP - //Convert from wstring to const schar* trough sstring - sstring font_path = string_cast(path); - FT_Error error = FT_New_Face(library,font_path.c_str(),0,&mFace); -#else - Resource resource(path); - if(!resource.Open()) - { - LOG(LogLevel::Error, - _T("Font : Failed to open file"), STARENGINE_LOG_TAG); - return false; - } - - int32 length = resource.GetLength(); - LOG(LogLevel::Info, - _T("Font : File size :") + star::string_cast(length), - STARENGINE_LOG_TAG); - mFontBuffer = new BYTE[length](); - - if(!resource.Read(mFontBuffer,length)) - { - LOG(LogLevel::Error, - _T("Font : Failed to read file"), STARENGINE_LOG_TAG); - resource.Close(); - return false; - } - - auto error = FT_New_Memory_Face(library,mFontBuffer,length,0,&mFace); - resource.Close(); -#endif - if(error == FT_Err_Unknown_File_Format) - { - LOG(star::LogLevel::Error, - _T("Font Manager : Font : ") + path + - _T(" ,could be opened but it's in an unsupported format"), - STARENGINE_LOG_TAG); - return (false); - } - else if(error) - { - LOG(star::LogLevel::Error, - _T("Font Manager : Font : ") + path + - _T(" ,is invalid and can't be opened or read."), - STARENGINE_LOG_TAG); - return (false); - } - LOG(star::LogLevel::Info, - _T("Font Manager : Font : ") + path + - _T(" ,loaded and ready for use"), - STARENGINE_LOG_TAG); - - int32 iSize = int32(size); - FT_Set_Char_Size(mFace, iSize << 6, iSize << 6, FONT_DPI, FONT_DPI); - - glGenTextures(FONT_TEXTURES, mTextures); - for(suchar i = 0; i < FONT_TEXTURES; ++i) - { - mCharacterInfoMap.insert(std::make_pair(i, CharacterInfo())); - Make_D_List(mFace, i, mTextures); - } - FT_Done_Face(mFace); - return true; - } - - void Font::DeleteFont() - { - glDeleteTextures(FONT_TEXTURES,mTextures); - delete[] mTextures; -#ifdef ANDROID - delete [] mFontBuffer; -#endif - } - - void Font::Make_D_List(FT_Face face, suchar ch,GLuint * tex_base) - { - auto error = FT_Load_Char(face, ch, FT_LOAD_DEFAULT); - if(error) - { - LOG(star::LogLevel::Error, - _T("Font : could not load glyph"), STARENGINE_LOG_TAG); - return; - } - - error = FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL); - if(error) - { - LOG(star::LogLevel::Error, - _T("Font : could not load glyph"), STARENGINE_LOG_TAG); - return; - } - - FT_Bitmap& bitmap = face->glyph->bitmap; - - int32 width = NextPowerOfTwo(bitmap.width); - int32 height = NextPowerOfTwo(bitmap.rows); - - GLubyte* expanded_data = new GLubyte[2 * width * height]; - - for(int32 j = 0; j < height; ++j) - { - for(int32 i = 0; i < width; ++i) - { - expanded_data[2 * (i + j * width)] = 255; - expanded_data[2 * (i + j * width) + 1] = - (i >= bitmap.width || j >= bitmap.rows) ? 0 : bitmap.buffer[i + bitmap.width * j]; - } - } - - glBindTexture(GL_TEXTURE_2D, tex_base[ch]); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR); -#ifdef DESKTOP - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, expanded_data); -#else - //For android "internal format" must be the same as "format" in glTexImage2D - glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, width, height, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, expanded_data); -#endif - OPENGL_LOG(); - delete[] expanded_data; - - //uvs - float32 x = static_cast(bitmap.width) / static_cast(width); - float32 y = static_cast(bitmap.rows) / static_cast(height); - //letter height - int32 dimX = (face->glyph->metrics.horiAdvance / 64); - int32 dimY = ((face->glyph->metrics.horiBearingY) - (face->glyph->metrics.height)) / 64; - if(mMaxLetterHeight < face->glyph->bitmap_top) - { - mMaxLetterHeight = face->glyph->bitmap_top; - } - if(mMinLetterHeight > dimY) - { - mMinLetterHeight = dimY; - } - mCharacterInfoMap.at(ch).letterDimensions = ivec2(dimX, dimY); - mCharacterInfoMap.at(ch).vertexDimensions = vec2(bitmap.width, bitmap.rows); - mCharacterInfoMap.at(ch).uvDimensions = vec2(x, y); - } - - const tstring & Font::GetFontPath() const - { - return m_FontPath; - } - - GLuint* Font::GetTextures() const - { - return mTextures; - } - - uint32 Font::GetFontSize() const - { - return mSize; - } - - int32 Font::NextPowerOfTwo(int32 number) const - { - int32 rval = 1; - while(rval < number) - { - rval <<= 1; - } - return rval; - } - - const std::unordered_map& Font::GetCharacterInfoMap() const - { - return mCharacterInfoMap; - } - - const CharacterInfo& Font::GetCharacterInfo(suchar character) const - { - //[COMMENT] Performing a good check here - //with std::find will only slow things down - //If the map.at has an unknown value, it will throw an exception anyway - return mCharacterInfoMap.at(character); - } - - int32 Font::GetMaxLetterHeight() const - { - return mMaxLetterHeight; - } - - int32 Font::GetMinLetterHeight() const - { - return mMinLetterHeight; - } - - uint32 Font::GetStringLength(const tstring& string) const - { - int32 length = 0; - sstring conv_text = star::string_cast(string); - const schar *line = conv_text.c_str(); - for(uint32 i = 0; line[i] != 0; ++i) - { - length += mCharacterInfoMap.at(line[i]).letterDimensions.x; - } - return length; - } -} +#include "Font.h" +#include "../Logger.h" + +#ifndef DESKTOP +#include "Resource.h" +#include "../StarEngine.h" +#endif + +namespace star +{ + Font::Font(): + m_FontPath(EMPTY_STRING), + mFace(0), + mTextures(nullptr), + mMaxLetterHeight(), + mMinLetterHeight(), + mCharacterInfoMap(), + mSize(0) + { + } + + Font::~Font() + { + mCharacterInfoMap.clear(); + } + + bool Font::Init(const tstring& path, uint32 size, FT_Library& library) + { + mSize = size; + mTextures = new GLuint[FONT_TEXTURES]; + m_FontPath = path; + +#ifdef DESKTOP + //Convert from wstring to const schar* trough sstring + sstring font_path = string_cast(path); + FT_Error error = FT_New_Face(library,font_path.c_str(),0,&mFace); +#elif defined(ANDROID) + Resource resource(path); + if(!resource.Open()) + { + LOG(LogLevel::Error, + _T("Font : Failed to open file"), STARENGINE_LOG_TAG); + return false; + } + + int32 length = resource.GetLength(); + LOG(LogLevel::Info, + _T("Font : File size :") + star::string_cast(length), + STARENGINE_LOG_TAG); + mFontBuffer = new BYTE[length](); + + if(!resource.Read(mFontBuffer,length)) + { + LOG(LogLevel::Error, + _T("Font : Failed to read file"), STARENGINE_LOG_TAG); + resource.Close(); + return false; + } + + auto error = FT_New_Memory_Face(library,mFontBuffer,length,0,&mFace); + resource.Close(); +#endif + if(error == FT_Err_Unknown_File_Format) + { + LOG(star::LogLevel::Error, + _T("Font Manager : Font : ") + path + + _T(" ,could be opened but it's in an unsupported format"), + STARENGINE_LOG_TAG); + return (false); + } + else if(error) + { + LOG(star::LogLevel::Error, + _T("Font Manager : Font : ") + path + + _T(" ,is invalid and can't be opened or read."), + STARENGINE_LOG_TAG); + return (false); + } + LOG(star::LogLevel::Info, + _T("Font Manager : Font : ") + path + + _T(" ,loaded and ready for use"), + STARENGINE_LOG_TAG); + + int32 iSize = int32(size); + FT_Set_Char_Size(mFace, iSize << 6, iSize << 6, FONT_DPI, FONT_DPI); + + glGenTextures(FONT_TEXTURES, mTextures); + for(suchar i = 0; i < FONT_TEXTURES; ++i) + { + mCharacterInfoMap.insert(std::make_pair(i, CharacterInfo())); + Make_D_List(mFace, i, mTextures); + } + FT_Done_Face(mFace); + return true; + } + + void Font::DeleteFont() + { + glDeleteTextures(FONT_TEXTURES,mTextures); + delete[] mTextures; +#ifdef ANDROID + delete [] mFontBuffer; +#endif + } + + void Font::Make_D_List(FT_Face face, suchar ch,GLuint * tex_base) + { + auto error = FT_Load_Char(face, ch, FT_LOAD_DEFAULT); + if(error) + { + LOG(star::LogLevel::Error, + _T("Font : could not load glyph"), STARENGINE_LOG_TAG); + return; + } + + error = FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL); + if(error) + { + LOG(star::LogLevel::Error, + _T("Font : could not load glyph"), STARENGINE_LOG_TAG); + return; + } + + FT_Bitmap& bitmap = face->glyph->bitmap; + + int32 width = NextPowerOfTwo(bitmap.width); + int32 height = NextPowerOfTwo(bitmap.rows); + + GLubyte* expanded_data = new GLubyte[2 * width * height]; + + for(int32 j = 0; j < height; ++j) + { + for(int32 i = 0; i < width; ++i) + { + expanded_data[2 * (i + j * width)] = 255; + expanded_data[2 * (i + j * width) + 1] = + (i >= bitmap.width || j >= bitmap.rows) ? 0 : bitmap.buffer[i + bitmap.width * j]; + } + } + + glBindTexture(GL_TEXTURE_2D, tex_base[ch]); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR); +#ifdef DESKTOP + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, expanded_data); +#elif defined(ANDROID) + //For android "internal format" must be the same as "format" in glTexImage2D + glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, width, height, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, expanded_data); +#endif + OPENGL_LOG(); + delete[] expanded_data; + + //uvs + float32 x = static_cast(bitmap.width) / static_cast(width); + float32 y = static_cast(bitmap.rows) / static_cast(height); + //letter height + int32 dimX = (face->glyph->metrics.horiAdvance / 64); + int32 dimY = ((face->glyph->metrics.horiBearingY) - (face->glyph->metrics.height)) / 64; + if(mMaxLetterHeight < face->glyph->bitmap_top) + { + mMaxLetterHeight = face->glyph->bitmap_top; + } + if(mMinLetterHeight > dimY) + { + mMinLetterHeight = dimY; + } + mCharacterInfoMap.at(ch).letterDimensions = ivec2(dimX, dimY); + mCharacterInfoMap.at(ch).vertexDimensions = vec2(bitmap.width, bitmap.rows); + mCharacterInfoMap.at(ch).uvDimensions = vec2(x, y); + } + + const tstring & Font::GetFontPath() const + { + return m_FontPath; + } + + GLuint* Font::GetTextures() const + { + return mTextures; + } + + uint32 Font::GetFontSize() const + { + return mSize; + } + + int32 Font::NextPowerOfTwo(int32 number) const + { + int32 rval = 1; + while(rval < number) + { + rval <<= 1; + } + return rval; + } + + const std::unordered_map& Font::GetCharacterInfoMap() const + { + return mCharacterInfoMap; + } + + const CharacterInfo& Font::GetCharacterInfo(suchar character) const + { + //[COMMENT] Performing a good check here + //with std::find will only slow things down + //If the map.at has an unknown value, it will throw an exception anyway + return mCharacterInfoMap.at(character); + } + + int32 Font::GetMaxLetterHeight() const + { + return mMaxLetterHeight; + } + + int32 Font::GetMinLetterHeight() const + { + return mMinLetterHeight; + } + + uint32 Font::GetStringLength(const tstring& string) const + { + int32 length = 0; + sstring conv_text = star::string_cast(string); + const schar *line = conv_text.c_str(); + for(uint32 i = 0; line[i] != 0; ++i) + { + length += mCharacterInfoMap.at(line[i]).letterDimensions.x; + } + return length; + } +} diff --git a/src/Graphics/Font.h b/src/Graphics/Font.h index da89ad3..f9c2151 100755 --- a/src/Graphics/Font.h +++ b/src/Graphics/Font.h @@ -1,75 +1,75 @@ -#pragma once - -#include -#include "../defines.h" -#include "../Helpers/FilePath.h" -#include "../Helpers/Helpers.h" - -#include "ft2build.h" -#include "freetype/freetype.h" - -#ifdef DESKTOP -#include -#else -#include -#include -#endif - -namespace star -{ -#define FONT_DPI 96 -#define FONT_TEXTURES 128 - - struct CharacterInfo - { - CharacterInfo() - : vertexDimensions() - , uvDimensions() - , letterDimensions() - { - - } - - vec2 vertexDimensions, - uvDimensions; - ivec2 letterDimensions; - - }; - - class Font - { - public: - Font(); - ~Font(); - - bool Init(const tstring& path, uint32 size, FT_Library& library); - void DeleteFont(); - - const tstring & GetFontPath() const; - - GLuint* GetTextures() const; - uint32 GetFontSize() const; - - const std::unordered_map& GetCharacterInfoMap() const; - const CharacterInfo& GetCharacterInfo(suchar character) const; - int32 GetMaxLetterHeight() const; - int32 GetMinLetterHeight() const; - uint32 GetStringLength(const tstring& string) const; - - private: - void Make_D_List(FT_Face face, suchar ch,GLuint * tex_base); - int32 NextPowerOfTwo(int32 number) const; - - tstring m_FontPath; - FT_Face mFace; - GLuint* mTextures; - int32 mMaxLetterHeight, - mMinLetterHeight; - -#ifdef ANDROID - BYTE* mFontBuffer; -#endif - std::unordered_map mCharacterInfoMap; - uint32 mSize; - }; -} +#pragma once + +#include +#include "../defines.h" +#include "../Helpers/Filepath.h" +#include "../Helpers/Helpers.h" + +#include "ft2build.h" +#include "freetype/freetype.h" + +#ifdef DESKTOP +#include +#elif defined(ANDROID) +#include +#include +#endif + +namespace star +{ +#define FONT_DPI 96 +#define FONT_TEXTURES 128 + + struct CharacterInfo + { + CharacterInfo() + : vertexDimensions() + , uvDimensions() + , letterDimensions() + { + + } + + vec2 vertexDimensions, + uvDimensions; + ivec2 letterDimensions; + + }; + + class Font + { + public: + Font(); + ~Font(); + + bool Init(const tstring& path, uint32 size, FT_Library& library); + void DeleteFont(); + + const tstring & GetFontPath() const; + + GLuint* GetTextures() const; + uint32 GetFontSize() const; + + const std::unordered_map& GetCharacterInfoMap() const; + const CharacterInfo& GetCharacterInfo(suchar character) const; + int32 GetMaxLetterHeight() const; + int32 GetMinLetterHeight() const; + uint32 GetStringLength(const tstring& string) const; + + private: + void Make_D_List(FT_Face face, suchar ch,GLuint * tex_base); + int32 NextPowerOfTwo(int32 number) const; + + tstring m_FontPath; + FT_Face mFace; + GLuint* mTextures; + int32 mMaxLetterHeight, + mMinLetterHeight; + +#ifdef ANDROID + BYTE* mFontBuffer; +#endif + std::unordered_map mCharacterInfoMap; + uint32 mSize; + }; +} diff --git a/src/Graphics/FontManager.cpp b/src/Graphics/FontManager.cpp index 39c1ac0..bfc8c12 100755 --- a/src/Graphics/FontManager.cpp +++ b/src/Graphics/FontManager.cpp @@ -1,5 +1,5 @@ #include "FontManager.h" -#include "../Helpers/FilePath.h" +#include "../Helpers/Filepath.h" #include "../Logger.h" #include "../Context.h" #include "../Graphics/GraphicsManager.h" diff --git a/src/Graphics/FontManager.h b/src/Graphics/FontManager.h index 36c5728..7d50678 100755 --- a/src/Graphics/FontManager.h +++ b/src/Graphics/FontManager.h @@ -1,65 +1,65 @@ -#pragma once - -#include -#include -#include "../defines.h" -#include "../Helpers/Helpers.h" -#include "../Helpers/Singleton.h" -#include "Font.h" -#include "../Components/TransformComponent.h" -#include "../Graphics/Color.h" -#include "../Graphics/Shader.h" - -#include "ft2build.h" -#include "freetype/freetype.h" - -#ifdef DESKTOP -#include -#else -#include -#include -#endif - -namespace star -{ - class FilePath; - - class FontManager final : public Singleton - { - public: - friend Singleton; - - bool LoadFont( - const tstring& path, - const tstring& name, - uint32 size - ); - - const Font* GetFont(const tstring& name); - bool DeleteFont(const tstring& name); - void EraseFonts(); - void SplitIntoLines( - std::vector &list, - const sstring &string - ); - - private: - FT_Library mLibrary; - - std::map mFontList; - - FontManager(); - ~FontManager(); - - void SplitString( - std::vector& wordArrayIn, - const tstring& stringIn, - const tstring& delimiter - ); - - FontManager(const FontManager& yRef); - FontManager(FontManager&& yRef); - FontManager& operator=(const FontManager& yRef); - FontManager& operator=(FontManager&& yRef); - }; -} +#pragma once + +#include +#include +#include "../defines.h" +#include "../Helpers/Helpers.h" +#include "../Helpers/Singleton.h" +#include "Font.h" +#include "../Components/TransformComponent.h" +#include "../Graphics/Color.h" +#include "../Graphics/Shader.h" + +#include "ft2build.h" +#include "freetype/freetype.h" + +#ifdef DESKTOP +#include +#elif defined(ANDROID) +#include +#include +#endif + +namespace star +{ + class FilePath; + + class FontManager final : public Singleton + { + public: + friend Singleton; + + bool LoadFont( + const tstring& path, + const tstring& name, + uint32 size + ); + + const Font* GetFont(const tstring& name); + bool DeleteFont(const tstring& name); + void EraseFonts(); + void SplitIntoLines( + std::vector &list, + const sstring &string + ); + + private: + FT_Library mLibrary; + + std::map mFontList; + + FontManager(); + ~FontManager(); + + void SplitString( + std::vector& wordArrayIn, + const tstring& stringIn, + const tstring& delimiter + ); + + FontManager(const FontManager& yRef); + FontManager(FontManager&& yRef); + FontManager& operator=(const FontManager& yRef); + FontManager& operator=(FontManager&& yRef); + }; +} diff --git a/src/Graphics/GraphicsManager.cpp b/src/Graphics/GraphicsManager.cpp index 390afe8..00f8fe8 100755 --- a/src/Graphics/GraphicsManager.cpp +++ b/src/Graphics/GraphicsManager.cpp @@ -1,448 +1,454 @@ -#include "GraphicsManager.h" -#include "SpriteBatch.h" -#include "ScaleSystem.h" -#include "../Logger.h" -#include "../defines.h" -#include "../Scenes/SceneManager.h" -#include "../Objects/BaseCamera.h" -#include "../Scenes/BaseScene.h" -#include "../Components/CameraComponent.h" - -#ifdef DESKTOP -#include -#endif - -#ifdef MOBILE -#include -#endif - -namespace star -{ - GraphicsManager::GraphicsManager() - : Singleton() - , mHorizontalViewportOffset(0) - , mVerticalViewportOffset(0) - , mViewProjectionMatrix() - , mViewInverseMatrix() - , mProjectionMatrix() - , mScreenResolution(0,0) - , mViewportResolution(0,0) - , mbHasWindowChanged(false) - , mIsInitialized(false) -#ifdef DESKTOP - , mWglSwapIntervalEXT(NULL) - , mWglGetSwapIntervalEXT(NULL) -#else - , mDisplay() - , mSurface() - , mContext() -#endif - { - LOG(star::LogLevel::Info, - _T("Graphics Manager : Constructor"), STARENGINE_LOG_TAG); - } - - GraphicsManager::~GraphicsManager() - { - LOG(star::LogLevel::Info, - _T("Graphics Manager : Destructor"), STARENGINE_LOG_TAG); - } - - void GraphicsManager::CalculateViewPort() - { - vec2 screenRes = GetWindowResolution(); - vec2 workingRes = ScaleSystem::GetInstance()->GetWorkingResolution(); - - float32 width = screenRes.x / workingRes.x; - float32 height = screenRes.y / workingRes.y; - - mHorizontalViewportOffset = 0; - mVerticalViewportOffset = 0; - float32 aspectRatio(0); - - if(width > height) - { - height = screenRes.y; - aspectRatio = (workingRes.x / workingRes.y); - width = height * aspectRatio; - - mHorizontalViewportOffset = static_cast((screenRes.x - width)/2); - } - else - { - width = screenRes.x; - aspectRatio = (workingRes.y / workingRes.x); - height = width * aspectRatio; - - mVerticalViewportOffset = static_cast((screenRes.y - height)/2); - } - - glViewport(mHorizontalViewportOffset, mVerticalViewportOffset, static_cast(width), static_cast(height)); - - mViewportResolution.x = width; - mViewportResolution.y = height; - - - - ScaleSystem::GetInstance()->CalculateScale(); - } - - void GraphicsManager::SetVSync(bool vSync) - { -#ifdef DESKTOP - //Enables or disables VSync. - //0 = No Sync , 1+ = VSync - //Default value is 1. - if(!vSync) - { - mWglSwapIntervalEXT(0); - } - else - { - mWglSwapIntervalEXT(1); - } - #else - LOG(LogLevel::Warning, - _T("Setting VSync on mobile is not supported. Default VSync is enabled"), - STARENGINE_LOG_TAG); -#endif - } - - bool GraphicsManager::GetVSync() const - { -#ifdef DESKTOP - return !(mWglGetSwapIntervalEXT() == 0); -#else - LOG(LogLevel::Warning, - _T("Toggeling VSync on mobile is not supported. Default VSync is enabled"), - STARENGINE_LOG_TAG); - return true; -#endif - } - -#ifdef DESKTOP - void GraphicsManager::Initialize(int32 screenWidth, int32 screenHeight) - { - if(!mIsInitialized) - { - mScreenResolution.x = float32(screenWidth); - mScreenResolution.y = float32(screenHeight); - glewInit(); - - LOG(star::LogLevel::Info, - _T("Graphics Manager : Initializing OpenGL Functors"), - STARENGINE_LOG_TAG); - if(!InitializeOpenGLFunctors()) - { - LOG(star::LogLevel::Error, - _T("Graphics Manager : Graphics card doesn't support VSync option!!"), - STARENGINE_LOG_TAG); - } - - SetVSync(true); - - //Initializes base GL state. - //DEPTH_TEST is default disabled - InitializeOpenGLStates(); - mIsInitialized = true; - } - } -#else - void GraphicsManager::Initialize(const android_app* pApplication) - { - if(!mIsInitialized) - { - LOG(star::LogLevel::Info, - _T("Graphics Manager : Initialize"), STARENGINE_LOG_TAG); - EGLint lFormat, lNumConfigs, lErrorResult; - EGLConfig lConfig; - // Defines display requirements. 16bits mode here. - const EGLint lAttributes[] = { - EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, - EGL_BLUE_SIZE, 5, EGL_GREEN_SIZE, 6, EGL_RED_SIZE, 5, - EGL_SURFACE_TYPE, EGL_WINDOW_BIT, - EGL_NONE - }; - mDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); - if (mDisplay == EGL_NO_DISPLAY) - { - LOG(star::LogLevel::Error, - _T("Graphics Manager : No display found"), STARENGINE_LOG_TAG); - return; - } - if (!eglInitialize(mDisplay, NULL, NULL)) - { - LOG(star::LogLevel::Error, - _T("Graphics Manager : Could not initialize display"), STARENGINE_LOG_TAG); - return; - } - if(!eglChooseConfig(mDisplay, lAttributes, &lConfig, 1,&lNumConfigs) || (lNumConfigs <= 0)) - { - LOG(star::LogLevel::Error, - _T("Graphics Manager : No display config"), STARENGINE_LOG_TAG); - return; - } - if (!eglGetConfigAttrib(mDisplay, lConfig,EGL_NATIVE_VISUAL_ID, &lFormat)) - { - LOG(star::LogLevel::Error, - _T("Graphics Manager : No config attributes"), STARENGINE_LOG_TAG); - return; - } - ANativeWindow_setBuffersGeometry(pApplication->window, 0, 0,lFormat); - - mSurface = eglCreateWindowSurface(mDisplay, lConfig, pApplication->window, NULL ); - if (mSurface == EGL_NO_SURFACE) - { - LOG(star::LogLevel::Error, - _T("Graphics Manager : Could not create surface"), STARENGINE_LOG_TAG); - return; - } - EGLint contextAttrs[] = { - EGL_CONTEXT_CLIENT_VERSION, 2, - EGL_NONE - }; - mContext = eglCreateContext(mDisplay, lConfig, EGL_NO_CONTEXT, contextAttrs); - if (mContext == EGL_NO_CONTEXT) - { - LOG(star::LogLevel::Error, - _T("Graphics Manager : Could not create context"), STARENGINE_LOG_TAG); - return; - } - EGLint sX(0), sY(0); - if (!eglMakeCurrent(mDisplay, mSurface, mSurface, mContext) - || !eglQuerySurface(mDisplay, mSurface, EGL_WIDTH, &sX) - || !eglQuerySurface(mDisplay, mSurface, EGL_HEIGHT, &sY) - || (sX <= 0) || (sY <= 0)) - { - LOG(star::LogLevel::Error, - _T("Graphics Manager : Could not activate display"), - STARENGINE_LOG_TAG); - return; - } - //[COMMENT] This might be redundant! - mViewportResolution.x = sX; - mViewportResolution.y = sY; - mScreenResolution = mViewportResolution; - glViewport(0, 0, mViewportResolution.x, mViewportResolution.y); - InitializeOpenGLStates(); - LOG(star::LogLevel::Info, - _T("Graphics Manager : Initialized"), STARENGINE_LOG_TAG); - - mIsInitialized = true; - } - } - - void GraphicsManager::Destroy() - { - LOG(star::LogLevel::Info, - _T("Graphics Manager : Destroy"), STARENGINE_LOG_TAG); - // Destroys OpenGL context. - if (mDisplay != EGL_NO_DISPLAY) - { - eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,EGL_NO_CONTEXT); - if (mContext != EGL_NO_CONTEXT) - { - eglDestroyContext(mDisplay, mContext); - mContext = EGL_NO_CONTEXT; - } - if (mSurface != EGL_NO_SURFACE) - { - eglDestroySurface(mDisplay, mSurface); - mSurface = EGL_NO_SURFACE; - } - eglTerminate(mDisplay); - mDisplay = EGL_NO_DISPLAY; - LOG(star::LogLevel::Info, - _T("Graphics Manager : Destroyed"), STARENGINE_LOG_TAG); - - mIsInitialized = false; - } - } -#endif - - void GraphicsManager::InitializeOpenGLStates() - { - //glDisable(GL_DEPTH_TEST); - glClearColor(0.f, 0.f, 0.f, 1.0f); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable(GL_BLEND); - } - - void GraphicsManager::StartDraw() - { - glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); - - } - - void GraphicsManager::StopDraw() - { -#ifdef ANDROID - if (eglSwapBuffers(mDisplay, mSurface) != EGL_TRUE) - { - return; - } -#endif - } - - void GraphicsManager::Update() - { - if(SceneManager::GetInstance()->GetActiveScene()) - { - auto projectionObject(SceneManager::GetInstance()->GetActiveScene()->GetActiveCamera()); - if(projectionObject) - { - const mat4& projection = projectionObject->GetComponent() - ->GetProjection(); - const mat4& view = projectionObject->GetComponent() - ->GetView(); - const mat4& viewInverse = projectionObject->GetComponent() - ->GetViewInverse(); - mProjectionMatrix = projection; - mViewMatrix = view; - mViewInverseMatrix = viewInverse; - mViewProjectionMatrix = projection * viewInverse; - } - } - } - - int32 GraphicsManager::GetWindowWidth() const - { - return int32(mScreenResolution.x); - } - - int32 GraphicsManager::GetWindowHeight() const - { - return int32(mScreenResolution.y); - } - - int32 GraphicsManager::GetViewportWidth() const - { - return int32(mViewportResolution.x); - } - - int32 GraphicsManager::GetViewportHeight() const - { - return int32(mViewportResolution.y); - } - - int32 GraphicsManager::GetScreenWidth() const - { - return int32(ScaleSystem::GetInstance()->GetWorkingResolution().x); - } - - int32 GraphicsManager::GetScreenHeight() const - { - return int32(ScaleSystem::GetInstance()->GetWorkingResolution().y); - } - - const mat4& GraphicsManager::GetViewInverseProjectionMatrix() const - { - return mViewProjectionMatrix; - } - - const mat4& GraphicsManager::GetProjectionMatrix() const - { - return mProjectionMatrix; - } - - const mat4& GraphicsManager::GetViewMatrix() const - { - return mViewMatrix; - } - - const mat4& GraphicsManager::GetViewInverseMatrix() const - { - return mViewInverseMatrix; - } - - float32 GraphicsManager::GetWindowAspectRatio() const - { - return mScreenResolution.x / mScreenResolution.y; - } - - const vec2 & GraphicsManager::GetWindowResolution() const - { - return mScreenResolution; - } - - const vec2 & GraphicsManager::GetViewportResolution() const - { - return mViewportResolution; - } - - const vec2 & GraphicsManager::GetScreenResolution() const - { - return ScaleSystem::GetInstance()->GetWorkingResolution(); - } - - float32 GraphicsManager::GetViewportAspectRatio() const - { - return mViewportResolution.x / mViewportResolution.y; - } - - int32 GraphicsManager::GetHorizontalViewportOffset() const - { - return mHorizontalViewportOffset; - } - - int32 GraphicsManager::GetVerticalViewportOffset() const - { - return mVerticalViewportOffset; - } - - void GraphicsManager::SetWindowDimensions(int32 width, int32 height) - { - mScreenResolution.x = float32(width); - mScreenResolution.y = float32(height); - CalculateViewPort(); - } - - void GraphicsManager::SetHasWindowChanged(bool isTrue) - { - mbHasWindowChanged = isTrue; - if(isTrue) - { - CalculateViewPort(); - } - } - - bool GraphicsManager::GetHasWindowChanged() const - { - return mbHasWindowChanged; - } - -#ifdef DESKTOP - - bool GraphicsManager::WGLExtensionSupported(const schar* extension_name) - { - // this is the pointer to the function which returns the pointer to string with the list of all wgl extensions - PFNWGLGETEXTENSIONSSTRINGEXTPROC _wglGetExtensionsStringEXT = NULL; - - // determine pointer to wglGetExtensionsStringEXT function - _wglGetExtensionsStringEXT = (PFNWGLGETEXTENSIONSSTRINGEXTPROC) wglGetProcAddress("wglGetExtensionsStringEXT"); - - if (strstr(_wglGetExtensionsStringEXT(), extension_name) == NULL) - { - // string was not found - return false; - } - - // extension is supported - return true; - } - - bool GraphicsManager::InitializeOpenGLFunctors() - { - if (WGLExtensionSupported("WGL_EXT_swap_control")) - { - // Extension is supported, init pointers. - mWglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC) wglGetProcAddress("wglSwapIntervalEXT"); - - // this is another function from WGL_EXT_swap_control extension - mWglGetSwapIntervalEXT = (PFNWGLGETSWAPINTERVALEXTPROC) wglGetProcAddress("wglGetSwapIntervalEXT"); - return true; - } - return false; - } -#endif -} +#include "GraphicsManager.h" +#include "SpriteBatch.h" +#include "ScaleSystem.h" +#include "../Logger.h" +#include "../defines.h" +#include "../Scenes/SceneManager.h" +#include "../Objects/BaseCamera.h" +#include "../Scenes/BaseScene.h" +#include "../Components/CameraComponent.h" + +#ifdef _WIN32 +#include +#endif + +#ifdef MOBILE +#include +#endif + +namespace star +{ + GraphicsManager::GraphicsManager() + : Singleton() + , mHorizontalViewportOffset(0) + , mVerticalViewportOffset(0) + , mViewProjectionMatrix() + , mViewInverseMatrix() + , mProjectionMatrix() + , mScreenResolution(0,0) + , mViewportResolution(0,0) + , mbHasWindowChanged(false) + , mIsInitialized(false) +#ifdef _WIN32 + , mWglSwapIntervalEXT(NULL) + , mWglGetSwapIntervalEXT(NULL) +#elif defined(ANDROID) + , mDisplay() + , mSurface() + , mContext() +#endif + { + LOG(star::LogLevel::Info, + _T("Graphics Manager : Constructor"), STARENGINE_LOG_TAG); + } + + GraphicsManager::~GraphicsManager() + { + LOG(star::LogLevel::Info, + _T("Graphics Manager : Destructor"), STARENGINE_LOG_TAG); + } + + void GraphicsManager::CalculateViewPort() + { + vec2 screenRes = GetWindowResolution(); + vec2 workingRes = ScaleSystem::GetInstance()->GetWorkingResolution(); + + float32 width = screenRes.x / workingRes.x; + float32 height = screenRes.y / workingRes.y; + + mHorizontalViewportOffset = 0; + mVerticalViewportOffset = 0; + float32 aspectRatio(0); + + if(width > height) + { + height = screenRes.y; + aspectRatio = (workingRes.x / workingRes.y); + width = height * aspectRatio; + + mHorizontalViewportOffset = static_cast((screenRes.x - width)/2); + } + else + { + width = screenRes.x; + aspectRatio = (workingRes.y / workingRes.x); + height = width * aspectRatio; + + mVerticalViewportOffset = static_cast((screenRes.y - height)/2); + } + + glViewport(mHorizontalViewportOffset, mVerticalViewportOffset, static_cast(width), static_cast(height)); + + mViewportResolution.x = width; + mViewportResolution.y = height; + + + + ScaleSystem::GetInstance()->CalculateScale(); + } + + void GraphicsManager::SetVSync(bool vSync) + { +#ifdef _WIN32 + //Enables or disables VSync. + //0 = No Sync , 1+ = VSync + //Default value is 1. + if(!vSync) + { + mWglSwapIntervalEXT(0); + } + else + { + mWglSwapIntervalEXT(1); + } +#elif defined(ANDROID) + LOG(LogLevel::Warning, + _T("Setting VSync on mobile is not supported. Default VSync is enabled"), + STARENGINE_LOG_TAG); +#elif defined(ANDROID) + // Linux: VSync control via SDL or GLX can be added here + LOG(LogLevel::Warning, + _T("VSync control not yet implemented on this platform"), + STARENGINE_LOG_TAG); +#endif + } + + bool GraphicsManager::GetVSync() const + { +#ifdef _WIN32 + return !(mWglGetSwapIntervalEXT() == 0); +#elif defined(ANDROID) + LOG(LogLevel::Warning, + _T("Toggeling VSync on mobile is not supported. Default VSync is enabled"), + STARENGINE_LOG_TAG); + return true; +#endif + } + +#ifdef DESKTOP + void GraphicsManager::Initialize(int32 screenWidth, int32 screenHeight) + { + if(!mIsInitialized) + { + mScreenResolution.x = float32(screenWidth); + mScreenResolution.y = float32(screenHeight); + glewInit(); + +#ifdef _WIN32 + LOG(star::LogLevel::Info, + _T("Graphics Manager : Initializing OpenGL Functors"), + STARENGINE_LOG_TAG); + if(!InitializeOpenGLFunctors()) + { + LOG(star::LogLevel::Error, + _T("Graphics Manager : Graphics card doesn't support VSync option!!"), + STARENGINE_LOG_TAG); + } +#endif + SetVSync(true); + + //Initializes base GL state. + //DEPTH_TEST is default disabled + InitializeOpenGLStates(); + mIsInitialized = true; + } + } +#else + void GraphicsManager::Initialize(const android_app* pApplication) + { + if(!mIsInitialized) + { + LOG(star::LogLevel::Info, + _T("Graphics Manager : Initialize"), STARENGINE_LOG_TAG); + EGLint lFormat, lNumConfigs, lErrorResult; + EGLConfig lConfig; + // Defines display requirements. 16bits mode here. + const EGLint lAttributes[] = { + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, + EGL_BLUE_SIZE, 5, EGL_GREEN_SIZE, 6, EGL_RED_SIZE, 5, + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_NONE + }; + mDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); + if (mDisplay == EGL_NO_DISPLAY) + { + LOG(star::LogLevel::Error, + _T("Graphics Manager : No display found"), STARENGINE_LOG_TAG); + return; + } + if (!eglInitialize(mDisplay, NULL, NULL)) + { + LOG(star::LogLevel::Error, + _T("Graphics Manager : Could not initialize display"), STARENGINE_LOG_TAG); + return; + } + if(!eglChooseConfig(mDisplay, lAttributes, &lConfig, 1,&lNumConfigs) || (lNumConfigs <= 0)) + { + LOG(star::LogLevel::Error, + _T("Graphics Manager : No display config"), STARENGINE_LOG_TAG); + return; + } + if (!eglGetConfigAttrib(mDisplay, lConfig,EGL_NATIVE_VISUAL_ID, &lFormat)) + { + LOG(star::LogLevel::Error, + _T("Graphics Manager : No config attributes"), STARENGINE_LOG_TAG); + return; + } + ANativeWindow_setBuffersGeometry(pApplication->window, 0, 0,lFormat); + + mSurface = eglCreateWindowSurface(mDisplay, lConfig, pApplication->window, NULL ); + if (mSurface == EGL_NO_SURFACE) + { + LOG(star::LogLevel::Error, + _T("Graphics Manager : Could not create surface"), STARENGINE_LOG_TAG); + return; + } + EGLint contextAttrs[] = { + EGL_CONTEXT_CLIENT_VERSION, 2, + EGL_NONE + }; + mContext = eglCreateContext(mDisplay, lConfig, EGL_NO_CONTEXT, contextAttrs); + if (mContext == EGL_NO_CONTEXT) + { + LOG(star::LogLevel::Error, + _T("Graphics Manager : Could not create context"), STARENGINE_LOG_TAG); + return; + } + EGLint sX(0), sY(0); + if (!eglMakeCurrent(mDisplay, mSurface, mSurface, mContext) + || !eglQuerySurface(mDisplay, mSurface, EGL_WIDTH, &sX) + || !eglQuerySurface(mDisplay, mSurface, EGL_HEIGHT, &sY) + || (sX <= 0) || (sY <= 0)) + { + LOG(star::LogLevel::Error, + _T("Graphics Manager : Could not activate display"), + STARENGINE_LOG_TAG); + return; + } + //[COMMENT] This might be redundant! + mViewportResolution.x = sX; + mViewportResolution.y = sY; + mScreenResolution = mViewportResolution; + glViewport(0, 0, mViewportResolution.x, mViewportResolution.y); + InitializeOpenGLStates(); + LOG(star::LogLevel::Info, + _T("Graphics Manager : Initialized"), STARENGINE_LOG_TAG); + + mIsInitialized = true; + } + } + + void GraphicsManager::Destroy() + { + LOG(star::LogLevel::Info, + _T("Graphics Manager : Destroy"), STARENGINE_LOG_TAG); + // Destroys OpenGL context. + if (mDisplay != EGL_NO_DISPLAY) + { + eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,EGL_NO_CONTEXT); + if (mContext != EGL_NO_CONTEXT) + { + eglDestroyContext(mDisplay, mContext); + mContext = EGL_NO_CONTEXT; + } + if (mSurface != EGL_NO_SURFACE) + { + eglDestroySurface(mDisplay, mSurface); + mSurface = EGL_NO_SURFACE; + } + eglTerminate(mDisplay); + mDisplay = EGL_NO_DISPLAY; + LOG(star::LogLevel::Info, + _T("Graphics Manager : Destroyed"), STARENGINE_LOG_TAG); + + mIsInitialized = false; + } + } +#endif + + void GraphicsManager::InitializeOpenGLStates() + { + //glDisable(GL_DEPTH_TEST); + glClearColor(0.f, 0.f, 0.f, 1.0f); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + } + + void GraphicsManager::StartDraw() + { + glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); + + } + + void GraphicsManager::StopDraw() + { +#ifdef ANDROID + if (eglSwapBuffers(mDisplay, mSurface) != EGL_TRUE) + { + return; + } +#endif + } + + void GraphicsManager::Update() + { + if(SceneManager::GetInstance()->GetActiveScene()) + { + auto projectionObject(SceneManager::GetInstance()->GetActiveScene()->GetActiveCamera()); + if(projectionObject) + { + const mat4& projection = projectionObject->GetComponent() + ->GetProjection(); + const mat4& view = projectionObject->GetComponent() + ->GetView(); + const mat4& viewInverse = projectionObject->GetComponent() + ->GetViewInverse(); + mProjectionMatrix = projection; + mViewMatrix = view; + mViewInverseMatrix = viewInverse; + mViewProjectionMatrix = projection * viewInverse; + } + } + } + + int32 GraphicsManager::GetWindowWidth() const + { + return int32(mScreenResolution.x); + } + + int32 GraphicsManager::GetWindowHeight() const + { + return int32(mScreenResolution.y); + } + + int32 GraphicsManager::GetViewportWidth() const + { + return int32(mViewportResolution.x); + } + + int32 GraphicsManager::GetViewportHeight() const + { + return int32(mViewportResolution.y); + } + + int32 GraphicsManager::GetScreenWidth() const + { + return int32(ScaleSystem::GetInstance()->GetWorkingResolution().x); + } + + int32 GraphicsManager::GetScreenHeight() const + { + return int32(ScaleSystem::GetInstance()->GetWorkingResolution().y); + } + + const mat4& GraphicsManager::GetViewInverseProjectionMatrix() const + { + return mViewProjectionMatrix; + } + + const mat4& GraphicsManager::GetProjectionMatrix() const + { + return mProjectionMatrix; + } + + const mat4& GraphicsManager::GetViewMatrix() const + { + return mViewMatrix; + } + + const mat4& GraphicsManager::GetViewInverseMatrix() const + { + return mViewInverseMatrix; + } + + float32 GraphicsManager::GetWindowAspectRatio() const + { + return mScreenResolution.x / mScreenResolution.y; + } + + const vec2 & GraphicsManager::GetWindowResolution() const + { + return mScreenResolution; + } + + const vec2 & GraphicsManager::GetViewportResolution() const + { + return mViewportResolution; + } + + const vec2 & GraphicsManager::GetScreenResolution() const + { + return ScaleSystem::GetInstance()->GetWorkingResolution(); + } + + float32 GraphicsManager::GetViewportAspectRatio() const + { + return mViewportResolution.x / mViewportResolution.y; + } + + int32 GraphicsManager::GetHorizontalViewportOffset() const + { + return mHorizontalViewportOffset; + } + + int32 GraphicsManager::GetVerticalViewportOffset() const + { + return mVerticalViewportOffset; + } + + void GraphicsManager::SetWindowDimensions(int32 width, int32 height) + { + mScreenResolution.x = float32(width); + mScreenResolution.y = float32(height); + CalculateViewPort(); + } + + void GraphicsManager::SetHasWindowChanged(bool isTrue) + { + mbHasWindowChanged = isTrue; + if(isTrue) + { + CalculateViewPort(); + } + } + + bool GraphicsManager::GetHasWindowChanged() const + { + return mbHasWindowChanged; + } + +#ifdef _WIN32 + + bool GraphicsManager::WGLExtensionSupported(const schar* extension_name) + { + // this is the pointer to the function which returns the pointer to string with the list of all wgl extensions + PFNWGLGETEXTENSIONSSTRINGEXTPROC _wglGetExtensionsStringEXT = NULL; + + // determine pointer to wglGetExtensionsStringEXT function + _wglGetExtensionsStringEXT = (PFNWGLGETEXTENSIONSSTRINGEXTPROC) wglGetProcAddress("wglGetExtensionsStringEXT"); + + if (strstr(_wglGetExtensionsStringEXT(), extension_name) == NULL) + { + // string was not found + return false; + } + + // extension is supported + return true; + } + + bool GraphicsManager::InitializeOpenGLFunctors() + { + if (WGLExtensionSupported("WGL_EXT_swap_control")) + { + // Extension is supported, init pointers. + mWglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC) wglGetProcAddress("wglSwapIntervalEXT"); + + // this is another function from WGL_EXT_swap_control extension + mWglGetSwapIntervalEXT = (PFNWGLGETSWAPINTERVALEXTPROC) wglGetProcAddress("wglGetSwapIntervalEXT"); + return true; + } + return false; + } +#endif +} diff --git a/src/Graphics/GraphicsManager.h b/src/Graphics/GraphicsManager.h index 5dd5fcd..e7115fa 100755 --- a/src/Graphics/GraphicsManager.h +++ b/src/Graphics/GraphicsManager.h @@ -1,102 +1,107 @@ -#pragma once - -#include "../defines.h" -#include "../Helpers/Singleton.h" - -#ifdef DESKTOP -#include -#include -#include -#else -#include -#include -#include -#include -#endif - -namespace star -{ - class GraphicsManager final : public Singleton - { - public: - friend Singleton; - -#ifdef DESKTOP - void Initialize(int32 screenWidth, int32 screenHeight); -#else - void Initialize(const android_app* pApplication); - void Destroy(); -#endif - - void StartDraw(); - void StopDraw(); - void Update(); - - int32 GetWindowWidth() const; - int32 GetWindowHeight() const; - - int32 GetViewportWidth() const; - int32 GetViewportHeight() const; - - int32 GetScreenWidth() const; - int32 GetScreenHeight() const; - - const mat4& GetViewInverseProjectionMatrix() const; - const mat4& GetViewMatrix() const; - const mat4& GetViewInverseMatrix() const; - const mat4& GetProjectionMatrix() const; - - float32 GetWindowAspectRatio() const; - - const vec2 & GetWindowResolution() const; - const vec2 & GetViewportResolution() const; - const vec2 & GetScreenResolution() const; - - float32 GetViewportAspectRatio() const; - - int32 GetHorizontalViewportOffset() const; - int32 GetVerticalViewportOffset() const; - - void SetWindowDimensions(int32 width, int32 height); - void SetHasWindowChanged(bool isTrue); - bool GetHasWindowChanged() const; - void CalculateViewPort(); - - void SetVSync(bool VSync); - bool GetVSync() const; - - private: - GraphicsManager(); - ~GraphicsManager(); - - void InitializeOpenGLStates(); -#ifdef DESKTOP - bool WGLExtensionSupported(const schar* extension_name); - bool InitializeOpenGLFunctors(); - - PFNWGLSWAPINTERVALEXTPROC mWglSwapIntervalEXT; - PFNWGLGETSWAPINTERVALEXTPROC mWglGetSwapIntervalEXT; -#endif - int32 mHorizontalViewportOffset, - mVerticalViewportOffset; - - mat4 mViewProjectionMatrix; - mat4 mViewMatrix; - mat4 mViewInverseMatrix; - mat4 mProjectionMatrix; - vec2 mScreenResolution, mViewportResolution; - bool mbHasWindowChanged; - bool mIsInitialized; - -#ifdef ANDROID - EGLDisplay mDisplay; - EGLSurface mSurface; - EGLContext mContext; -#endif - - GraphicsManager(const GraphicsManager& yRef); - GraphicsManager(GraphicsManager&& yRef); - GraphicsManager& operator=(const GraphicsManager& yRef); - GraphicsManager& operator=(GraphicsManager&& yRef); - }; -} +#pragma once + +#include "../defines.h" +#include "../Helpers/Singleton.h" + +#ifdef DESKTOP + #ifdef _WIN32 + #include + #include + #include + #else + #include + #include + #endif +#elif defined(ANDROID) + #include + #include + #include + #include +#endif + +namespace star +{ + class GraphicsManager final : public Singleton + { + public: + friend Singleton; + +#ifdef DESKTOP + void Initialize(int32 screenWidth, int32 screenHeight); +#elif defined(ANDROID) + void Initialize(const android_app* pApplication); + void Destroy(); +#endif + + void StartDraw(); + void StopDraw(); + void Update(); + + int32 GetWindowWidth() const; + int32 GetWindowHeight() const; + + int32 GetViewportWidth() const; + int32 GetViewportHeight() const; + + int32 GetScreenWidth() const; + int32 GetScreenHeight() const; + + const mat4& GetViewInverseProjectionMatrix() const; + const mat4& GetViewMatrix() const; + const mat4& GetViewInverseMatrix() const; + const mat4& GetProjectionMatrix() const; + + float32 GetWindowAspectRatio() const; + + const vec2 & GetWindowResolution() const; + const vec2 & GetViewportResolution() const; + const vec2 & GetScreenResolution() const; + + float32 GetViewportAspectRatio() const; + + int32 GetHorizontalViewportOffset() const; + int32 GetVerticalViewportOffset() const; + + void SetWindowDimensions(int32 width, int32 height); + void SetHasWindowChanged(bool isTrue); + bool GetHasWindowChanged() const; + void CalculateViewPort(); + + void SetVSync(bool VSync); + bool GetVSync() const; + + private: + GraphicsManager(); + ~GraphicsManager(); + + void InitializeOpenGLStates(); +#ifdef _WIN32 + bool WGLExtensionSupported(const schar* extension_name); + bool InitializeOpenGLFunctors(); + + PFNWGLSWAPINTERVALEXTPROC mWglSwapIntervalEXT; + PFNWGLGETSWAPINTERVALEXTPROC mWglGetSwapIntervalEXT; +#endif + int32 mHorizontalViewportOffset, + mVerticalViewportOffset; + + mat4 mViewProjectionMatrix; + mat4 mViewMatrix; + mat4 mViewInverseMatrix; + mat4 mProjectionMatrix; + vec2 mScreenResolution, mViewportResolution; + bool mbHasWindowChanged; + bool mIsInitialized; + +#ifdef ANDROID + EGLDisplay mDisplay; + EGLSurface mSurface; + EGLContext mContext; +#endif + + GraphicsManager(const GraphicsManager& yRef); + GraphicsManager(GraphicsManager&& yRef); + GraphicsManager& operator=(const GraphicsManager& yRef); + GraphicsManager& operator=(GraphicsManager&& yRef); + }; +} diff --git a/src/Graphics/Resource.h b/src/Graphics/Resource.h index 524d98d..f6b59e6 100755 --- a/src/Graphics/Resource.h +++ b/src/Graphics/Resource.h @@ -1,6 +1,6 @@ #pragma once -#ifndef _WIN32 +#ifdef ANDROID #include "../defines.h" #include diff --git a/src/Graphics/Shader.h b/src/Graphics/Shader.h index 66f6f88..001bc5b 100755 --- a/src/Graphics/Shader.h +++ b/src/Graphics/Shader.h @@ -1,144 +1,144 @@ -#pragma once - -#include "../defines.h" - -#ifdef DESKTOP -#include -#include -#else -#include -#include -#include -#include -#include -#include "../Graphics/Resource.h" -#endif - -namespace star -{ - /// - /// Processing and loading of a provided vertex and fragment shader. - /// Can be used for all materials consisting of a vertex and fragment shader. - /// Compiles shaders, creates program and links the shaders to the program. - /// Provides managed interface for easily creating shader programs. - /// - class Shader final - { - public: - /// - /// creates a new instance of the class. - /// - /// The vertex shader file. - /// The fragment shader file. - Shader(const tstring& vsFile, const tstring& fsFile); - /// - /// creates a new instance of the class. - /// - /// The inline vertex shader. - /// The inline fragment shader. - Shader(const GLchar* inlineVert, const GLchar* inlineFrag); - /// - /// Finalizes an instance of the class. - /// - ~Shader(); - - /// - /// Binds this shader program to openGL. - /// - void Bind(); - /// - /// Unbinds this shader program from openGL. - /// - void Unbind(); - - /// - /// Gets the unique number of this program. - /// This number is used by OpenGL to reference to this shader program. - /// - /// The unique program number. - const GLuint GetProgramID() const; - /// - /// Looks up the location of this uniform in the shader. - /// - /// The name of the uniform in the shader. - /// The location of the uniform in the shader. - GLuint GetUniformLocation(const GLchar* nameInShader) const; - /// - /// Looks up the location of this attribute in the shader. - /// - /// The name of the attribute in the shader. - /// The location of the attribute in the shader. - GLuint GetAttribLocation(const GLchar* nameInShader) const; - /// - /// Prints the active attributes. - /// - void PrintActiveAttribs() const; - /// - /// Prints the active uniforms. - /// - void PrintActiveUniforms() const; - - private: - /// - /// Starts the process of compiling shaders, creating the program - /// and linking the shaders to the program. - /// - /// The vertex shader file. - /// The fragment shader file. - /// True if everything was succesfull. - bool Init(const tstring& vsFile, const tstring& fsFile); - /// - /// Starts the process of compiling shaders, creating the program - /// and linking the shaders to the program. - /// - /// The inline vertex shader. - /// The inline fragment shader. - /// True if everything was succesfull. - bool Init(const GLchar* inlineVert, const GLchar* inlineFrag); - - /// - /// Compiles the shader. - /// - /// The shader to compile. - /// - /// The type of the shader. Example: GL_VERTEX_SHADER - /// - /// The file to compile. - /// True if the compilation was succesfull. - bool CompileShader(GLuint* shader, GLenum type, const tstring& file); - /// - /// Compiles the shader. - /// - /// The shader to compile. - /// - /// The type of the shader. Example: GL_VERTEX_SHADER - /// - /// The inline file to compile. - /// True if the compilation was succesfull. - bool CompileShader(GLuint* shader, GLenum type, const GLchar* inlineFile); - - /// - /// wraps the OpenGL parts of the shader creation process. - /// - /// True if everything was succesfull. - bool GLInit(); - /// - /// wraps the OpenGL parts of the shader compilation process. - /// - /// True if everything was succesfull. - bool GLCompileShader(); - - GLuint m_ProgramID; - GLuint m_VertexShader; - GLuint m_FragmentShader; - -#ifdef ANDROID - static const int32 ANDROID_ERROR_SIZE = 4096; -#endif - - Shader(const Shader& t); - Shader(Shader&& t); - Shader& operator=(const Shader& t); - Shader& operator=(Shader&&); - }; -} +#pragma once + +#include "../defines.h" + +#ifdef DESKTOP +#include +#include +#elif defined(ANDROID) +#include +#include +#include +#include +#include +#include "../Graphics/Resource.h" +#endif + +namespace star +{ + /// + /// Processing and loading of a provided vertex and fragment shader. + /// Can be used for all materials consisting of a vertex and fragment shader. + /// Compiles shaders, creates program and links the shaders to the program. + /// Provides managed interface for easily creating shader programs. + /// + class Shader final + { + public: + /// + /// creates a new instance of the class. + /// + /// The vertex shader file. + /// The fragment shader file. + Shader(const tstring& vsFile, const tstring& fsFile); + /// + /// creates a new instance of the class. + /// + /// The inline vertex shader. + /// The inline fragment shader. + Shader(const GLchar* inlineVert, const GLchar* inlineFrag); + /// + /// Finalizes an instance of the class. + /// + ~Shader(); + + /// + /// Binds this shader program to openGL. + /// + void Bind(); + /// + /// Unbinds this shader program from openGL. + /// + void Unbind(); + + /// + /// Gets the unique number of this program. + /// This number is used by OpenGL to reference to this shader program. + /// + /// The unique program number. + const GLuint GetProgramID() const; + /// + /// Looks up the location of this uniform in the shader. + /// + /// The name of the uniform in the shader. + /// The location of the uniform in the shader. + GLuint GetUniformLocation(const GLchar* nameInShader) const; + /// + /// Looks up the location of this attribute in the shader. + /// + /// The name of the attribute in the shader. + /// The location of the attribute in the shader. + GLuint GetAttribLocation(const GLchar* nameInShader) const; + /// + /// Prints the active attributes. + /// + void PrintActiveAttribs() const; + /// + /// Prints the active uniforms. + /// + void PrintActiveUniforms() const; + + private: + /// + /// Starts the process of compiling shaders, creating the program + /// and linking the shaders to the program. + /// + /// The vertex shader file. + /// The fragment shader file. + /// True if everything was succesfull. + bool Init(const tstring& vsFile, const tstring& fsFile); + /// + /// Starts the process of compiling shaders, creating the program + /// and linking the shaders to the program. + /// + /// The inline vertex shader. + /// The inline fragment shader. + /// True if everything was succesfull. + bool Init(const GLchar* inlineVert, const GLchar* inlineFrag); + + /// + /// Compiles the shader. + /// + /// The shader to compile. + /// + /// The type of the shader. Example: GL_VERTEX_SHADER + /// + /// The file to compile. + /// True if the compilation was succesfull. + bool CompileShader(GLuint* shader, GLenum type, const tstring& file); + /// + /// Compiles the shader. + /// + /// The shader to compile. + /// + /// The type of the shader. Example: GL_VERTEX_SHADER + /// + /// The inline file to compile. + /// True if the compilation was succesfull. + bool CompileShader(GLuint* shader, GLenum type, const GLchar* inlineFile); + + /// + /// wraps the OpenGL parts of the shader creation process. + /// + /// True if everything was succesfull. + bool GLInit(); + /// + /// wraps the OpenGL parts of the shader compilation process. + /// + /// True if everything was succesfull. + bool GLCompileShader(); + + GLuint m_ProgramID; + GLuint m_VertexShader; + GLuint m_FragmentShader; + +#ifdef ANDROID + static const int32 ANDROID_ERROR_SIZE = 4096; +#endif + + Shader(const Shader& t); + Shader(Shader&& t); + Shader& operator=(const Shader& t); + Shader& operator=(Shader&&); + }; +} diff --git a/src/Graphics/SpriteAnimationManager.h b/src/Graphics/SpriteAnimationManager.h index 7f36ad6..c731336 100755 --- a/src/Graphics/SpriteAnimationManager.h +++ b/src/Graphics/SpriteAnimationManager.h @@ -1,7 +1,7 @@ #pragma once #include "../defines.h" -#include "../Helpers/SpriteSheet.h" +#include "../Helpers/Spritesheet.h" #include "../Helpers/Singleton.h" #include diff --git a/src/Graphics/Texture2D.cpp b/src/Graphics/Texture2D.cpp index 674692e..e4c6b59 100755 --- a/src/Graphics/Texture2D.cpp +++ b/src/Graphics/Texture2D.cpp @@ -1,371 +1,371 @@ -#include "Texture2D.h" -#include -#include "../Helpers/Helpers.h" - -namespace star -{ - const tstring Texture2D::LIBPNG_LOG_TAG = _T("LIBPNG"); - - Texture2D::Texture2D(const tstring & pPath) - : mTextureId(0) - , mFormat(0) - , mWidth(0) - , mHeight(0) -#ifdef ANDROID - , mResource(pPath) -#else - , mPath(pPath) -#endif - { - Load(); - } -#ifdef ANDROID - void Texture2D::CallbackRead(png_structp png, png_bytep data, png_size_t size) - { - Resource& lReader = *((Resource*)png_get_io_ptr(png)); - if(!lReader.Read(data,size)) - { - lReader.Close(); - png_error(png, "Error while reading PNG file"); - } - } -#endif - - Texture2D::~Texture2D() - { - if(mTextureId != 0) - { - glDeleteTextures(1, &mTextureId); - mTextureId = 0; - } - mWidth = 0; - mHeight = 0; - mFormat = 0; - } - - uint8* Texture2D::ReadPNG() - { - png_byte header[8]; - png_structp lPngPtr = NULL; - png_infop lInfoPtr = NULL; - png_byte* lImageBuffer = NULL; - png_bytep* lRowPtrs = NULL; - png_int_32 lRowSize; - bool lTransparency; - -#ifdef DESKTOP - FILE *fp; - tfopen(&fp, mPath.c_str(), _T("rb")); - - if(fp == NULL) - { - LOG(LogLevel::Error, - _T("Texture2D::ReadPNG: the png \"") + - mPath + - _T("\" could not be loaded"), LIBPNG_LOG_TAG - ); - return NULL; - } - - fread(header, 8, 1, fp); -#else - if(!mResource.Open()) - { - mResource.Close(); - LOG(LogLevel::Error, - _T("PNG : Could Not Open Resource"), LIBPNG_LOG_TAG); - return NULL; - } - if(!mResource.Read(header, sizeof(header))) - { - mResource.Close(); - LOG(LogLevel::Error, - _T("PNG : Could Not Read"), - LIBPNG_LOG_TAG); - return NULL; - } -#endif - - if(png_sig_cmp(header, 0, 8)) - { - LOG(LogLevel::Error, - _T("PNG : Not a PNG file"), - LIBPNG_LOG_TAG); - return NULL; - } - lPngPtr = png_create_read_struct( - PNG_LIBPNG_VER_STRING, - NULL, - NULL, - NULL - ); - if(!lPngPtr) - { - LOG(LogLevel::Error, - _T("PNG : create struct string failed"), - LIBPNG_LOG_TAG); - return NULL; - } - - png_set_error_fn(lPngPtr, NULL, CustomErrorFunction, CustomWarningFunction); - - lInfoPtr = png_create_info_struct(lPngPtr); - if(!lInfoPtr) - { - LOG(LogLevel::Error, - _T("PNG : create info failed"), LIBPNG_LOG_TAG); - return NULL; - } - -#ifdef DESKTOP - png_init_io(lPngPtr, fp); - if(setjmp(png_jmpbuf(lPngPtr))) - { - LOG(LogLevel::Error, - _T("PNG : Error during init io"), LIBPNG_LOG_TAG); - return NULL; - } -#else - png_set_read_fn(lPngPtr, &mResource, CallbackRead); - if(setjmp(png_jmpbuf(lPngPtr))) - { - mResource.Close(); - LOG(LogLevel::Error, - _T("PNG : Error during init io"), LIBPNG_LOG_TAG); - return NULL; - } -#endif - png_set_sig_bytes(lPngPtr, 8); - png_read_info(lPngPtr,lInfoPtr); - - png_uint_32 pWidth, pHeight; - png_int_32 lDepth, lColorType; - png_get_IHDR( - lPngPtr, - lInfoPtr, - &pWidth, - &pHeight, - &lDepth, - &lColorType, - NULL, - NULL, - NULL - ); - mWidth = pWidth; - mHeight = pHeight; - - lTransparency = false; - if(png_get_valid(lPngPtr, lInfoPtr, PNG_INFO_tRNS)) - { - png_set_tRNS_to_alpha(lPngPtr); - lTransparency=true; - -#ifdef ANDROID - mResource.Close(); -#endif - delete [] lRowPtrs; - delete [] lImageBuffer; - if(lPngPtr != NULL) - { - png_infop* lInfoPtrP = lInfoPtr != NULL ? &lInfoPtr: NULL; - png_destroy_read_struct(&lPngPtr, lInfoPtrP, NULL); - } - return NULL; - } - - if(lDepth < 8 ) - { - png_set_packing(lPngPtr); - } - else if(lDepth == 16) - { - png_set_strip_16(lPngPtr); - } - - switch(lColorType) - { - case PNG_COLOR_TYPE_PALETTE: - png_set_palette_to_rgb(lPngPtr); - mFormat = lTransparency ? GL_RGBA : GL_RGB; - break; - case PNG_COLOR_TYPE_RGB: - mFormat = lTransparency ? GL_RGBA : GL_RGB; - break; - case PNG_COLOR_TYPE_RGBA: - mFormat = GL_RGBA; - break; - case PNG_COLOR_TYPE_GRAY: - png_set_expand_gray_1_2_4_to_8(lPngPtr); - mFormat = lTransparency ? GL_LUMINANCE_ALPHA : GL_LUMINANCE; - break; - case PNG_COLOR_TYPE_GA: - png_set_expand_gray_1_2_4_to_8(lPngPtr); - mFormat = GL_LUMINANCE_ALPHA; - break; - } - - //mNumber_of_passes = png_set_interlace_handling(mPng_ptr); - png_read_update_info(lPngPtr,lInfoPtr); - - /*if(setjmp(png_jmpbuf(mPng_ptr))) - { - LOG(LogLevel::Info, - _T("PNG : Error during read image"), LIBPNG_LOG_TAG); - return NULL; - }*/ - - lRowSize = png_get_rowbytes(lPngPtr,lInfoPtr); - if(lRowSize <= 0) - { - LOG(LogLevel::Error, - _T("PNG : png rowsize smaller or equal to 0"), - LIBPNG_LOG_TAG); - return NULL; - } - - lImageBuffer = new png_byte[lRowSize * pHeight]; - if(!lImageBuffer) - { - LOG(LogLevel::Error, - _T("PNG : Error during image buffer creation"), - LIBPNG_LOG_TAG); - return NULL; - } - - lRowPtrs = new png_bytep[pHeight]; - if(!lRowPtrs) - { - LOG(LogLevel::Error, - _T("PNG : Error during row pointer creation"), - LIBPNG_LOG_TAG); - return NULL; - } - - for(uint32 i = 0; i < pHeight; ++i) - { - lRowPtrs[pHeight - (i+1)] = lImageBuffer + i * lRowSize; - } - png_read_image(lPngPtr, lRowPtrs); -#ifdef DESKTOP - fclose(fp); -#else - mResource.Close(); -#endif - png_destroy_read_struct(&lPngPtr, &lInfoPtr, NULL); - delete[] lRowPtrs; - -#ifdef DESKTOP - DEBUG_LOG(LogLevel::Info, - _T("PNG : ") + mPath + _T(" Created Succesfull"), - LIBPNG_LOG_TAG); -#else - DEBUG_LOG(LogLevel::Info, - _T("PNG : ") + mResource.GetPath() + _T(" Created Succesfull"), - LIBPNG_LOG_TAG); -#endif - return lImageBuffer; - - } - - void Texture2D::Load() - { - uint8* lImageBuffer = ReadPNG(); - if(lImageBuffer == NULL) - { - LOG(LogLevel::Error, - _T("PNG : READING PNG FAILED - NO IMAGE BUFFER"), LIBPNG_LOG_TAG); - return; - } - - glGenTextures(1, &mTextureId); - glBindTexture(GL_TEXTURE_2D, mTextureId); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - glTexImage2D(GL_TEXTURE_2D, 0, mFormat, mWidth, mHeight, 0, mFormat, GL_UNSIGNED_BYTE, lImageBuffer); - delete[] lImageBuffer; - -#if defined(DEBUG) | defined(_DEBUG) - bool hasError = false; - GLenum errorMsg; - errorMsg = glGetError(); - while(errorMsg != GL_NO_ERROR) - { - hasError=true; - switch(errorMsg) - { - case GL_INVALID_ENUM: - LOG(LogLevel::Error, - _T("PNG : Unacceptable value for imagebuffer"), - LIBPNG_LOG_TAG); - break; - case GL_INVALID_VALUE: - LOG(LogLevel::Error, - _T("PNG : value out of range"), LIBPNG_LOG_TAG); - break; - case GL_INVALID_OPERATION: - LOG(LogLevel::Error, - _T("PNG : Not allowed in current state"), LIBPNG_LOG_TAG); - break; - case GL_OUT_OF_MEMORY: - LOG(LogLevel::Error, - _T("PNG : Out of Memory"), LIBPNG_LOG_TAG); - break; - } - errorMsg = glGetError(); - } - - if(hasError) - { - LOG(LogLevel::Error, - _T("PNG : Error loading png into OpenGl"), LIBPNG_LOG_TAG); - if(mTextureId != 0) - { - glDeleteTextures(1, &mTextureId); - mTextureId = 0; - } - mWidth = 0; - mHeight = 0; - mFormat = 0; - } -#endif - } - - const tstring & Texture2D::GetPath() const - { -#ifdef DESKTOP - return mPath; -#else - return mResource.GetPath(); -#endif - } - - int32 Texture2D::GetHeight() const - { - return mHeight; - } - - int32 Texture2D::GetWidth() const - { - return mWidth; - } - - GLuint Texture2D::GetTextureID() const - { - return mTextureId; - } - - void Texture2D::CustomErrorFunction(png_structp pngPtr, png_const_charp error) - { - DEBUG_LOG(LogLevel::Error, string_cast(error), LIBPNG_LOG_TAG); - setjmp(png_jmpbuf(pngPtr)); - } - - void Texture2D::CustomWarningFunction(png_structp pngPtr, png_const_charp warning) - { - DEBUG_LOG(LogLevel::Warning, string_cast(warning), LIBPNG_LOG_TAG); - } -} +#include "Texture2D.h" +#include +#include "../Helpers/Helpers.h" + +namespace star +{ + const tstring Texture2D::LIBPNG_LOG_TAG = _T("LIBPNG"); + + Texture2D::Texture2D(const tstring & pPath) + : mTextureId(0) + , mFormat(0) + , mWidth(0) + , mHeight(0) +#ifdef ANDROID + , mResource(pPath) +#else + , mPath(pPath) +#endif + { + Load(); + } +#ifdef ANDROID + void Texture2D::CallbackRead(png_structp png, png_bytep data, png_size_t size) + { + Resource& lReader = *((Resource*)png_get_io_ptr(png)); + if(!lReader.Read(data,size)) + { + lReader.Close(); + png_error(png, "Error while reading PNG file"); + } + } +#endif + + Texture2D::~Texture2D() + { + if(mTextureId != 0) + { + glDeleteTextures(1, &mTextureId); + mTextureId = 0; + } + mWidth = 0; + mHeight = 0; + mFormat = 0; + } + + uint8* Texture2D::ReadPNG() + { + png_byte header[8]; + png_structp lPngPtr = NULL; + png_infop lInfoPtr = NULL; + png_byte* lImageBuffer = NULL; + png_bytep* lRowPtrs = NULL; + png_int_32 lRowSize; + bool lTransparency; + +#ifdef DESKTOP + FILE *fp; + tfopen(&fp, mPath.c_str(), _T("rb")); + + if(fp == NULL) + { + LOG(LogLevel::Error, + _T("Texture2D::ReadPNG: the png \"") + + mPath + + _T("\" could not be loaded"), LIBPNG_LOG_TAG + ); + return NULL; + } + + fread(header, 8, 1, fp); +#elif defined(ANDROID) + if(!mResource.Open()) + { + mResource.Close(); + LOG(LogLevel::Error, + _T("PNG : Could Not Open Resource"), LIBPNG_LOG_TAG); + return NULL; + } + if(!mResource.Read(header, sizeof(header))) + { + mResource.Close(); + LOG(LogLevel::Error, + _T("PNG : Could Not Read"), + LIBPNG_LOG_TAG); + return NULL; + } +#endif + + if(png_sig_cmp(header, 0, 8)) + { + LOG(LogLevel::Error, + _T("PNG : Not a PNG file"), + LIBPNG_LOG_TAG); + return NULL; + } + lPngPtr = png_create_read_struct( + PNG_LIBPNG_VER_STRING, + NULL, + NULL, + NULL + ); + if(!lPngPtr) + { + LOG(LogLevel::Error, + _T("PNG : create struct string failed"), + LIBPNG_LOG_TAG); + return NULL; + } + + png_set_error_fn(lPngPtr, NULL, CustomErrorFunction, CustomWarningFunction); + + lInfoPtr = png_create_info_struct(lPngPtr); + if(!lInfoPtr) + { + LOG(LogLevel::Error, + _T("PNG : create info failed"), LIBPNG_LOG_TAG); + return NULL; + } + +#ifdef DESKTOP + png_init_io(lPngPtr, fp); + if(setjmp(png_jmpbuf(lPngPtr))) + { + LOG(LogLevel::Error, + _T("PNG : Error during init io"), LIBPNG_LOG_TAG); + return NULL; + } +#elif defined(ANDROID) + png_set_read_fn(lPngPtr, &mResource, CallbackRead); + if(setjmp(png_jmpbuf(lPngPtr))) + { + mResource.Close(); + LOG(LogLevel::Error, + _T("PNG : Error during init io"), LIBPNG_LOG_TAG); + return NULL; + } +#endif + png_set_sig_bytes(lPngPtr, 8); + png_read_info(lPngPtr,lInfoPtr); + + png_uint_32 pWidth, pHeight; + png_int_32 lDepth, lColorType; + png_get_IHDR( + lPngPtr, + lInfoPtr, + &pWidth, + &pHeight, + &lDepth, + &lColorType, + NULL, + NULL, + NULL + ); + mWidth = pWidth; + mHeight = pHeight; + + lTransparency = false; + if(png_get_valid(lPngPtr, lInfoPtr, PNG_INFO_tRNS)) + { + png_set_tRNS_to_alpha(lPngPtr); + lTransparency=true; + +#ifdef ANDROID + mResource.Close(); +#endif + delete [] lRowPtrs; + delete [] lImageBuffer; + if(lPngPtr != NULL) + { + png_infop* lInfoPtrP = lInfoPtr != NULL ? &lInfoPtr: NULL; + png_destroy_read_struct(&lPngPtr, lInfoPtrP, NULL); + } + return NULL; + } + + if(lDepth < 8 ) + { + png_set_packing(lPngPtr); + } + else if(lDepth == 16) + { + png_set_strip_16(lPngPtr); + } + + switch(lColorType) + { + case PNG_COLOR_TYPE_PALETTE: + png_set_palette_to_rgb(lPngPtr); + mFormat = lTransparency ? GL_RGBA : GL_RGB; + break; + case PNG_COLOR_TYPE_RGB: + mFormat = lTransparency ? GL_RGBA : GL_RGB; + break; + case PNG_COLOR_TYPE_RGBA: + mFormat = GL_RGBA; + break; + case PNG_COLOR_TYPE_GRAY: + png_set_expand_gray_1_2_4_to_8(lPngPtr); + mFormat = lTransparency ? GL_LUMINANCE_ALPHA : GL_LUMINANCE; + break; + case PNG_COLOR_TYPE_GA: + png_set_expand_gray_1_2_4_to_8(lPngPtr); + mFormat = GL_LUMINANCE_ALPHA; + break; + } + + //mNumber_of_passes = png_set_interlace_handling(mPng_ptr); + png_read_update_info(lPngPtr,lInfoPtr); + + /*if(setjmp(png_jmpbuf(mPng_ptr))) + { + LOG(LogLevel::Info, + _T("PNG : Error during read image"), LIBPNG_LOG_TAG); + return NULL; + }*/ + + lRowSize = png_get_rowbytes(lPngPtr,lInfoPtr); + if(lRowSize <= 0) + { + LOG(LogLevel::Error, + _T("PNG : png rowsize smaller or equal to 0"), + LIBPNG_LOG_TAG); + return NULL; + } + + lImageBuffer = new png_byte[lRowSize * pHeight]; + if(!lImageBuffer) + { + LOG(LogLevel::Error, + _T("PNG : Error during image buffer creation"), + LIBPNG_LOG_TAG); + return NULL; + } + + lRowPtrs = new png_bytep[pHeight]; + if(!lRowPtrs) + { + LOG(LogLevel::Error, + _T("PNG : Error during row pointer creation"), + LIBPNG_LOG_TAG); + return NULL; + } + + for(uint32 i = 0; i < pHeight; ++i) + { + lRowPtrs[pHeight - (i+1)] = lImageBuffer + i * lRowSize; + } + png_read_image(lPngPtr, lRowPtrs); +#ifdef DESKTOP + fclose(fp); +#elif defined(ANDROID) + mResource.Close(); +#endif + png_destroy_read_struct(&lPngPtr, &lInfoPtr, NULL); + delete[] lRowPtrs; + +#ifdef DESKTOP + DEBUG_LOG(LogLevel::Info, + _T("PNG : ") + mPath + _T(" Created Succesfull"), + LIBPNG_LOG_TAG); +#elif defined(ANDROID) + DEBUG_LOG(LogLevel::Info, + _T("PNG : ") + mResource.GetPath() + _T(" Created Succesfull"), + LIBPNG_LOG_TAG); +#endif + return lImageBuffer; + + } + + void Texture2D::Load() + { + uint8* lImageBuffer = ReadPNG(); + if(lImageBuffer == NULL) + { + LOG(LogLevel::Error, + _T("PNG : READING PNG FAILED - NO IMAGE BUFFER"), LIBPNG_LOG_TAG); + return; + } + + glGenTextures(1, &mTextureId); + glBindTexture(GL_TEXTURE_2D, mTextureId); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + glTexImage2D(GL_TEXTURE_2D, 0, mFormat, mWidth, mHeight, 0, mFormat, GL_UNSIGNED_BYTE, lImageBuffer); + delete[] lImageBuffer; + +#if defined(DEBUG) | defined(_DEBUG) + bool hasError = false; + GLenum errorMsg; + errorMsg = glGetError(); + while(errorMsg != GL_NO_ERROR) + { + hasError=true; + switch(errorMsg) + { + case GL_INVALID_ENUM: + LOG(LogLevel::Error, + _T("PNG : Unacceptable value for imagebuffer"), + LIBPNG_LOG_TAG); + break; + case GL_INVALID_VALUE: + LOG(LogLevel::Error, + _T("PNG : value out of range"), LIBPNG_LOG_TAG); + break; + case GL_INVALID_OPERATION: + LOG(LogLevel::Error, + _T("PNG : Not allowed in current state"), LIBPNG_LOG_TAG); + break; + case GL_OUT_OF_MEMORY: + LOG(LogLevel::Error, + _T("PNG : Out of Memory"), LIBPNG_LOG_TAG); + break; + } + errorMsg = glGetError(); + } + + if(hasError) + { + LOG(LogLevel::Error, + _T("PNG : Error loading png into OpenGl"), LIBPNG_LOG_TAG); + if(mTextureId != 0) + { + glDeleteTextures(1, &mTextureId); + mTextureId = 0; + } + mWidth = 0; + mHeight = 0; + mFormat = 0; + } +#endif + } + + const tstring & Texture2D::GetPath() const + { +#ifdef DESKTOP + return mPath; +#elif defined(ANDROID) + return mResource.GetPath(); +#endif + } + + int32 Texture2D::GetHeight() const + { + return mHeight; + } + + int32 Texture2D::GetWidth() const + { + return mWidth; + } + + GLuint Texture2D::GetTextureID() const + { + return mTextureId; + } + + void Texture2D::CustomErrorFunction(png_structp pngPtr, png_const_charp error) + { + DEBUG_LOG(LogLevel::Error, string_cast(error), LIBPNG_LOG_TAG); + setjmp(png_jmpbuf(pngPtr)); + } + + void Texture2D::CustomWarningFunction(png_structp pngPtr, png_const_charp warning) + { + DEBUG_LOG(LogLevel::Warning, string_cast(warning), LIBPNG_LOG_TAG); + } +} diff --git a/src/Graphics/Texture2D.h b/src/Graphics/Texture2D.h index eba895b..de20a87 100755 --- a/src/Graphics/Texture2D.h +++ b/src/Graphics/Texture2D.h @@ -1,63 +1,63 @@ -#pragma once - -#include "../defines.h" -#include "../Logger.h" - -#ifdef DESKTOP -//#pragma warning (disable : 4172) -//#pragma warning (disable : 4099) -#include -//#pragma warning (default : 4172) -//#pragma warning (default : 4099) -#include -#else -#include -#include -#include -#include -#include "Resource.h" -#endif - - -namespace star -{ - class Texture2D final - { - public: - //[NOTE] You're not supposed to make Textures yourself. - // Use the TextureManager to load your textures. - // This ensures a same texture is not loaded multiple times - Texture2D(const tstring & pPath); - ~Texture2D(); - - const tstring & GetPath() const; - int32 GetHeight() const; - int32 GetWidth() const; - GLuint GetTextureID() const; - - private: - uint8* ReadPNG(); - void Load(); - - GLuint mTextureId; - GLint mFormat; - int32 mWidth, mHeight; -#ifdef ANDROID - Resource mResource; - static void CallbackRead(png_structp png, png_bytep data, png_size_t size); -#else - tstring mPath; -#endif - static const tstring LIBPNG_LOG_TAG; - - static void CustomErrorFunction(png_structp pngPtr, png_const_charp error); - static void CustomWarningFunction(png_structp pngPtr, png_const_charp warning); - - Texture2D(const Texture2D& yRef); - Texture2D(Texture2D&& yRef); - Texture2D& operator=(const Texture2D& yRef); - Texture2D& operator=(Texture2D&& yRef); - }; -} - - +#pragma once + +#include "../defines.h" +#include "../Logger.h" + +#ifdef DESKTOP +//#pragma warning (disable : 4172) +//#pragma warning (disable : 4099) +#include +//#pragma warning (default : 4172) +//#pragma warning (default : 4099) +#include +#elif defined(ANDROID) +#include +#include +#include +#include +#include "Resource.h" +#endif + + +namespace star +{ + class Texture2D final + { + public: + //[NOTE] You're not supposed to make Textures yourself. + // Use the TextureManager to load your textures. + // This ensures a same texture is not loaded multiple times + Texture2D(const tstring & pPath); + ~Texture2D(); + + const tstring & GetPath() const; + int32 GetHeight() const; + int32 GetWidth() const; + GLuint GetTextureID() const; + + private: + uint8* ReadPNG(); + void Load(); + + GLuint mTextureId; + GLint mFormat; + int32 mWidth, mHeight; +#ifdef ANDROID + Resource mResource; + static void CallbackRead(png_structp png, png_bytep data, png_size_t size); +#else + tstring mPath; +#endif + static const tstring LIBPNG_LOG_TAG; + + static void CustomErrorFunction(png_structp pngPtr, png_const_charp error); + static void CustomWarningFunction(png_structp pngPtr, png_const_charp warning); + + Texture2D(const Texture2D& yRef); + Texture2D(Texture2D&& yRef); + Texture2D& operator=(const Texture2D& yRef); + Texture2D& operator=(Texture2D&& yRef); + }; +} + + diff --git a/src/Graphics/TextureManager.h b/src/Graphics/TextureManager.h index e33f376..2ff3c4e 100755 --- a/src/Graphics/TextureManager.h +++ b/src/Graphics/TextureManager.h @@ -1,42 +1,42 @@ -#pragma once - -#include -#include -#include "../defines.h" -#include "../Helpers/Singleton.h" - -#ifdef DESKTOP -#include -#else -#include "GLES/gl.h" -#endif - -namespace star -{ - class Texture2D; - - class TextureManager final : public Singleton - { - public: - friend Singleton; - - void LoadTexture(const tstring& path, const tstring& name); - bool DeleteTexture(const tstring& name); - GLuint GetTextureID(const tstring& name); - ivec2 GetTextureDimensions(const tstring& name); - void EraseAllTextures(); - bool ReloadAllTextures(); - - private: - std::map> m_TextureMap; - std::map m_PathList; - - TextureManager(); - ~TextureManager(); - - TextureManager(const TextureManager& yRef); - TextureManager(TextureManager&& yRef); - TextureManager& operator=(const TextureManager& yRef); - TextureManager& operator=(TextureManager&& yRef); - }; -} +#pragma once + +#include +#include +#include "../defines.h" +#include "../Helpers/Singleton.h" + +#ifdef DESKTOP +#include +#elif defined(ANDROID) +#include "GLES/gl.h" +#endif + +namespace star +{ + class Texture2D; + + class TextureManager final : public Singleton + { + public: + friend Singleton; + + void LoadTexture(const tstring& path, const tstring& name); + bool DeleteTexture(const tstring& name); + GLuint GetTextureID(const tstring& name); + ivec2 GetTextureDimensions(const tstring& name); + void EraseAllTextures(); + bool ReloadAllTextures(); + + private: + std::map> m_TextureMap; + std::map m_PathList; + + TextureManager(); + ~TextureManager(); + + TextureManager(const TextureManager& yRef); + TextureManager(TextureManager&& yRef); + TextureManager& operator=(const TextureManager& yRef); + TextureManager& operator=(TextureManager&& yRef); + }; +} diff --git a/src/Graphics/UI/UIAnimatedButton.cpp b/src/Graphics/UI/UIAnimatedButton.cpp index 7c29835..eabcb3a 100755 --- a/src/Graphics/UI/UIAnimatedButton.cpp +++ b/src/Graphics/UI/UIAnimatedButton.cpp @@ -1,6 +1,6 @@ #include "UIAnimatedButton.h" -#include "../../Components/Graphics/SpriteSheetComponent.h" +#include "../../Components/Graphics/SpritesheetComponent.h" #include "../../Graphics/SpriteAnimationManager.h" namespace star diff --git a/src/Graphics/UI/UIAnimatedImage.cpp b/src/Graphics/UI/UIAnimatedImage.cpp index a9cb7a5..e984d4c 100755 --- a/src/Graphics/UI/UIAnimatedImage.cpp +++ b/src/Graphics/UI/UIAnimatedImage.cpp @@ -1,5 +1,5 @@ #include "UIAnimatedImage.h" -#include "../../Components/Graphics/SpriteSheetComponent.h" +#include "../../Components/Graphics/SpritesheetComponent.h" namespace star { diff --git a/src/Graphics/UI/UICursor.cpp b/src/Graphics/UI/UICursor.cpp index df6df38..a3120d0 100755 --- a/src/Graphics/UI/UICursor.cpp +++ b/src/Graphics/UI/UICursor.cpp @@ -1,5 +1,5 @@ #include "UICursor.h" -#include "../../Components/Graphics/SpriteSheetComponent.h" +#include "../../Components/Graphics/SpritesheetComponent.h" #include "../../Input/InputManager.h" namespace star diff --git a/src/Helpers/AARect.h b/src/Helpers/AARect.h index c070c98..38e1e70 100755 --- a/src/Helpers/AARect.h +++ b/src/Helpers/AARect.h @@ -1,8 +1,8 @@ #pragma once -#include "glm\glm.h" +#include "glm/glm.h" #include -#include "..\Logger.h" +#include "../Logger.h" namespace star { diff --git a/src/Helpers/Debug/DebugDraw.h b/src/Helpers/Debug/DebugDraw.h index 2921049..a4b4605 100755 --- a/src/Helpers/Debug/DebugDraw.h +++ b/src/Helpers/Debug/DebugDraw.h @@ -1,168 +1,172 @@ -#pragma once - -#include "../../defines.h" -#include "../Singleton.h" -#include "../../Graphics/Color.h" -#include "../../Graphics/Shader.h" -#include -#ifdef DESKTOP -#include -#else -#include -#endif - -namespace star -{ - class AARect; - class Rect; - - struct PrimitiveInfo - { - PrimitiveInfo() - : primitiveType(0) - , count(0) - , color() - , opacityTriangles(0) - , opacityLines(0) - , opacityPoints(0) - { - //Don't initialize the array's elements to vec2(), - //not necessairy in this case. - } - private: - static const uint32 MAX_VERTICES = 64; - - public: - vec2 vertices[MAX_VERTICES]; - uint32 primitiveType; - uint32 count; - Color color; - float32 opacityTriangles - , opacityLines - , opacityPoints; - }; - - class DebugDraw final : public Singleton - { - public: - friend Singleton; - - void Initialize(); - - void DrawPolygon( - const vec2* vertices, - int32 vertexCount, - const Color& color - ); - void DrawSolidPolygon( - const vec2* vertices, - int32 vertexCount, - const Color& color - ); - void DrawCircle( - const vec2& center, - float32 radius, - const Color& color, - uint32 segments = 16 - ); - void DrawSolidCircle( - const vec2& center, - float32 radius, - const Color& color, - uint32 segments = 16 - ); - void DrawSegment( - const vec2& pos1, - const vec2& pos2, - const Color& aColor - ); - //[TODO] DrawTransform: Draw the transformed Axises of the object/matrix - // void DrawTransform(const mat4& aXf); - void DrawPoint( - const vec2& pos, - float32 size, - const Color& color - ); - void DrawLine( - const vec2& pos1, - const vec2& pos2, - const Color& color - ); - void DrawString( - int32 xPos, - int32 yPos, - const tstring& text - ); - void DrawRect( - const AARect& rect, - const Color& color - ); - void DrawRect( - const Rect& rect, - const Color& color - ); - void DrawSolidRect( - const AARect& rect, - const Color& color - ); - void DrawSolidRect( - const Rect& rect, - const Color& color - ); - - void SetDrawOpacityTriangles(float32 opacity); - void SetDrawOpacityLines(float32 opacity); - void SetDrawOpacityPoints(float32 opacity); - - void Flush(); - - private: - static const uint32 MAX_VERTICES = 64; - - enum - { - Triangles = 0x01, - Lines = 0x02, - Points = 0x04 - }; - - DebugDraw(); - ~DebugDraw(); - - void CreatePolygonVertices( - const vec2* vertices, - uint32 vertexCount - ); - void CreateCircleVertices( - const vec2& center, - float32 radius, - uint8 segments - ); - void AddToVertexQueue( - uint32 primitiveTypes, - uint32 count, - const Color& color - ); - - void Begin(); - void End(); - - std::vector m_VertexBuffer; - vec2 m_Vertices[MAX_VERTICES]; - float32 m_PointSize; - - float32 m_DrawOpTriangles; - float32 m_DrawOpLines; - float32 m_DrawOpPoints; - - Shader* m_Shader; - GLuint m_ColorLocation; - GLuint m_MVPLocation; - GLuint m_PositionLocation; - - DebugDraw(const DebugDraw &); - DebugDraw(DebugDraw &&); - DebugDraw & operator=(const DebugDraw &); - DebugDraw & operator=(DebugDraw&&); - }; -} +#pragma once + +#include "../../defines.h" +#include "../Singleton.h" +#include "../../Graphics/Color.h" +#include "../../Graphics/Shader.h" +#include +#ifdef DESKTOP + #ifdef _WIN32 + #include + #elif defined(ANDROID) + #include + #endif +#else + #include +#endif + +namespace star +{ + class AARect; + class Rect; + + struct PrimitiveInfo + { + PrimitiveInfo() + : primitiveType(0) + , count(0) + , color() + , opacityTriangles(0) + , opacityLines(0) + , opacityPoints(0) + { + //Don't initialize the array's elements to vec2(), + //not necessairy in this case. + } + private: + static const uint32 MAX_VERTICES = 64; + + public: + vec2 vertices[MAX_VERTICES]; + uint32 primitiveType; + uint32 count; + Color color; + float32 opacityTriangles + , opacityLines + , opacityPoints; + }; + + class DebugDraw final : public Singleton + { + public: + friend Singleton; + + void Initialize(); + + void DrawPolygon( + const vec2* vertices, + int32 vertexCount, + const Color& color + ); + void DrawSolidPolygon( + const vec2* vertices, + int32 vertexCount, + const Color& color + ); + void DrawCircle( + const vec2& center, + float32 radius, + const Color& color, + uint32 segments = 16 + ); + void DrawSolidCircle( + const vec2& center, + float32 radius, + const Color& color, + uint32 segments = 16 + ); + void DrawSegment( + const vec2& pos1, + const vec2& pos2, + const Color& aColor + ); + //[TODO] DrawTransform: Draw the transformed Axises of the object/matrix + // void DrawTransform(const mat4& aXf); + void DrawPoint( + const vec2& pos, + float32 size, + const Color& color + ); + void DrawLine( + const vec2& pos1, + const vec2& pos2, + const Color& color + ); + void DrawString( + int32 xPos, + int32 yPos, + const tstring& text + ); + void DrawRect( + const AARect& rect, + const Color& color + ); + void DrawRect( + const Rect& rect, + const Color& color + ); + void DrawSolidRect( + const AARect& rect, + const Color& color + ); + void DrawSolidRect( + const Rect& rect, + const Color& color + ); + + void SetDrawOpacityTriangles(float32 opacity); + void SetDrawOpacityLines(float32 opacity); + void SetDrawOpacityPoints(float32 opacity); + + void Flush(); + + private: + static const uint32 MAX_VERTICES = 64; + + enum + { + Triangles = 0x01, + Lines = 0x02, + Points = 0x04 + }; + + DebugDraw(); + ~DebugDraw(); + + void CreatePolygonVertices( + const vec2* vertices, + uint32 vertexCount + ); + void CreateCircleVertices( + const vec2& center, + float32 radius, + uint8 segments + ); + void AddToVertexQueue( + uint32 primitiveTypes, + uint32 count, + const Color& color + ); + + void Begin(); + void End(); + + std::vector m_VertexBuffer; + vec2 m_Vertices[MAX_VERTICES]; + float32 m_PointSize; + + float32 m_DrawOpTriangles; + float32 m_DrawOpLines; + float32 m_DrawOpPoints; + + Shader* m_Shader; + GLuint m_ColorLocation; + GLuint m_MVPLocation; + GLuint m_PositionLocation; + + DebugDraw(const DebugDraw &); + DebugDraw(DebugDraw &&); + DebugDraw & operator=(const DebugDraw &); + DebugDraw & operator=(DebugDraw&&); + }; +} diff --git a/src/Helpers/Dictionary.h b/src/Helpers/Dictionary.h index 929e0d1..d8e0a53 100755 --- a/src/Helpers/Dictionary.h +++ b/src/Helpers/Dictionary.h @@ -1,9 +1,9 @@ #pragma once -#include "..\defines.h" +#include "../defines.h" #include #include "Helpers.h" -#include "..\Logger.h" +#include "../Logger.h" namespace star { diff --git a/src/Helpers/Dictionary.inl b/src/Helpers/Dictionary.inl index 8ac2dff..3ab1c14 100755 --- a/src/Helpers/Dictionary.inl +++ b/src/Helpers/Dictionary.inl @@ -1,292 +1,292 @@ -#include "..\defines.h" -#include -#include "Helpers.h" -#include "..\Logger.h" - -namespace star -{ - template < typename TKey, typename TValue > - Dictionary::Dictionary() - : m_MultiMap() - { - - } - - template < typename TKey, typename TValue > - Dictionary::Dictionary(const Dictionary & yRef) - : m_MultiMap(yRef.m_MultiMap) - { - - } - - template < typename TKey, typename TValue > - Dictionary::Dictionary(Dictionary && yRef) - : m_MultiMap(yRef.m_MultiMap) - { - } - - template < typename TKey, typename TValue > - Dictionary::Dictionary - ( typename Dictionary::iterator begin, - typename Dictionary::iterator end ) - : m_MultiMap(begin, end) - { - - } - - template < typename TKey, typename TValue > - Dictionary::~Dictionary() - { - clear(); - } - - template < typename TKey, typename TValue > - Dictionary & - Dictionary::operator=(const Dictionary& yRef) - { - m_MultiMap = yRef.m_MultiMap; - return (*this); - } - - template < typename TKey, typename TValue > - Dictionary & - Dictionary::operator=(Dictionary&& yRef) - { - m_MultiMap = yRef.m_MultiMap; - return (*this); - } - - template < typename TKey, typename TValue > - TValue & Dictionary::operator[](const TKey & key) - { - return (at(key)); - } - - template < typename TKey, typename TValue > - TValue & Dictionary::operator[](dki_pair & ki_pair) - { - return (at(ki_pair)); - } - - template < typename TKey, typename TValue > - TValue & Dictionary::at(const TKey & key) - { - auto it = m_MultiMap.find(key); - ASSERT_LOG(it != m_MultiMap.end(), _T("Dictionary::at: Couldn't find key '") + - string_cast(key) + _T("'."), STARENGINE_LOG_TAG); - return ((*it).second); - } - - template < typename TKey, typename TValue > - TValue & Dictionary::at - (dki_pair & ki_pair) - { - return (at(ki_pair.first, ki_pair.second)); - } - - template < typename TKey, typename TValue > - TValue & Dictionary::at(const TKey & key, size_type index) - { - std::pair range = m_MultiMap.equal_range(key); - auto it = range.first; - size_type i(0); - while(i < index && it != range.second) - { - ++i; - ++it; - ASSERT_LOG(it != range.second, _T("Dictionary::at: The value with key '") + - string_cast(key) + _T("' and index '") + - string_cast(index) + _T("' couldn't be found."), - STARENGINE_LOG_TAG); - } - return ((*it).second); - } - - template < typename TKey, typename TValue > - typename Dictionary::iterator Dictionary::begin() - { - return (m_MultiMap.begin()); - } - - template < typename TKey, typename TValue > - typename Dictionary::iterator Dictionary::end() - { - return (m_MultiMap.end()); - } - - template < typename TKey, typename TValue > - typename Dictionary::const_interator Dictionary::cbegin() const - { - return (m_MultiMap.cbegin()); - } - - template < typename TKey, typename TValue > - typename Dictionary::const_interator Dictionary::cend() const - { - return (m_MultiMap.cend()); - } - - template < typename TKey, typename TValue > - typename Dictionary::const_interator Dictionary::find - (const TKey & key) const - { - return (m_MultiMap.find(key)); - } - - template < typename TKey, typename TValue > - typename Dictionary::size_type Dictionary::count - (const TKey & key) const - { - return (m_MultiMap.count(key)); - } - - template < typename TKey, typename TValue > - std::pair< - typename Dictionary::const_interator, - typename Dictionary::const_interator - > - Dictionary::equal_range(const TKey & key) const - { - return m_MultiMap.equal_range(key); - } - - template < typename TKey, typename TValue > - typename Dictionary::const_interator - Dictionary::lower_bound(const TKey & key) const - { -#ifdef DESKTOP - return (m_MultiMap.lower_bound(key)); -#else - return m_MultiMap.equal_range(key).first; -#endif - } - - template < typename TKey, typename TValue > - typename Dictionary::const_interator - Dictionary::upper_bound(const TKey & key) const - { -#ifdef DESKTOP - return (m_MultiMap.upper_bound(key)); -#else - return m_MultiMap.equal_range(key).second; -#endif - } - - template < typename TKey, typename TValue > - typename Dictionary::iterator - Dictionary::insert(const TValue & value) - { - return (m_MultiMap.insert(value)); - } - - template < typename TKey, typename TValue > - typename Dictionary::iterator - Dictionary::insert(TValue && value) - { - return (m_MultiMap.insert(value)); - } - - template < typename TKey, typename TValue > - typename Dictionary::iterator - Dictionary::insert( - typename Dictionary::const_interator hint, - const typename Dictionary::value_type & value) - { - return (m_MultiMap.insert(hint, value)); - } - - template < typename TKey, typename TValue > - typename Dictionary::iterator - Dictionary::insert( - typename Dictionary::const_interator hint, - typename Dictionary::value_type && value) - { - return (m_MultiMap.insert(hint, value)); - } - - template < typename TKey, typename TValue > - typename Dictionary::iterator - Dictionary::insert - (const dkv_pair & kv_pair) - { - return (m_MultiMap.insert(kv_pair)); - } - - template < typename TKey, typename TValue > - typename Dictionary::iterator - Dictionary::erase - (typename Dictionary::const_interator position) - { - return (m_MultiMap.erase(position)); - } - - template < typename TKey, typename TValue > - typename Dictionary::size_type - Dictionary::erase - (const typename Dictionary::key_type& key) - { - return (m_MultiMap.erase(key)); - } - - template < typename TKey, typename TValue > - typename Dictionary::iterator - Dictionary::erase( - typename Dictionary::const_interator first, - typename Dictionary::const_interator last ) - { - return (m_MultiMap.erase(first, last)); - } - - template < typename TKey, typename TValue > - void Dictionary::clear() - { - m_MultiMap.clear(); - } - - template < typename TKey, typename TValue > - void Dictionary::swap(Dictionary & yRef) - { - m_MultiMap.swap(yRef.m_MultiMap); - } - - template < typename TKey, typename TValue > - bool Dictionary::empty() const - { - return (m_MultiMap.empty()); - } - - template < typename TKey, typename TValue > - typename Dictionary::size_type - Dictionary::size() const - { - return (m_MultiMap.size()); - } - - template < typename TKey, typename TValue > - typename Dictionary::size_type - Dictionary::max_size() const - { - return (m_MultiMap.max_size()); - } - - template < typename TKey, typename TValue > - void swap( Dictionary& lhs, - Dictionary& rhs) - { - std::swap(lhs.m_MultiMap, rhs.m_MultiMap); - } - - template < typename TKey, typename TValue > - bool operator== ( Dictionary& lhs, - Dictionary& rhs) - { - return (lhs.m_MultiMap == rhs.m_MultiMap); - } - - template < typename TKey, typename TValue > - bool operator!= ( Dictionary& lhs, - Dictionary& rhs) - { - return (lhs.m_MultiMap != rhs.m_MultiMap); - } -} +#include "../defines.h" +#include +#include "Helpers.h" +#include "../Logger.h" + +namespace star +{ + template < typename TKey, typename TValue > + Dictionary::Dictionary() + : m_MultiMap() + { + + } + + template < typename TKey, typename TValue > + Dictionary::Dictionary(const Dictionary & yRef) + : m_MultiMap(yRef.m_MultiMap) + { + + } + + template < typename TKey, typename TValue > + Dictionary::Dictionary(Dictionary && yRef) + : m_MultiMap(yRef.m_MultiMap) + { + } + + template < typename TKey, typename TValue > + Dictionary::Dictionary + ( typename Dictionary::iterator begin, + typename Dictionary::iterator end ) + : m_MultiMap(begin, end) + { + + } + + template < typename TKey, typename TValue > + Dictionary::~Dictionary() + { + clear(); + } + + template < typename TKey, typename TValue > + Dictionary & + Dictionary::operator=(const Dictionary& yRef) + { + m_MultiMap = yRef.m_MultiMap; + return (*this); + } + + template < typename TKey, typename TValue > + Dictionary & + Dictionary::operator=(Dictionary&& yRef) + { + m_MultiMap = yRef.m_MultiMap; + return (*this); + } + + template < typename TKey, typename TValue > + TValue & Dictionary::operator[](const TKey & key) + { + return (at(key)); + } + + template < typename TKey, typename TValue > + TValue & Dictionary::operator[](dki_pair & ki_pair) + { + return (at(ki_pair)); + } + + template < typename TKey, typename TValue > + TValue & Dictionary::at(const TKey & key) + { + auto it = m_MultiMap.find(key); + ASSERT_LOG(it != m_MultiMap.end(), _T("Dictionary::at: Couldn't find key '") + + string_cast(key) + _T("'."), STARENGINE_LOG_TAG); + return ((*it).second); + } + + template < typename TKey, typename TValue > + TValue & Dictionary::at + (dki_pair & ki_pair) + { + return (at(ki_pair.first, ki_pair.second)); + } + + template < typename TKey, typename TValue > + TValue & Dictionary::at(const TKey & key, size_type index) + { + std::pair range = m_MultiMap.equal_range(key); + auto it = range.first; + size_type i(0); + while(i < index && it != range.second) + { + ++i; + ++it; + ASSERT_LOG(it != range.second, _T("Dictionary::at: The value with key '") + + string_cast(key) + _T("' and index '") + + string_cast(index) + _T("' couldn't be found."), + STARENGINE_LOG_TAG); + } + return ((*it).second); + } + + template < typename TKey, typename TValue > + typename Dictionary::iterator Dictionary::begin() + { + return (m_MultiMap.begin()); + } + + template < typename TKey, typename TValue > + typename Dictionary::iterator Dictionary::end() + { + return (m_MultiMap.end()); + } + + template < typename TKey, typename TValue > + typename Dictionary::const_interator Dictionary::cbegin() const + { + return (m_MultiMap.cbegin()); + } + + template < typename TKey, typename TValue > + typename Dictionary::const_interator Dictionary::cend() const + { + return (m_MultiMap.cend()); + } + + template < typename TKey, typename TValue > + typename Dictionary::const_interator Dictionary::find + (const TKey & key) const + { + return (m_MultiMap.find(key)); + } + + template < typename TKey, typename TValue > + typename Dictionary::size_type Dictionary::count + (const TKey & key) const + { + return (m_MultiMap.count(key)); + } + + template < typename TKey, typename TValue > + std::pair< + typename Dictionary::const_interator, + typename Dictionary::const_interator + > + Dictionary::equal_range(const TKey & key) const + { + return m_MultiMap.equal_range(key); + } + + template < typename TKey, typename TValue > + typename Dictionary::const_interator + Dictionary::lower_bound(const TKey & key) const + { +#ifdef _WIN32 + return (m_MultiMap.lower_bound(key)); +#else + return m_MultiMap.equal_range(key).first; +#endif + } + + template < typename TKey, typename TValue > + typename Dictionary::const_interator + Dictionary::upper_bound(const TKey & key) const + { +#ifdef _WIN32 + return (m_MultiMap.upper_bound(key)); +#else + return m_MultiMap.equal_range(key).second; +#endif + } + + template < typename TKey, typename TValue > + typename Dictionary::iterator + Dictionary::insert(const TValue & value) + { + return (m_MultiMap.insert(value)); + } + + template < typename TKey, typename TValue > + typename Dictionary::iterator + Dictionary::insert(TValue && value) + { + return (m_MultiMap.insert(value)); + } + + template < typename TKey, typename TValue > + typename Dictionary::iterator + Dictionary::insert( + typename Dictionary::const_interator hint, + const typename Dictionary::value_type & value) + { + return (m_MultiMap.insert(hint, value)); + } + + template < typename TKey, typename TValue > + typename Dictionary::iterator + Dictionary::insert( + typename Dictionary::const_interator hint, + typename Dictionary::value_type && value) + { + return (m_MultiMap.insert(hint, value)); + } + + template < typename TKey, typename TValue > + typename Dictionary::iterator + Dictionary::insert + (const dkv_pair & kv_pair) + { + return (m_MultiMap.insert(kv_pair)); + } + + template < typename TKey, typename TValue > + typename Dictionary::iterator + Dictionary::erase + (typename Dictionary::const_interator position) + { + return (m_MultiMap.erase(position)); + } + + template < typename TKey, typename TValue > + typename Dictionary::size_type + Dictionary::erase + (const typename Dictionary::key_type& key) + { + return (m_MultiMap.erase(key)); + } + + template < typename TKey, typename TValue > + typename Dictionary::iterator + Dictionary::erase( + typename Dictionary::const_interator first, + typename Dictionary::const_interator last ) + { + return (m_MultiMap.erase(first, last)); + } + + template < typename TKey, typename TValue > + void Dictionary::clear() + { + m_MultiMap.clear(); + } + + template < typename TKey, typename TValue > + void Dictionary::swap(Dictionary & yRef) + { + m_MultiMap.swap(yRef.m_MultiMap); + } + + template < typename TKey, typename TValue > + bool Dictionary::empty() const + { + return (m_MultiMap.empty()); + } + + template < typename TKey, typename TValue > + typename Dictionary::size_type + Dictionary::size() const + { + return (m_MultiMap.size()); + } + + template < typename TKey, typename TValue > + typename Dictionary::size_type + Dictionary::max_size() const + { + return (m_MultiMap.max_size()); + } + + template < typename TKey, typename TValue > + void swap( Dictionary& lhs, + Dictionary& rhs) + { + std::swap(lhs.m_MultiMap, rhs.m_MultiMap); + } + + template < typename TKey, typename TValue > + bool operator== ( Dictionary& lhs, + Dictionary& rhs) + { + return (lhs.m_MultiMap == rhs.m_MultiMap); + } + + template < typename TKey, typename TValue > + bool operator!= ( Dictionary& lhs, + Dictionary& rhs) + { + return (lhs.m_MultiMap != rhs.m_MultiMap); + } +} diff --git a/src/Helpers/Filepath.cpp b/src/Helpers/Filepath.cpp index da9aabf..60a974b 100755 --- a/src/Helpers/Filepath.cpp +++ b/src/Helpers/Filepath.cpp @@ -1,302 +1,302 @@ -#include "FilePath.h" -#ifdef _WIN32 - #include - #include "../StarEngine.h" -#endif -#include "../Logger.h" -#ifdef ANDROID - #include - #include "../StarEngine.h" -#endif -#include "../Helpers/Helpers.h" - -namespace star -{ -#ifdef DESKTOP -tstring FilePath::m_AssetsRoot = EMPTY_STRING; -tstring FilePath::m_InternalRoot = EMPTY_STRING; -tstring FilePath::m_ExternalRoot = EMPTY_STRING; -const tchar FilePath::PATH_SEPERATOR = WIN_PATH_SEPERATOR; -#else -const tchar FilePath::PATH_SEPERATOR = ANDR_PATH_SEPERATOR; -const tstring FilePath::ANDR_INTERNAL_PATH = - string_cast(StarEngine::GetInstance()->GetAndroidApp() - ->activity->internalDataPath) + string_cast(ANDR_PATH_SEPERATOR); -const tstring FilePath::ANDR_EXTERNAL_PATH = - string_cast(StarEngine::GetInstance()->GetAndroidApp() - ->activity->externalDataPath) + string_cast(ANDR_PATH_SEPERATOR); -#endif - - FilePath::FilePath() - : m_Path(EMPTY_STRING) - , m_File(EMPTY_STRING) - , m_DirectoryMode(DEFAULT_DIRECTORY_MODE) - { - - } - - FilePath::FilePath(const tstring & full_path, DirectoryMode mode) - : m_Path(EMPTY_STRING) - , m_File(EMPTY_STRING) - , m_DirectoryMode(mode) - { - auto index = full_path.find_last_of(ANDR_PATH_SEPERATOR); - if(index == tstring::npos) - { - index = full_path.find_last_of(WIN_PATH_SEPERATOR); - } - if(index != tstring::npos) - { - index += 1; - m_Path = full_path.substr(0, index); - m_File = full_path.substr(index, full_path.length() - index); - } - else - { - m_File = full_path; - } - ConvertPathToCorrectPlatformStyle(m_Path); - CheckIfPathIsCapitalCorrect(GetRoot() + m_Path + m_File); - } - - FilePath::FilePath(const FilePath & yRef) - : m_Path(yRef.m_Path) - , m_File(yRef.m_File) - { - - } - - FilePath::FilePath(FilePath && yRef) - : m_Path(std::move(yRef.m_Path)) - , m_File(std::move(yRef.m_File)) - { - - } - - FilePath::~FilePath() - { - - } - - FilePath & FilePath::operator=(const FilePath & yRef) - { - m_Path = yRef.m_Path; - m_File = yRef.m_File; - return *this; - } - - FilePath & FilePath::operator=(FilePath && yRef) - { - m_Path = std::move(yRef.m_Path); - m_File = std::move(yRef.m_File); - return *this; - } - - bool FilePath::operator==(const FilePath & yRef) - { - return m_Path == yRef.m_Path && m_File == yRef.m_File; - } - - const tstring & FilePath::GetPath() const - { - return m_Path; - } - - const tstring & FilePath::GetFile() const - { - return m_File; - } - - tstring FilePath::GetName() const - { - tstring name(m_File); - auto index(name.find_last_of(_T("."))); - return name.substr(0, index); - } - - tstring FilePath::GetExtension() const - { - tstring extension(m_File); - auto index(extension.find_last_of(_T("."))); - return extension.substr(index, extension.size() - index); - } - - const tstring & FilePath::GetRoot() const - { -#ifdef DESKTOP - switch(m_DirectoryMode) - { - case DirectoryMode::assets: - return m_AssetsRoot; - case DirectoryMode::internal: - return m_InternalRoot; - case DirectoryMode::external: - return m_ExternalRoot; - default: - return EMPTY_STRING; - } -#endif -#ifdef ANDROID - switch(m_DirectoryMode) - { - case DirectoryMode::assets: - return EMPTY_STRING; - case DirectoryMode::internal: - return ANDR_INTERNAL_PATH; - case DirectoryMode::external: - return ANDR_EXTERNAL_PATH; - default: - return EMPTY_STRING; - } -#endif - } - - tstring FilePath::GetLocalPath() const - { - return m_Path + m_File; - } - - void FilePath::GetFullPath(tstring & correct_path) const - { - correct_path = GetRoot() + GetLocalPath(); - } - - tstring FilePath::GetFullPath() const - { - return GetRoot() + GetLocalPath(); - } - - DirectoryMode FilePath::GetDirectoryMode() const - { - return m_DirectoryMode; - } - -#ifdef DESKTOP - void FilePath::SetAssetsRoot(const tstring & root) - { - m_AssetsRoot = root; - ConvertPathToCorrectPlatformStyle(m_AssetsRoot); - } - - void FilePath::SetInternalRoot(const tstring & root) - { - m_InternalRoot = root; - ConvertPathToCorrectPlatformStyle(m_InternalRoot); - } - - void FilePath::SetExternalRoot(const tstring & root) - { - m_ExternalRoot = root; - ConvertPathToCorrectPlatformStyle(m_ExternalRoot); - } -#endif - - - bool FilePath::GetActualPathName(const tstring & pathIn, tstring & pathOut) - { -#ifdef _WIN32 - tstring buffer(pathIn); - - size_t i = 0; - pathOut = EMPTY_STRING; - - bool addSeparator = false; - - while(i < buffer.size()) - { - // skip until path separator - while(i < buffer.size() && buffer[i] != WIN_PATH_SEPERATOR) - { - ++i; - } - - if(addSeparator) - { - pathOut += WIN_PATH_SEPERATOR; - } - - // if we found path separator, get real filename of this - // last path name component - bool foundSeparator = (i < buffer.size()); - buffer[i] = 0; - TSHFILEINFO info; - - // nuke the path separator so that we get real name of current path component - info.szDisplayName[0] = 0; - if(SHGetFileInfo(buffer.c_str(), 0, &info, sizeof(info), SHGFI_DISPLAYNAME)) - { - pathOut += info.szDisplayName; - } - else - { - tstringstream message; - message << _T("FilePath::GetActualPathName: ") - << _T("The path \"") - << pathIn - << _T("\" points to an unexisting file! ") - << _T("The file might be created or this can \ -be unexpected behaviour. Please verify!"); - LOG(LogLevel::Info, - message.str(), STARENGINE_LOG_TAG); - return false; - } - - // restore path separator that we might have nuked before - if(foundSeparator) - { - buffer[i] = WIN_PATH_SEPERATOR; - } - - ++i; - addSeparator = true; - } - return true; -#endif - } - void FilePath::ConvertPathToCorrectPlatformStyle(tstring & path) - { -#ifdef _WIN32 - std::replace(path.begin(), path.end(), ANDR_PATH_SEPERATOR, WIN_PATH_SEPERATOR); -#else - std::replace(path.begin(), path.end(), WIN_PATH_SEPERATOR, ANDR_PATH_SEPERATOR); -#endif - } - - void FilePath::CheckIfPathIsCapitalCorrect(const tstring & full_path) - { -#if defined (_WIN32) & defined (_DEBUG) - tstring shellPath; - if(GetActualPathName(full_path, shellPath)) - { - auto seperatorIndex(shellPath.find_last_of(WIN_PATH_SEPERATOR)); - if(seperatorIndex != tstring::npos) - { - shellPath = shellPath.substr(seperatorIndex + 1, shellPath.size() - (seperatorIndex + 1)); - } - auto extensionIndex = m_File.find_last_of(_T(".")); - auto fileWithoutExtension(m_File); - if(extensionIndex != tstring::npos) - { - fileWithoutExtension = m_File.substr(0, extensionIndex); - } - auto shellExtensionIndex = shellPath.find_last_of(_T(".")); - auto shellNameWithoutExtension(shellPath); - if(shellExtensionIndex != tstring::npos) - { - shellNameWithoutExtension = shellPath.substr(0, shellExtensionIndex); - } - if(fileWithoutExtension != shellNameWithoutExtension) - { - tstringstream buffer; - buffer << - _T("The path \" ") << - full_path << - _T(" \" is not capital correct. Please change the name in code to \" ") << - shellPath << - _T(" \" or your game will crash on Android and Linux"); - DEBUG_LOG(LogLevel::Error, buffer.str(), STARENGINE_LOG_TAG); - } - } -#endif - } -} +#include "Filepath.h" +#ifdef _WIN32 + #include + #include "../StarEngine.h" +#endif +#include "../Logger.h" +#ifdef ANDROID + #include + #include "../StarEngine.h" +#endif +#include "../Helpers/Helpers.h" + +namespace star +{ +#ifdef DESKTOP +tstring FilePath::m_AssetsRoot = EMPTY_STRING; +tstring FilePath::m_InternalRoot = EMPTY_STRING; +tstring FilePath::m_ExternalRoot = EMPTY_STRING; +const tchar FilePath::PATH_SEPERATOR = WIN_PATH_SEPERATOR; +#elif defined(ANDROID) +const tchar FilePath::PATH_SEPERATOR = ANDR_PATH_SEPERATOR; +const tstring FilePath::ANDR_INTERNAL_PATH = + string_cast(StarEngine::GetInstance()->GetAndroidApp() + ->activity->internalDataPath) + string_cast(ANDR_PATH_SEPERATOR); +const tstring FilePath::ANDR_EXTERNAL_PATH = + string_cast(StarEngine::GetInstance()->GetAndroidApp() + ->activity->externalDataPath) + string_cast(ANDR_PATH_SEPERATOR); +#endif + + FilePath::FilePath() + : m_Path(EMPTY_STRING) + , m_File(EMPTY_STRING) + , m_DirectoryMode(DEFAULT_DIRECTORY_MODE) + { + + } + + FilePath::FilePath(const tstring & full_path, DirectoryMode mode) + : m_Path(EMPTY_STRING) + , m_File(EMPTY_STRING) + , m_DirectoryMode(mode) + { + auto index = full_path.find_last_of(ANDR_PATH_SEPERATOR); + if(index == tstring::npos) + { + index = full_path.find_last_of(WIN_PATH_SEPERATOR); + } + if(index != tstring::npos) + { + index += 1; + m_Path = full_path.substr(0, index); + m_File = full_path.substr(index, full_path.length() - index); + } + else + { + m_File = full_path; + } + ConvertPathToCorrectPlatformStyle(m_Path); + CheckIfPathIsCapitalCorrect(GetRoot() + m_Path + m_File); + } + + FilePath::FilePath(const FilePath & yRef) + : m_Path(yRef.m_Path) + , m_File(yRef.m_File) + { + + } + + FilePath::FilePath(FilePath && yRef) + : m_Path(std::move(yRef.m_Path)) + , m_File(std::move(yRef.m_File)) + { + + } + + FilePath::~FilePath() + { + + } + + FilePath & FilePath::operator=(const FilePath & yRef) + { + m_Path = yRef.m_Path; + m_File = yRef.m_File; + return *this; + } + + FilePath & FilePath::operator=(FilePath && yRef) + { + m_Path = std::move(yRef.m_Path); + m_File = std::move(yRef.m_File); + return *this; + } + + bool FilePath::operator==(const FilePath & yRef) + { + return m_Path == yRef.m_Path && m_File == yRef.m_File; + } + + const tstring & FilePath::GetPath() const + { + return m_Path; + } + + const tstring & FilePath::GetFile() const + { + return m_File; + } + + tstring FilePath::GetName() const + { + tstring name(m_File); + auto index(name.find_last_of(_T("."))); + return name.substr(0, index); + } + + tstring FilePath::GetExtension() const + { + tstring extension(m_File); + auto index(extension.find_last_of(_T("."))); + return extension.substr(index, extension.size() - index); + } + + const tstring & FilePath::GetRoot() const + { +#ifdef DESKTOP + switch(m_DirectoryMode) + { + case DirectoryMode::assets: + return m_AssetsRoot; + case DirectoryMode::internal: + return m_InternalRoot; + case DirectoryMode::external: + return m_ExternalRoot; + default: + return EMPTY_STRING; + } +#endif +#ifdef ANDROID + switch(m_DirectoryMode) + { + case DirectoryMode::assets: + return EMPTY_STRING; + case DirectoryMode::internal: + return ANDR_INTERNAL_PATH; + case DirectoryMode::external: + return ANDR_EXTERNAL_PATH; + default: + return EMPTY_STRING; + } +#endif + } + + tstring FilePath::GetLocalPath() const + { + return m_Path + m_File; + } + + void FilePath::GetFullPath(tstring & correct_path) const + { + correct_path = GetRoot() + GetLocalPath(); + } + + tstring FilePath::GetFullPath() const + { + return GetRoot() + GetLocalPath(); + } + + DirectoryMode FilePath::GetDirectoryMode() const + { + return m_DirectoryMode; + } + +#ifdef DESKTOP + void FilePath::SetAssetsRoot(const tstring & root) + { + m_AssetsRoot = root; + ConvertPathToCorrectPlatformStyle(m_AssetsRoot); + } + + void FilePath::SetInternalRoot(const tstring & root) + { + m_InternalRoot = root; + ConvertPathToCorrectPlatformStyle(m_InternalRoot); + } + + void FilePath::SetExternalRoot(const tstring & root) + { + m_ExternalRoot = root; + ConvertPathToCorrectPlatformStyle(m_ExternalRoot); + } +#endif + + + bool FilePath::GetActualPathName(const tstring & pathIn, tstring & pathOut) + { +#ifdef _WIN32 + tstring buffer(pathIn); + + size_t i = 0; + pathOut = EMPTY_STRING; + + bool addSeparator = false; + + while(i < buffer.size()) + { + // skip until path separator + while(i < buffer.size() && buffer[i] != WIN_PATH_SEPERATOR) + { + ++i; + } + + if(addSeparator) + { + pathOut += WIN_PATH_SEPERATOR; + } + + // if we found path separator, get real filename of this + // last path name component + bool foundSeparator = (i < buffer.size()); + buffer[i] = 0; + TSHFILEINFO info; + + // nuke the path separator so that we get real name of current path component + info.szDisplayName[0] = 0; + if(SHGetFileInfo(buffer.c_str(), 0, &info, sizeof(info), SHGFI_DISPLAYNAME)) + { + pathOut += info.szDisplayName; + } + else + { + tstringstream message; + message << _T("FilePath::GetActualPathName: ") + << _T("The path \"") + << pathIn + << _T("\" points to an unexisting file! ") + << _T("The file might be created or this can \ +be unexpected behaviour. Please verify!"); + LOG(LogLevel::Info, + message.str(), STARENGINE_LOG_TAG); + return false; + } + + // restore path separator that we might have nuked before + if(foundSeparator) + { + buffer[i] = WIN_PATH_SEPERATOR; + } + + ++i; + addSeparator = true; + } + return true; +#endif + } + void FilePath::ConvertPathToCorrectPlatformStyle(tstring & path) + { +#ifdef _WIN32 + std::replace(path.begin(), path.end(), ANDR_PATH_SEPERATOR, WIN_PATH_SEPERATOR); +#elif defined(ANDROID) + std::replace(path.begin(), path.end(), WIN_PATH_SEPERATOR, ANDR_PATH_SEPERATOR); +#endif + } + + void FilePath::CheckIfPathIsCapitalCorrect(const tstring & full_path) + { +#if defined (_WIN32) & defined (_DEBUG) + tstring shellPath; + if(GetActualPathName(full_path, shellPath)) + { + auto seperatorIndex(shellPath.find_last_of(WIN_PATH_SEPERATOR)); + if(seperatorIndex != tstring::npos) + { + shellPath = shellPath.substr(seperatorIndex + 1, shellPath.size() - (seperatorIndex + 1)); + } + auto extensionIndex = m_File.find_last_of(_T(".")); + auto fileWithoutExtension(m_File); + if(extensionIndex != tstring::npos) + { + fileWithoutExtension = m_File.substr(0, extensionIndex); + } + auto shellExtensionIndex = shellPath.find_last_of(_T(".")); + auto shellNameWithoutExtension(shellPath); + if(shellExtensionIndex != tstring::npos) + { + shellNameWithoutExtension = shellPath.substr(0, shellExtensionIndex); + } + if(fileWithoutExtension != shellNameWithoutExtension) + { + tstringstream buffer; + buffer << + _T("The path \" ") << + full_path << + _T(" \" is not capital correct. Please change the name in code to \" ") << + shellPath << + _T(" \" or your game will crash on Android and Linux"); + DEBUG_LOG(LogLevel::Error, buffer.str(), STARENGINE_LOG_TAG); + } + } +#endif + } +} diff --git a/src/Helpers/Filepath.h b/src/Helpers/Filepath.h index b5194eb..29d0bd9 100755 --- a/src/Helpers/Filepath.h +++ b/src/Helpers/Filepath.h @@ -1,176 +1,176 @@ -#pragma once - -#include "..\defines.h" - -namespace star -{ - /// - /// A class that is mostly used internally in the engine. - /// It allows you to get the full static path, of several locations. - /// It allows you to get the extension and filename of the filepath. - /// - class FilePath final - { - public: - /// - /// Default constructor for the filepath, - /// assigning an EMPTY_STRING value to all datamembers. - /// - FilePath(); - /// - /// Constructor overload requiring a string of the full filepath, - /// starting from the root directory. - /// - /// a reference of a FilePath object - /// the mode to be used, defining the root directory - explicit FilePath(const tstring & full_path, - DirectoryMode mode = DirectoryMode::assets); - /// - /// An overload of the constructor requiring the reference - /// of an FilePath object where the datamembers will be copped from. - /// - /// a reference of a FilePath object - FilePath(const FilePath & yRef); - /// - /// An overload of the constructor requiring - /// a FilePath object where the datamembers will be moved from. - /// - /// the FilePath object to be moved - FilePath(FilePath && yRef); - /// - /// Cleans up the path and file tstring datamembers. - /// - ~FilePath(); - - /// - /// Copy the path and file tstring datamembers. - /// - /// a reference of a FilePath object - /// a reference to the object where - /// assignment operator get invoked off. - FilePath & operator=(const FilePath & yRef); - /// - /// Move the path and file tstring datamembers. - /// - /// a FilePath object to be moved - /// a reference to the object where - /// assignment operator get invoked off. - FilePath & operator=(FilePath && yRef); - /// - /// Comparing the path and file tstrings combining it into a boolean result. - /// - /// a reference of a FilePath object - /// true if the yRef object and the current invoked object are equal - bool operator==(const FilePath & yRef); - - /// - /// Get the path variable of the filepath. - /// - /// a const reference to the path datamember. - const tstring & GetPath() const; - /// - /// Get the file variable of the filepath. - /// - /// a const reference to the file datamember. - const tstring & GetFile() const; - /// - /// Get the name of the file without the extension part. - /// - /// the name of the file hidden in the filepath - tstring GetName() const; - /// - /// Get the extension of the file hidden in the filepath - /// - /// the extension of the file - tstring GetExtension() const; - /// - /// Get the root of the path, using the correct DirectoryMode. - /// - /// the root of the path - /// - const tstring & GetRoot() const; - /// - /// Get the complete local path which is equal - /// to a combination of the path and file datamembers. - /// - /// the complete local path - tstring GetLocalPath() const; - /// - /// Get the correct complete dynamic path with the root being used, - /// defined based on the mode value. - /// the complete dynamic path, combining the - /// directory defined by the mode value and the full local path. - /// - /// - void GetFullPath(tstring & correct_path) const; - /// - /// Get the correct complete dynamic path with the root being used, - /// defined based on the mode value. - /// - /// the complete dynamic path, combining the - /// directory defined by the mode value and the full local path. - /// - tstring GetFullPath() const; - /// - /// Gets the directory mode. - /// - /// The directory mode defined in the constructor - DirectoryMode GetDirectoryMode() const; - -#ifdef DESKTOP - /// - /// Sets the static datamember that represents the assets root directory. - /// - /// the path of the assets directory - static void SetAssetsRoot(const tstring & root); - /// - /// Sets the static datamember that represents the internal root directory. - /// - /// the path of the internal directory - static void SetInternalRoot(const tstring & root); - /// - /// Sets the static datamember that represents the external root directory. - /// - /// the path of the external directory - static void SetExternalRoot(const tstring & root); -#endif - - private: - - tstring m_Path, - m_File; -#ifdef DESKTOP - static tstring m_AssetsRoot, m_InternalRoot, m_ExternalRoot; -#else -static const tstring ANDR_INTERNAL_PATH; -static const tstring ANDR_EXTERNAL_PATH; -#endif - static const tchar PATH_SEPERATOR; - DirectoryMode m_DirectoryMode; - - - /// - /// Checks if the path is capital correct. - /// This check is important for unix based operating system, - /// as their file system is capital sensitive. - /// - /// The path. - void CheckIfPathIsCapitalCorrect(const tstring & path); - /// - /// A function to get the static capital-sensitive path - /// of the current file. - /// - /// the path to be checked - /// the correct capital-sensitive static path - /// True if the file existed, false if the file didnt exist. - static bool GetActualPathName(const tstring & pathIn, tstring & pathOut); - /// - /// For windows: Converts all / seperators to \\ seperators. - /// For android and linux: Converts all \\ seperators to / seperators. - /// - /// The path to convert. - /// - /// - static void ConvertPathToCorrectPlatformStyle(tstring & path); - }; -} +#pragma once + +#include "../defines.h" + +namespace star +{ + /// + /// A class that is mostly used internally in the engine. + /// It allows you to get the full static path, of several locations. + /// It allows you to get the extension and filename of the filepath. + /// + class FilePath final + { + public: + /// + /// Default constructor for the filepath, + /// assigning an EMPTY_STRING value to all datamembers. + /// + FilePath(); + /// + /// Constructor overload requiring a string of the full filepath, + /// starting from the root directory. + /// + /// a reference of a FilePath object + /// the mode to be used, defining the root directory + explicit FilePath(const tstring & full_path, + DirectoryMode mode = DirectoryMode::assets); + /// + /// An overload of the constructor requiring the reference + /// of an FilePath object where the datamembers will be copped from. + /// + /// a reference of a FilePath object + FilePath(const FilePath & yRef); + /// + /// An overload of the constructor requiring + /// a FilePath object where the datamembers will be moved from. + /// + /// the FilePath object to be moved + FilePath(FilePath && yRef); + /// + /// Cleans up the path and file tstring datamembers. + /// + ~FilePath(); + + /// + /// Copy the path and file tstring datamembers. + /// + /// a reference of a FilePath object + /// a reference to the object where + /// assignment operator get invoked off. + FilePath & operator=(const FilePath & yRef); + /// + /// Move the path and file tstring datamembers. + /// + /// a FilePath object to be moved + /// a reference to the object where + /// assignment operator get invoked off. + FilePath & operator=(FilePath && yRef); + /// + /// Comparing the path and file tstrings combining it into a boolean result. + /// + /// a reference of a FilePath object + /// true if the yRef object and the current invoked object are equal + bool operator==(const FilePath & yRef); + + /// + /// Get the path variable of the filepath. + /// + /// a const reference to the path datamember. + const tstring & GetPath() const; + /// + /// Get the file variable of the filepath. + /// + /// a const reference to the file datamember. + const tstring & GetFile() const; + /// + /// Get the name of the file without the extension part. + /// + /// the name of the file hidden in the filepath + tstring GetName() const; + /// + /// Get the extension of the file hidden in the filepath + /// + /// the extension of the file + tstring GetExtension() const; + /// + /// Get the root of the path, using the correct DirectoryMode. + /// + /// the root of the path + /// + const tstring & GetRoot() const; + /// + /// Get the complete local path which is equal + /// to a combination of the path and file datamembers. + /// + /// the complete local path + tstring GetLocalPath() const; + /// + /// Get the correct complete dynamic path with the root being used, + /// defined based on the mode value. + /// the complete dynamic path, combining the + /// directory defined by the mode value and the full local path. + /// + /// + void GetFullPath(tstring & correct_path) const; + /// + /// Get the correct complete dynamic path with the root being used, + /// defined based on the mode value. + /// + /// the complete dynamic path, combining the + /// directory defined by the mode value and the full local path. + /// + tstring GetFullPath() const; + /// + /// Gets the directory mode. + /// + /// The directory mode defined in the constructor + DirectoryMode GetDirectoryMode() const; + +#ifdef DESKTOP + /// + /// Sets the static datamember that represents the assets root directory. + /// + /// the path of the assets directory + static void SetAssetsRoot(const tstring & root); + /// + /// Sets the static datamember that represents the internal root directory. + /// + /// the path of the internal directory + static void SetInternalRoot(const tstring & root); + /// + /// Sets the static datamember that represents the external root directory. + /// + /// the path of the external directory + static void SetExternalRoot(const tstring & root); +#endif + + private: + + tstring m_Path, + m_File; +#ifdef DESKTOP + static tstring m_AssetsRoot, m_InternalRoot, m_ExternalRoot; +#elif defined(ANDROID) +static const tstring ANDR_INTERNAL_PATH; +static const tstring ANDR_EXTERNAL_PATH; +#endif + static const tchar PATH_SEPERATOR; + DirectoryMode m_DirectoryMode; + + + /// + /// Checks if the path is capital correct. + /// This check is important for unix based operating system, + /// as their file system is capital sensitive. + /// + /// The path. + void CheckIfPathIsCapitalCorrect(const tstring & path); + /// + /// A function to get the static capital-sensitive path + /// of the current file. + /// + /// the path to be checked + /// the correct capital-sensitive static path + /// True if the file existed, false if the file didnt exist. + static bool GetActualPathName(const tstring & pathIn, tstring & pathOut); + /// + /// For windows: Converts all / seperators to \\ seperators. + /// For android and linux: Converts all \\ seperators to / seperators. + /// + /// The path to convert. + /// + /// + static void ConvertPathToCorrectPlatformStyle(tstring & path); + }; +} diff --git a/src/Helpers/Helpers.cpp b/src/Helpers/Helpers.cpp index f773813..a5740b8 100755 --- a/src/Helpers/Helpers.cpp +++ b/src/Helpers/Helpers.cpp @@ -1,6 +1,6 @@ #include "Helpers.h" -#include "..\Logger.h" -#include "FilePath.h" +#include "../Logger.h" +#include "Filepath.h" #include #include #include diff --git a/src/Helpers/Math.inl b/src/Helpers/Math.inl index 20ac89a..f424c29 100755 --- a/src/Helpers/Math.inl +++ b/src/Helpers/Math.inl @@ -1,4 +1,4 @@ -#include "..\defines.h" +#include "../defines.h" namespace star { diff --git a/src/Helpers/Spritesheet.cpp b/src/Helpers/Spritesheet.cpp index 15a7be6..fcc766d 100755 --- a/src/Helpers/Spritesheet.cpp +++ b/src/Helpers/Spritesheet.cpp @@ -1,4 +1,4 @@ -#include "SpriteSheet.h" +#include "Spritesheet.h" #include "../Input/XMLContainer.h" #include "../Helpers/Helpers.h" diff --git a/src/Helpers/State.h b/src/Helpers/State.h index e19f97f..9f60664 100755 --- a/src/Helpers/State.h +++ b/src/Helpers/State.h @@ -1,6 +1,6 @@ #pragma once -#include "..\defines.h" +#include "../defines.h" namespace star { diff --git a/src/Helpers/StateManager.cpp b/src/Helpers/StateManager.cpp index a6f8ea6..05ecb78 100755 --- a/src/Helpers/StateManager.cpp +++ b/src/Helpers/StateManager.cpp @@ -1,6 +1,6 @@ #include "StateManager.h" -#include "..\Helpers\Helpers.h" -#include "..\Context.h" +#include "../Helpers/Helpers.h" +#include "../Context.h" #include "State.h" namespace star diff --git a/src/Helpers/Timer.cpp b/src/Helpers/Timer.cpp index a9489ca..f9b359e 100755 --- a/src/Helpers/Timer.cpp +++ b/src/Helpers/Timer.cpp @@ -1,5 +1,5 @@ #include "Timer.h" -#include "..\Context.h" +#include "../Context.h" namespace star { diff --git a/src/Input/Gestures/BaseGesture.cpp b/src/Input/Gestures/BaseGesture.cpp index bc97369..f9a7d2f 100755 --- a/src/Input/Gestures/BaseGesture.cpp +++ b/src/Input/Gestures/BaseGesture.cpp @@ -1,97 +1,97 @@ -#include "BaseGesture.h" -#include "../../Logger.h" -#include "../../Context.h" - -namespace star -{ - BaseGesture::BaseGesture() - : m_bCompletedGesture(false) - , m_Callback(nullptr) - { - - } - - BaseGesture::~BaseGesture() - { - - } - -#ifdef _WIN32 - void BaseGesture::OnUpdateWinInputStateBase() - { - m_bCompletedGesture = false; - OnUpdateWinInputState(); - } - - void BaseGesture::OnUpdateWinInputState() - { - //Use everything from the WinInputState struct at your will to define your gestures. - } -#else - void BaseGesture::OnTouchEventBase(AInputEvent* pEvent) - { - m_bCompletedGesture = false; - OnTouchEvent(pEvent); - } - - void BaseGesture::OnTouchEvent(AInputEvent* pEvent) - { - //*********************************************** - // This is the base layout of this function. - // Please copy paste this into your child class - // If you want to use Gestures for android. - //*********************************************** - - /* - - int32 action = AMotionEvent_getAction(pEvent); - uint32 flags = action & AMOTION_EVENT_ACTION_MASK; - switch(flags) - { - case AMOTION_EVENT_ACTION_DOWN: - break; - case AMOTION_EVENT_ACTION_UP: - break; - case AMOTION_EVENT_ACTION_MOVE: - break; - case AMOTION_EVENT_ACTION_CANCEL: - break; - case AMOTION_EVENT_ACTION_POINTER_DOWN: - break; - case AMOTION_EVENT_ACTION_POINTER_UP: - break; - case AMOTION_EVENT_ACTION_OUTSIDE: - break; - } - - */ - } - -#endif - void BaseGesture::Update(const Context& context) - { - - } - - void BaseGesture::EndUpdate() - { - if(m_bCompletedGesture) - { - if(m_Callback) - { - m_Callback(); - } - m_bCompletedGesture = false; - } - } - - bool BaseGesture::CompletedGesture() - { - return m_bCompletedGesture; - } - - void BaseGesture::SetOnCompletedCallback(std::function callback) - { - m_Callback = callback; - } -} +#include "BaseGesture.h" +#include "../../Logger.h" +#include "../../Context.h" + +namespace star +{ + BaseGesture::BaseGesture() + : m_bCompletedGesture(false) + , m_Callback(nullptr) + { + + } + + BaseGesture::~BaseGesture() + { + + } + +#ifdef _WIN32 + void BaseGesture::OnUpdateWinInputStateBase() + { + m_bCompletedGesture = false; + OnUpdateWinInputState(); + } + + void BaseGesture::OnUpdateWinInputState() + { + //Use everything from the WinInputState struct at your will to define your gestures. + } +#elif defined(ANDROID) + void BaseGesture::OnTouchEventBase(AInputEvent* pEvent) + { + m_bCompletedGesture = false; + OnTouchEvent(pEvent); + } + + void BaseGesture::OnTouchEvent(AInputEvent* pEvent) + { + //*********************************************** + // This is the base layout of this function. + // Please copy paste this into your child class + // If you want to use Gestures for android. + //*********************************************** + + /* + + int32 action = AMotionEvent_getAction(pEvent); + uint32 flags = action & AMOTION_EVENT_ACTION_MASK; + switch(flags) + { + case AMOTION_EVENT_ACTION_DOWN: + break; + case AMOTION_EVENT_ACTION_UP: + break; + case AMOTION_EVENT_ACTION_MOVE: + break; + case AMOTION_EVENT_ACTION_CANCEL: + break; + case AMOTION_EVENT_ACTION_POINTER_DOWN: + break; + case AMOTION_EVENT_ACTION_POINTER_UP: + break; + case AMOTION_EVENT_ACTION_OUTSIDE: + break; + } + + */ + } + +#endif + void BaseGesture::Update(const Context& context) + { + + } + + void BaseGesture::EndUpdate() + { + if(m_bCompletedGesture) + { + if(m_Callback) + { + m_Callback(); + } + m_bCompletedGesture = false; + } + } + + bool BaseGesture::CompletedGesture() + { + return m_bCompletedGesture; + } + + void BaseGesture::SetOnCompletedCallback(std::function callback) + { + m_Callback = callback; + } +} diff --git a/src/Input/Gestures/BaseGesture.h b/src/Input/Gestures/BaseGesture.h index efd64d8..4c808bd 100755 --- a/src/Input/Gestures/BaseGesture.h +++ b/src/Input/Gestures/BaseGesture.h @@ -1,6 +1,5 @@ #pragma once -#ifdef _WIN32 -#else +#ifdef ANDROID #include #include #endif @@ -19,7 +18,7 @@ namespace star virtual ~BaseGesture(); #ifdef _WIN32 void OnUpdateWinInputStateBase(); -#else +#elif defined(ANDROID) void OnTouchEventBase(AInputEvent* pEvent); #endif virtual void Update(const Context& context); @@ -30,7 +29,7 @@ namespace star protected: #ifdef _WIN32 virtual void OnUpdateWinInputState(); -#else +#elif defined(ANDROID) virtual void OnTouchEvent(AInputEvent* pEvent); #endif bool m_bCompletedGesture; diff --git a/src/Input/Gestures/DoubleTapGesture.cpp b/src/Input/Gestures/DoubleTapGesture.cpp index 0848da8..84ae49b 100755 --- a/src/Input/Gestures/DoubleTapGesture.cpp +++ b/src/Input/Gestures/DoubleTapGesture.cpp @@ -1,144 +1,144 @@ -#include "DoubleTapGesture.h" -#include "../../Logger.h" -#include "../../defines.h" -#include "../../Context.h" -#include "../../Helpers/Math.h" - -#include "../InputManager.h" -#define INPUT_MANAGER (InputManager::GetInstance()) - -namespace star -{ - DoubleTapGesture::DoubleTapGesture(): - BaseGesture(), - m_StartTime(0), - m_TimeSinceBeginning(0), - m_TimeBetweenTaps(0), - m_StartPos(), - m_bIsGestureOk(false), - m_Count(0) - { - - } - - DoubleTapGesture::~DoubleTapGesture() - { - - } - - #ifdef _WIN32 - void DoubleTapGesture::OnUpdateWinInputState() - { - if(INPUT_MANAGER->IsMouseButtonPressedWIN(VK_LBUTTON)) - { - m_StartTime = m_TimeSinceBeginning; - if(m_Count < 1) - { - m_bIsGestureOk = true; - m_StartPos = INPUT_MANAGER->GetCurrentMousePosition(); - } - else - { - vec2 currentPos = INPUT_MANAGER->GetCurrentMousePosition(); - if(abs(Mag(m_StartPos - currentPos)) >= MAXIMUM_MOVEMENT_RANGE) - { - m_bIsGestureOk = false; - } - } - } - if(INPUT_MANAGER->IsMouseButtonReleasedWIN(VK_LBUTTON)) - { - if(m_bIsGestureOk) - { - float64 timeSinceDown = m_TimeSinceBeginning - m_StartTime; - if( timeSinceDown > MINIMUM_TAP_TIME && - timeSinceDown < MAXIMUM_TAP_TIME && - m_TimeBetweenTaps < MAXIMUM_TIME_BETWEEN_TAPS) - { - ++m_Count; - if(m_Count >= 2) - { - m_Count = 0; - m_bCompletedGesture = true; - } - } - else - { - m_Count = 0; - } - m_TimeBetweenTaps = 0; - } - else - { - m_Count = 0; - } - } - } - #else - void DoubleTapGesture::OnTouchEvent(AInputEvent* pEvent) - { - int32 action = AMotionEvent_getAction(pEvent); - uint32 flags = action & AMOTION_EVENT_ACTION_MASK; - switch(flags) - { - case AMOTION_EVENT_ACTION_DOWN: - m_StartTime = m_TimeSinceBeginning; - if(m_Count < 1) - { - m_bIsGestureOk = true; - m_StartPos = INPUT_MANAGER->GetCurrentTouchPosANDR(); - } - else - { - vec2 currentPos = INPUT_MANAGER->GetCurrentTouchPosANDR(); - if(abs(Mag(m_StartPos - currentPos)) >= MAXIMUM_MOVEMENT_RANGE) - { - m_bIsGestureOk = false; - } - } - break; - case AMOTION_EVENT_ACTION_UP: - { - if(m_bIsGestureOk) - { - float64 timeSinceDown = m_TimeSinceBeginning - m_StartTime; - if( timeSinceDown > MINIMUM_TAP_TIME && - timeSinceDown < MAXIMUM_TAP_TIME && - m_TimeBetweenTaps < MAXIMUM_TIME_BETWEEN_TAPS) - { - ++m_Count; - if(m_Count >= 2) - { - m_Count = 0; - m_bCompletedGesture = true; - } - } - else - { - m_Count = 0; - } - m_TimeBetweenTaps = 0; - } - else - { - m_Count = 0; - } - break; - } - } - } - - #endif - - void DoubleTapGesture::Update(const Context& context) - { - m_TimeSinceBeginning = - context.time->TimeSinceStart().GetMilliSeconds(); - if(m_Count == 1) - { - m_TimeBetweenTaps += - context.time->DeltaTime().GetMilliSeconds(); - } - } - -} +#include "DoubleTapGesture.h" +#include "../../Logger.h" +#include "../../defines.h" +#include "../../Context.h" +#include "../../Helpers/Math.h" + +#include "../InputManager.h" +#define INPUT_MANAGER (InputManager::GetInstance()) + +namespace star +{ + DoubleTapGesture::DoubleTapGesture(): + BaseGesture(), + m_StartTime(0), + m_TimeSinceBeginning(0), + m_TimeBetweenTaps(0), + m_StartPos(), + m_bIsGestureOk(false), + m_Count(0) + { + + } + + DoubleTapGesture::~DoubleTapGesture() + { + + } + + #ifdef _WIN32 + void DoubleTapGesture::OnUpdateWinInputState() + { + if(INPUT_MANAGER->IsMouseButtonPressedWIN(VK_LBUTTON)) + { + m_StartTime = m_TimeSinceBeginning; + if(m_Count < 1) + { + m_bIsGestureOk = true; + m_StartPos = INPUT_MANAGER->GetCurrentMousePosition(); + } + else + { + vec2 currentPos = INPUT_MANAGER->GetCurrentMousePosition(); + if(abs(Mag(m_StartPos - currentPos)) >= MAXIMUM_MOVEMENT_RANGE) + { + m_bIsGestureOk = false; + } + } + } + if(INPUT_MANAGER->IsMouseButtonReleasedWIN(VK_LBUTTON)) + { + if(m_bIsGestureOk) + { + float64 timeSinceDown = m_TimeSinceBeginning - m_StartTime; + if( timeSinceDown > MINIMUM_TAP_TIME && + timeSinceDown < MAXIMUM_TAP_TIME && + m_TimeBetweenTaps < MAXIMUM_TIME_BETWEEN_TAPS) + { + ++m_Count; + if(m_Count >= 2) + { + m_Count = 0; + m_bCompletedGesture = true; + } + } + else + { + m_Count = 0; + } + m_TimeBetweenTaps = 0; + } + else + { + m_Count = 0; + } + } + } + #elif defined(ANDROID) + void DoubleTapGesture::OnTouchEvent(AInputEvent* pEvent) + { + int32 action = AMotionEvent_getAction(pEvent); + uint32 flags = action & AMOTION_EVENT_ACTION_MASK; + switch(flags) + { + case AMOTION_EVENT_ACTION_DOWN: + m_StartTime = m_TimeSinceBeginning; + if(m_Count < 1) + { + m_bIsGestureOk = true; + m_StartPos = INPUT_MANAGER->GetCurrentTouchPosANDR(); + } + else + { + vec2 currentPos = INPUT_MANAGER->GetCurrentTouchPosANDR(); + if(abs(Mag(m_StartPos - currentPos)) >= MAXIMUM_MOVEMENT_RANGE) + { + m_bIsGestureOk = false; + } + } + break; + case AMOTION_EVENT_ACTION_UP: + { + if(m_bIsGestureOk) + { + float64 timeSinceDown = m_TimeSinceBeginning - m_StartTime; + if( timeSinceDown > MINIMUM_TAP_TIME && + timeSinceDown < MAXIMUM_TAP_TIME && + m_TimeBetweenTaps < MAXIMUM_TIME_BETWEEN_TAPS) + { + ++m_Count; + if(m_Count >= 2) + { + m_Count = 0; + m_bCompletedGesture = true; + } + } + else + { + m_Count = 0; + } + m_TimeBetweenTaps = 0; + } + else + { + m_Count = 0; + } + break; + } + } + } + + #endif + + void DoubleTapGesture::Update(const Context& context) + { + m_TimeSinceBeginning = + context.time->TimeSinceStart().GetMilliSeconds(); + if(m_Count == 1) + { + m_TimeBetweenTaps += + context.time->DeltaTime().GetMilliSeconds(); + } + } + +} diff --git a/src/Input/Gestures/DoubleTapGesture.h b/src/Input/Gestures/DoubleTapGesture.h index 9a7b849..b0095e5 100755 --- a/src/Input/Gestures/DoubleTapGesture.h +++ b/src/Input/Gestures/DoubleTapGesture.h @@ -1,38 +1,38 @@ -#pragma once -#include "BaseGesture.h" -#ifdef ANDROID -#include -#endif - -namespace star -{ - class DoubleTapGesture : public BaseGesture - { - public: - DoubleTapGesture(); - virtual ~DoubleTapGesture(); - - virtual void Update(const Context& context); - private: - #ifdef _WIN32 - virtual void OnUpdateWinInputState(); - #else - virtual void OnTouchEvent(AInputEvent* pEvent); - #endif - float64 m_StartTime; - float64 m_TimeSinceBeginning; - float64 m_TimeBetweenTaps; - vec2 m_StartPos; - bool m_bIsGestureOk; - static const int32 MINIMUM_TAP_TIME = 10; - static const int32 MAXIMUM_TAP_TIME = 500; - static const int32 MAXIMUM_TIME_BETWEEN_TAPS = 300; - static const int32 MAXIMUM_MOVEMENT_RANGE = 50; - int32 m_Count; - - DoubleTapGesture(const DoubleTapGesture& t); - DoubleTapGesture(DoubleTapGesture&& t); - DoubleTapGesture& operator=(const DoubleTapGesture& t); - DoubleTapGesture& operator=(DoubleTapGesture&& t); - }; -} +#pragma once +#include "BaseGesture.h" +#ifdef ANDROID +#include +#endif + +namespace star +{ + class DoubleTapGesture : public BaseGesture + { + public: + DoubleTapGesture(); + virtual ~DoubleTapGesture(); + + virtual void Update(const Context& context); + private: + #ifdef _WIN32 + virtual void OnUpdateWinInputState(); + #elif defined(ANDROID) + virtual void OnTouchEvent(AInputEvent* pEvent); + #endif + float64 m_StartTime; + float64 m_TimeSinceBeginning; + float64 m_TimeBetweenTaps; + vec2 m_StartPos; + bool m_bIsGestureOk; + static const int32 MINIMUM_TAP_TIME = 10; + static const int32 MAXIMUM_TAP_TIME = 500; + static const int32 MAXIMUM_TIME_BETWEEN_TAPS = 300; + static const int32 MAXIMUM_MOVEMENT_RANGE = 50; + int32 m_Count; + + DoubleTapGesture(const DoubleTapGesture& t); + DoubleTapGesture(DoubleTapGesture&& t); + DoubleTapGesture& operator=(const DoubleTapGesture& t); + DoubleTapGesture& operator=(DoubleTapGesture&& t); + }; +} diff --git a/src/Input/Gestures/GestureManager.cpp b/src/Input/Gestures/GestureManager.cpp index 8ecf511..e733d2e 100755 --- a/src/Input/Gestures/GestureManager.cpp +++ b/src/Input/Gestures/GestureManager.cpp @@ -1,128 +1,128 @@ -#include "GestureManager.h" -#include -#include "BaseGesture.h" -#include "../InputManager.h" -#include "../../Logger.h" - -namespace star -{ - GestureManager::GestureManager() - : m_GestureMap() - { - - } - - GestureManager::~GestureManager() - { - for(auto& gesture : m_GestureMap) - { - delete gesture.second; - } - m_GestureMap.clear(); - } - -#ifdef _WIN32 - - void GestureManager::OnUpdateWinInputState() - { - if(!m_GestureMap.empty()) - { - for(auto& gesture : m_GestureMap) - { - gesture.second->OnUpdateWinInputStateBase(); - } - } - } -#else - void GestureManager::OnTouchEvent(AInputEvent* pEvent) - { - if(!m_GestureMap.empty()) - { - for(auto& gesture : m_GestureMap) - { - gesture.second->OnTouchEventBase(pEvent); - } - } - } -#endif - - void GestureManager::AddGesture(BaseGesture* gesture, const tstring& tag) - { - if(!gesture) - { - LOG(LogLevel::Error, - _T("GestureManager::AddGesture: Trying to add a nullptr gesture.")); - return; - } - if(m_GestureMap.find(tag) == m_GestureMap.end()) - { - m_GestureMap.insert(std::make_pair(tag, gesture)); - } - else - { - LOG(LogLevel::Warning, - _T("The gesture manager already contains ") + tag, - STARENGINE_LOG_TAG); - } - } - - - void GestureManager::RemoveGesture(BaseGesture* gesture) - { - LOG(LogLevel::Warning, - _T("GestureManager::RemoveGesture: \ -Please use the method RemoveGesture(const tstring& tag) to remove gestures.\ -using GestureManager::RemoveGesture(BaseGesture* gesture) is much slower, use with care!"), - STARENGINE_LOG_TAG); - - auto it = m_GestureMap.begin(); - for ( ; it != m_GestureMap.end(); ++it ) - { - if (it->second == gesture) - { - m_GestureMap.erase(it); - delete (*it).second; - return; - } - } - ASSERT_LOG(it != m_GestureMap.end(), - _T("Gesture not found!"), STARENGINE_LOG_TAG); - - } - - void GestureManager::RemoveGesture(const tstring& tag) - { - auto it = m_GestureMap.find(tag); - ASSERT_LOG(it != m_GestureMap.end(), - _T("GestureManager::RemoveGesture(const tstring& tag): Gesture \"") + - tag + - tstring(_T("\" not found!")), - STARENGINE_LOG_TAG - ); - - m_GestureMap.erase(it); - delete (*it).second; - } - - void GestureManager::Update(const Context& context) - { - if(!m_GestureMap.empty()) - { - for(auto& gesture : m_GestureMap) - { - gesture.second->Update(context); - } - } - } - - void GestureManager::EndUpdate() - { - if(!m_GestureMap.empty()) - { - for(auto& gesture : m_GestureMap) - { - gesture.second->EndUpdate(); - } - } - } -} +#include "GestureManager.h" +#include +#include "BaseGesture.h" +#include "../InputManager.h" +#include "../../Logger.h" + +namespace star +{ + GestureManager::GestureManager() + : m_GestureMap() + { + + } + + GestureManager::~GestureManager() + { + for(auto& gesture : m_GestureMap) + { + delete gesture.second; + } + m_GestureMap.clear(); + } + +#ifdef _WIN32 + + void GestureManager::OnUpdateWinInputState() + { + if(!m_GestureMap.empty()) + { + for(auto& gesture : m_GestureMap) + { + gesture.second->OnUpdateWinInputStateBase(); + } + } + } +#elif defined(ANDROID) + void GestureManager::OnTouchEvent(AInputEvent* pEvent) + { + if(!m_GestureMap.empty()) + { + for(auto& gesture : m_GestureMap) + { + gesture.second->OnTouchEventBase(pEvent); + } + } + } +#endif + + void GestureManager::AddGesture(BaseGesture* gesture, const tstring& tag) + { + if(!gesture) + { + LOG(LogLevel::Error, + _T("GestureManager::AddGesture: Trying to add a nullptr gesture.")); + return; + } + if(m_GestureMap.find(tag) == m_GestureMap.end()) + { + m_GestureMap.insert(std::make_pair(tag, gesture)); + } + else + { + LOG(LogLevel::Warning, + _T("The gesture manager already contains ") + tag, + STARENGINE_LOG_TAG); + } + } + + + void GestureManager::RemoveGesture(BaseGesture* gesture) + { + LOG(LogLevel::Warning, + _T("GestureManager::RemoveGesture: \ +Please use the method RemoveGesture(const tstring& tag) to remove gestures.\ +using GestureManager::RemoveGesture(BaseGesture* gesture) is much slower, use with care!"), + STARENGINE_LOG_TAG); + + auto it = m_GestureMap.begin(); + for ( ; it != m_GestureMap.end(); ++it ) + { + if (it->second == gesture) + { + m_GestureMap.erase(it); + delete (*it).second; + return; + } + } + ASSERT_LOG(it != m_GestureMap.end(), + _T("Gesture not found!"), STARENGINE_LOG_TAG); + + } + + void GestureManager::RemoveGesture(const tstring& tag) + { + auto it = m_GestureMap.find(tag); + ASSERT_LOG(it != m_GestureMap.end(), + _T("GestureManager::RemoveGesture(const tstring& tag): Gesture \"") + + tag + + tstring(_T("\" not found!")), + STARENGINE_LOG_TAG + ); + + m_GestureMap.erase(it); + delete (*it).second; + } + + void GestureManager::Update(const Context& context) + { + if(!m_GestureMap.empty()) + { + for(auto& gesture : m_GestureMap) + { + gesture.second->Update(context); + } + } + } + + void GestureManager::EndUpdate() + { + if(!m_GestureMap.empty()) + { + for(auto& gesture : m_GestureMap) + { + gesture.second->EndUpdate(); + } + } + } +} diff --git a/src/Input/Gestures/GestureManager.h b/src/Input/Gestures/GestureManager.h index 482135c..b7f4703 100755 --- a/src/Input/Gestures/GestureManager.h +++ b/src/Input/Gestures/GestureManager.h @@ -1,6 +1,5 @@ #pragma once -#ifdef _WIN32 -#else +#ifdef ANDROID #include #endif #include @@ -27,7 +26,7 @@ namespace star T* GetGesture(const tstring & name) const; #ifdef _WIN32 void OnUpdateWinInputState(); -#else +#elif defined(ANDROID) void OnTouchEvent(AInputEvent* pEvent); #endif private: diff --git a/src/Input/Gestures/SwipeGesture.cpp b/src/Input/Gestures/SwipeGesture.cpp index 6925f2a..a9ee020 100755 --- a/src/Input/Gestures/SwipeGesture.cpp +++ b/src/Input/Gestures/SwipeGesture.cpp @@ -1,228 +1,228 @@ -#include "SwipeGesture.h" -#include "../../Logger.h" -#include "../../defines.h" -#include "../../Context.h" -#include "../../Helpers/Helpers.h" -#include "../../Helpers/Math.h" -#include "../InputManager.h" -#define INPUT_MANAGER (InputManager::GetInstance()) - -namespace star -{ - SwipeGesture::SwipeGesture( - int32 minSwipeDistance, - int32 minSwipeSpeed, - bool enableAngleFlex, - int32 angleFlex - ) - : star::BaseGesture() - , m_ElapsedTime() - , m_Speed() - , m_StartPos() - , m_CurrentPos() - , m_OldPos() - , m_OldDirection() - , m_AngleFlex(angleFlex) - , m_MinSwipeDistance(minSwipeDistance) - , m_MinSwipeSpeed(minSwipeSpeed) - , m_bEnableAngleFlex(enableAngleFlex) - , m_bIsGestureOk(true) - , m_TotalDistance(0) - { - } - - SwipeGesture::~SwipeGesture() - { - - } - - #ifdef _WIN32 - void SwipeGesture::OnUpdateWinInputState() - { - if(INPUT_MANAGER->IsMouseButtonPressedWIN(VK_LBUTTON)) - { - InitializeAllVars(); - } - if(INPUT_MANAGER->IsMouseButtonDownWIN(VK_LBUTTON)) - { - //Analyze the movement, its only a swipe if it's a relatively straight line (dot product?) - //Get the direction, check if it's different from the last one and add it to an average direction - if(m_bIsGestureOk) - { - m_CurrentPos = INPUT_MANAGER->GetCurrentMousePosition(); - if(m_OldPos != m_CurrentPos) - { - //The mouse moved - vec2 dir = m_CurrentPos - m_OldPos; - dir = Normalize(dir); - if(m_OldDirection != vec2()) - { - if(m_bEnableAngleFlex) - { - if(Dot(dir, m_OldDirection) >= cos(DegreesToRadians(float32(m_AngleFlex)))) - { - m_OldPos = INPUT_MANAGER->GetCurrentMousePosition(); - m_OldDirection = dir; - } - else - { - m_bIsGestureOk = false; - } - } - else - { - m_bIsGestureOk = true; - } - - } - else - { - m_OldPos = INPUT_MANAGER->GetCurrentMousePosition(); - m_OldDirection = dir; - } - //Check speed: - m_TotalDistance = Mag(m_CurrentPos - m_StartPos); - m_Speed = m_TotalDistance / float32(m_ElapsedTime); - } - } - - } - if(INPUT_MANAGER->IsMouseButtonReleasedWIN(VK_LBUTTON)) - { - //Check if it really was a swipe: speed & distance - //div average dir by amount of times it was down, calc speed, dir and length :) - if(m_bIsGestureOk) - { - if(m_Speed >= m_MinSwipeSpeed && m_TotalDistance >= m_MinSwipeDistance) - { - m_bCompletedGesture = true; - } - } - } - } - #else - void SwipeGesture::OnTouchEvent(AInputEvent* pEvent) - { - int32 action = AMotionEvent_getAction(pEvent); - uint32 flags = action & AMOTION_EVENT_ACTION_MASK; - switch(flags) - { - case AMOTION_EVENT_ACTION_DOWN: - InitializeAllVars(); - break; - case AMOTION_EVENT_ACTION_MOVE: - //Analyze the movement, its only a swipe if it's a relatively straight line (dot product?) - //Get the direction, check if it's different from the last one and add it to an average direction - if(m_bIsGestureOk) - { - m_CurrentPos = INPUT_MANAGER->GetCurrentTouchPosANDR(); - if(m_OldPos != m_CurrentPos) - { - vec2 dir = m_CurrentPos - m_OldPos; - dir = Normalize(dir); - if(m_OldDirection != vec2()) - { - if(m_bEnableAngleFlex) - { - if(Dot(dir, m_OldDirection) >= cos(DegreesToRadians(float32(m_AngleFlex)))) - { - m_OldPos = INPUT_MANAGER->GetCurrentTouchPosANDR(); - m_OldDirection = dir; - } - else - { - m_bIsGestureOk = false; - } - } - else - { - m_bIsGestureOk = true; - } - } - else - { - m_OldPos = INPUT_MANAGER->GetCurrentTouchPosANDR(); - m_OldDirection = dir; - } - //Check speed: - m_TotalDistance = Mag(m_CurrentPos - m_StartPos); - m_Speed = m_TotalDistance / (float32)m_ElapsedTime ; - } - } - break; - case AMOTION_EVENT_ACTION_UP: - //Check if it really was a swipe: speed & distance - //div average dir by amount of times it was down, calc speed, dir and length :) - if(m_bIsGestureOk) - { - if(m_Speed >= m_MinSwipeSpeed && m_TotalDistance >= m_MinSwipeDistance) - { - m_bCompletedGesture = true; - } - } - break; - } - } - - #endif - void SwipeGesture::Update(const Context& context) - { - if(m_bIsGestureOk) - { - m_ElapsedTime += context.time->DeltaTime().GetSeconds(); - } - } - - void SwipeGesture::InitializeAllVars() - { - //Start recording the move - m_StartPos = INPUT_MANAGER->GetCurrentFingerPosCP(); - m_CurrentPos = m_StartPos; - m_OldPos = m_StartPos; - m_ElapsedTime = 0; - m_Speed = 0; - m_bIsGestureOk = true; - m_OldDirection = vec2(); - m_TotalDistance = 0; - } - - vec2 SwipeGesture::GetSwipeDirection() const - { - vec2 vec = m_CurrentPos - m_StartPos; - if(vec != vec2()) - { - return Normalize(vec); - } - return vec; - } - - float32 SwipeGesture::GetSwipeSpeed() const - { - return m_Speed; - } - - float32 SwipeGesture::GetSwipeLength() const - { - return m_TotalDistance; - } - - void SwipeGesture::SetAngleCheck(bool angleCheck) - { - - } - - void SwipeGesture::SetAngleFlex(float32 degrees) - { - - } - - void SwipeGesture::SetMinSwipeSpeed(float32 speed) - { - - } - - void SwipeGesture::SetMinSwipeDistane(float32 distance) - { - - } -} +#include "SwipeGesture.h" +#include "../../Logger.h" +#include "../../defines.h" +#include "../../Context.h" +#include "../../Helpers/Helpers.h" +#include "../../Helpers/Math.h" +#include "../InputManager.h" +#define INPUT_MANAGER (InputManager::GetInstance()) + +namespace star +{ + SwipeGesture::SwipeGesture( + int32 minSwipeDistance, + int32 minSwipeSpeed, + bool enableAngleFlex, + int32 angleFlex + ) + : star::BaseGesture() + , m_ElapsedTime() + , m_Speed() + , m_StartPos() + , m_CurrentPos() + , m_OldPos() + , m_OldDirection() + , m_AngleFlex(angleFlex) + , m_MinSwipeDistance(minSwipeDistance) + , m_MinSwipeSpeed(minSwipeSpeed) + , m_bEnableAngleFlex(enableAngleFlex) + , m_bIsGestureOk(true) + , m_TotalDistance(0) + { + } + + SwipeGesture::~SwipeGesture() + { + + } + + #ifdef _WIN32 + void SwipeGesture::OnUpdateWinInputState() + { + if(INPUT_MANAGER->IsMouseButtonPressedWIN(VK_LBUTTON)) + { + InitializeAllVars(); + } + if(INPUT_MANAGER->IsMouseButtonDownWIN(VK_LBUTTON)) + { + //Analyze the movement, its only a swipe if it's a relatively straight line (dot product?) + //Get the direction, check if it's different from the last one and add it to an average direction + if(m_bIsGestureOk) + { + m_CurrentPos = INPUT_MANAGER->GetCurrentMousePosition(); + if(m_OldPos != m_CurrentPos) + { + //The mouse moved + vec2 dir = m_CurrentPos - m_OldPos; + dir = Normalize(dir); + if(m_OldDirection != vec2()) + { + if(m_bEnableAngleFlex) + { + if(Dot(dir, m_OldDirection) >= cos(DegreesToRadians(float32(m_AngleFlex)))) + { + m_OldPos = INPUT_MANAGER->GetCurrentMousePosition(); + m_OldDirection = dir; + } + else + { + m_bIsGestureOk = false; + } + } + else + { + m_bIsGestureOk = true; + } + + } + else + { + m_OldPos = INPUT_MANAGER->GetCurrentMousePosition(); + m_OldDirection = dir; + } + //Check speed: + m_TotalDistance = Mag(m_CurrentPos - m_StartPos); + m_Speed = m_TotalDistance / float32(m_ElapsedTime); + } + } + + } + if(INPUT_MANAGER->IsMouseButtonReleasedWIN(VK_LBUTTON)) + { + //Check if it really was a swipe: speed & distance + //div average dir by amount of times it was down, calc speed, dir and length :) + if(m_bIsGestureOk) + { + if(m_Speed >= m_MinSwipeSpeed && m_TotalDistance >= m_MinSwipeDistance) + { + m_bCompletedGesture = true; + } + } + } + } + #elif defined(ANDROID) + void SwipeGesture::OnTouchEvent(AInputEvent* pEvent) + { + int32 action = AMotionEvent_getAction(pEvent); + uint32 flags = action & AMOTION_EVENT_ACTION_MASK; + switch(flags) + { + case AMOTION_EVENT_ACTION_DOWN: + InitializeAllVars(); + break; + case AMOTION_EVENT_ACTION_MOVE: + //Analyze the movement, its only a swipe if it's a relatively straight line (dot product?) + //Get the direction, check if it's different from the last one and add it to an average direction + if(m_bIsGestureOk) + { + m_CurrentPos = INPUT_MANAGER->GetCurrentTouchPosANDR(); + if(m_OldPos != m_CurrentPos) + { + vec2 dir = m_CurrentPos - m_OldPos; + dir = Normalize(dir); + if(m_OldDirection != vec2()) + { + if(m_bEnableAngleFlex) + { + if(Dot(dir, m_OldDirection) >= cos(DegreesToRadians(float32(m_AngleFlex)))) + { + m_OldPos = INPUT_MANAGER->GetCurrentTouchPosANDR(); + m_OldDirection = dir; + } + else + { + m_bIsGestureOk = false; + } + } + else + { + m_bIsGestureOk = true; + } + } + else + { + m_OldPos = INPUT_MANAGER->GetCurrentTouchPosANDR(); + m_OldDirection = dir; + } + //Check speed: + m_TotalDistance = Mag(m_CurrentPos - m_StartPos); + m_Speed = m_TotalDistance / (float32)m_ElapsedTime ; + } + } + break; + case AMOTION_EVENT_ACTION_UP: + //Check if it really was a swipe: speed & distance + //div average dir by amount of times it was down, calc speed, dir and length :) + if(m_bIsGestureOk) + { + if(m_Speed >= m_MinSwipeSpeed && m_TotalDistance >= m_MinSwipeDistance) + { + m_bCompletedGesture = true; + } + } + break; + } + } + + #endif + void SwipeGesture::Update(const Context& context) + { + if(m_bIsGestureOk) + { + m_ElapsedTime += context.time->DeltaTime().GetSeconds(); + } + } + + void SwipeGesture::InitializeAllVars() + { + //Start recording the move + m_StartPos = INPUT_MANAGER->GetCurrentFingerPosCP(); + m_CurrentPos = m_StartPos; + m_OldPos = m_StartPos; + m_ElapsedTime = 0; + m_Speed = 0; + m_bIsGestureOk = true; + m_OldDirection = vec2(); + m_TotalDistance = 0; + } + + vec2 SwipeGesture::GetSwipeDirection() const + { + vec2 vec = m_CurrentPos - m_StartPos; + if(vec != vec2()) + { + return Normalize(vec); + } + return vec; + } + + float32 SwipeGesture::GetSwipeSpeed() const + { + return m_Speed; + } + + float32 SwipeGesture::GetSwipeLength() const + { + return m_TotalDistance; + } + + void SwipeGesture::SetAngleCheck(bool angleCheck) + { + + } + + void SwipeGesture::SetAngleFlex(float32 degrees) + { + + } + + void SwipeGesture::SetMinSwipeSpeed(float32 speed) + { + + } + + void SwipeGesture::SetMinSwipeDistane(float32 distance) + { + + } +} diff --git a/src/Input/Gestures/SwipeGesture.h b/src/Input/Gestures/SwipeGesture.h index 99a78e5..025748f 100755 --- a/src/Input/Gestures/SwipeGesture.h +++ b/src/Input/Gestures/SwipeGesture.h @@ -1,55 +1,55 @@ -#pragma once -#include "BaseGesture.h" -#ifdef ANDROID -#include -#endif - -namespace star -{ - class SwipeGesture : public BaseGesture - { - public: - SwipeGesture( - int32 minSwipeDistance = 200, - int32 minSwipeSpeed = 1000, - bool enableAngleFlex = false, - int32 angleFlex = 20); - virtual ~SwipeGesture(); - - virtual void Update(const Context& context); - vec2 GetSwipeDirection() const; - float32 GetSwipeSpeed() const; - float32 GetSwipeLength() const; - - void SetAngleCheck(bool angleCheck); - void SetAngleFlex(float32 degrees); - void SetMinSwipeSpeed(float32 speed); - void SetMinSwipeDistane(float32 distance); - - private: - #ifdef _WIN32 - virtual void OnUpdateWinInputState(); - #else - virtual void OnTouchEvent(AInputEvent* pEvent); - #endif - void InitializeAllVars(); - - float64 m_ElapsedTime; - float32 m_Speed; - vec2 m_StartPos; - vec2 m_CurrentPos; - vec2 m_OldPos; - vec2 m_OldDirection; - int32 m_AngleFlex; - int32 m_MinSwipeSpeed; - int32 m_MinSwipeDistance; - bool m_bEnableAngleFlex; - bool m_bIsGestureOk; - float32 m_TotalDistance; - - SwipeGesture(const SwipeGesture& t); - SwipeGesture(SwipeGesture&& t); - SwipeGesture& operator=(const SwipeGesture& t); - SwipeGesture& operator=(SwipeGesture&& t); - }; -} +#pragma once +#include "BaseGesture.h" +#ifdef ANDROID +#include +#endif + +namespace star +{ + class SwipeGesture : public BaseGesture + { + public: + SwipeGesture( + int32 minSwipeDistance = 200, + int32 minSwipeSpeed = 1000, + bool enableAngleFlex = false, + int32 angleFlex = 20); + virtual ~SwipeGesture(); + + virtual void Update(const Context& context); + vec2 GetSwipeDirection() const; + float32 GetSwipeSpeed() const; + float32 GetSwipeLength() const; + + void SetAngleCheck(bool angleCheck); + void SetAngleFlex(float32 degrees); + void SetMinSwipeSpeed(float32 speed); + void SetMinSwipeDistane(float32 distance); + + private: + #ifdef _WIN32 + virtual void OnUpdateWinInputState(); + #elif defined(ANDROID) + virtual void OnTouchEvent(AInputEvent* pEvent); + #endif + void InitializeAllVars(); + + float64 m_ElapsedTime; + float32 m_Speed; + vec2 m_StartPos; + vec2 m_CurrentPos; + vec2 m_OldPos; + vec2 m_OldDirection; + int32 m_AngleFlex; + int32 m_MinSwipeSpeed; + int32 m_MinSwipeDistance; + bool m_bEnableAngleFlex; + bool m_bIsGestureOk; + float32 m_TotalDistance; + + SwipeGesture(const SwipeGesture& t); + SwipeGesture(SwipeGesture&& t); + SwipeGesture& operator=(const SwipeGesture& t); + SwipeGesture& operator=(SwipeGesture&& t); + }; +} diff --git a/src/Input/Gestures/TapGesture.cpp b/src/Input/Gestures/TapGesture.cpp index d552c0d..bfe3d57 100755 --- a/src/Input/Gestures/TapGesture.cpp +++ b/src/Input/Gestures/TapGesture.cpp @@ -1,68 +1,68 @@ -#include "TapGesture.h" -#include "../../StarEngine/jni/Logger.h" -#include "../../StarEngine/jni/defines.h" -#include "../../StarEngine/jni/Context.h" - -#include "../../StarEngine/jni/Input/InputManager.h" -#define INPUT_MANAGER (InputManager::GetInstance()) - -namespace star -{ - TapGesture::TapGesture(): - star::BaseGesture(), - m_StartTime(0), - m_TimeSinceBeginning(0) - { - - } - - TapGesture::~TapGesture() - { - - } - - #ifdef _WIN32 - void TapGesture::OnUpdateWinInputState() - { - if(INPUT_MANAGER->IsMouseButtonPressedWIN(VK_LBUTTON)) - { - m_StartTime = m_TimeSinceBeginning; - } - if(INPUT_MANAGER->IsMouseButtonReleasedWIN(VK_LBUTTON)) - { - float64 timeSinceDown = m_TimeSinceBeginning - m_StartTime; - if(timeSinceDown > MINIMUM_TAP_TIME && timeSinceDown < MAXIMUM_TAP_TIME) - { - m_bCompletedGesture = true; - } - } - } - #else - void TapGesture::OnTouchEvent(AInputEvent* pEvent) - { - int32 action = AMotionEvent_getAction(pEvent); - uint32 flags = action & AMOTION_EVENT_ACTION_MASK; - switch(flags) - { - case AMOTION_EVENT_ACTION_DOWN: - m_StartTime = m_TimeSinceBeginning; - break; - case AMOTION_EVENT_ACTION_UP: - { - float64 timeSinceDown = m_TimeSinceBeginning - m_StartTime; - if(timeSinceDown > MINIMUM_TAP_TIME && - timeSinceDown < MAXIMUM_TAP_TIME) - { - m_bCompletedGesture = true; - } - break; - } - } - } - - #endif - void TapGesture::Update(const Context& context) - { - m_TimeSinceBeginning = context.time->TimeSinceStart().GetMilliSeconds(); - } -} +#include "TapGesture.h" +#include "../../Logger.h" +#include "../../defines.h" +#include "../../Context.h" + +#include "../InputManager.h" +#define INPUT_MANAGER (InputManager::GetInstance()) + +namespace star +{ + TapGesture::TapGesture(): + star::BaseGesture(), + m_StartTime(0), + m_TimeSinceBeginning(0) + { + + } + + TapGesture::~TapGesture() + { + + } + + #ifdef _WIN32 + void TapGesture::OnUpdateWinInputState() + { + if(INPUT_MANAGER->IsMouseButtonPressedWIN(VK_LBUTTON)) + { + m_StartTime = m_TimeSinceBeginning; + } + if(INPUT_MANAGER->IsMouseButtonReleasedWIN(VK_LBUTTON)) + { + float64 timeSinceDown = m_TimeSinceBeginning - m_StartTime; + if(timeSinceDown > MINIMUM_TAP_TIME && timeSinceDown < MAXIMUM_TAP_TIME) + { + m_bCompletedGesture = true; + } + } + } + #elif defined(ANDROID) + void TapGesture::OnTouchEvent(AInputEvent* pEvent) + { + int32 action = AMotionEvent_getAction(pEvent); + uint32 flags = action & AMOTION_EVENT_ACTION_MASK; + switch(flags) + { + case AMOTION_EVENT_ACTION_DOWN: + m_StartTime = m_TimeSinceBeginning; + break; + case AMOTION_EVENT_ACTION_UP: + { + float64 timeSinceDown = m_TimeSinceBeginning - m_StartTime; + if(timeSinceDown > MINIMUM_TAP_TIME && + timeSinceDown < MAXIMUM_TAP_TIME) + { + m_bCompletedGesture = true; + } + break; + } + } + } + + #endif + void TapGesture::Update(const Context& context) + { + m_TimeSinceBeginning = context.time->TimeSinceStart().GetMilliSeconds(); + } +} diff --git a/src/Input/Gestures/TapGesture.h b/src/Input/Gestures/TapGesture.h index f37d17c..b3ba46d 100755 --- a/src/Input/Gestures/TapGesture.h +++ b/src/Input/Gestures/TapGesture.h @@ -1,33 +1,33 @@ -#pragma once -#include "BaseGesture.h" -#ifdef ANDROID -#include -#endif - -namespace star -{ - class TapGesture : public BaseGesture - { - public: - TapGesture(); - virtual ~TapGesture(); - - virtual void Update(const Context& context); - - private: - #ifdef _WIN32 - virtual void OnUpdateWinInputState(); - #else - virtual void OnTouchEvent(AInputEvent* pEvent); - #endif - float64 m_StartTime; - float64 m_TimeSinceBeginning; - static const int32 MINIMUM_TAP_TIME = 10; - static const int32 MAXIMUM_TAP_TIME = 500; - - TapGesture(const TapGesture& t); - TapGesture(TapGesture&& t); - TapGesture& operator=(const TapGesture& t); - TapGesture& operator=(TapGesture&& t); - }; -} +#pragma once +#include "BaseGesture.h" +#ifdef ANDROID +#include +#endif + +namespace star +{ + class TapGesture : public BaseGesture + { + public: + TapGesture(); + virtual ~TapGesture(); + + virtual void Update(const Context& context); + + private: + #ifdef _WIN32 + virtual void OnUpdateWinInputState(); + #elif defined(ANDROID) + virtual void OnTouchEvent(AInputEvent* pEvent); + #endif + float64 m_StartTime; + float64 m_TimeSinceBeginning; + static const int32 MINIMUM_TAP_TIME = 10; + static const int32 MAXIMUM_TAP_TIME = 500; + + TapGesture(const TapGesture& t); + TapGesture(TapGesture&& t); + TapGesture& operator=(const TapGesture& t); + TapGesture& operator=(TapGesture&& t); + }; +} diff --git a/src/Input/InputManager.cpp b/src/Input/InputManager.cpp index 1898fb2..e5f8d2f 100755 --- a/src/Input/InputManager.cpp +++ b/src/Input/InputManager.cpp @@ -1,943 +1,943 @@ -#include "InputManager.h" - -#ifdef DESKTOP -#include -#else -#include -#include -#endif -#include "../Logger.h" -#include "../StarEngine.h" -#include "../Graphics/GraphicsManager.h" -#include "../Graphics/ScaleSystem.h" -#include "../Scenes/SceneManager.h" -#include "../Components/CameraComponent.h" -#include "../Scenes/BaseScene.h" -#include "../Objects/BaseCamera.h" -#include "../Helpers/Helpers.h" -#include "../Helpers/Math.h" - -namespace star -{ -#ifdef DESKTOP - const float32 InputManager::BYTE_TO_DOUBLE_VALUE = 255.0f; -#else - const float32 InputManager::UNDEFINED_POINTER_POSITION = -123456.0f; -#endif - -#ifdef DESKTOP - InputAction::InputAction(): - ActionID(-1), - TriggerState(InputTriggerState::Pressed), - KeyboardCode(-1), - MouseButtonCode(-1), - GamepadButtonCode(0), - PlayerIndex(GamepadIndex::PlayerOne), - IsTriggered(false) - { - } - - InputAction::InputAction(int32 actionID, InputTriggerState triggerState, - int32 keyboardCode, int32 mouseButtonCode, WORD gamepadButtonCode, - GamepadIndex playerIndex): - ActionID(actionID), - TriggerState(triggerState), - KeyboardCode(keyboardCode), - MouseButtonCode(mouseButtonCode), - GamepadButtonCode(gamepadButtonCode), - PlayerIndex(playerIndex), - IsTriggered(false) - { - } -#else - FingerPointerANDR::FingerPointerANDR(): - Position(), - RawPosition(), - Pressure(0.0f), - ToolMajor(0.0f), - ToolMinor(0.0f), - ID(0) - { - } -#endif - - InputManager::InputManager() - : Singleton() - #ifdef DESKTOP - , m_ThreadAvailable(false) - , m_KeyboardState0Active(true) - , mWindowsHandle() - #else - , m_bMainIsDown(false) - , m_bMainIsUp(false) - , m_bPointerIsDown(false) - , m_bPointerIsUp(false) - , m_NumberOfPointers(0) - , m_NumberOfPointersOLD(0) - , m_ActivePointerID(0) - , m_PointerVec() - , m_OldPointerVec() - , m_OnBackButtonDown(nullptr) - , m_OnMenuButtonDown(nullptr) - #endif - , m_GestureManager(nullptr) - , m_IndependantGestureManager(nullptr) - , m_OldMousePosition() - , m_CurrMousePosition() - , m_MouseMovement() - , m_GestureID(0) - { - m_IndependantGestureManager = new GestureManager(); -#ifdef DESKTOP - //Init new keyboard states - GetKeyboardState(m_pKeyboardState0); - GetKeyboardState(m_pKeyboardState1); - UpdateWin(); -#endif - } - - InputManager::~InputManager(void) - { - delete m_IndependantGestureManager; - } - - void InputManager::UpdateGestures(const Context & context) - { - m_GestureManager->Update(context); - m_IndependantGestureManager->Update(context); - } - -#ifdef DESKTOP - //[TODO] add this for android - - //Adds an inputAction to the list of inputActions - bool InputManager::AddInputAction(const InputAction& action) - { - auto it = m_InputActions.find(action.ActionID); - if(it != m_InputActions.end()) - { - return false; - } - m_InputActions[action.ActionID] = action; - return true; - } - - bool InputManager::IsActionTriggered(int32 actionID) const - { - return m_InputActions.at(actionID).IsTriggered; - } - //[TODO] -- end TODO - - void InputManager::IsCursorVisible(bool visible) - { - ShowCursor(visible); - } - - void InputManager::UpdateGamepadStates() - { - DWORD dwResult; - for(DWORD i = 0; i < XUSER_MAX_COUNT; ++i) - { - m_OldGamepadState[i] = m_CurrGamepadState[i]; - - XINPUT_STATE state; - ZeroMemory(&state, sizeof(XINPUT_STATE)); - - //returns ERROR_DEVICE_NOT_CONNECTED if i is invalid - dwResult = XInputGetState(i, &state); - m_CurrGamepadState[i] = state; - - //If the gamepad was connected, update the "connected gamepad array - if(dwResult == ERROR_SUCCESS) - { - m_ConnectedGamepads[i] = true; - } - else - { - m_ConnectedGamepads[i] = false; - } - } - } - - bool InputManager::UpdateKeyboardStates() - { - //Get Current KeyboardState and set Old KeyboardState (needed for "released" checks) - BOOL getKeyboardResult; - if(m_KeyboardState0Active) - { - //GetKeyboardState is thread dependant! use AttachThreadInput to link them! - getKeyboardResult = GetKeyboardState(m_pKeyboardState1); - for(int32 i = 0 ; i < NUMBER_OF_KEYBOARDKEYS ; ++i) - { - m_pOldKeyboardState[i] = m_pKeyboardState0[i]; - m_pCurrKeyboardState[i] = m_pKeyboardState1[i]; - } - } - else - { - getKeyboardResult = GetKeyboardState(m_pKeyboardState0); - for(int32 i = 0 ; i < NUMBER_OF_KEYBOARDKEYS ; ++i) - { - m_pOldKeyboardState[i] = m_pKeyboardState1[i]; - m_pCurrKeyboardState[i] = m_pKeyboardState0[i]; - } - } - - m_KeyboardState0Active = !m_KeyboardState0Active; - return getKeyboardResult > 0 ? true : false; - } - - bool InputManager::IsKeyboardKeyDown(uint8 key, bool previousFrame) const - { - if(key > 0x07 && key <= 0xFE) - { - return IsKeyboardKeyDown_unsafe(key, previousFrame); - } - return false; - } - - bool InputManager::IsMouseButtonPressedWIN(uint8 button) const - { - if(IsMouseButtonDownWIN(button) && !IsMouseButtonDownWIN(button, true)) - { - return true; - } - return false; - } - - bool InputManager::IsMouseButtonDownWIN(uint8 button, bool previousFrame) const - { - if(button > 0x00 && button <= 0x06) - { - return IsMouseButtonDown_unsafe(button, previousFrame); - } - return false; - } - - bool InputManager::IsMouseButtonReleasedWIN(uint8 button) const - { - if(!IsMouseButtonDownWIN(button) && IsMouseButtonDownWIN(button, true)) - { - return true; - } - return false; - } - - void InputManager::SetWindowsHandle(HWND hWnd) - { - mWindowsHandle = hWnd; - } - - bool InputManager::IsGamepadButtonDown(WORD button, GamepadIndex playerIndex, bool previousFrame) const - { - if(button > 0x0000 && button<=0x8000) - { - return IsGamepadButtonDown_unsafe(button, playerIndex, previousFrame); - } - return false; - } - - const vec2 & InputManager::GetCurrentMousePosition() const - { - return m_CurrMousePosition; - } - - const vec2 & InputManager::GetOldMousePosition() const - { - return m_OldMousePosition; - } - - const vec2 & InputManager::GetMouseMovement() const - { - return m_MouseMovement; - } - - bool InputManager::IsAnyKeyDown() const - { - for (uint16 i = 0; i < NUMBER_OF_KEYBOARDKEYS; ++i) - { - if( (schar) (GetAsyncKeyState(i) >> 8)) - { - return true; - } - } - for(uint8 index = 0; index < XUSER_MAX_COUNT; ++index) - { - if(m_ConnectedGamepads[index] == true) - { - for(WORD button = 0x00000001; button < MAX_GAMEPAD_VALUE; button *= 2) - { - if(IsGamepadButtonDown(button,static_cast(index))) - { - return true; - } - } - } - } - return false; - } - - //NO RANGE CHECKS - bool InputManager::IsKeyboardKeyDown_unsafe(uint8 key, bool previousFrame) const - { - if(previousFrame) - { - return (m_pOldKeyboardState[key] & 0xF0) != 0; - } - else - { - return (m_pCurrKeyboardState[key] & 0xF0) != 0; - } - } - - //NO RANGE CHECKS - bool InputManager::IsMouseButtonDown_unsafe(uint8 button, bool previousFrame) const - { - if(previousFrame) - { - return (m_pOldKeyboardState[button ]& 0xF0) != 0; - } - else - { - return (m_pCurrKeyboardState[button] & 0xF0) != 0; - } - } - - //NO RANGE CHECKS - bool InputManager::IsGamepadButtonDown_unsafe(WORD button, GamepadIndex playerIndex, - bool previousFrame) const - { - if(!m_ConnectedGamepads[playerIndex]) - { - return false; - } - if(previousFrame) - { - return (m_OldGamepadState[playerIndex].Gamepad.wButtons&button) != 0; - } - else - { - return (m_CurrGamepadState[playerIndex].Gamepad.wButtons&button) != 0; - } - } - - DWORD InputManager::UpdateWin() - { - //while(m_ThreadAvailable) - { - UpdateKeyboardStates(); - UpdateGamepadStates(); - - //Reset previous InputAction States - for(auto it = m_InputActions.begin(); it != m_InputActions.end(); ++it) - { - auto currAction = &(it->second); - //Reset the previous state before updating/checking the new state - currAction->IsTriggered = false; - - switch(currAction->TriggerState) - { - //if the input wasnt down last frame, but it is now, it is pressed - case InputTriggerState::Pressed: - //KEYBOARD - if( currAction->KeyboardCode > MIN_KEYBOARD_VALUE && - currAction->KeyboardCode <= MAX_KEYBOARD_VALUE) - { - if(!IsKeyboardKeyDown_unsafe(currAction->KeyboardCode,true) && - IsKeyboardKeyDown_unsafe(currAction->KeyboardCode)) - { - currAction->IsTriggered = true; - } - } - - //MOUSE - if(!currAction->IsTriggered && - currAction->MouseButtonCode > MIN_MOUSE_BUTTON_VALUE && - currAction->MouseButtonCode <= MAX_MOUSE_BUTTON_VALUE) - { - if(!IsMouseButtonDown_unsafe(currAction->MouseButtonCode,true) && - IsMouseButtonDown_unsafe(currAction->MouseButtonCode)) - { - currAction->IsTriggered = true; - LOG(LogLevel::Info, - _T("Clicked mouse button."), STARENGINE_LOG_TAG); - } - } - - //GAMEPADS - if(!currAction->IsTriggered && currAction->GamepadButtonCode != 0) - if(!IsGamepadButtonDown_unsafe( - currAction->GamepadButtonCode,currAction->PlayerIndex,true) && - IsGamepadButtonDown_unsafe( - currAction->GamepadButtonCode,currAction->PlayerIndex)) - { - currAction->IsTriggered = true; - } - - break; - - //if the input was down last frame, and is down now, it is down. - case InputTriggerState::Down: - //KEYBOARD - if(currAction->KeyboardCode > MIN_KEYBOARD_VALUE && - currAction->KeyboardCode <= MAX_KEYBOARD_VALUE) - { - if(IsKeyboardKeyDown_unsafe(currAction->KeyboardCode,true) && - IsKeyboardKeyDown_unsafe(currAction->KeyboardCode)) - { - currAction->IsTriggered = true; - } - } - - //MOUSE - if(!currAction->IsTriggered && - currAction->MouseButtonCode > MIN_MOUSE_BUTTON_VALUE && - currAction->MouseButtonCode <= MAX_MOUSE_BUTTON_VALUE) - { - if( IsMouseButtonDown_unsafe(currAction->MouseButtonCode,true) && - IsMouseButtonDown_unsafe(currAction->MouseButtonCode)) - { - currAction->IsTriggered = true; - } - } - //GAMEPADS - if(!currAction->IsTriggered && currAction->GamepadButtonCode != 0) - { - if( IsGamepadButtonDown_unsafe( - currAction->GamepadButtonCode,currAction->PlayerIndex,true) && - IsGamepadButtonDown_unsafe( - currAction->GamepadButtonCode,currAction->PlayerIndex)) - { - currAction->IsTriggered = true; - } - } - break; - - //If the input was down last frame, but isn't down anymore, it was released. - case InputTriggerState::Released: - //KEYBOARD - if( currAction->KeyboardCode > MIN_KEYBOARD_VALUE && - currAction->KeyboardCode <= MAX_KEYBOARD_VALUE) - { - if( IsKeyboardKeyDown_unsafe(currAction->KeyboardCode,true) && - !IsKeyboardKeyDown_unsafe(currAction->KeyboardCode)) - { - currAction->IsTriggered = true; - } - } - - //MOUSE - if(!currAction->IsTriggered && - currAction->MouseButtonCode > MIN_MOUSE_BUTTON_VALUE && - currAction->MouseButtonCode <= MAX_MOUSE_BUTTON_VALUE) - { - if( IsMouseButtonDown_unsafe(currAction->MouseButtonCode,true) && - !IsMouseButtonDown_unsafe(currAction->MouseButtonCode)) - { - currAction->IsTriggered = true; - } - } - - //GAMEPADS - if(!currAction->IsTriggered && - currAction->GamepadButtonCode > MIN_GAMEPAD_VALUE && - currAction->GamepadButtonCode <= MAX_GAMEPAD_VALUE) - { - if( IsGamepadButtonDown_unsafe( - currAction->GamepadButtonCode,currAction->PlayerIndex,true) && - !IsGamepadButtonDown_unsafe( - currAction->GamepadButtonCode,currAction->PlayerIndex)) - { - currAction->IsTriggered = true; - } - } - break; - } - } - - //Mouse Position - m_OldMousePosition = m_CurrMousePosition; - POINT mousePos; - if(GetCursorPos(&mousePos)) - { - ScreenToClient(mWindowsHandle,&mousePos); - } - - m_CurrMousePosition = vec2( - mousePos.x , - float32(GraphicsManager::GetInstance()->GetWindowHeight() - mousePos.y) - ); - m_CurrMousePosition -= vec2( - float32(GraphicsManager::GetInstance()->GetHorizontalViewportOffset()), - float32(GraphicsManager::GetInstance()->GetVerticalViewportOffset()) - ); - m_CurrMousePosition /= GraphicsManager::GetInstance()->GetViewportResolution(); - m_CurrMousePosition *= GraphicsManager::GetInstance()->GetScreenResolution(); - - if(SceneManager::GetInstance()->GetActiveScene()) - { - BaseCamera* projectionObject = SceneManager::GetInstance()-> - GetActiveScene()->GetActiveCamera(); - if(projectionObject) - { - auto worldPos = projectionObject->GetTransform()->GetWorldPosition().pos2D(); - worldPos.x /= (star::ScaleSystem::GetInstance()->GetWorkingResolution().x / 2.0f); - worldPos.y /= (star::ScaleSystem::GetInstance()->GetWorkingResolution().y / 2.0f); - m_CurrMousePosition += worldPos; - } - } - - m_MouseMovement.x = m_CurrMousePosition.x - m_OldMousePosition.x; - m_MouseMovement.y = m_CurrMousePosition.y - m_OldMousePosition.y; - - if(m_GestureManager != nullptr) - { - m_GestureManager->OnUpdateWinInputState(); - } - m_IndependantGestureManager->OnUpdateWinInputState(); - //Sleep(1000/60); - } - return 0; - } - - void InputManager::StartKeyboardThread() - { - m_ThreadAvailable = true; - } - - void InputManager::StopKeyboardThread() - { - m_ThreadAvailable = false; - } - vec2 InputManager::GetThumbstickPosition - (bool leftThumbstick, GamepadIndex playerIndex) const - { - vec2 pos; - if(leftThumbstick) - { - pos = vec2( m_CurrGamepadState[playerIndex].Gamepad.sThumbLX, - m_CurrGamepadState[playerIndex].Gamepad.sThumbLY); - if( pos.x > -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE && - pos.x < XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE) - { - pos.x = 0; - } - if( pos.y > -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE && - pos.y < XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE) - { - pos.y = 0; - } - } - else - { - pos = vec2( m_CurrGamepadState[playerIndex].Gamepad.sThumbRX, - m_CurrGamepadState[playerIndex].Gamepad.sThumbRY); - if( pos.x > -XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE && - pos.x < XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE) - { - pos.x = 0; - } - if( pos.y > -XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE && - pos.y < XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE) - { - pos.y = 0; - } - } - - //Shorts have a range of 32768, so to convert that range to a float64, - //devide it by that range - if(pos.x < 0) - { - pos.x /= MAX_VALUE_OF_SHORT; - } - else - { - pos.x /= MAX_VALUE_OF_SHORT; - } - - if(pos.y < 0) - { - pos.y /= MAX_VALUE_OF_SHORT; - } - else - { - pos.y /= MAX_VALUE_OF_SHORT; - } - - return pos; - } - - float32 InputManager::GetTriggerPressure(bool leftTrigger, GamepadIndex playerIndex) const - { - if(leftTrigger) - { - //bLeftTrigger returns a byte, div by 255 to cast to float64 - return m_CurrGamepadState[playerIndex].Gamepad.bLeftTrigger - / BYTE_TO_DOUBLE_VALUE; - } - else - { - return m_CurrGamepadState[playerIndex].Gamepad.bRightTrigger - / BYTE_TO_DOUBLE_VALUE; - } - } - - void InputManager::SetVibration(float32 leftVibration, float32 rightVibration, - GamepadIndex playerIndex) - { - XINPUT_VIBRATION vibration; - Clamp(leftVibration, 0.0f, 1.0f); - Clamp(rightVibration, 0.0f, 1.0f); - ZeroMemory(&vibration, sizeof(XINPUT_VIBRATION)); - //convert from float32 to word -> float32 * lenght of word - vibration.wLeftMotorSpeed = static_cast(leftVibration * MAX_VALUE_OF_WORD); - vibration.wRightMotorSpeed = static_cast(rightVibration * MAX_VALUE_OF_WORD); - XInputSetState(playerIndex, &vibration); - } - - uint8 InputManager::ConvertIndexToVK(uint8 fingerIndex) const - { - switch(fingerIndex) - { - case 1: - return VK_LBUTTON; - case 2: - return VK_RBUTTON; - case 3: - return VK_MBUTTON; - case 4: - return VK_XBUTTON1; - case 5: - return VK_XBUTTON2; - default: - LOG(LogLevel::Warning, - _T("Only 5 (0 - 4) finger Indices supported for mouse. Using VK_XBUTTON2"), - STARENGINE_LOG_TAG); - return VK_XBUTTON2; - } - } -#else - - bool InputManager::IsTouchPressedANDR(uint8 fingerIndex) const - { - if(m_NumberOfPointers >= fingerIndex && (m_bMainIsDown || m_bPointerIsDown)) - { - return (true); - } - return (false); - } - - bool InputManager::IsTouchDownANDR(uint8 fingerIndex) const - { - if(m_NumberOfPointers >= fingerIndex) - { - return (true); - } - return (false); - } - - bool InputManager::IsTouchReleasedANDR(uint8 fingerIndex) const - { - if(m_NumberOfPointers >= fingerIndex -1 && (m_bMainIsUp || m_bPointerIsUp)) - { - return (true); - } - return (false); - } - - vec2 InputManager::GetCurrentTouchPosANDR(uint8 fingerIndex) - { - if((fingerIndex <= m_PointerVec.size() && fingerIndex > 0)) - { - m_CurrMousePosition = m_PointerVec.at(fingerIndex-1).Position; - m_CurrMousePosition = vec2( - m_CurrMousePosition.x , - (float32)GraphicsManager::GetInstance()->GetWindowHeight() - m_CurrMousePosition.y); - m_CurrMousePosition -= vec2( - float32(GraphicsManager::GetInstance()->GetHorizontalViewportOffset()), - float32(GraphicsManager::GetInstance()->GetVerticalViewportOffset())); - m_CurrMousePosition /= GraphicsManager::GetInstance()->GetViewportResolution(); - m_CurrMousePosition *= GraphicsManager::GetInstance()->GetScreenResolution(); - - if(SceneManager::GetInstance()->GetActiveScene()) - { - BaseCamera* projectionObject = SceneManager::GetInstance()-> - GetActiveScene()->GetActiveCamera(); - if(projectionObject) - { - m_CurrMousePosition += projectionObject->GetTransform()-> - GetWorldPosition().pos2D(); - } - } - } - return m_CurrMousePosition; - } - - vec2 InputManager::GetOldTouchPosANDR(uint8 fingerIndex) - { - if(((fingerIndex <= m_OldPointerVec.size() && fingerIndex > 0) && - (fingerIndex <= m_PointerVec.size() && fingerIndex > 0))) - { - if(m_OldPointerVec.at(fingerIndex-1).ID == m_PointerVec.at(fingerIndex-1).ID) - { - m_OldMousePosition = m_OldPointerVec.at(fingerIndex-1).Position; - m_OldMousePosition = vec2( - m_OldMousePosition.x , - (float32)GraphicsManager::GetInstance()->GetWindowHeight() - m_OldMousePosition.y); - m_OldMousePosition -= vec2( - float32(GraphicsManager::GetInstance()->GetHorizontalViewportOffset()), - float32(GraphicsManager::GetInstance()->GetVerticalViewportOffset())); - m_OldMousePosition /= GraphicsManager::GetInstance()->GetViewportResolution(); - m_OldMousePosition *= GraphicsManager::GetInstance()->GetScreenResolution(); - - //[BUG] if camera moves, this might be a bad idea.. - if(SceneManager::GetInstance()->GetActiveScene()) - { - BaseCamera* projectionObject = SceneManager::GetInstance()-> - GetActiveScene()->GetActiveCamera(); - if(projectionObject) - { - m_OldMousePosition += projectionObject->GetTransform()-> - GetWorldPosition().pos2D(); - } - } - } - } - return m_OldMousePosition; - } - - void InputManager::OnTouchEvent(AInputEvent* pEvent) - { - m_NumberOfPointersOLD = m_NumberOfPointers; - int32 action = AMotionEvent_getAction(pEvent); - uint32 flags = action & AMOTION_EVENT_ACTION_MASK; - switch(flags) - { - case AMOTION_EVENT_ACTION_POINTER_UP: - { - int32 pointerIndex((action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) - >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT); - int32 pointerID(AMotionEvent_getPointerId(pEvent,pointerIndex)); - if(pointerID == m_ActivePointerID) - { - //This was our active pointer going up. Choose a new active pointer and adjust - int32 newPointerIndex = pointerIndex == 0? 1 : 0; - m_ActivePointerID = AMotionEvent_getPointerId(pEvent, newPointerIndex); - } - --m_NumberOfPointers; - m_bPointerIsUp = true; - break; - } - case AMOTION_EVENT_ACTION_POINTER_DOWN: - ++m_NumberOfPointers; - m_bPointerIsDown = true; - break; - case AMOTION_EVENT_ACTION_DOWN: - m_ActivePointerID = AMotionEvent_getPointerId(pEvent, 0); - ++m_NumberOfPointers; - m_bMainIsDown = true; - break; - case AMOTION_EVENT_ACTION_UP: - for(auto pointer : m_PointerVec) - { - pointer.Position = vec2(); - pointer.Pressure = 0; - pointer.RawPosition = vec2(); - } - m_ActivePointerID = INVALID_POINTER_ID; - --m_NumberOfPointers; - m_bMainIsUp = true; - break; - case AMOTION_EVENT_ACTION_CANCEL: - m_ActivePointerID = INVALID_POINTER_ID; - LOG(LogLevel::Info, - _T("Canceled"), STARENGINE_LOG_TAG); - break; - case AMOTION_EVENT_ACTION_OUTSIDE: - LOG(LogLevel::Info, - _T("Outside"), STARENGINE_LOG_TAG); - break; - case AMOTION_EVENT_ACTION_MOVE: - break; - default: - break; - } - - m_OldPointerVec = m_PointerVec; - m_PointerVec.clear(); - //Store every pointer in a vector, with their position and everything else we need - for(int32 i = 0; i < AMotionEvent_getPointerCount(pEvent); ++i) - { - FingerPointerANDR temp = FingerPointerANDR(); - temp.ID = AMotionEvent_getPointerId(pEvent,i); - temp.Position = vec2(AMotionEvent_getX(pEvent, i), AMotionEvent_getY(pEvent, i)); - temp.Pressure = AMotionEvent_getPressure(pEvent,i); - temp.RawPosition = vec2(AMotionEvent_getRawX(pEvent, i), AMotionEvent_getRawY(pEvent, i)); - temp.ToolMajor = AMotionEvent_getToolMajor(pEvent, i); - temp.ToolMinor = AMotionEvent_getToolMinor(pEvent, i); - - m_PointerVec.push_back(temp); - } - std::sort(m_PointerVec.begin(),m_PointerVec.end(), - [] (const FingerPointerANDR& a, const FingerPointerANDR& b) - { - return (a.ID < b.ID); - }); - if(m_GestureManager != nullptr) - { - m_GestureManager->OnTouchEvent(pEvent); - } - m_IndependantGestureManager->OnTouchEvent(pEvent); - } - - bool InputManager::OnKeyboardEvent(AInputEvent* pEvent) - { - //[TODO] I will still clean this up later, might need this - - if(AKeyEvent_getAction(pEvent) == AKEY_EVENT_ACTION_DOWN) - { - //Try: (schar) cast the keycode - switch(AKeyEvent_getKeyCode(pEvent)) - { - case AKEYCODE_MENU: - if(m_OnMenuButtonDown) - { - m_OnMenuButtonDown(); - return true; - } - break; - case AKEYCODE_BACK: - if(m_OnBackButtonDown) - { - m_OnBackButtonDown(); - return true; - } - break; - } - return false; - } - else - { - return false; - } - } - - void InputManager::SetOnBackButtonCallback(CallBack callback) - { - m_OnBackButtonDown = callback; - } - - void InputManager::SetOnMenuButtonCallback(CallBack callback) - { - m_OnMenuButtonDown = callback; - } - - FingerPointerANDR InputManager::GetTouchPropertiesANDR(uint8 fingerIndex)const - { - if(fingerIndex <= m_PointerVec.size() && fingerIndex > 0) - { - return (m_PointerVec.at(fingerIndex - 1)); - } - return (FingerPointerANDR()); - } -#endif - - bool InputManager::IsFingerPressedCP(uint8 fingerIndex) const - { - ++fingerIndex; -#ifdef _WIN32 - return IsMouseButtonPressedWIN(ConvertIndexToVK(fingerIndex)); -#else - return (IsTouchPressedANDR(fingerIndex)); -#endif - } - - bool InputManager::IsFingerDownCP(uint8 fingerIndex) const - { - ++fingerIndex; -#ifdef _WIN32 - return IsMouseButtonDownWIN(ConvertIndexToVK(fingerIndex)); -#else - return (IsTouchDownANDR(fingerIndex)); -#endif - } - - bool InputManager::IsFingerReleasedCP(uint8 fingerIndex) const - { - ++fingerIndex; -#ifdef _WIN32 - return IsMouseButtonReleasedWIN(ConvertIndexToVK(fingerIndex)); -#else - return (IsTouchReleasedANDR(fingerIndex)); -#endif - } - - vec2 InputManager::GetCurrentFingerPosCP(uint8 fingerIndex) - { - ++fingerIndex; -#ifdef DESKTOP - return GetCurrentMousePosition(); -#else - return GetCurrentTouchPosANDR(fingerIndex); -#endif - } - - vec2 InputManager::GetOldFingerPosCP(uint8 fingerIndex) - { - ++fingerIndex; -#ifdef DESKTOP - return GetOldMousePosition(); -#else - return (GetOldTouchPosANDR(fingerIndex)); -#endif - } - - void InputManager::EndUpdate() - { - m_GestureManager->EndUpdate(); - m_IndependantGestureManager->EndUpdate(); -#ifndef DESKTOP - m_bMainIsDown = false; - m_bMainIsUp = false; - m_bPointerIsDown = false; - m_bPointerIsUp = false; -#endif - } - - void InputManager::SetGestureManager(std::shared_ptr gestureManager) - { - m_GestureManager = gestureManager; - } - - std::shared_ptr InputManager::GetGestureManager() const - { - return m_GestureManager; - } - - void InputManager::AddGlobalGesture(BaseGesture* gesture) - { - LOG(LogLevel::Warning, -_T("Please use the method AddGesture(BaseGesture* gesture, \ -const tstring & name) to add gestures. \ -using InputManager::AddGesture(BaseGesture* gesture) is much slower, use with care!"), - STARENGINE_LOG_TAG); - - m_IndependantGestureManager->AddGesture(gesture, _T("Gesture_") + string_cast(m_GestureID)); - ++m_GestureID; - } - - void InputManager::AddGlobalGesture(BaseGesture* gesture, const tstring & name) - { - m_IndependantGestureManager->AddGesture(gesture, name); - } - - void InputManager::RemoveGlobalGesture(BaseGesture* gesture) - { - m_IndependantGestureManager->RemoveGesture(gesture); - } - - void InputManager::RemoveGlobalGesture(const tstring & name) - { - m_IndependantGestureManager->RemoveGesture(name); - } -} +#include "InputManager.h" + +#ifdef _WIN32 +#include +#elif defined(ANDROID) +#include +#include +#endif +#include "../Logger.h" +#include "../StarEngine.h" +#include "../Graphics/GraphicsManager.h" +#include "../Graphics/ScaleSystem.h" +#include "../Scenes/SceneManager.h" +#include "../Components/CameraComponent.h" +#include "../Scenes/BaseScene.h" +#include "../Objects/BaseCamera.h" +#include "../Helpers/Helpers.h" +#include "../Helpers/Math.h" + +namespace star +{ +#ifdef _WIN32 + const float32 InputManager::BYTE_TO_DOUBLE_VALUE = 255.0f; +#elif defined(ANDROID) + const float32 InputManager::UNDEFINED_POINTER_POSITION = -123456.0f; +#endif + +#ifdef _WIN32 + InputAction::InputAction(): + ActionID(-1), + TriggerState(InputTriggerState::Pressed), + KeyboardCode(-1), + MouseButtonCode(-1), + GamepadButtonCode(0), + PlayerIndex(GamepadIndex::PlayerOne), + IsTriggered(false) + { + } + + InputAction::InputAction(int32 actionID, InputTriggerState triggerState, + int32 keyboardCode, int32 mouseButtonCode, WORD gamepadButtonCode, + GamepadIndex playerIndex): + ActionID(actionID), + TriggerState(triggerState), + KeyboardCode(keyboardCode), + MouseButtonCode(mouseButtonCode), + GamepadButtonCode(gamepadButtonCode), + PlayerIndex(playerIndex), + IsTriggered(false) + { + } +#elif defined(ANDROID) + FingerPointerANDR::FingerPointerANDR(): + Position(), + RawPosition(), + Pressure(0.0f), + ToolMajor(0.0f), + ToolMinor(0.0f), + ID(0) + { + } +#endif + + InputManager::InputManager() + : Singleton() + #ifdef _WIN32 + , m_ThreadAvailable(false) + , m_KeyboardState0Active(true) + , mWindowsHandle() + #elif defined(ANDROID) + , m_bMainIsDown(false) + , m_bMainIsUp(false) + , m_bPointerIsDown(false) + , m_bPointerIsUp(false) + , m_NumberOfPointers(0) + , m_NumberOfPointersOLD(0) + , m_ActivePointerID(0) + , m_PointerVec() + , m_OldPointerVec() + , m_OnBackButtonDown(nullptr) + , m_OnMenuButtonDown(nullptr) + #endif + , m_GestureManager(nullptr) + , m_IndependantGestureManager(nullptr) + , m_OldMousePosition() + , m_CurrMousePosition() + , m_MouseMovement() + , m_GestureID(0) + { + m_IndependantGestureManager = new GestureManager(); +#ifdef _WIN32 + //Init new keyboard states + GetKeyboardState(m_pKeyboardState0); + GetKeyboardState(m_pKeyboardState1); + UpdateWin(); +#endif + } + + InputManager::~InputManager(void) + { + delete m_IndependantGestureManager; + } + + void InputManager::UpdateGestures(const Context & context) + { + m_GestureManager->Update(context); + m_IndependantGestureManager->Update(context); + } + +#ifdef _WIN32 + //[TODO] add this for android + + //Adds an inputAction to the list of inputActions + bool InputManager::AddInputAction(const InputAction& action) + { + auto it = m_InputActions.find(action.ActionID); + if(it != m_InputActions.end()) + { + return false; + } + m_InputActions[action.ActionID] = action; + return true; + } + + bool InputManager::IsActionTriggered(int32 actionID) const + { + return m_InputActions.at(actionID).IsTriggered; + } + //[TODO] -- end TODO + + void InputManager::IsCursorVisible(bool visible) + { + ShowCursor(visible); + } + + void InputManager::UpdateGamepadStates() + { + DWORD dwResult; + for(DWORD i = 0; i < XUSER_MAX_COUNT; ++i) + { + m_OldGamepadState[i] = m_CurrGamepadState[i]; + + XINPUT_STATE state; + ZeroMemory(&state, sizeof(XINPUT_STATE)); + + //returns ERROR_DEVICE_NOT_CONNECTED if i is invalid + dwResult = XInputGetState(i, &state); + m_CurrGamepadState[i] = state; + + //If the gamepad was connected, update the "connected gamepad array + if(dwResult == ERROR_SUCCESS) + { + m_ConnectedGamepads[i] = true; + } + else + { + m_ConnectedGamepads[i] = false; + } + } + } + + bool InputManager::UpdateKeyboardStates() + { + //Get Current KeyboardState and set Old KeyboardState (needed for "released" checks) + BOOL getKeyboardResult; + if(m_KeyboardState0Active) + { + //GetKeyboardState is thread dependant! use AttachThreadInput to link them! + getKeyboardResult = GetKeyboardState(m_pKeyboardState1); + for(int32 i = 0 ; i < NUMBER_OF_KEYBOARDKEYS ; ++i) + { + m_pOldKeyboardState[i] = m_pKeyboardState0[i]; + m_pCurrKeyboardState[i] = m_pKeyboardState1[i]; + } + } + else + { + getKeyboardResult = GetKeyboardState(m_pKeyboardState0); + for(int32 i = 0 ; i < NUMBER_OF_KEYBOARDKEYS ; ++i) + { + m_pOldKeyboardState[i] = m_pKeyboardState1[i]; + m_pCurrKeyboardState[i] = m_pKeyboardState0[i]; + } + } + + m_KeyboardState0Active = !m_KeyboardState0Active; + return getKeyboardResult > 0 ? true : false; + } + + bool InputManager::IsKeyboardKeyDown(uint8 key, bool previousFrame) const + { + if(key > 0x07 && key <= 0xFE) + { + return IsKeyboardKeyDown_unsafe(key, previousFrame); + } + return false; + } + + bool InputManager::IsMouseButtonPressedWIN(uint8 button) const + { + if(IsMouseButtonDownWIN(button) && !IsMouseButtonDownWIN(button, true)) + { + return true; + } + return false; + } + + bool InputManager::IsMouseButtonDownWIN(uint8 button, bool previousFrame) const + { + if(button > 0x00 && button <= 0x06) + { + return IsMouseButtonDown_unsafe(button, previousFrame); + } + return false; + } + + bool InputManager::IsMouseButtonReleasedWIN(uint8 button) const + { + if(!IsMouseButtonDownWIN(button) && IsMouseButtonDownWIN(button, true)) + { + return true; + } + return false; + } + + void InputManager::SetWindowsHandle(HWND hWnd) + { + mWindowsHandle = hWnd; + } + + bool InputManager::IsGamepadButtonDown(WORD button, GamepadIndex playerIndex, bool previousFrame) const + { + if(button > 0x0000 && button<=0x8000) + { + return IsGamepadButtonDown_unsafe(button, playerIndex, previousFrame); + } + return false; + } + + const vec2 & InputManager::GetCurrentMousePosition() const + { + return m_CurrMousePosition; + } + + const vec2 & InputManager::GetOldMousePosition() const + { + return m_OldMousePosition; + } + + const vec2 & InputManager::GetMouseMovement() const + { + return m_MouseMovement; + } + + bool InputManager::IsAnyKeyDown() const + { + for (uint16 i = 0; i < NUMBER_OF_KEYBOARDKEYS; ++i) + { + if( (schar) (GetAsyncKeyState(i) >> 8)) + { + return true; + } + } + for(uint8 index = 0; index < XUSER_MAX_COUNT; ++index) + { + if(m_ConnectedGamepads[index] == true) + { + for(WORD button = 0x00000001; button < MAX_GAMEPAD_VALUE; button *= 2) + { + if(IsGamepadButtonDown(button,static_cast(index))) + { + return true; + } + } + } + } + return false; + } + + //NO RANGE CHECKS + bool InputManager::IsKeyboardKeyDown_unsafe(uint8 key, bool previousFrame) const + { + if(previousFrame) + { + return (m_pOldKeyboardState[key] & 0xF0) != 0; + } + else + { + return (m_pCurrKeyboardState[key] & 0xF0) != 0; + } + } + + //NO RANGE CHECKS + bool InputManager::IsMouseButtonDown_unsafe(uint8 button, bool previousFrame) const + { + if(previousFrame) + { + return (m_pOldKeyboardState[button ]& 0xF0) != 0; + } + else + { + return (m_pCurrKeyboardState[button] & 0xF0) != 0; + } + } + + //NO RANGE CHECKS + bool InputManager::IsGamepadButtonDown_unsafe(WORD button, GamepadIndex playerIndex, + bool previousFrame) const + { + if(!m_ConnectedGamepads[playerIndex]) + { + return false; + } + if(previousFrame) + { + return (m_OldGamepadState[playerIndex].Gamepad.wButtons&button) != 0; + } + else + { + return (m_CurrGamepadState[playerIndex].Gamepad.wButtons&button) != 0; + } + } + + DWORD InputManager::UpdateWin() + { + //while(m_ThreadAvailable) + { + UpdateKeyboardStates(); + UpdateGamepadStates(); + + //Reset previous InputAction States + for(auto it = m_InputActions.begin(); it != m_InputActions.end(); ++it) + { + auto currAction = &(it->second); + //Reset the previous state before updating/checking the new state + currAction->IsTriggered = false; + + switch(currAction->TriggerState) + { + //if the input wasnt down last frame, but it is now, it is pressed + case InputTriggerState::Pressed: + //KEYBOARD + if( currAction->KeyboardCode > MIN_KEYBOARD_VALUE && + currAction->KeyboardCode <= MAX_KEYBOARD_VALUE) + { + if(!IsKeyboardKeyDown_unsafe(currAction->KeyboardCode,true) && + IsKeyboardKeyDown_unsafe(currAction->KeyboardCode)) + { + currAction->IsTriggered = true; + } + } + + //MOUSE + if(!currAction->IsTriggered && + currAction->MouseButtonCode > MIN_MOUSE_BUTTON_VALUE && + currAction->MouseButtonCode <= MAX_MOUSE_BUTTON_VALUE) + { + if(!IsMouseButtonDown_unsafe(currAction->MouseButtonCode,true) && + IsMouseButtonDown_unsafe(currAction->MouseButtonCode)) + { + currAction->IsTriggered = true; + LOG(LogLevel::Info, + _T("Clicked mouse button."), STARENGINE_LOG_TAG); + } + } + + //GAMEPADS + if(!currAction->IsTriggered && currAction->GamepadButtonCode != 0) + if(!IsGamepadButtonDown_unsafe( + currAction->GamepadButtonCode,currAction->PlayerIndex,true) && + IsGamepadButtonDown_unsafe( + currAction->GamepadButtonCode,currAction->PlayerIndex)) + { + currAction->IsTriggered = true; + } + + break; + + //if the input was down last frame, and is down now, it is down. + case InputTriggerState::Down: + //KEYBOARD + if(currAction->KeyboardCode > MIN_KEYBOARD_VALUE && + currAction->KeyboardCode <= MAX_KEYBOARD_VALUE) + { + if(IsKeyboardKeyDown_unsafe(currAction->KeyboardCode,true) && + IsKeyboardKeyDown_unsafe(currAction->KeyboardCode)) + { + currAction->IsTriggered = true; + } + } + + //MOUSE + if(!currAction->IsTriggered && + currAction->MouseButtonCode > MIN_MOUSE_BUTTON_VALUE && + currAction->MouseButtonCode <= MAX_MOUSE_BUTTON_VALUE) + { + if( IsMouseButtonDown_unsafe(currAction->MouseButtonCode,true) && + IsMouseButtonDown_unsafe(currAction->MouseButtonCode)) + { + currAction->IsTriggered = true; + } + } + //GAMEPADS + if(!currAction->IsTriggered && currAction->GamepadButtonCode != 0) + { + if( IsGamepadButtonDown_unsafe( + currAction->GamepadButtonCode,currAction->PlayerIndex,true) && + IsGamepadButtonDown_unsafe( + currAction->GamepadButtonCode,currAction->PlayerIndex)) + { + currAction->IsTriggered = true; + } + } + break; + + //If the input was down last frame, but isn't down anymore, it was released. + case InputTriggerState::Released: + //KEYBOARD + if( currAction->KeyboardCode > MIN_KEYBOARD_VALUE && + currAction->KeyboardCode <= MAX_KEYBOARD_VALUE) + { + if( IsKeyboardKeyDown_unsafe(currAction->KeyboardCode,true) && + !IsKeyboardKeyDown_unsafe(currAction->KeyboardCode)) + { + currAction->IsTriggered = true; + } + } + + //MOUSE + if(!currAction->IsTriggered && + currAction->MouseButtonCode > MIN_MOUSE_BUTTON_VALUE && + currAction->MouseButtonCode <= MAX_MOUSE_BUTTON_VALUE) + { + if( IsMouseButtonDown_unsafe(currAction->MouseButtonCode,true) && + !IsMouseButtonDown_unsafe(currAction->MouseButtonCode)) + { + currAction->IsTriggered = true; + } + } + + //GAMEPADS + if(!currAction->IsTriggered && + currAction->GamepadButtonCode > MIN_GAMEPAD_VALUE && + currAction->GamepadButtonCode <= MAX_GAMEPAD_VALUE) + { + if( IsGamepadButtonDown_unsafe( + currAction->GamepadButtonCode,currAction->PlayerIndex,true) && + !IsGamepadButtonDown_unsafe( + currAction->GamepadButtonCode,currAction->PlayerIndex)) + { + currAction->IsTriggered = true; + } + } + break; + } + } + + //Mouse Position + m_OldMousePosition = m_CurrMousePosition; + POINT mousePos; + if(GetCursorPos(&mousePos)) + { + ScreenToClient(mWindowsHandle,&mousePos); + } + + m_CurrMousePosition = vec2( + mousePos.x , + float32(GraphicsManager::GetInstance()->GetWindowHeight() - mousePos.y) + ); + m_CurrMousePosition -= vec2( + float32(GraphicsManager::GetInstance()->GetHorizontalViewportOffset()), + float32(GraphicsManager::GetInstance()->GetVerticalViewportOffset()) + ); + m_CurrMousePosition /= GraphicsManager::GetInstance()->GetViewportResolution(); + m_CurrMousePosition *= GraphicsManager::GetInstance()->GetScreenResolution(); + + if(SceneManager::GetInstance()->GetActiveScene()) + { + BaseCamera* projectionObject = SceneManager::GetInstance()-> + GetActiveScene()->GetActiveCamera(); + if(projectionObject) + { + auto worldPos = projectionObject->GetTransform()->GetWorldPosition().pos2D(); + worldPos.x /= (star::ScaleSystem::GetInstance()->GetWorkingResolution().x / 2.0f); + worldPos.y /= (star::ScaleSystem::GetInstance()->GetWorkingResolution().y / 2.0f); + m_CurrMousePosition += worldPos; + } + } + + m_MouseMovement.x = m_CurrMousePosition.x - m_OldMousePosition.x; + m_MouseMovement.y = m_CurrMousePosition.y - m_OldMousePosition.y; + + if(m_GestureManager != nullptr) + { + m_GestureManager->OnUpdateWinInputState(); + } + m_IndependantGestureManager->OnUpdateWinInputState(); + //Sleep(1000/60); + } + return 0; + } + + void InputManager::StartKeyboardThread() + { + m_ThreadAvailable = true; + } + + void InputManager::StopKeyboardThread() + { + m_ThreadAvailable = false; + } + vec2 InputManager::GetThumbstickPosition + (bool leftThumbstick, GamepadIndex playerIndex) const + { + vec2 pos; + if(leftThumbstick) + { + pos = vec2( m_CurrGamepadState[playerIndex].Gamepad.sThumbLX, + m_CurrGamepadState[playerIndex].Gamepad.sThumbLY); + if( pos.x > -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE && + pos.x < XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE) + { + pos.x = 0; + } + if( pos.y > -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE && + pos.y < XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE) + { + pos.y = 0; + } + } + else + { + pos = vec2( m_CurrGamepadState[playerIndex].Gamepad.sThumbRX, + m_CurrGamepadState[playerIndex].Gamepad.sThumbRY); + if( pos.x > -XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE && + pos.x < XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE) + { + pos.x = 0; + } + if( pos.y > -XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE && + pos.y < XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE) + { + pos.y = 0; + } + } + + //Shorts have a range of 32768, so to convert that range to a float64, + //devide it by that range + if(pos.x < 0) + { + pos.x /= MAX_VALUE_OF_SHORT; + } + else + { + pos.x /= MAX_VALUE_OF_SHORT; + } + + if(pos.y < 0) + { + pos.y /= MAX_VALUE_OF_SHORT; + } + else + { + pos.y /= MAX_VALUE_OF_SHORT; + } + + return pos; + } + + float32 InputManager::GetTriggerPressure(bool leftTrigger, GamepadIndex playerIndex) const + { + if(leftTrigger) + { + //bLeftTrigger returns a byte, div by 255 to cast to float64 + return m_CurrGamepadState[playerIndex].Gamepad.bLeftTrigger + / BYTE_TO_DOUBLE_VALUE; + } + else + { + return m_CurrGamepadState[playerIndex].Gamepad.bRightTrigger + / BYTE_TO_DOUBLE_VALUE; + } + } + + void InputManager::SetVibration(float32 leftVibration, float32 rightVibration, + GamepadIndex playerIndex) + { + XINPUT_VIBRATION vibration; + Clamp(leftVibration, 0.0f, 1.0f); + Clamp(rightVibration, 0.0f, 1.0f); + ZeroMemory(&vibration, sizeof(XINPUT_VIBRATION)); + //convert from float32 to word -> float32 * lenght of word + vibration.wLeftMotorSpeed = static_cast(leftVibration * MAX_VALUE_OF_WORD); + vibration.wRightMotorSpeed = static_cast(rightVibration * MAX_VALUE_OF_WORD); + XInputSetState(playerIndex, &vibration); + } + + uint8 InputManager::ConvertIndexToVK(uint8 fingerIndex) const + { + switch(fingerIndex) + { + case 1: + return VK_LBUTTON; + case 2: + return VK_RBUTTON; + case 3: + return VK_MBUTTON; + case 4: + return VK_XBUTTON1; + case 5: + return VK_XBUTTON2; + default: + LOG(LogLevel::Warning, + _T("Only 5 (0 - 4) finger Indices supported for mouse. Using VK_XBUTTON2"), + STARENGINE_LOG_TAG); + return VK_XBUTTON2; + } + } +#elif defined(ANDROID) + + bool InputManager::IsTouchPressedANDR(uint8 fingerIndex) const + { + if(m_NumberOfPointers >= fingerIndex && (m_bMainIsDown || m_bPointerIsDown)) + { + return (true); + } + return (false); + } + + bool InputManager::IsTouchDownANDR(uint8 fingerIndex) const + { + if(m_NumberOfPointers >= fingerIndex) + { + return (true); + } + return (false); + } + + bool InputManager::IsTouchReleasedANDR(uint8 fingerIndex) const + { + if(m_NumberOfPointers >= fingerIndex -1 && (m_bMainIsUp || m_bPointerIsUp)) + { + return (true); + } + return (false); + } + + vec2 InputManager::GetCurrentTouchPosANDR(uint8 fingerIndex) + { + if((fingerIndex <= m_PointerVec.size() && fingerIndex > 0)) + { + m_CurrMousePosition = m_PointerVec.at(fingerIndex-1).Position; + m_CurrMousePosition = vec2( + m_CurrMousePosition.x , + (float32)GraphicsManager::GetInstance()->GetWindowHeight() - m_CurrMousePosition.y); + m_CurrMousePosition -= vec2( + float32(GraphicsManager::GetInstance()->GetHorizontalViewportOffset()), + float32(GraphicsManager::GetInstance()->GetVerticalViewportOffset())); + m_CurrMousePosition /= GraphicsManager::GetInstance()->GetViewportResolution(); + m_CurrMousePosition *= GraphicsManager::GetInstance()->GetScreenResolution(); + + if(SceneManager::GetInstance()->GetActiveScene()) + { + BaseCamera* projectionObject = SceneManager::GetInstance()-> + GetActiveScene()->GetActiveCamera(); + if(projectionObject) + { + m_CurrMousePosition += projectionObject->GetTransform()-> + GetWorldPosition().pos2D(); + } + } + } + return m_CurrMousePosition; + } + + vec2 InputManager::GetOldTouchPosANDR(uint8 fingerIndex) + { + if(((fingerIndex <= m_OldPointerVec.size() && fingerIndex > 0) && + (fingerIndex <= m_PointerVec.size() && fingerIndex > 0))) + { + if(m_OldPointerVec.at(fingerIndex-1).ID == m_PointerVec.at(fingerIndex-1).ID) + { + m_OldMousePosition = m_OldPointerVec.at(fingerIndex-1).Position; + m_OldMousePosition = vec2( + m_OldMousePosition.x , + (float32)GraphicsManager::GetInstance()->GetWindowHeight() - m_OldMousePosition.y); + m_OldMousePosition -= vec2( + float32(GraphicsManager::GetInstance()->GetHorizontalViewportOffset()), + float32(GraphicsManager::GetInstance()->GetVerticalViewportOffset())); + m_OldMousePosition /= GraphicsManager::GetInstance()->GetViewportResolution(); + m_OldMousePosition *= GraphicsManager::GetInstance()->GetScreenResolution(); + + //[BUG] if camera moves, this might be a bad idea.. + if(SceneManager::GetInstance()->GetActiveScene()) + { + BaseCamera* projectionObject = SceneManager::GetInstance()-> + GetActiveScene()->GetActiveCamera(); + if(projectionObject) + { + m_OldMousePosition += projectionObject->GetTransform()-> + GetWorldPosition().pos2D(); + } + } + } + } + return m_OldMousePosition; + } + + void InputManager::OnTouchEvent(AInputEvent* pEvent) + { + m_NumberOfPointersOLD = m_NumberOfPointers; + int32 action = AMotionEvent_getAction(pEvent); + uint32 flags = action & AMOTION_EVENT_ACTION_MASK; + switch(flags) + { + case AMOTION_EVENT_ACTION_POINTER_UP: + { + int32 pointerIndex((action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) + >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT); + int32 pointerID(AMotionEvent_getPointerId(pEvent,pointerIndex)); + if(pointerID == m_ActivePointerID) + { + //This was our active pointer going up. Choose a new active pointer and adjust + int32 newPointerIndex = pointerIndex == 0? 1 : 0; + m_ActivePointerID = AMotionEvent_getPointerId(pEvent, newPointerIndex); + } + --m_NumberOfPointers; + m_bPointerIsUp = true; + break; + } + case AMOTION_EVENT_ACTION_POINTER_DOWN: + ++m_NumberOfPointers; + m_bPointerIsDown = true; + break; + case AMOTION_EVENT_ACTION_DOWN: + m_ActivePointerID = AMotionEvent_getPointerId(pEvent, 0); + ++m_NumberOfPointers; + m_bMainIsDown = true; + break; + case AMOTION_EVENT_ACTION_UP: + for(auto pointer : m_PointerVec) + { + pointer.Position = vec2(); + pointer.Pressure = 0; + pointer.RawPosition = vec2(); + } + m_ActivePointerID = INVALID_POINTER_ID; + --m_NumberOfPointers; + m_bMainIsUp = true; + break; + case AMOTION_EVENT_ACTION_CANCEL: + m_ActivePointerID = INVALID_POINTER_ID; + LOG(LogLevel::Info, + _T("Canceled"), STARENGINE_LOG_TAG); + break; + case AMOTION_EVENT_ACTION_OUTSIDE: + LOG(LogLevel::Info, + _T("Outside"), STARENGINE_LOG_TAG); + break; + case AMOTION_EVENT_ACTION_MOVE: + break; + default: + break; + } + + m_OldPointerVec = m_PointerVec; + m_PointerVec.clear(); + //Store every pointer in a vector, with their position and everything else we need + for(int32 i = 0; i < AMotionEvent_getPointerCount(pEvent); ++i) + { + FingerPointerANDR temp = FingerPointerANDR(); + temp.ID = AMotionEvent_getPointerId(pEvent,i); + temp.Position = vec2(AMotionEvent_getX(pEvent, i), AMotionEvent_getY(pEvent, i)); + temp.Pressure = AMotionEvent_getPressure(pEvent,i); + temp.RawPosition = vec2(AMotionEvent_getRawX(pEvent, i), AMotionEvent_getRawY(pEvent, i)); + temp.ToolMajor = AMotionEvent_getToolMajor(pEvent, i); + temp.ToolMinor = AMotionEvent_getToolMinor(pEvent, i); + + m_PointerVec.push_back(temp); + } + std::sort(m_PointerVec.begin(),m_PointerVec.end(), + [] (const FingerPointerANDR& a, const FingerPointerANDR& b) + { + return (a.ID < b.ID); + }); + if(m_GestureManager != nullptr) + { + m_GestureManager->OnTouchEvent(pEvent); + } + m_IndependantGestureManager->OnTouchEvent(pEvent); + } + + bool InputManager::OnKeyboardEvent(AInputEvent* pEvent) + { + //[TODO] I will still clean this up later, might need this + + if(AKeyEvent_getAction(pEvent) == AKEY_EVENT_ACTION_DOWN) + { + //Try: (schar) cast the keycode + switch(AKeyEvent_getKeyCode(pEvent)) + { + case AKEYCODE_MENU: + if(m_OnMenuButtonDown) + { + m_OnMenuButtonDown(); + return true; + } + break; + case AKEYCODE_BACK: + if(m_OnBackButtonDown) + { + m_OnBackButtonDown(); + return true; + } + break; + } + return false; + } + else + { + return false; + } + } + + void InputManager::SetOnBackButtonCallback(CallBack callback) + { + m_OnBackButtonDown = callback; + } + + void InputManager::SetOnMenuButtonCallback(CallBack callback) + { + m_OnMenuButtonDown = callback; + } + + FingerPointerANDR InputManager::GetTouchPropertiesANDR(uint8 fingerIndex)const + { + if(fingerIndex <= m_PointerVec.size() && fingerIndex > 0) + { + return (m_PointerVec.at(fingerIndex - 1)); + } + return (FingerPointerANDR()); + } +#endif + + bool InputManager::IsFingerPressedCP(uint8 fingerIndex) const + { + ++fingerIndex; +#ifdef _WIN32 + return IsMouseButtonPressedWIN(ConvertIndexToVK(fingerIndex)); +#elif defined(ANDROID) + return (IsTouchPressedANDR(fingerIndex)); +#endif + } + + bool InputManager::IsFingerDownCP(uint8 fingerIndex) const + { + ++fingerIndex; +#ifdef _WIN32 + return IsMouseButtonDownWIN(ConvertIndexToVK(fingerIndex)); +#elif defined(ANDROID) + return (IsTouchDownANDR(fingerIndex)); +#endif + } + + bool InputManager::IsFingerReleasedCP(uint8 fingerIndex) const + { + ++fingerIndex; +#ifdef _WIN32 + return IsMouseButtonReleasedWIN(ConvertIndexToVK(fingerIndex)); +#elif defined(ANDROID) + return (IsTouchReleasedANDR(fingerIndex)); +#endif + } + + vec2 InputManager::GetCurrentFingerPosCP(uint8 fingerIndex) + { + ++fingerIndex; +#ifdef _WIN32 + return GetCurrentMousePosition(); +#elif defined(ANDROID) + return GetCurrentTouchPosANDR(fingerIndex); +#endif + } + + vec2 InputManager::GetOldFingerPosCP(uint8 fingerIndex) + { + ++fingerIndex; +#ifdef _WIN32 + return GetOldMousePosition(); +#elif defined(ANDROID) + return (GetOldTouchPosANDR(fingerIndex)); +#endif + } + + void InputManager::EndUpdate() + { + m_GestureManager->EndUpdate(); + m_IndependantGestureManager->EndUpdate(); +#ifdef ANDROID + m_bMainIsDown = false; + m_bMainIsUp = false; + m_bPointerIsDown = false; + m_bPointerIsUp = false; +#endif + } + + void InputManager::SetGestureManager(std::shared_ptr gestureManager) + { + m_GestureManager = gestureManager; + } + + std::shared_ptr InputManager::GetGestureManager() const + { + return m_GestureManager; + } + + void InputManager::AddGlobalGesture(BaseGesture* gesture) + { + LOG(LogLevel::Warning, +_T("Please use the method AddGesture(BaseGesture* gesture, \ +const tstring & name) to add gestures. \ +using InputManager::AddGesture(BaseGesture* gesture) is much slower, use with care!"), + STARENGINE_LOG_TAG); + + m_IndependantGestureManager->AddGesture(gesture, _T("Gesture_") + string_cast(m_GestureID)); + ++m_GestureID; + } + + void InputManager::AddGlobalGesture(BaseGesture* gesture, const tstring & name) + { + m_IndependantGestureManager->AddGesture(gesture, name); + } + + void InputManager::RemoveGlobalGesture(BaseGesture* gesture) + { + m_IndependantGestureManager->RemoveGesture(gesture); + } + + void InputManager::RemoveGlobalGesture(const tstring & name) + { + m_IndependantGestureManager->RemoveGesture(name); + } +} diff --git a/src/Input/InputManager.h b/src/Input/InputManager.h index 2874675..e8efadb 100755 --- a/src/Input/InputManager.h +++ b/src/Input/InputManager.h @@ -1,210 +1,216 @@ -#pragma once - -#ifdef _WIN32 -#include -#include -#include -#include - -#pragma comment(lib, "XInput9_1_0.lib") -#else -#include -#include -#include -#include -#endif - -#include "../defines.h" -#include "../Helpers/Singleton.h" -#include "Gestures/GestureManager.h" - -namespace star -{ -#ifdef DESKTOP - - enum GamepadIndex : byte - { - PlayerOne = 0, - PlayerTwo = 1, - PlayerThree = 2, - PlayerFour = 3 - }; - - enum InputTriggerState : byte - { - Pressed, - Released, - Down - }; - -//[TODO] - Add for android - struct InputAction - { - InputAction(); - InputAction(int32 actionID, InputTriggerState triggerState = InputTriggerState::Pressed, - int32 keyboardCode = -1, int32 mouseButtonCode = -1, WORD gamepadButtonCode = 0, - GamepadIndex playerIndex = GamepadIndex::PlayerOne); - - int32 ActionID; - InputTriggerState TriggerState; - int32 KeyboardCode; //VK_... (Range 0x07 <> 0xFE) - int32 MouseButtonCode; //VK_... (Range 0x00 <> 0x06) - WORD GamepadButtonCode; //XINPUT_GAMEPAD_... - GamepadIndex PlayerIndex; - bool IsTriggered; - }; - -#else - struct FingerPointerANDR - { - FingerPointerANDR(); - - vec2 Position; - vec2 RawPosition; - float32 Pressure; - float32 ToolMajor; - float32 ToolMinor; - int32 ID; - }; - - typedef std::function CallBack; -#endif - - class InputManager final : public Singleton - { - public: - friend Singleton; - - void UpdateGestures(const Context & context); - - bool IsFingerPressedCP(uint8 finger = 0) const; - bool IsFingerDownCP(uint8 finger = 0) const; - bool IsFingerReleasedCP(uint8 finger = 0) const; - vec2 GetCurrentFingerPosCP(uint8 finger = 0); - vec2 GetOldFingerPosCP(uint8 finger = 0); - void EndUpdate(); - - void SetGestureManager(std::shared_ptr gestureManager); - std::shared_ptr GetGestureManager() const; - - void AddGlobalGesture(BaseGesture* gesture); - void AddGlobalGesture(BaseGesture* gesture, const tstring & name); - void RemoveGlobalGesture(BaseGesture* gesture); - void RemoveGlobalGesture(const tstring & name); - - template - T * GetGlobalGesture(const tstring & name) const; -#ifdef DESKTOP - - //[TODO] add InputActions for android - bool AddInputAction(const InputAction& action); - bool IsActionTriggered(int32 actionID) const; - //[TODO] -- END TODO - void IsCursorVisible(bool visible); - - vec2 GetThumbstickPosition(bool leftThumbstick = true, - GamepadIndex playerIndex = GamepadIndex::PlayerOne) const; - - float32 GetTriggerPressure(bool leftTrigger = true, - GamepadIndex playerIndex = GamepadIndex::PlayerOne) const; - - void SetVibration(float32 leftVibration, float32 rightVibration, - GamepadIndex playerIndex = GamepadIndex::PlayerOne); - - bool IsGamepadConnected(GamepadIndex index) const { return m_ConnectedGamepads[(DWORD)index]; } - bool IsGamepadButtonDown(WORD button, - GamepadIndex playerIndex = GamepadIndex::PlayerOne, bool previousFrame = false) const; - - const vec2 & GetCurrentMousePosition() const; - const vec2 & GetOldMousePosition() const; - const vec2 & GetMouseMovement() const; - bool IsKeyboardKeyDown(uint8 key, bool previousFrame = false) const; - bool IsAnyKeyDown() const; - - bool IsMouseButtonDownWIN(uint8 button , bool previousFrame = false) const; - bool IsMouseButtonPressedWIN(uint8 button) const; - bool IsMouseButtonReleasedWIN(uint8 button) const; - - void SetWindowsHandle(const HWND hWnd); - DWORD UpdateWin(); - void StartKeyboardThread(); - void StopKeyboardThread(); - - uint8 ConvertIndexToVK(uint8 fingerIndex) const; -#else - bool IsTouchPressedANDR(uint8 fingerIndex = 0) const; - bool IsTouchDownANDR(uint8 fingerIndex = 0) const; - bool IsTouchReleasedANDR(uint8 fingerIndex = 0) const; - vec2 GetCurrentTouchPosANDR(uint8 fingerIndex = 1); - vec2 GetOldTouchPosANDR(uint8 fingerIndex = 1); - FingerPointerANDR GetTouchPropertiesANDR(uint8 fingerIndex = 0) const; - - void OnTouchEvent(AInputEvent* pEvent); - bool OnKeyboardEvent(AInputEvent* pEvent); - - void SetOnBackButtonCallback(CallBack callback); - void SetOnMenuButtonCallback(CallBack callback); -#endif - - private: - InputManager(); - ~InputManager(); - -#ifdef DESKTOP - static const int32 NUMBER_OF_KEYBOARDKEYS = 256; - static const int32 MIN_KEYBOARD_VALUE = 0x07; - static const int32 MAX_KEYBOARD_VALUE = 0xFE; - static const int32 MIN_MOUSE_BUTTON_VALUE = 0x00; - static const int32 MAX_MOUSE_BUTTON_VALUE = 0x06; - static const WORD MIN_GAMEPAD_VALUE = 0x0000; - static const WORD MAX_GAMEPAD_VALUE = 0x8000; - static const int32 MAX_VALUE_OF_SHORT = 32768; - static const int32 MAX_VALUE_OF_WORD = 65535; - static const float32 BYTE_TO_DOUBLE_VALUE; - - std::map m_InputActions; - BYTE m_pCurrKeyboardState[NUMBER_OF_KEYBOARDKEYS], - m_pOldKeyboardState[NUMBER_OF_KEYBOARDKEYS], - m_pKeyboardState0[NUMBER_OF_KEYBOARDKEYS], - m_pKeyboardState1[NUMBER_OF_KEYBOARDKEYS]; - bool m_KeyboardState0Active; - XINPUT_STATE m_OldGamepadState[XUSER_MAX_COUNT], m_CurrGamepadState[XUSER_MAX_COUNT]; - bool m_ConnectedGamepads[XUSER_MAX_COUNT]; - bool m_ThreadAvailable; - HWND mWindowsHandle; - - void UpdateGamepadStates(); - bool IsGamepadButtonDown_unsafe(WORD button, - GamepadIndex playerIndex = GamepadIndex::PlayerOne, - bool previousFrame = false) const; - bool UpdateKeyboardStates(); - bool IsKeyboardKeyDown_unsafe(uint8 key, bool previousFrame = false) const; - bool IsMouseButtonDown_unsafe(uint8 button, bool previousFrame = false) const; -#else - static const int32 INVALID_POINTER_ID = -1; - static const float32 UNDEFINED_POINTER_POSITION; - bool m_bMainIsDown; - bool m_bPointerIsDown; - bool m_bMainIsUp; - bool m_bPointerIsUp; - uint8 m_NumberOfPointers; - uint8 m_NumberOfPointersOLD; - uint32 m_ActivePointerID; - std::vector m_PointerVec; - std::vector m_OldPointerVec; - CallBack m_OnBackButtonDown; - CallBack m_OnMenuButtonDown; -#endif - vec2 m_CurrMousePosition, m_OldMousePosition, m_MouseMovement; - std::shared_ptr m_GestureManager; - GestureManager* m_IndependantGestureManager; - uint32 m_GestureID; - - InputManager(const InputManager& t); - InputManager(InputManager&& t); - InputManager& operator=(const InputManager& t); - InputManager& operator=(InputManager&& t); - }; -} - -#include "InputManager.inl" +#pragma once + +#ifdef _WIN32 +#include +#include +#include +#include + +#pragma comment(lib, "XInput9_1_0.lib") +#elif defined(ANDROID) +#include +#include +#include +#include +#elif defined(ANDROID) +// Linux +#include +#include +#endif + +#include "../defines.h" +#include "../Helpers/Singleton.h" +#include "Gestures/GestureManager.h" + +namespace star +{ +#ifdef DESKTOP + + enum GamepadIndex : byte + { + PlayerOne = 0, + PlayerTwo = 1, + PlayerThree = 2, + PlayerFour = 3 + }; + + enum InputTriggerState : byte + { + Pressed, + Released, + Down + }; + +#ifdef _WIN32 +//[TODO] - Add for android + struct InputAction + { + InputAction(); + InputAction(int32 actionID, InputTriggerState triggerState = InputTriggerState::Pressed, + int32 keyboardCode = -1, int32 mouseButtonCode = -1, WORD gamepadButtonCode = 0, + GamepadIndex playerIndex = GamepadIndex::PlayerOne); + + int32 ActionID; + InputTriggerState TriggerState; + int32 KeyboardCode; //VK_... (Range 0x07 <> 0xFE) + int32 MouseButtonCode; //VK_... (Range 0x00 <> 0x06) + WORD GamepadButtonCode; //XINPUT_GAMEPAD_... + GamepadIndex PlayerIndex; + bool IsTriggered; + }; +#endif // _WIN32 + +#elif defined(ANDROID) + struct FingerPointerANDR + { + FingerPointerANDR(); + + vec2 Position; + vec2 RawPosition; + float32 Pressure; + float32 ToolMajor; + float32 ToolMinor; + int32 ID; + }; + + typedef std::function CallBack; +#endif + + class InputManager final : public Singleton + { + public: + friend Singleton; + + void UpdateGestures(const Context & context); + + bool IsFingerPressedCP(uint8 finger = 0) const; + bool IsFingerDownCP(uint8 finger = 0) const; + bool IsFingerReleasedCP(uint8 finger = 0) const; + vec2 GetCurrentFingerPosCP(uint8 finger = 0); + vec2 GetOldFingerPosCP(uint8 finger = 0); + void EndUpdate(); + + void SetGestureManager(std::shared_ptr gestureManager); + std::shared_ptr GetGestureManager() const; + + void AddGlobalGesture(BaseGesture* gesture); + void AddGlobalGesture(BaseGesture* gesture, const tstring & name); + void RemoveGlobalGesture(BaseGesture* gesture); + void RemoveGlobalGesture(const tstring & name); + + template + T * GetGlobalGesture(const tstring & name) const; +#ifdef _WIN32 + + //[TODO] add InputActions for android + bool AddInputAction(const InputAction& action); + bool IsActionTriggered(int32 actionID) const; + //[TODO] -- END TODO + void IsCursorVisible(bool visible); + + vec2 GetThumbstickPosition(bool leftThumbstick = true, + GamepadIndex playerIndex = GamepadIndex::PlayerOne) const; + + float32 GetTriggerPressure(bool leftTrigger = true, + GamepadIndex playerIndex = GamepadIndex::PlayerOne) const; + + void SetVibration(float32 leftVibration, float32 rightVibration, + GamepadIndex playerIndex = GamepadIndex::PlayerOne); + + bool IsGamepadConnected(GamepadIndex index) const { return m_ConnectedGamepads[(DWORD)index]; } + bool IsGamepadButtonDown(WORD button, + GamepadIndex playerIndex = GamepadIndex::PlayerOne, bool previousFrame = false) const; + + const vec2 & GetCurrentMousePosition() const; + const vec2 & GetOldMousePosition() const; + const vec2 & GetMouseMovement() const; + bool IsKeyboardKeyDown(uint8 key, bool previousFrame = false) const; + bool IsAnyKeyDown() const; + + bool IsMouseButtonDownWIN(uint8 button , bool previousFrame = false) const; + bool IsMouseButtonPressedWIN(uint8 button) const; + bool IsMouseButtonReleasedWIN(uint8 button) const; + + void SetWindowsHandle(const HWND hWnd); + DWORD UpdateWin(); + void StartKeyboardThread(); + void StopKeyboardThread(); + + uint8 ConvertIndexToVK(uint8 fingerIndex) const; +#elif defined(ANDROID) + bool IsTouchPressedANDR(uint8 fingerIndex = 0) const; + bool IsTouchDownANDR(uint8 fingerIndex = 0) const; + bool IsTouchReleasedANDR(uint8 fingerIndex = 0) const; + vec2 GetCurrentTouchPosANDR(uint8 fingerIndex = 1); + vec2 GetOldTouchPosANDR(uint8 fingerIndex = 1); + FingerPointerANDR GetTouchPropertiesANDR(uint8 fingerIndex = 0) const; + + void OnTouchEvent(AInputEvent* pEvent); + bool OnKeyboardEvent(AInputEvent* pEvent); + + void SetOnBackButtonCallback(CallBack callback); + void SetOnMenuButtonCallback(CallBack callback); +#endif + + private: + InputManager(); + ~InputManager(); + +#ifdef _WIN32 + static const int32 NUMBER_OF_KEYBOARDKEYS = 256; + static const int32 MIN_KEYBOARD_VALUE = 0x07; + static const int32 MAX_KEYBOARD_VALUE = 0xFE; + static const int32 MIN_MOUSE_BUTTON_VALUE = 0x00; + static const int32 MAX_MOUSE_BUTTON_VALUE = 0x06; + static const WORD MIN_GAMEPAD_VALUE = 0x0000; + static const WORD MAX_GAMEPAD_VALUE = 0x8000; + static const int32 MAX_VALUE_OF_SHORT = 32768; + static const int32 MAX_VALUE_OF_WORD = 65535; + static const float32 BYTE_TO_DOUBLE_VALUE; + + std::map m_InputActions; + BYTE m_pCurrKeyboardState[NUMBER_OF_KEYBOARDKEYS], + m_pOldKeyboardState[NUMBER_OF_KEYBOARDKEYS], + m_pKeyboardState0[NUMBER_OF_KEYBOARDKEYS], + m_pKeyboardState1[NUMBER_OF_KEYBOARDKEYS]; + bool m_KeyboardState0Active; + XINPUT_STATE m_OldGamepadState[XUSER_MAX_COUNT], m_CurrGamepadState[XUSER_MAX_COUNT]; + bool m_ConnectedGamepads[XUSER_MAX_COUNT]; + bool m_ThreadAvailable; + HWND mWindowsHandle; + + void UpdateGamepadStates(); + bool IsGamepadButtonDown_unsafe(WORD button, + GamepadIndex playerIndex = GamepadIndex::PlayerOne, + bool previousFrame = false) const; + bool UpdateKeyboardStates(); + bool IsKeyboardKeyDown_unsafe(uint8 key, bool previousFrame = false) const; + bool IsMouseButtonDown_unsafe(uint8 button, bool previousFrame = false) const; +#elif defined(ANDROID) + static const int32 INVALID_POINTER_ID = -1; + static const float32 UNDEFINED_POINTER_POSITION; + bool m_bMainIsDown; + bool m_bPointerIsDown; + bool m_bMainIsUp; + bool m_bPointerIsUp; + uint8 m_NumberOfPointers; + uint8 m_NumberOfPointersOLD; + uint32 m_ActivePointerID; + std::vector m_PointerVec; + std::vector m_OldPointerVec; + CallBack m_OnBackButtonDown; + CallBack m_OnMenuButtonDown; +#endif + vec2 m_CurrMousePosition, m_OldMousePosition, m_MouseMovement; + std::shared_ptr m_GestureManager; + GestureManager* m_IndependantGestureManager; + uint32 m_GestureID; + + InputManager(const InputManager& t); + InputManager(InputManager&& t); + InputManager& operator=(const InputManager& t); + InputManager& operator=(InputManager&& t); + }; +} + +#include "InputManager.inl" diff --git a/src/Input/XMLContainer.cpp b/src/Input/XMLContainer.cpp index 9ab1c9b..dae1700 100755 --- a/src/Input/XMLContainer.cpp +++ b/src/Input/XMLContainer.cpp @@ -1,432 +1,432 @@ -#include "XMLContainer.h" -#include "../Helpers/Helpers.h" -#include "../Logger.h" - -namespace star -{ - XMLContainer::XMLContainer() - : Dictionary>() - { - - } - - XMLContainer::XMLContainer(const XMLContainer & yRef) - : Dictionary>(yRef) - , m_Value(yRef.m_Value) - , m_Name(yRef.m_Name) - , m_Attributes(yRef.m_Attributes) - { - - } - - XMLContainer::XMLContainer(XMLContainer && yRef) - : Dictionary>(yRef) - , m_Value(yRef.m_Value) - , m_Name(yRef.m_Name) - , m_Attributes(yRef.m_Attributes) - { - - } - - XMLContainer::~XMLContainer() - { - m_Attributes.clear(); - } - - XMLContainer & XMLContainer::operator=(const XMLContainer & yRef) - { - m_MultiMap = yRef.m_MultiMap; - m_Value = yRef.m_Value; - m_Name = yRef.m_Name; - m_Attributes = yRef.m_Attributes; - return *this; - } - - XMLContainer & XMLContainer::operator=(XMLContainer && yRef) - { - m_MultiMap = yRef.m_MultiMap; - m_Value = yRef.m_Value; - m_Name = yRef.m_Name; - m_Attributes = yRef.m_Attributes; - return *this; - } - - Dictionary & XMLContainer::GetAttributes() - { - return m_Attributes; - } - - const tstring & XMLContainer::GetValue() const - { - return m_Value; - } - - const tstring & XMLContainer::GetName() const - { - return m_Name; - } - - void XMLContainer::SetValue(const tstring & value) - { - m_Value = value; - } - - void XMLContainer::SetName(const tstring & name) - { - m_Name = name; - } - - void XMLContainer::clear() - { - Dictionary>::clear(); - m_Value = _T(""); - m_Attributes.clear(); - } - - void XMLContainer::swap(XMLContainer & yRef) - { - Dictionary>::swap(yRef); - m_Value = yRef.m_Value; - m_Attributes.swap(yRef.m_Attributes); - } - - void XMLContainer::AddChild(const tstring & name) - { - auto container = std::make_shared(); - container->SetName(name); - m_MultiMap.insert( - std::pair>( - name, container - ) - ); - } - - void XMLContainer::AddChild(const tstring & name, const tstring & value) - { - auto container = std::make_shared(); - container->SetName(name); - container->SetValue(value); - m_MultiMap.insert( - std::pair>( - name, container - ) - ); - } - - void XMLContainer::Serialize(const tstring & file, DirectoryMode mode) - { - SerializedData data; - SerializeXMLContainer(data, this); - WriteBinaryFile(file, data.data, data.size, mode); - delete [] data.data; - } - - void XMLContainer::Deserialize(const tstring & file, DirectoryMode mode) - { - clear(); - - SerializedData buffer; - buffer.data = ReadBinaryFile(file, buffer.size, mode); - uint32 counter(1); // first byte == SER_START_OF_CHILD - DeserializeXMLContainer(buffer, counter, this); - - delete [] buffer.data; - } - - bool XMLContainer::DeserializeSafe(const tstring & file, DirectoryMode mode) - { - clear(); - - SerializedData buffer; - bool result = ReadBinaryFileSafe(file, buffer.data, buffer.size, mode); - - if(result) - { - uint32 counter(1); // first byte == SER_START_OF_CHILD - DeserializeXMLContainer(buffer, counter, this); - delete [] buffer.data; - } - else - { - LOG(LogLevel::Warning, - _T("XMLContainer::DeserializeSafe: Couldn't read file '") - + file + _T("'."), STARENGINE_LOG_TAG); - } - - return result; - } - - uint32 XMLContainer::SerializeString( - const tstring & value, schar ** data, schar end) - { - #ifdef _WIN32 - #ifndef _UNICODE - sstring_16 wValue = - string_cast(value); - #endif - #else - sstring_16 wValue = - string_cast(value); - #endif - auto size = value.length() * sizeof(swchar); - uint8 extra(0); - if(end != NULL) ++extra; - *data = new schar[size + extra]; - #ifdef _WIN32 - #ifdef _UNICODE - memcpy(*data, value.c_str(), size); - #else - memcpy(*data, wValue.c_str(), size); - #endif - #else - memcpy(*data, wValue.c_str(), size); - #endif - if(end != NULL) - { - (*data)[size] = end; - } - return size + extra; - } - - void XMLContainer::SerializeChildren(SerializedData & data, - const dictionary & map) - { - data.size = 2; - auto mapSize = map.size(); - if(mapSize > 0) - { - SerializedData * buffers = new SerializedData[mapSize]; - auto it = map.cbegin(); - auto end = map.cend(); - uint32 counter(0); - - while(it != end) - { - SerializeXMLContainer(buffers[counter], it->second.get()); - data.size += buffers[counter].size; - ++it; - ++counter; - } - - data.data = new schar[data.size]; - counter = 1; // 0th character is SER_START_OF_CHILDREN - - for(uint32 i = 0 ; i < mapSize ; ++i) - { - auto & buffer = buffers[i]; - for(uint32 u = 0 ; u < buffer.size ; ++u) - { - data.data[counter] = buffer.data[u]; - ++counter; - } - delete [] buffer.data; - } - - delete [] buffers; - } - else - { - data.data = new schar[data.size]; - } - data.data[0] = SER_START_OF_CHILDREN; - data.data[data.size - 1] = SER_END_OF_CHILDREN; - } - - - void XMLContainer::SerializeXMLContainer(SerializedData & data, - XMLContainer * container) - { - uint8 n(4); - SerializedData *buffers; - - buffers = new SerializedData[n]; - - buffers[0].size = SerializeString(container->m_Name, - &buffers[0].data, SER_END_OF_NAME_OR_VALUE); - - buffers[1].size = SerializeString(container->m_Value, - &buffers[1].data , SER_END_OF_NAME_OR_VALUE); - - SerializeAttributes(data, container->m_Attributes); - buffers[2].size = data.size; - buffers[2].data = data.data; - - SerializeChildren(data, container->m_MultiMap); - buffers[3].size= data.size; - buffers[3].data = data.data; - - data.size = buffers[0].size + - buffers[1].size + buffers[2].size - + buffers[3].size + 2; - - data.data = new schar[data.size]; - uint32 c(1); // 0th character is SER_START_OF_CHILD - data.data[0] = SER_START_OF_CHILD; - data.data[data.size-1] = SER_END_OF_CHILD; - - for(uint32 i = 0 ; i < n ; ++i) - { - for(uint32 u = 0 ; u < buffers[i].size ; ++u) - { - data.data[c] = buffers[i].data[u]; - ++c; - } - delete [] buffers[i].data; - } - - delete [] buffers; - } - - void XMLContainer::SerializeAttributes(SerializedData & data, - const Dictionary & container) - { - data.size = 2; - auto it = container.cbegin(); - auto end = container.cend(); - - SerializedData ** buffers; - auto cSize = container.size(); - buffers = new SerializedData*[cSize]; - - uint32 i(0); - while(it != end) - { - buffers[i] = new SerializedData[2]; - - buffers[i][0].size = SerializeString(it->first, - &buffers[i][0].data, SER_END_OF_NAME_OR_VALUE); - buffers[i][1].size = SerializeString(it->second, - &buffers[i][1].data, SER_END_OF_NAME_OR_VALUE); - - data.size += buffers[i][0].size + buffers[i][1].size; - - ++it; - ++i; - } - - data.data = new schar[data.size]; - uint32 c(1); - - data.data[0] = SER_START_OF_ATTRIBUTES; - data.data[data.size-1] = SER_END_OF_ATTRIBUTES; - - for(i = 0 ; i < cSize ; ++i) - { - for(uint32 u = 0 ; u < 2 ; ++u) - { - for(uint32 t = 0 ; t < buffers[i][u].size ; ++t) - { - data.data[c] = buffers[i][u].data[t]; - ++c; - } - delete [] buffers[i][u].data; - } - delete [] buffers[i]; - } - delete [] buffers; - } - - void XMLContainer::DeserializeString( - SerializedData & data, uint32 & counter, tstring & str) - { - sstring buffer; - schar c; - uint32 size(0); - - do - { - c = data.data[counter]; - buffer += c; - ++size; - ++counter; - } while(c != SER_END_OF_NAME_OR_VALUE); - - --size; - -#ifdef _WIN32 - #ifdef _UNICODE - str.clear(); - str.resize(size / sizeof(tchar)); - memcpy(&str[0], &buffer[0], size); - #else - swstring stringBuffer; - stringBuffer.resize(size / sizeof(swchar)); - memcpy(&stringBuffer[0], &buffer[0], size); - str = string_cast(stringBuffer); - #endif -#else - sstring_16 stringBuffer; - stringBuffer.resize(size / sizeof(schar_16)); - memcpy(&stringBuffer[0], &buffer[0], size); - str = string_cast(stringBuffer); -#endif - } - - void XMLContainer::DeserializeAttributes(SerializedData & data, uint32 & counter, - Dictionary & container) - { - while(data.data[counter] != SER_START_OF_ATTRIBUTES) - { - ++counter; - } - ++counter; - bool isValue(false); - tstring name,value; - while(data.data[counter] != SER_END_OF_ATTRIBUTES) - { - if(!isValue) - { - DeserializeString(data, counter, name); - isValue = true; - } - else - { - DeserializeString(data, counter, value); - container.insert(std::pair(name, value)); - isValue = false; - } - } - } - - void XMLContainer::DeserializeChildren(SerializedData & data, uint32 & counter, - dictionary & map) - { - while(data.data[counter] != SER_START_OF_CHILDREN) - { - ++counter; - } - ++counter; - bool isValue(false); - tstring name,value; - while(data.data[counter] != SER_END_OF_CHILDREN) - { - while(data.data[counter] != SER_START_OF_CHILD) - { - if(data.data[counter] == SER_END_OF_CHILDREN) - { - ++counter; - return; - } - ++counter; - } - ++counter; - XMLContainer * container = new XMLContainer(); - DeserializeXMLContainer(data, counter, container); - map.insert(dkv_pair(container->GetName(), std::shared_ptr(container))); - while(data.data[counter] != SER_END_OF_CHILD) - { - ++counter; - } - ++counter; - } - } - - void XMLContainer::DeserializeXMLContainer(SerializedData & data, uint32 & counter, - XMLContainer * container) - { - DeserializeString(data, counter, container->m_Name); - DeserializeString(data, counter, container->m_Value); - DeserializeAttributes(data, counter, container->m_Attributes); - DeserializeChildren(data, counter, container->m_MultiMap); - } -} +#include "XMLContainer.h" +#include "../Helpers/Helpers.h" +#include "../Logger.h" + +namespace star +{ + XMLContainer::XMLContainer() + : Dictionary>() + { + + } + + XMLContainer::XMLContainer(const XMLContainer & yRef) + : Dictionary>(yRef) + , m_Value(yRef.m_Value) + , m_Name(yRef.m_Name) + , m_Attributes(yRef.m_Attributes) + { + + } + + XMLContainer::XMLContainer(XMLContainer && yRef) + : Dictionary>(yRef) + , m_Value(yRef.m_Value) + , m_Name(yRef.m_Name) + , m_Attributes(yRef.m_Attributes) + { + + } + + XMLContainer::~XMLContainer() + { + m_Attributes.clear(); + } + + XMLContainer & XMLContainer::operator=(const XMLContainer & yRef) + { + m_MultiMap = yRef.m_MultiMap; + m_Value = yRef.m_Value; + m_Name = yRef.m_Name; + m_Attributes = yRef.m_Attributes; + return *this; + } + + XMLContainer & XMLContainer::operator=(XMLContainer && yRef) + { + m_MultiMap = yRef.m_MultiMap; + m_Value = yRef.m_Value; + m_Name = yRef.m_Name; + m_Attributes = yRef.m_Attributes; + return *this; + } + + Dictionary & XMLContainer::GetAttributes() + { + return m_Attributes; + } + + const tstring & XMLContainer::GetValue() const + { + return m_Value; + } + + const tstring & XMLContainer::GetName() const + { + return m_Name; + } + + void XMLContainer::SetValue(const tstring & value) + { + m_Value = value; + } + + void XMLContainer::SetName(const tstring & name) + { + m_Name = name; + } + + void XMLContainer::clear() + { + Dictionary>::clear(); + m_Value = _T(""); + m_Attributes.clear(); + } + + void XMLContainer::swap(XMLContainer & yRef) + { + Dictionary>::swap(yRef); + m_Value = yRef.m_Value; + m_Attributes.swap(yRef.m_Attributes); + } + + void XMLContainer::AddChild(const tstring & name) + { + auto container = std::make_shared(); + container->SetName(name); + m_MultiMap.insert( + std::pair>( + name, container + ) + ); + } + + void XMLContainer::AddChild(const tstring & name, const tstring & value) + { + auto container = std::make_shared(); + container->SetName(name); + container->SetValue(value); + m_MultiMap.insert( + std::pair>( + name, container + ) + ); + } + + void XMLContainer::Serialize(const tstring & file, DirectoryMode mode) + { + SerializedData data; + SerializeXMLContainer(data, this); + WriteBinaryFile(file, data.data, data.size, mode); + delete [] data.data; + } + + void XMLContainer::Deserialize(const tstring & file, DirectoryMode mode) + { + clear(); + + SerializedData buffer; + buffer.data = ReadBinaryFile(file, buffer.size, mode); + uint32 counter(1); // first byte == SER_START_OF_CHILD + DeserializeXMLContainer(buffer, counter, this); + + delete [] buffer.data; + } + + bool XMLContainer::DeserializeSafe(const tstring & file, DirectoryMode mode) + { + clear(); + + SerializedData buffer; + bool result = ReadBinaryFileSafe(file, buffer.data, buffer.size, mode); + + if(result) + { + uint32 counter(1); // first byte == SER_START_OF_CHILD + DeserializeXMLContainer(buffer, counter, this); + delete [] buffer.data; + } + else + { + LOG(LogLevel::Warning, + _T("XMLContainer::DeserializeSafe: Couldn't read file '") + + file + _T("'."), STARENGINE_LOG_TAG); + } + + return result; + } + + uint32 XMLContainer::SerializeString( + const tstring & value, schar ** data, schar end) + { + #ifdef _WIN32 + #ifndef _UNICODE + sstring_16 wValue = + string_cast(value); + #endif + #elif defined(ANDROID) + sstring_16 wValue = + string_cast(value); + #endif + auto size = value.length() * sizeof(swchar); + uint8 extra(0); + if(end != NULL) ++extra; + *data = new schar[size + extra]; + #ifdef _WIN32 + #ifdef _UNICODE + memcpy(*data, value.c_str(), size); + #else + memcpy(*data, wValue.c_str(), size); + #endif + #elif defined(ANDROID) + memcpy(*data, wValue.c_str(), size); + #endif + if(end != NULL) + { + (*data)[size] = end; + } + return size + extra; + } + + void XMLContainer::SerializeChildren(SerializedData & data, + const dictionary & map) + { + data.size = 2; + auto mapSize = map.size(); + if(mapSize > 0) + { + SerializedData * buffers = new SerializedData[mapSize]; + auto it = map.cbegin(); + auto end = map.cend(); + uint32 counter(0); + + while(it != end) + { + SerializeXMLContainer(buffers[counter], it->second.get()); + data.size += buffers[counter].size; + ++it; + ++counter; + } + + data.data = new schar[data.size]; + counter = 1; // 0th character is SER_START_OF_CHILDREN + + for(uint32 i = 0 ; i < mapSize ; ++i) + { + auto & buffer = buffers[i]; + for(uint32 u = 0 ; u < buffer.size ; ++u) + { + data.data[counter] = buffer.data[u]; + ++counter; + } + delete [] buffer.data; + } + + delete [] buffers; + } + else + { + data.data = new schar[data.size]; + } + data.data[0] = SER_START_OF_CHILDREN; + data.data[data.size - 1] = SER_END_OF_CHILDREN; + } + + + void XMLContainer::SerializeXMLContainer(SerializedData & data, + XMLContainer * container) + { + uint8 n(4); + SerializedData *buffers; + + buffers = new SerializedData[n]; + + buffers[0].size = SerializeString(container->m_Name, + &buffers[0].data, SER_END_OF_NAME_OR_VALUE); + + buffers[1].size = SerializeString(container->m_Value, + &buffers[1].data , SER_END_OF_NAME_OR_VALUE); + + SerializeAttributes(data, container->m_Attributes); + buffers[2].size = data.size; + buffers[2].data = data.data; + + SerializeChildren(data, container->m_MultiMap); + buffers[3].size= data.size; + buffers[3].data = data.data; + + data.size = buffers[0].size + + buffers[1].size + buffers[2].size + + buffers[3].size + 2; + + data.data = new schar[data.size]; + uint32 c(1); // 0th character is SER_START_OF_CHILD + data.data[0] = SER_START_OF_CHILD; + data.data[data.size-1] = SER_END_OF_CHILD; + + for(uint32 i = 0 ; i < n ; ++i) + { + for(uint32 u = 0 ; u < buffers[i].size ; ++u) + { + data.data[c] = buffers[i].data[u]; + ++c; + } + delete [] buffers[i].data; + } + + delete [] buffers; + } + + void XMLContainer::SerializeAttributes(SerializedData & data, + const Dictionary & container) + { + data.size = 2; + auto it = container.cbegin(); + auto end = container.cend(); + + SerializedData ** buffers; + auto cSize = container.size(); + buffers = new SerializedData*[cSize]; + + uint32 i(0); + while(it != end) + { + buffers[i] = new SerializedData[2]; + + buffers[i][0].size = SerializeString(it->first, + &buffers[i][0].data, SER_END_OF_NAME_OR_VALUE); + buffers[i][1].size = SerializeString(it->second, + &buffers[i][1].data, SER_END_OF_NAME_OR_VALUE); + + data.size += buffers[i][0].size + buffers[i][1].size; + + ++it; + ++i; + } + + data.data = new schar[data.size]; + uint32 c(1); + + data.data[0] = SER_START_OF_ATTRIBUTES; + data.data[data.size-1] = SER_END_OF_ATTRIBUTES; + + for(i = 0 ; i < cSize ; ++i) + { + for(uint32 u = 0 ; u < 2 ; ++u) + { + for(uint32 t = 0 ; t < buffers[i][u].size ; ++t) + { + data.data[c] = buffers[i][u].data[t]; + ++c; + } + delete [] buffers[i][u].data; + } + delete [] buffers[i]; + } + delete [] buffers; + } + + void XMLContainer::DeserializeString( + SerializedData & data, uint32 & counter, tstring & str) + { + sstring buffer; + schar c; + uint32 size(0); + + do + { + c = data.data[counter]; + buffer += c; + ++size; + ++counter; + } while(c != SER_END_OF_NAME_OR_VALUE); + + --size; + +#ifdef _WIN32 + #ifdef _UNICODE + str.clear(); + str.resize(size / sizeof(tchar)); + memcpy(&str[0], &buffer[0], size); + #else + swstring stringBuffer; + stringBuffer.resize(size / sizeof(swchar)); + memcpy(&stringBuffer[0], &buffer[0], size); + str = string_cast(stringBuffer); + #endif +#elif defined(ANDROID) + sstring_16 stringBuffer; + stringBuffer.resize(size / sizeof(schar_16)); + memcpy(&stringBuffer[0], &buffer[0], size); + str = string_cast(stringBuffer); +#endif + } + + void XMLContainer::DeserializeAttributes(SerializedData & data, uint32 & counter, + Dictionary & container) + { + while(data.data[counter] != SER_START_OF_ATTRIBUTES) + { + ++counter; + } + ++counter; + bool isValue(false); + tstring name,value; + while(data.data[counter] != SER_END_OF_ATTRIBUTES) + { + if(!isValue) + { + DeserializeString(data, counter, name); + isValue = true; + } + else + { + DeserializeString(data, counter, value); + container.insert(std::pair(name, value)); + isValue = false; + } + } + } + + void XMLContainer::DeserializeChildren(SerializedData & data, uint32 & counter, + dictionary & map) + { + while(data.data[counter] != SER_START_OF_CHILDREN) + { + ++counter; + } + ++counter; + bool isValue(false); + tstring name,value; + while(data.data[counter] != SER_END_OF_CHILDREN) + { + while(data.data[counter] != SER_START_OF_CHILD) + { + if(data.data[counter] == SER_END_OF_CHILDREN) + { + ++counter; + return; + } + ++counter; + } + ++counter; + XMLContainer * container = new XMLContainer(); + DeserializeXMLContainer(data, counter, container); + map.insert(dkv_pair(container->GetName(), std::shared_ptr(container))); + while(data.data[counter] != SER_END_OF_CHILD) + { + ++counter; + } + ++counter; + } + } + + void XMLContainer::DeserializeXMLContainer(SerializedData & data, uint32 & counter, + XMLContainer * container) + { + DeserializeString(data, counter, container->m_Name); + DeserializeString(data, counter, container->m_Value); + DeserializeAttributes(data, counter, container->m_Attributes); + DeserializeChildren(data, counter, container->m_MultiMap); + } +} diff --git a/src/Input/XMLFileParser.cpp b/src/Input/XMLFileParser.cpp index 5c9791a..ba51e23 100755 --- a/src/Input/XMLFileParser.cpp +++ b/src/Input/XMLFileParser.cpp @@ -1,10 +1,10 @@ #include "XMLFileParser.h" -#include "PugiXML\src\pugixml.hpp" -#include "PugiXML\src\pugiconfig.hpp" +#include "PugiXML/src/pugixml.hpp" +#include "PugiXML/src/pugiconfig.hpp" #include "XMLContainer.h" #include "XMLFileSerializer.h" -#include "..\Helpers\Helpers.h" -#include "..\Logger.h" +#include "../Helpers/Helpers.h" +#include "../Logger.h" #ifdef ANDROID #include "../Helpers/HelpersAndroid.h" diff --git a/src/Input/XMLFileParser.h b/src/Input/XMLFileParser.h index 7b7a42d..bb44ebc 100755 --- a/src/Input/XMLFileParser.h +++ b/src/Input/XMLFileParser.h @@ -1,7 +1,7 @@ #pragma once -#include "..\Helpers\FilePath.h" -#include "..\defines.h" +#include "../Helpers/Filepath.h" +#include "../defines.h" namespace pugi { diff --git a/src/Input/XMLFileSerializer.cpp b/src/Input/XMLFileSerializer.cpp index c515035..65c853b 100755 --- a/src/Input/XMLFileSerializer.cpp +++ b/src/Input/XMLFileSerializer.cpp @@ -1,5 +1,5 @@ #include "XMLFileSerializer.h" -#include "..\Helpers\Helpers.h" +#include "../Helpers/Helpers.h" #include "XMLContainer.h" namespace star diff --git a/src/Input/XMLFileSerializer.h b/src/Input/XMLFileSerializer.h index adf8718..d99e9c7 100755 --- a/src/Input/XMLFileSerializer.h +++ b/src/Input/XMLFileSerializer.h @@ -1,7 +1,7 @@ #pragma once -#include "..\defines.h" -#include "..\Helpers\FilePath.h" +#include "../defines.h" +#include "../Helpers/Filepath.h" namespace star { diff --git a/src/Logger.cpp b/src/Logger.cpp index afd618d..d00350b 100755 --- a/src/Logger.cpp +++ b/src/Logger.cpp @@ -1,404 +1,431 @@ -#include "Logger.h" - -#ifdef _WIN32 -#include -#include "Console.h" -#elif defined(ANDROID) -#include -#endif -#ifdef DESKTOP -#include -#else -#include -#endif - -#include "Scenes/SceneManager.h" -#include "Helpers/Helpers.h" - -#include "Context.h" -#include "TimeManager.h" -#include "StarEngine.h" - -namespace star -{ - Logger::Logger() - :Singleton() -#ifdef _WIN32 - ,m_ConsoleHandle(nullptr) - ,m_UseConsole(false) - ,m_LogStream() -#else - ,m_LogStream() -#endif - ,m_TimeStamp(_T("00:00:00")) - { - - } - - Logger::~Logger() - { - SaveLogFile(); -#ifdef _WIN32 - if(m_UseConsole) - { - star_w::CleanUpConsole(); - } -#endif - } - -#ifdef _WIN32 - void Logger::Initialize(bool useConsole) - { - m_UseConsole = useConsole; - if(useConsole) - { - star_w::RedirectIOToConsole(); - m_ConsoleHandle = GetStdHandle(STD_OUTPUT_HANDLE); - } -#ifndef NO_LOG_FILE - InitializeLogStream(); -#endif - } -#else - void Logger::Initialize() - { -#ifndef NO_LOG_FILE - InitializeLogStream(); -#endif - } -#endif - - void Logger::Update(const Context& context) - { - m_TimeStamp = context.time->GetTimeStamp(); - } - - void Logger::Log( - LogLevel level, - const tstring& message, - const tstring& tag, - const BreakInformation& breakInfo - ) - { - tstring levelName; - switch(level) - { - case LogLevel::Info : - levelName = _T("INFO"); - break; - case LogLevel::Warning: - levelName = _T("WARNING"); - break; - case LogLevel::Error: - levelName = _T("ERROR"); - break; - case LogLevel::Debug: - levelName = _T("DEBUG"); - break; - } - - PrivateLog(level, message, tag, levelName, breakInfo); - } - - void Logger::Log( - LogLevel level, - const tstring& message, - const BreakInformation& breakInfo - ) - { - Log(level, message, GAME_LOG_TAG, breakInfo); - } - - void Logger::DebugLog( - LogLevel level, - const tstring& message, - const tstring& tag, - const BreakInformation& breakInfo - ) - { - #ifdef _DEBUG - tstring levelName; - switch(level) - { - case LogLevel::Info : - levelName = _T("INFO-D"); - break; - case LogLevel::Warning: - levelName = _T("WARNING-D"); - break; - case LogLevel::Error: - levelName = _T("ERROR-D"); - break; - case LogLevel::Debug: - levelName = _T("DEBUG"); - break; - } - - PrivateLog(level, message, tag, levelName, breakInfo); - #endif - } - - void Logger::DebugLog( - LogLevel level, - const tstring& message, - const BreakInformation& breakInfo - ) - { - #ifdef _DEBUG - DebugLog(level, message, GAME_LOG_TAG, breakInfo); - #endif - } - - void Logger::DebugLog( - const tstring& message, - const tstring& tag, - const BreakInformation& breakInfo - ) - { - #ifdef _DEBUG - DebugLog(LogLevel::Debug, message, tag, breakInfo); - #endif - } - - void Logger::DebugLog( - const tstring& message, - const BreakInformation& breakInfo - ) - { - #ifdef _DEBUG - DebugLog(message, GAME_LOG_TAG, breakInfo); - #endif - } - - void Logger::OpenGLLog(const BreakInformation& breakInfo) - { -#if LOGGER_MIN_LEVEL > 0 - GLenum err(glGetError()); - while(err != GL_NO_ERROR) - { - tstring error; - switch(err) - { - case GL_INVALID_OPERATION: - error = _T("INVALID_OPERATION"); - break; - case GL_INVALID_ENUM: - error = _T("INVALID_ENUM"); - break; - case GL_INVALID_VALUE: - error = _T("INVALID_VALUE"); - break; - case GL_OUT_OF_MEMORY: - error = _T("OUT_OF_MEMORY"); - break; - case GL_INVALID_FRAMEBUFFER_OPERATION: - error = _T("INVALID_FRAMEBUFFER_OPERATION"); - break; - default: - error =_T("UNKNOWN_ERROR"); - break; - } - tstringstream buffer; - buffer << "GL_" << error - << " - " << breakInfo.file << ":" - << breakInfo.line; -#ifndef NO_LOG_FILE - LogMessage(buffer.str()); -#endif - Log(LogLevel::Error, - buffer.str(), _T("OPENGL"), breakInfo); - err = glGetError(); - } -#endif - } - - void Logger::SetLogSaveDelayTime(float32 seconds) - { -#ifndef NO_LOG_FILE - SceneManager::GetInstance()->GetTimerManager()->SetTargetTimeTimer( - _T("STAR_LogSaveFileTimer"), seconds, true, false); - SaveLogFile(); -#endif - } - - void Logger::PrivateLog( - LogLevel level, - const tstring& message, - const tstring& tag, - const tstring& levelName, - const BreakInformation& breakInfo - ) - { -#if LOGGER_MIN_LEVEL > 0 - #ifdef DESKTOP - tstringstream messageBuffer; - messageBuffer << _T("[") << tag - << _T("] ") << _T("[") - << levelName << _T("] ") - << message; - if(breakInfo.line != -1 && tag != STARENGINE_LOG_TAG) - { - messageBuffer << _T(" (L") - << string_cast(breakInfo.line) - << _T("@") << breakInfo.file - << _T(")"); - } - messageBuffer << std::endl; - tstring combinedMessage = messageBuffer.str(); - - if(m_UseConsole) - { - switch(level) - { - case LogLevel::Info : - #if LOGGER_MIN_LEVEL < 2 - SetConsoleTextAttribute( - m_ConsoleHandle, - FOREGROUND_INTENSITY | - FOREGROUND_RED | - FOREGROUND_GREEN | - FOREGROUND_BLUE - ); - #endif - break; - case LogLevel::Warning : - #if LOGGER_MIN_LEVEL < 3 - SetConsoleTextAttribute( - m_ConsoleHandle, - FOREGROUND_INTENSITY | - FOREGROUND_RED | - FOREGROUND_GREEN - ); - #endif - break; - case LogLevel::Error : - #if LOGGER_MIN_LEVEL < 4 - SetConsoleTextAttribute( - m_ConsoleHandle, - FOREGROUND_INTENSITY | - FOREGROUND_RED - ); - #endif - break; - case LogLevel::Debug : - #if LOGGER_MIN_LEVEL < 5 - #ifdef _DEBUG - SetConsoleTextAttribute( - m_ConsoleHandle, - FOREGROUND_INTENSITY | - FOREGROUND_GREEN - ); - #endif - #endif - break; - } - tprintf(combinedMessage.c_str()); - } - else - { - OutputDebugString(combinedMessage.c_str()); - } - #ifndef NO_LOG_FILE - LogMessage(combinedMessage); - #endif - #else - switch(level) - { - case LogLevel::Info: - #if LOGGER_MIN_LEVEL < 2 - __android_log_print( - ANDROID_LOG_INFO, - tag.c_str(), "%s", - message.c_str() - ); - #endif - break; - case LogLevel::Warning: - #if LOGGER_MIN_LEVEL < 3 - __android_log_print( - ANDROID_LOG_WARN, - tag.c_str(), "%s", - message.c_str() - ); - #endif - break; - case LogLevel::Error: - #if LOGGER_MIN_LEVEL < 4 - __android_log_print( - ANDROID_LOG_ERROR, - tag.c_str(), "%s", - message.c_str() - ); - #endif - break; - case LogLevel::Debug: - #if LOGGER_MIN_LEVEL < 5 - #ifdef DEBUG - __android_log_print( - ANDROID_LOG_DEBUG, - tag.c_str(), - message.c_str() - ); - #endif - #endif - break; - } - #ifndef NO_LOG_FILE - tstringstream messageBuffer; - messageBuffer << _T("[") << tag - << _T("] ") << _T("[") - << levelName << _T("] ") - << message << std::endl; - LogMessage(messageBuffer.str()); - #endif - #endif -#endif - } - - void Logger::InitializeLogStream() - { - SceneManager::GetInstance()->GetTimerManager()->CreateTimer( - _T("STAR_LogSaveFileTimer"), 60.0f, - false, true, [&] () { SaveLogFile(); }, false); - - m_LogStream << _T("++++++++++++++++++++++++++++++++++++++\ -++++++++++++++++++++++++++++++++++++++++++++++++++") << std::endl << std::endl; - m_LogStream << _T(" Star Engine version ") - << STARENGINE_VERSION << std::endl - << std::endl; - m_LogStream << _T(" Game is compiled in"); - - #ifdef _DEBUG - m_LogStream << _T(" debug mode.") << std::endl; - #else - m_LogStream << _T(" release mode.") << std::endl; -#endif - #if LOGGER_MIN_LEVEL < 2 - m_LogStream << _T(" All Star::Logging levels are enabled.") << std::endl; - #elif LOGGER_MIN_LEVEL < 3 - m_LogStream << _T(" Star::Logging level info is disabled.") << std::endl; - #elif LOGGER_MIN_LEVEL < 4 - m_LogStream << _T(" Star::Logging levels info and warning is disabled.") << std::endl; - #elif LOGGER_MIN_LEVEL < 5 - m_LogStream << _T(" Star::Logging levels info, warning and error is disabled.") << std::endl; - #elif LOGGER_MIN_LEVEL < 6 - m_LogStream << _T(" All Star::Logging levels are disabled.") << std::endl; - #endif - m_LogStream << std::endl; - m_LogStream << _T(" The Star Engine is licensed under the MIT License.") << std::endl; - m_LogStream << _T(" For more information, go to: \ -http://www.starengine.eu/") << std::endl << std::endl; - m_LogStream << _T("++++++++++++++++++++++++++++++++++\ -++++++++++++++++++++++++++++++++++++++++++++++++++++++") << std::endl << std::endl; - } - - void Logger::LogMessage(const tstring& message) - { - m_LogStream << _T("[") << m_TimeStamp << _T("] ") << message; - } - - void Logger::SaveLogFile() - { - WriteTextFile(_T("StarLog.txt"), m_LogStream.str(), DirectoryMode::internal); - } -} +#include "Logger.h" + +#ifdef _WIN32 +#include +#include "Console.h" +#elif defined(ANDROID) +#include +#endif +#ifdef DESKTOP +#include +#elif defined(ANDROID) +#include +#endif + +#include "Scenes/SceneManager.h" +#include "Helpers/Helpers.h" + +#include "Context.h" +#include "TimeManager.h" +#include "StarEngine.h" + +namespace star +{ + Logger::Logger() + :Singleton() +#ifdef _WIN32 + ,m_ConsoleHandle(nullptr) + ,m_UseConsole(false) + ,m_LogStream() +#elif defined(ANDROID) + ,m_LogStream() +#endif + ,m_TimeStamp(_T("00:00:00")) + { + + } + + Logger::~Logger() + { + SaveLogFile(); +#ifdef _WIN32 + if(m_UseConsole) + { + star_w::CleanUpConsole(); + } +#endif + } + +#ifdef _WIN32 + void Logger::Initialize(bool useConsole) + { + m_UseConsole = useConsole; + if(useConsole) + { + star_w::RedirectIOToConsole(); + m_ConsoleHandle = GetStdHandle(STD_OUTPUT_HANDLE); + } +#ifndef NO_LOG_FILE + InitializeLogStream(); +#endif + } +#elif defined(ANDROID) + void Logger::Initialize() + { +#ifndef NO_LOG_FILE + InitializeLogStream(); +#endif + } +#else + // Linux / other platforms + void Logger::Initialize() + { +#ifndef NO_LOG_FILE + InitializeLogStream(); +#endif + } +#endif + + void Logger::Update(const Context& context) + { + m_TimeStamp = context.time->GetTimeStamp(); + } + + void Logger::Log( + LogLevel level, + const tstring& message, + const tstring& tag, + const BreakInformation& breakInfo + ) + { + tstring levelName; + switch(level) + { + case LogLevel::Info : + levelName = _T("INFO"); + break; + case LogLevel::Warning: + levelName = _T("WARNING"); + break; + case LogLevel::Error: + levelName = _T("ERROR"); + break; + case LogLevel::Debug: + levelName = _T("DEBUG"); + break; + } + + PrivateLog(level, message, tag, levelName, breakInfo); + } + + void Logger::Log( + LogLevel level, + const tstring& message, + const BreakInformation& breakInfo + ) + { + Log(level, message, GAME_LOG_TAG, breakInfo); + } + + void Logger::DebugLog( + LogLevel level, + const tstring& message, + const tstring& tag, + const BreakInformation& breakInfo + ) + { + #ifdef _DEBUG + tstring levelName; + switch(level) + { + case LogLevel::Info : + levelName = _T("INFO-D"); + break; + case LogLevel::Warning: + levelName = _T("WARNING-D"); + break; + case LogLevel::Error: + levelName = _T("ERROR-D"); + break; + case LogLevel::Debug: + levelName = _T("DEBUG"); + break; + } + + PrivateLog(level, message, tag, levelName, breakInfo); + #endif + } + + void Logger::DebugLog( + LogLevel level, + const tstring& message, + const BreakInformation& breakInfo + ) + { + #ifdef _DEBUG + DebugLog(level, message, GAME_LOG_TAG, breakInfo); + #endif + } + + void Logger::DebugLog( + const tstring& message, + const tstring& tag, + const BreakInformation& breakInfo + ) + { + #ifdef _DEBUG + DebugLog(LogLevel::Debug, message, tag, breakInfo); + #endif + } + + void Logger::DebugLog( + const tstring& message, + const BreakInformation& breakInfo + ) + { + #ifdef _DEBUG + DebugLog(message, GAME_LOG_TAG, breakInfo); + #endif + } + + void Logger::OpenGLLog(const BreakInformation& breakInfo) + { +#if LOGGER_MIN_LEVEL > 0 + GLenum err(glGetError()); + while(err != GL_NO_ERROR) + { + tstring error; + switch(err) + { + case GL_INVALID_OPERATION: + error = _T("INVALID_OPERATION"); + break; + case GL_INVALID_ENUM: + error = _T("INVALID_ENUM"); + break; + case GL_INVALID_VALUE: + error = _T("INVALID_VALUE"); + break; + case GL_OUT_OF_MEMORY: + error = _T("OUT_OF_MEMORY"); + break; + case GL_INVALID_FRAMEBUFFER_OPERATION: + error = _T("INVALID_FRAMEBUFFER_OPERATION"); + break; + default: + error =_T("UNKNOWN_ERROR"); + break; + } + tstringstream buffer; + buffer << "GL_" << error + << " - " << breakInfo.file << ":" + << breakInfo.line; +#ifndef NO_LOG_FILE + LogMessage(buffer.str()); +#endif + Log(LogLevel::Error, + buffer.str(), _T("OPENGL"), breakInfo); + err = glGetError(); + } +#endif + } + + void Logger::SetLogSaveDelayTime(float32 seconds) + { +#ifndef NO_LOG_FILE + SceneManager::GetInstance()->GetTimerManager()->SetTargetTimeTimer( + _T("STAR_LogSaveFileTimer"), seconds, true, false); + SaveLogFile(); +#endif + } + + void Logger::PrivateLog( + LogLevel level, + const tstring& message, + const tstring& tag, + const tstring& levelName, + const BreakInformation& breakInfo + ) + { +#if LOGGER_MIN_LEVEL > 0 + #ifdef _WIN32 + tstringstream messageBuffer; + messageBuffer << _T("[") << tag + << _T("] ") << _T("[") + << levelName << _T("] ") + << message; + if(breakInfo.line != -1 && tag != STARENGINE_LOG_TAG) + { + messageBuffer << _T(" (L") + << string_cast(breakInfo.line) + << _T("@") << breakInfo.file + << _T(")"); + } + messageBuffer << std::endl; + tstring combinedMessage = messageBuffer.str(); + + if(m_UseConsole) + { + switch(level) + { + case LogLevel::Info : + #if LOGGER_MIN_LEVEL < 2 + SetConsoleTextAttribute( + m_ConsoleHandle, + FOREGROUND_INTENSITY | + FOREGROUND_RED | + FOREGROUND_GREEN | + FOREGROUND_BLUE + ); + #endif + break; + case LogLevel::Warning : + #if LOGGER_MIN_LEVEL < 3 + SetConsoleTextAttribute( + m_ConsoleHandle, + FOREGROUND_INTENSITY | + FOREGROUND_RED | + FOREGROUND_GREEN + ); + #endif + break; + case LogLevel::Error : + #if LOGGER_MIN_LEVEL < 4 + SetConsoleTextAttribute( + m_ConsoleHandle, + FOREGROUND_INTENSITY | + FOREGROUND_RED + ); + #endif + break; + case LogLevel::Debug : + #if LOGGER_MIN_LEVEL < 5 + #ifdef _DEBUG + SetConsoleTextAttribute( + m_ConsoleHandle, + FOREGROUND_INTENSITY | + FOREGROUND_GREEN + ); + #endif + #endif + break; + } + tprintf(combinedMessage.c_str()); + } + else + { + OutputDebugString(combinedMessage.c_str()); + } + #ifndef NO_LOG_FILE + LogMessage(combinedMessage); + #endif + #elif defined(ANDROID) + switch(level) + { + case LogLevel::Info: + #if LOGGER_MIN_LEVEL < 2 + __android_log_print( + ANDROID_LOG_INFO, + tag.c_str(), "%s", + message.c_str() + ); + #endif + break; + case LogLevel::Warning: + #if LOGGER_MIN_LEVEL < 3 + __android_log_print( + ANDROID_LOG_WARN, + tag.c_str(), "%s", + message.c_str() + ); + #endif + break; + case LogLevel::Error: + #if LOGGER_MIN_LEVEL < 4 + __android_log_print( + ANDROID_LOG_ERROR, + tag.c_str(), "%s", + message.c_str() + ); + #endif + break; + case LogLevel::Debug: + #if LOGGER_MIN_LEVEL < 5 + #ifdef DEBUG + __android_log_print( + ANDROID_LOG_DEBUG, + tag.c_str(), + message.c_str() + ); + #endif + #endif + break; + } + #ifndef NO_LOG_FILE + tstringstream messageBuffer; + messageBuffer << _T("[") << tag + << _T("] ") << _T("[") + << levelName << _T("] ") + << message << std::endl; + LogMessage(messageBuffer.str()); + #endif + #else + // Linux / other platforms: output to stderr + tstringstream messageBuffer; + messageBuffer << _T("[") << tag + << _T("] ") << _T("[") + << levelName << _T("] ") + << message; + if(breakInfo.line != -1 && tag != STARENGINE_LOG_TAG) + { + messageBuffer << _T(" (L") + << string_cast(breakInfo.line) + << _T("@") << breakInfo.file + << _T(")"); + } + messageBuffer << std::endl; + std::cerr << messageBuffer.str(); + #ifndef NO_LOG_FILE + LogMessage(messageBuffer.str()); + #endif + #endif +#endif + } + + void Logger::InitializeLogStream() + { + SceneManager::GetInstance()->GetTimerManager()->CreateTimer( + _T("STAR_LogSaveFileTimer"), 60.0f, + false, true, [&] () { SaveLogFile(); }, false); + + m_LogStream << _T("++++++++++++++++++++++++++++++++++++++\ +++++++++++++++++++++++++++++++++++++++++++++++++++") << std::endl << std::endl; + m_LogStream << _T(" Star Engine version ") + << STARENGINE_VERSION << std::endl + << std::endl; + m_LogStream << _T(" Game is compiled in"); + + #ifdef _DEBUG + m_LogStream << _T(" debug mode.") << std::endl; + #else + m_LogStream << _T(" release mode.") << std::endl; +#endif + #if LOGGER_MIN_LEVEL < 2 + m_LogStream << _T(" All Star::Logging levels are enabled.") << std::endl; + #elif LOGGER_MIN_LEVEL < 3 + m_LogStream << _T(" Star::Logging level info is disabled.") << std::endl; + #elif LOGGER_MIN_LEVEL < 4 + m_LogStream << _T(" Star::Logging levels info and warning is disabled.") << std::endl; + #elif LOGGER_MIN_LEVEL < 5 + m_LogStream << _T(" Star::Logging levels info, warning and error is disabled.") << std::endl; + #elif LOGGER_MIN_LEVEL < 6 + m_LogStream << _T(" All Star::Logging levels are disabled.") << std::endl; + #endif + m_LogStream << std::endl; + m_LogStream << _T(" The Star Engine is licensed under the MIT License.") << std::endl; + m_LogStream << _T(" For more information, go to: \ +http://www.starengine.eu/") << std::endl << std::endl; + m_LogStream << _T("++++++++++++++++++++++++++++++++++\ +++++++++++++++++++++++++++++++++++++++++++++++++++++++") << std::endl << std::endl; + } + + void Logger::LogMessage(const tstring& message) + { + m_LogStream << _T("[") << m_TimeStamp << _T("] ") << message; + } + + void Logger::SaveLogFile() + { + WriteTextFile(_T("StarLog.txt"), m_LogStream.str(), DirectoryMode::internal); + } +} diff --git a/src/Logger.h b/src/Logger.h index 9da5edf..d9c90a5 100755 --- a/src/Logger.h +++ b/src/Logger.h @@ -1,141 +1,141 @@ -#pragma once - -#include "defines.h" -#include "Helpers/Singleton.h" - -namespace star -{ - enum LogLevel : byte - { - Info, - Warning, - Error, - Debug - }; - - struct Context; - - class Logger final : public Singleton - { - public: - friend Singleton; - -#ifdef _WIN32 - void Initialize(bool useConsole); -#else - void Initialize(); -#endif - void Update(const Context & context); - - void Log( - LogLevel level, - const tstring& message, - const tstring& tag, - const BreakInformation& breakInfo = BreakInformation() - ); - void Log( - LogLevel level, - const tstring& message, - const BreakInformation& breakInfo = BreakInformation() - ); - - void DebugLog( - LogLevel level, - const tstring& message, - const tstring& tag, - const BreakInformation& breakInfo = BreakInformation() - ); - void DebugLog( - LogLevel level, - const tstring& message, - const BreakInformation& breakInfo = BreakInformation() - ); - - void DebugLog( - const tstring& message, - const tstring& tag, - const BreakInformation& breakInfo = BreakInformation() - ); - void DebugLog( - const tstring& message, - const BreakInformation& breakInfo = BreakInformation() - ); - - void OpenGLLog( - const BreakInformation& breakInfo - ); - - void SetLogSaveDelayTime(float32 seconds); - - private: - Logger(); - ~Logger(); - - void PrivateLog( - LogLevel level, - const tstring& message, - const tstring& tag, - const tstring& levelName, - const BreakInformation& breakInfo - ); - - void InitializeLogStream(); - void LogMessage(const tstring& message); - void SaveLogFile(); - - #ifdef _WIN32 - bool m_UseConsole; - HANDLE m_ConsoleHandle; - #endif - - tstringstream m_LogStream; - tstring m_TimeStamp; - - Logger(const Logger& t); - Logger(Logger&& t); - Logger& operator=(const Logger& t); - Logger& operator=(Logger&& t); - }; -} - -#define LOG(...) \ - star::Logger::GetInstance()->Log( \ - __VA_ARGS__, \ - BREAK_INFO() \ - ) - -#ifdef _DEBUG - #define X_ASSERT_LOG_BREAK __asm { int 3 } -#else - #define X_ASSERT_LOG_BREAK -#endif - -#define ASSERT_LOG \ - if ( false ) {} \ - else \ - struct LocalAssertLog { \ - int32 mLine; \ - LocalAssertLog(int32 line=__LINE__) : mLine(line) {} \ - LocalAssertLog(bool isOK, const tstring& message, \ - const tstring& tag = GAME_LOG_TAG) : mLine(0) { \ - if ( !isOK ) { \ - LocalAssertLog info; \ - star::Logger::GetInstance()->Log( \ - star::LogLevel::Error, message, tag, \ - BreakInformation(info.mLine, __FILE__)); \ - X_ASSERT_LOG_BREAK \ - } \ - } \ - } myAssertLogger = LocalAssertLog - -#ifdef _DEBUG - #define DEBUG_LOG(...) \ - star::Logger::GetInstance()->DebugLog( \ - ##__VA_ARGS__, \ - BREAK_INFO() \ - ) -#else - #define DEBUG_LOG(...) ((void)0) -#endif - #define OPENGL_LOG() \ - star::Logger::GetInstance()->OpenGLLog(BREAK_INFO()); +#pragma once + +#include "defines.h" +#include "Helpers/Singleton.h" + +namespace star +{ + enum LogLevel : byte + { + Info, + Warning, + Error, + Debug + }; + + struct Context; + + class Logger final : public Singleton + { + public: + friend Singleton; + +#ifdef _WIN32 + void Initialize(bool useConsole); +#else + void Initialize(); +#endif + void Update(const Context & context); + + void Log( + LogLevel level, + const tstring& message, + const tstring& tag, + const BreakInformation& breakInfo = BreakInformation() + ); + void Log( + LogLevel level, + const tstring& message, + const BreakInformation& breakInfo = BreakInformation() + ); + + void DebugLog( + LogLevel level, + const tstring& message, + const tstring& tag, + const BreakInformation& breakInfo = BreakInformation() + ); + void DebugLog( + LogLevel level, + const tstring& message, + const BreakInformation& breakInfo = BreakInformation() + ); + + void DebugLog( + const tstring& message, + const tstring& tag, + const BreakInformation& breakInfo = BreakInformation() + ); + void DebugLog( + const tstring& message, + const BreakInformation& breakInfo = BreakInformation() + ); + + void OpenGLLog( + const BreakInformation& breakInfo + ); + + void SetLogSaveDelayTime(float32 seconds); + + private: + Logger(); + ~Logger(); + + void PrivateLog( + LogLevel level, + const tstring& message, + const tstring& tag, + const tstring& levelName, + const BreakInformation& breakInfo + ); + + void InitializeLogStream(); + void LogMessage(const tstring& message); + void SaveLogFile(); + + #ifdef _WIN32 + bool m_UseConsole; + HANDLE m_ConsoleHandle; + #endif + + tstringstream m_LogStream; + tstring m_TimeStamp; + + Logger(const Logger& t); + Logger(Logger&& t); + Logger& operator=(const Logger& t); + Logger& operator=(Logger&& t); + }; +} + +#define LOG(...) \ + star::Logger::GetInstance()->Log( \ + __VA_ARGS__, \ + BREAK_INFO() \ + ) + +#ifdef _DEBUG + #define X_ASSERT_LOG_BREAK __asm { int 3 } +#else + #define X_ASSERT_LOG_BREAK +#endif + +#define ASSERT_LOG \ + if ( false ) {} \ + else \ + struct LocalAssertLog { \ + int32 mLine; \ + LocalAssertLog(int32 line=__LINE__) : mLine(line) {} \ + LocalAssertLog(bool isOK, const tstring& message, \ + const tstring& tag = GAME_LOG_TAG) : mLine(0) { \ + if ( !isOK ) { \ + LocalAssertLog info; \ + star::Logger::GetInstance()->Log( \ + star::LogLevel::Error, message, tag, \ + BreakInformation(info.mLine, __FILE__)); \ + X_ASSERT_LOG_BREAK \ + } \ + } \ + } myAssertLogger = LocalAssertLog + +#ifdef _DEBUG + #define DEBUG_LOG(...) \ + star::Logger::GetInstance()->DebugLog( \ + ##__VA_ARGS__, \ + BREAK_INFO() \ + ) +#else + #define DEBUG_LOG(...) ((void)0) +#endif + #define OPENGL_LOG() \ + star::Logger::GetInstance()->OpenGLLog(BREAK_INFO()); diff --git a/src/Objects/FreeCamera.cpp b/src/Objects/FreeCamera.cpp index 87008ea..f72288a 100755 --- a/src/Objects/FreeCamera.cpp +++ b/src/Objects/FreeCamera.cpp @@ -56,7 +56,7 @@ namespace star vec3 move = vec3(0,0,0); vec2 look = vec2(0,0); -#ifdef DESKTOP +#ifdef _WIN32 if(!m_bisStatic) { move.y = InputManager::GetInstance()->IsKeyboardKeyDown('Z') ? 1.0f : 0.0f; diff --git a/src/Platforms/Windows/Window.cpp b/src/Platforms/Windows/Window.cpp index eb2060e..4a9cbe6 100755 --- a/src/Platforms/Windows/Window.cpp +++ b/src/Platforms/Windows/Window.cpp @@ -8,7 +8,7 @@ #include "jni/Logger.h" #include "jni/TimeManager.h" #include "jni/Helpers/Helpers.h" -#include "jni/Helpers/FilePath.h" +#include "jni/Helpers/Filepath.h" #include "jni/Input/XMLContainer.h" #ifdef _DEBUG #include "jni/Input/XMLFileParser.h" diff --git a/src/Scenes/SlideScene.cpp b/src/Scenes/SlideScene.cpp index edac8d2..a42929c 100755 --- a/src/Scenes/SlideScene.cpp +++ b/src/Scenes/SlideScene.cpp @@ -48,7 +48,7 @@ namespace star void SlideScene::Update(const star::Context& context) { if( (m_AllowFingerInput && InputManager::GetInstance()->IsFingerReleasedCP(0)) - #ifdef DESKTOP + #ifdef _WIN32 || (m_AllowKeyboardInput && InputManager::GetInstance()->IsAnyKeyDown()) #endif ) diff --git a/src/Sound/AudioManager.cpp b/src/Sound/AudioManager.cpp index 4c4a47b..f11656a 100755 --- a/src/Sound/AudioManager.cpp +++ b/src/Sound/AudioManager.cpp @@ -1,1564 +1,1564 @@ -#include "AudioManager.h" -#include "../Logger.h" -#include "../Helpers/Helpers.h" -#include "../Helpers/Math.h" - -#ifdef ANDROID -#include "../Graphics/Resource.h" -#endif - -namespace star -{ - bool AudioManager::mbIsInitialized = false; - - AudioManager::AudioManager() - : Singleton() - , mMusicList() - , mMusicPathList() - , mEffectsList() - , mSoundEffectPathList() - , mBackgroundQueue() - , mQueueIterator() - , mChannels() - , mEmptyChannel() - , mCurrentSoundFile(nullptr) - , mCurrentSoundEffect(nullptr) - , mVolume(1.0f) - , mbMusicMuted(false) - , mbEffectsMuted(false) -#ifdef ANDROID - , mEngineObj(nullptr) - , mEngine(nullptr) - , mOutputMixObj(nullptr) - , mOutputMixVolume(nullptr) -#endif - { - mQueueIterator = mBackgroundQueue.begin(); - } - - AudioManager::~AudioManager() - { - for(auto & music : mMusicList) - { - delete music.second; - } - - mMusicList.clear(); - - for(auto & effect : mEffectsList) - { - delete effect.second; - } - - mEffectsList.clear(); - - mChannels.clear(); - } - - void AudioManager::Start() - { - if(mbIsInitialized) - { - return; - } - - mbIsInitialized = true; - LOG(LogLevel::Info, - _T("AudioManager::Start: Started making Audio Engine"), STARENGINE_LOG_TAG); - -#ifdef DESKTOP - int32 audio_rate(44100); - uint16 audio_format(MIX_DEFAULT_FORMAT); - int32 audio_channels(2); - int32 audio_buffers(4096); - - SDL_Init(SDL_INIT_AUDIO); - int32 flags = MIX_INIT_OGG | MIX_INIT_MP3; - int32 innited = Mix_Init(flags); - if((innited & flags) != flags) - { - LOG(LogLevel::Info, - _T("AudioManager::Start: Could not init Ogg and Mp3, reason : ") + - string_cast(Mix_GetError()), STARENGINE_LOG_TAG); - } - - if(Mix_OpenAudio(audio_rate, audio_format,audio_channels,audio_buffers)) - { - LOG(LogLevel::Info, - _T("AudioManager::Start: Could Not open Audio Mix SDL"), STARENGINE_LOG_TAG); - Stop(); - return; - } - Mix_AllocateChannels(16); - - //check What we got - int32 actual_rate, actual_channels; - uint16 actual_format; - - Mix_QuerySpec(&actual_rate,&actual_format,&actual_channels); - tstringstream buffer; - buffer << "Actual Rate : " << actual_rate; - buffer << ", Actual Format : " << actual_format; - buffer << ", Actual Channels : " << actual_channels; - buffer << std::endl; - LOG(LogLevel::Info, - _T("AudioManager::Start: SDL specs : ") + buffer.str(), STARENGINE_LOG_TAG); - Mix_Volume(-1,100); -#else - - SLresult lRes; - const SLuint32 lEngineMixIIDCount = 1; - const SLInterfaceID lEngineMixIIDs[] = { SL_IID_ENGINE }; - const SLboolean lEngineMixReqs[] = { SL_BOOLEAN_TRUE }; - const SLuint32 lOutputMixIIDCount= 1; - const SLInterfaceID lOutputMixIIDs[] = { SL_IID_VOLUME }; - const SLboolean lOutputMixReqs[] = { SL_BOOLEAN_FALSE}; - - lRes = slCreateEngine( - &mEngineObj, - 0, - NULL, - lEngineMixIIDCount, - lEngineMixIIDs, - lEngineMixReqs - ); - - if(lRes != SL_RESULT_SUCCESS) - { - LOG(LogLevel::Error, - _T("AudioManager::Start: Can't make Audio Engine"), STARENGINE_LOG_TAG); - Stop(); - return; - } - - lRes = (*mEngineObj)->Realize(mEngineObj, SL_BOOLEAN_FALSE); - if(lRes != SL_RESULT_SUCCESS) - { - LOG(LogLevel::Error, - _T("AudioManager::Start: Can't realize Engine"), STARENGINE_LOG_TAG); - Stop(); - return; - } - - lRes = (*mEngineObj)->GetInterface( - mEngineObj, - SL_IID_ENGINE, - &mEngine - ); - - if(lRes != SL_RESULT_SUCCESS) - { - LOG(LogLevel::Error, - _T("AudioManager::Start: Can't fetch engine interface"), STARENGINE_LOG_TAG); - Stop(); - return; - } - - lRes = (*mEngine)->CreateOutputMix( - mEngine, - &mOutputMixObj, - lOutputMixIIDCount, - lOutputMixIIDs, - lOutputMixReqs - ); - - if(lRes != SL_RESULT_SUCCESS) - { - LOG(LogLevel::Error, - _T("AudioManager::Start: Can't create outputmix"), STARENGINE_LOG_TAG); - Stop(); - return; - } - - lRes = (*mOutputMixObj)->Realize(mOutputMixObj,SL_BOOLEAN_FALSE); - if(lRes != SL_RESULT_SUCCESS) - { - LOG(LogLevel::Error, - _T("AudioManager::Start: Can't realise output object"), STARENGINE_LOG_TAG); - Stop(); - return; - } - - lRes = (*mOutputMixObj)->GetInterface( - mOutputMixObj, - SL_IID_VOLUME, - &mOutputMixVolume - ); - - if(lRes != SL_RESULT_SUCCESS) - { - LOG(LogLevel::Warning, - _T("AudioManager::Start: Can't get volume interface!"), STARENGINE_LOG_TAG); - mOutputMixVolume = nullptr; - } - LOG(LogLevel::Info, - _T("AudioManager::Start: Succesfull made Audio Engine"), STARENGINE_LOG_TAG); -#endif - } - - void AudioManager::Stop() - { - StopAllSounds(); - DeleteAllSounds(); - -#ifdef DESKTOP - Mix_CloseAudio(); - Mix_Quit(); - SDL_Quit(); -#else - if(mOutputMixObj != NULL) - { - (*mOutputMixObj)->Destroy(mOutputMixObj); - mOutputMixObj = NULL; - } - if(mEngineObj != NULL) - { - (*mEngineObj)->Destroy(mEngineObj); - mEngineObj = NULL; - mEngine = NULL; - } -#endif - LOG(LogLevel::Info, - _T("AudioManager::Stop: Stopped audio Engine"), STARENGINE_LOG_TAG); - } - - void AudioManager::LoadMusic(const tstring& path, const tstring& name, uint8 channel) - { - LoadMusic(path, name, 1.0f, channel); - } - - void AudioManager::LoadEffect(const tstring& path, const tstring& name, uint8 channel) - { - LoadEffect(path, name, 1.0f, channel); - } - - void AudioManager::LoadMusic( - const tstring& path, - const tstring& name, - float32 volume, - uint8 channel - ) - { - if(mMusicList.find(name) != mMusicList.end()) - { - LOG(LogLevel::Warning, - _T("AudioManager::LoadMusic: The music file '") + name + - _T("' is already loaded."), STARENGINE_LOG_TAG); - return; - } - - auto pathit = mMusicPathList.find(path); - if(pathit != mMusicPathList.end()) - { - LOG(LogLevel::Warning, - _T("AudioManager::LoadMusic: Sound File Path Already Exists"), - STARENGINE_LOG_TAG); - tstring nameold = pathit->second; - auto nameit = mMusicList.find(nameold); - if(nameit != mMusicList.end()) - { - LOG(LogLevel::Warning, - _T("AudioManager::LoadMusic: Found\ - sound file of old path, making copy for new name"), - STARENGINE_LOG_TAG); - mMusicList[name] = nameit->second; - return; - } - mMusicPathList.erase(pathit); - return; - } - - SoundFile* music = new SoundFile(path, channel); - music->SetCompleteVolume( - volume, - GetChannelVolume(channel), - GetVolume() - ); - mMusicList[name] = music; - mMusicPathList[path] = name; - return; - } - - void AudioManager::LoadEffect( - const tstring& path, - const tstring& name, - float32 volume, - uint8 channel - ) - { - if(mEffectsList.find(name) != mEffectsList.end()) - { - LOG(LogLevel::Warning, - _T("AudioManager::LoadEffect: The effect '") + name + - _T("' already exists."), STARENGINE_LOG_TAG); - return; - } - - auto pathit = mSoundEffectPathList.find(path); - if(pathit != mSoundEffectPathList.end()) - { - LOG(LogLevel::Warning, - _T("AudioManager::LoadEffect: Sound Effect Path Already Exists"), - STARENGINE_LOG_TAG); - tstring nameold = pathit->second; - auto nameit = mMusicList.find(nameold); - if(nameit!= mMusicList.end()) - { - LOG(LogLevel::Warning, - _T("AudioManager::LoadEffect: \ -Found Sound Effect of old path, making copy for new name")); - mMusicList[name] = nameit->second; - } - mSoundEffectPathList.erase(pathit); - } - - SoundEffect* effect = new SoundEffect(path, channel); - effect->SetCompleteVolume( - volume, - GetChannelVolume(channel), - GetVolume() - ); - mEffectsList[name] = effect; - mSoundEffectPathList[path] = name; - return; - } - - void AudioManager::PlayMusic( - const tstring& path, - const tstring& name, - uint8 channel, - int32 loopTimes - ) - { - if(mMusicList.find(name) == mMusicList.end()) - { - LoadMusic(path, name, channel); - } - return PlayMusic(name, loopTimes); - } - - void AudioManager::PlayMusic( - const tstring& name, - int32 loopTimes - ) - { - auto it = mMusicList.find(name); - if(it != mMusicList.end()) - { - if(mCurrentSoundFile != nullptr) mCurrentSoundFile->Stop(); - mCurrentSoundFile = mMusicList[name]; - mCurrentSoundFile->SetMuted(mbMusicMuted); - mCurrentSoundFile->Play(loopTimes); - return; - } - else - { - mCurrentSoundFile = nullptr; - star::Logger::GetInstance()-> - Log(LogLevel::Warning, - _T("AudioManager::PlayMusic: \ -AudioManager::PlayMusic: Couldn't find the song '") + name + - _T("'."), STARENGINE_LOG_TAG); - } - } - - void AudioManager::PlayEffect( - const tstring& path, - const tstring& name, - uint8 channel, - int32 loopTimes - ) - { - if(mEffectsList.find(name) == mEffectsList.end()) - { - LoadEffect(path, name, channel); - } - PlayEffect(name, loopTimes); - } - - void AudioManager::PlayEffect( - const tstring& name, - int32 loopTimes - ) - { - auto it = mEffectsList.find(name); - if(it != mEffectsList.end()) - { - mCurrentSoundEffect = mEffectsList[name]; - mCurrentSoundEffect->SetMuted(mbEffectsMuted); - mCurrentSoundEffect->Play(loopTimes); - } - else - { - star::Logger::GetInstance()-> - Log(LogLevel::Warning, - _T("AudioManager::PlayEffect: Couldn't find effect '") + name + - _T("'.")); - } - } - - void AudioManager::PlayMusic( - const tstring& path, - const tstring& name, - float32 volume, - uint8 channel, - int32 loopTimes - ) - { - if(mMusicList.find(name) == mMusicList.end()) - { - LoadMusic(path, name, channel); - } - return PlayMusic(name, volume, loopTimes); - } - - void AudioManager::PlayMusic( - const tstring& name, - float32 volume, - int32 loopTimes - ) - { - auto it = mMusicList.find(name); - if(it != mMusicList.end()) - { - if(mCurrentSoundFile != nullptr) mCurrentSoundFile->Stop(); - mCurrentSoundFile = mMusicList[name]; - mCurrentSoundFile->Play(loopTimes); - mCurrentSoundFile->SetMuted(mbMusicMuted); - mCurrentSoundFile->SetBaseVolume(volume); - return; - } - else - { - mCurrentSoundFile = nullptr; - star::Logger::GetInstance()-> - Log(LogLevel::Warning, - _T("AudioManager::PlayMusic: Couldn't find the song '") + name + - _T("'."), STARENGINE_LOG_TAG); - } - } - - void AudioManager::PlayEffect( - const tstring& path, - const tstring& name, - float32 volume, - uint8 channel, - int32 loopTimes - ) - { - if(mEffectsList.find(name) == mEffectsList.end()) - { - LoadEffect(path, name, channel); - } - PlayEffect(name, volume, loopTimes); - } - - void AudioManager::PlayEffect( - const tstring& name, - float32 volume, - int32 loopTimes - ) - { - auto it = mEffectsList.find(name); - if(it != mEffectsList.end()) - { - mCurrentSoundEffect = mEffectsList[name]; - mCurrentSoundEffect->Play(loopTimes); - mCurrentSoundEffect->SetMuted(mbEffectsMuted); - mCurrentSoundEffect->SetBaseVolume(volume); - } - else - { - star::Logger::GetInstance()-> - Log(LogLevel::Warning, - _T("AudioManager::PlayEffect: Couldn't find effect '") + name + - _T("'."), STARENGINE_LOG_TAG); - } - } - - void AudioManager::AddToBackgroundQueue(const tstring& name) - { - auto it = mMusicList.find(name); - if(it != mMusicList.end()) - { - auto music = mMusicList[name]; - music->SetMuted(mbMusicMuted); - mBackgroundQueue.push_back(music); - } - else - { - star::Logger::GetInstance()-> - Log(LogLevel::Warning, - _T("AudioManager::AddToBackgroundQueue: Couldn't find background song '") + name + - _T("'."), STARENGINE_LOG_TAG); - } - } - - void AudioManager::PlayBackgroundQueue() - { - mQueueIterator = mBackgroundQueue.begin(); - if(mQueueIterator != mBackgroundQueue.end()) - { - (*mQueueIterator)->SetMuted(mbMusicMuted); - (*mQueueIterator)->PlayQueued(0); - } - else - { - LOG(LogLevel::Warning, - _T("PlayEffect::AddToBackgroundQueue: No song in background queue."), - STARENGINE_LOG_TAG); - } - } - - void AudioManager::PlayNextSongInQueue() - { - if(mBackgroundQueue.size() == 0) - { - return; - } - - ++mQueueIterator; - if(mQueueIterator != mBackgroundQueue.end()) - { - (*mQueueIterator)->SetMuted(mbMusicMuted); - (*mQueueIterator)->PlayQueued(0); - } - } - - void AudioManager::PauseBackgroundQueue() - { - if(mBackgroundQueue.size() == 0) - { - return; - } - - if(mQueueIterator != mBackgroundQueue.end()) - { - (*mQueueIterator)->Pause(); - } - } - - void AudioManager::ResumeBackgroundQueue() - { - if(mBackgroundQueue.size() == 0) - { - return; - } - - if(mQueueIterator != mBackgroundQueue.end()) - { - (*mQueueIterator)->Resume(); - } - else - { - LOG(LogLevel::Warning, - _T("AudioManager::ResumeBackgroundQueue: \ -Sound Service : No song in background queue."), - STARENGINE_LOG_TAG); - } - } - - void AudioManager::StopBackgroundQueue() - { - if(mBackgroundQueue.size() == 0) - { - return; - } - - if(mQueueIterator != mBackgroundQueue.end()) - { - (*mQueueIterator)->Stop(); - mQueueIterator = mBackgroundQueue.begin(); - } - else - { - LOG(LogLevel::Warning, - _T("AudioManager::StopBackgroundQueue: \ -Sound Service : No song in background queue."), - STARENGINE_LOG_TAG); - } - } - - void AudioManager::PauseMusic(const tstring & name) - { - auto it = mMusicList.find(name); - if(it != mMusicList.end()) - { - it->second->Pause(); - } - else - { - LOG(LogLevel::Error, - _T("AudioManager::PauseMusic: Couldn't find '") + - name + _T("'."), STARENGINE_LOG_TAG); - } - } - - void AudioManager::ResumeMusic(const tstring & name) - { - auto it = mMusicList.find(name); - if(it != mMusicList.end()) - { - it->second->SetMuted(mbMusicMuted); - it->second->Resume(); - } - else - { - LOG(LogLevel::Error, - _T("AudioManager::ResumeMusic: Couldn't find '") + - name + _T("'."), STARENGINE_LOG_TAG); - } - } - - void AudioManager::StopMusic(const tstring & name) - { - auto it = mMusicList.find(name); - if(it != mMusicList.end()) - { - it->second->Stop(); - } - else - { - LOG(LogLevel::Error, - _T("AudioManager::StopMusic: Couldn't find '") + - name + _T("'."), STARENGINE_LOG_TAG); - } - } - - bool AudioManager::IsMusicPaused(const tstring & name) const - { - auto it = mMusicList.find(name); - if(it != mMusicList.end()) - { - return it->second->IsPaused(); - } - else - { - LOG(LogLevel::Error, - _T("AudioManager::IsMusicPaused: Couldn't find '") + - name + _T("'."), STARENGINE_LOG_TAG); - } - return false; - } - - bool AudioManager::IsMusicStopped(const tstring & name) const - { - auto it = mMusicList.find(name); - if(it != mMusicList.end()) - { - return it->second->IsStopped(); - } - else - { - LOG(LogLevel::Error, - _T("AudioManager::IsMusicStopped: Couldn't find '") + - name + _T("'."), STARENGINE_LOG_TAG); - } - return false; - } - - bool AudioManager::IsMusicPlaying(const tstring & name) const - { - auto it = mMusicList.find(name); - if(it != mMusicList.end()) - { - return it->second->IsPlaying(); - } - else - { - LOG(LogLevel::Error, - _T("AudioManager::IsMusicPlaying: Couldn't find '") + - name + _T("'."), STARENGINE_LOG_TAG); - } - return false; - } - - bool AudioManager::IsMusicLooping(const tstring & name) const - { - auto it = mMusicList.find(name); - if(it != mMusicList.end()) - { - return it->second->IsLooping(); - } - else - { - LOG(LogLevel::Error, - _T("AudioManager::IsMusicLooping: Couldn't find '") + - name + _T("'."), STARENGINE_LOG_TAG); - } - return false; - } - - void AudioManager::PauseEffect(const tstring & name) - { - auto it = mEffectsList.find(name); - if(it != mEffectsList.end()) - { - it->second->Pause(); - } - else - { - LOG(LogLevel::Error, - _T("AudioManager::PauseEffect: Couldn't find '") + - name + _T("'."), STARENGINE_LOG_TAG); - } - } - - void AudioManager::ResumeEffect(const tstring & name) - { - auto it = mEffectsList.find(name); - if(it != mEffectsList.end()) - { - it->second->SetMuted(mbEffectsMuted); - it->second->Resume(); - } - else - { - LOG(LogLevel::Error, - _T("AudioManager::ResumeEffect: Couldn't find '") + - name + _T("'."), STARENGINE_LOG_TAG); - } - } - - void AudioManager::StopEffect(const tstring & name) - { - auto it = mEffectsList.find(name); - if(it != mEffectsList.end()) - { - it->second->Stop(); - } - else - { - LOG(LogLevel::Error, - _T("AudioManager::StopEffect: Couldn't find '") + - name + _T("'."), STARENGINE_LOG_TAG); - } - } - - bool AudioManager::IsEffectPaused(const tstring & name) const - { - auto it = mEffectsList.find(name); - if(it != mEffectsList.end()) - { - return it->second->IsPaused(); - } - else - { - LOG(LogLevel::Error, - _T("AudioManager::IsEffectPaused: Couldn't find '") + - name + _T("'."), STARENGINE_LOG_TAG); - } - return false; - } - - bool AudioManager::IsEffectStopped(const tstring & name) const - { - auto it = mEffectsList.find(name); - if(it != mEffectsList.end()) - { - return it->second->IsStopped(); - } - else - { - LOG(LogLevel::Error, - _T("AudioManager::IsEffectStopped: Couldn't find '") + - name + _T("'."), STARENGINE_LOG_TAG); - } - return false; - } - - bool AudioManager::IsEffectPlaying(const tstring & name) const - { - auto it = mEffectsList.find(name); - if(it != mEffectsList.end()) - { - return it->second->IsPlaying(); - } - else - { - LOG(LogLevel::Error, - _T("AudioManager::IsEffectPlaying: Couldn't find '") + - name + _T("'."), STARENGINE_LOG_TAG); - } - return false; - } - - bool AudioManager::IsEffectLooping(const tstring & name) const - { - auto it = mEffectsList.find(name); - if(it != mEffectsList.end()) - { - return it->second->IsLooping(); - } - else - { - LOG(LogLevel::Error, - _T("AudioManager::IsEffectLooping: Couldn't find '") + - name + _T("'."), STARENGINE_LOG_TAG); - } - return false; - } - - void AudioManager::SetMusicVolume(const tstring& name, float32 volume) - { - auto it = mMusicList.find(name); - if(it != mMusicList.end()) - { - it->second->SetBaseVolume(volume); - } - else - { - LOG(LogLevel::Error, - _T("AudioManager::SetMusicVolume: Couldn't find '") + - name + _T("'."), STARENGINE_LOG_TAG); - } - } - - float32 AudioManager::GetMusicVolume(const tstring& name) const - { - auto it = mMusicList.find(name); - if(it != mMusicList.end()) - { - return it->second->GetVolume(); - } - else - { - LOG(LogLevel::Error, - _T("AudioManager::SetMusicVolume: Couldn't find '") + - name + _T("'."), STARENGINE_LOG_TAG); - } - return 0; - } - - void AudioManager::SetEffectVolume(const tstring& name, float32 volume) - { - auto it = mEffectsList.find(name); - if(it != mEffectsList.end()) - { - it->second->SetBaseVolume(volume); - } - else - { - LOG(LogLevel::Error, - _T("AudioManager::SetEffectVolume: Couldn't find '") + - name + _T("'."), STARENGINE_LOG_TAG); - } - } - - float32 AudioManager::GetEffectVolume(const tstring& name) const - { - auto it = mEffectsList.find(name); - if(it != mEffectsList.end()) - { - return it->second->GetVolume(); - } - else - { - LOG(LogLevel::Error, - _T("AudioManager::GetEffectVolume: Couldn't find '") + - name + _T("'."), STARENGINE_LOG_TAG); - } - return 0; - } - - void AudioManager::IncreaseMusicVolume(const tstring& name, float32 volume) - { - auto it = mMusicList.find(name); - if(it != mMusicList.end()) - { - it->second->IncreaseVolume(volume); - } - else - { - LOG(LogLevel::Error, - _T("AudioManager::IncreaseMusicVolume: Couldn't find '") + - name + _T("'."), STARENGINE_LOG_TAG); - } - } - - void AudioManager::DecreaseMusicVolume(const tstring& name, float32 volume) - { - auto it = mMusicList.find(name); - if(it != mMusicList.end()) - { - it->second->DecreaseVolume(volume); - } - else - { - LOG(LogLevel::Error, - _T("AudioManager::DecreaseMusicVolume: Couldn't find '") + - name + _T("'."), STARENGINE_LOG_TAG); - } - } - - void AudioManager::IncreaseEffectVolume(const tstring& name, float32 volume) - { - auto it = mEffectsList.find(name); - if(it != mEffectsList.end()) - { - it->second->IncreaseVolume(volume); - } - else - { - LOG(LogLevel::Error, - _T("AudioManager::IncreaseEffectVolume: Couldn't find '") + - name + _T("'."), STARENGINE_LOG_TAG); - } - } - void AudioManager::DecreaseEffectVolume(const tstring& name, float32 volume) - { - auto it = mEffectsList.find(name); - if(it != mEffectsList.end()) - { - it->second->DecreaseVolume(volume); - } - else - { - LOG(LogLevel::Error, - _T("AudioManager::DecreaseEffectVolume: Couldn't find '") + - name + _T("'."), STARENGINE_LOG_TAG); - } - } - - void AudioManager::MuteAllMusic(bool mute) - { - mbMusicMuted = mute; - for(auto & it : mMusicList) - { - it.second->SetMuted(mute); - } - } - - bool AudioManager::IsAllMusicMuted() const - { - return mbMusicMuted; - } - - void AudioManager::SetMusicMuted(const tstring& name, bool muted) - { - if(mbMusicMuted && !muted) - { - mbMusicMuted = false; - MuteAllMusic(false); - } - auto it = mMusicList.find(name); - if(it != mMusicList.end()) - { - it->second->SetMuted(muted); - } - else - { - LOG(LogLevel::Error, - _T("AudioManager::SetMusicMuted: Couldn't find '") + - name + _T("'."), STARENGINE_LOG_TAG); - } - } - - bool AudioManager::IsMusicMuted(const tstring& name) const - { - auto it = mMusicList.find(name); - if(it != mMusicList.end()) - { - return it->second->IsMuted(); - } - else - { - LOG(LogLevel::Error, - _T("AudioManager::IsMusicMuted: Couldn't find '") + - name + _T("'."), STARENGINE_LOG_TAG); - return false; - } - } - - void AudioManager::MuteAllEffects(bool mute) - { - mbEffectsMuted = mute; - for(auto & it : mEffectsList) - { - it.second->SetMuted(mute); - } - } - - bool AudioManager::IsAllEffectsMuted() const - { - return mbEffectsMuted; - } - - void AudioManager::SetEffectMuted(const tstring& name, bool muted) - { - if(mbEffectsMuted && !muted) - { - mbEffectsMuted = false; - MuteAllEffects(false); - } - auto it = mEffectsList.find(name); - if(it != mEffectsList.end()) - { - it->second->SetMuted(muted); - } - else - { - LOG(LogLevel::Error, - _T("AudioManager::SetEffectMuted: Couldn't find '") + - name + _T("'."), STARENGINE_LOG_TAG); - } - } - - bool AudioManager::IsEffectMuted(const tstring& name) const - { - auto it = mEffectsList.find(name); - if(it != mEffectsList.end()) - { - return it->second->IsMuted(); - } - else - { - LOG(LogLevel::Error, - _T("AudioManager::IsEffectMuted: Couldn't find '") + - name + _T("'."), STARENGINE_LOG_TAG); - return false; - } - } - - bool AudioManager::ToggleMusicMuted(const tstring& name) - { - auto it = mEffectsList.find(name); - if(it != mEffectsList.end()) - { - it->second->SetMuted(!it->second->IsMuted()); - return it->second->IsMuted(); - } - else - { - LOG(LogLevel::Error, - _T("AudioManager::ToggleMusicMuted: Couldn't find '") + - name + _T("'."), STARENGINE_LOG_TAG); - return false; - } - } - - bool AudioManager::ToggleEffectMuted(const tstring& name) - { - auto it = mMusicList.find(name); - if(it != mMusicList.end()) - { - it->second->SetMuted(!it->second->IsMuted()); - return it->second->IsMuted(); - } - else - { - LOG(LogLevel::Error, - _T("AudioManager::ToggleEffectMuted: Couldn't find '") + - name + _T("'."), STARENGINE_LOG_TAG); - return false; - } - } - - void AudioManager::AddSoundToChannel(uint8 channel, BaseSound * pSound) - { - auto & chnl = mChannels[channel]; - auto it = chnl.sounds.begin(); - auto end = chnl.sounds.end(); - for(auto sound : chnl.sounds) - { - if(sound == pSound) - { - LOG(LogLevel::Warning, - _T("AudioManager::AddSoundToChannel: Trying to add a sound twice in channel '") - + string_cast(channel) + _T("'."), STARENGINE_LOG_TAG); - return; - } - } - pSound->SetChannelVolume(chnl.volume); - chnl.sounds.push_back(pSound); - chnl.channel = channel; - switch(chnl.state) - { - case ChannelState::paused: - pSound->Pause(); - break; - case ChannelState::stopped: - pSound->Stop(); - break; - } - } - - void AudioManager::RemoveSoundFromChannel(uint8 channel, BaseSound * pSound) - { - bool result; - SoundChannel & chnl = GetChannel( - channel, - _T("AudioManager::RemoveSoundFromChannel"), - result - ); - if(result) - { - for(auto it = chnl.sounds.begin() ; - it != chnl.sounds.end() ; - ++it - ) - { - if(*it == pSound) - { - pSound->SetChannelVolume(1.0f); - chnl.sounds.erase(it); - return; - } - } - LOG(LogLevel::Warning, - _T("AudioManager::RemoveSoundFromChannel: Sound not found in channel '") - + string_cast(channel) + _T("'."), STARENGINE_LOG_TAG); - } - } - - void AudioManager::SetChannelVolume(uint8 channel, float32 volume) - { - bool result; - SoundChannel & chnl = GetChannel( - channel, - _T("AudioManager::SetChannelVolume"), - result - ); - if(result) - { - chnl.SetVolume(volume); - } - } - - float32 AudioManager::GetChannelVolume(uint8 channel) - { - bool result; - SoundChannel & chnl = GetChannel( - channel, - _T("AudioManager::GetChannelVolume"), - result - ); - if(result) - { - return chnl.volume; - } - return 0; - } - - void AudioManager::IncreaseChannelVolume(uint8 channel, float32 volume) - { - bool result; - SoundChannel & chnl = GetChannel( - channel, - _T("AudioManager::IncreaseChannelVolume"), - result - ); - if(result) - { - chnl.IncreaseVolume(volume); - } - } - - void AudioManager::DecreaseChannelVolume(uint8 channel, float32 volume) - { - bool result; - SoundChannel & chnl = GetChannel( - channel, - _T("AudioManager::DecreaseChannelVolume"), - result - ); - if(result) - { - chnl.DecreaseVolume(volume); - } - } - - void AudioManager::SetChannelMuted(uint8 channel, bool muted) - { - bool result; - SoundChannel & chnl = GetChannel( - channel, - _T("AudioManager::SetChannelMuted"), - result - ); - if(result) - { - chnl.SetMuted(muted); - } - } - - bool AudioManager::IsChannelMuted(uint8 channel) - { - bool result; - SoundChannel & chnl = GetChannel( - channel, - _T("AudioManager::IsChannelMuted"), - result - ); - if(result) - { - return chnl.isMuted; - } - return false; - } - - bool AudioManager::ToggleChannelMuted(uint8 channel) - { - bool result; - SoundChannel & chnl = GetChannel( - channel, - _T("AudioManager::ToggleChannelMuted"), - result - ); - if(result) - { - chnl.SetMuted(!chnl.isMuted); - return chnl.isMuted; - } - return false; - } - - void AudioManager::SetMusicChannel(const tstring & name, uint8 channel) - { - auto it = mMusicList.find(name); - if(it != mMusicList.end()) - { - it->second->SetChannel(channel); - } - else - { - LOG(LogLevel::Error, - _T("AudioManager::SetMusicChannel: Couldn't find '") + - name + _T("'."), STARENGINE_LOG_TAG); - } - } - - void AudioManager::UnsetMusicChannel(const tstring & name) - { - auto it = mMusicList.find(name); - if(it != mMusicList.end()) - { - it->second->UnsetChannel(); - } - else - { - LOG(LogLevel::Error, - _T("AudioManager::SetMusicChannel: Couldn't find '") + - name + _T("'."), STARENGINE_LOG_TAG); - } - } - - void AudioManager::SetEffectChannel(const tstring & name, uint8 channel) - { - auto it = mEffectsList.find(name); - if(it != mEffectsList.end()) - { - it->second->SetChannel(channel); - } - else - { - LOG(LogLevel::Error, - _T("AudioManager::SetEffectChannel: Couldn't find '") + - name + _T("'."), STARENGINE_LOG_TAG); - } - } - - void AudioManager::UnsetEffectChannel(const tstring & name) - { - auto it = mEffectsList.find(name); - if(it != mEffectsList.end()) - { - it->second->UnsetChannel(); - } - else - { - LOG(LogLevel::Error, - _T("AudioManager::UnsetEffectChannel: Couldn't find '") + - name + _T("'."), STARENGINE_LOG_TAG); - } - } - - void AudioManager::PauseChannel(uint8 channel) - { - bool result; - SoundChannel & chnl = GetChannel( - channel, - _T("AudioManager::PauseChannel"), - result - ); - if(result) - { - for(auto sound : chnl.sounds) - { - sound->Pause(); - } - chnl.state = ChannelState::paused; - } - } - - bool AudioManager::IsChannelPaused(uint8 channel) - { - bool result; - SoundChannel & chnl = GetChannel( - channel, - _T("AudioManager::IsChannelPaused"), - result - ); - if(result) - { - return chnl.state == ChannelState::paused; - } - return false; - } - - void AudioManager::ResumeChannel(uint8 channel) - { - bool result; - SoundChannel & chnl = GetChannel( - channel, - _T("AudioManager::ResumeChannel"), - result - ); - if(result) - { - for(auto sound : chnl.sounds) - { - sound->Resume(); - } - chnl.state = ChannelState::playing; - } - } - - bool AudioManager::IsChannelPlaying(uint8 channel) - { - bool result; - SoundChannel & chnl = GetChannel( - channel, - _T("AudioManager::IsChannelPlaying"), - result - ); - if(result) - { - return chnl.state == ChannelState::playing; - } - return false; - } - - void AudioManager::StopChannel(uint8 channel) - { - bool result; - SoundChannel & chnl = GetChannel( - channel, - _T("AudioManager::StopChannel"), - result - ); - if(result) - { - for(auto sound : chnl.sounds) - { - sound->Stop(); - } - chnl.state = ChannelState::stopped; - } - } - - bool AudioManager::IsChannelStopped(uint8 channel) - { - bool result; - SoundChannel & chnl = GetChannel( - channel, - _T("AudioManager::IsChannelStopped"), - result - ); - if(result) - { - return chnl.state == ChannelState::stopped; - } - return false; - } - - void AudioManager::PlayChannel(uint8 channel, int32 loopTimes) - { - bool result; - SoundChannel & chnl = GetChannel( - channel, - _T("AudioManager::PlayChannel"), - result - ); - if(result) - { - for(auto sound : chnl.sounds) - { - sound->Play(loopTimes); - } - chnl.state = ChannelState::playing; - } - } - - void AudioManager::StopAllSounds() - { - for(auto & song : mMusicList) - { - song.second->Stop(); - } - - for(auto & effect : mEffectsList) - { - effect.second->Stop(); - } - } - - void AudioManager::PauseAllSounds() - { - for(auto & song : mMusicList) - { - song.second->Pause(); - } - - for(auto & effect : mEffectsList) - { - effect.second->Pause(); - } - } - - void AudioManager::ResumeAllSounds() - { - for(auto & song : mMusicList) - { - song.second->Resume(); - } - - for(auto & effect : mEffectsList) - { - effect.second->Resume(); - } - } - - void AudioManager::DeleteAllSounds() - { - for(auto & song : mMusicList) - { - delete song.second; - } - mMusicList.clear(); - - for(auto & effect : mEffectsList) - { - delete effect.second; - } - mEffectsList.clear(); - - } - - void AudioManager::SetVolume(float32 volume) - { - mVolume = Clamp(volume, 0.0f, 1.0f); - - for(auto & song : mMusicList) - { - song.second->SetMasterVolume(volume); - } - - for(auto & effect : mEffectsList) - { - effect.second->SetMasterVolume(volume); - } - } - - float32 AudioManager::GetVolume() const - { - return mVolume; - } - - void AudioManager::IncreaseVolume(float32 volume) - { - float32 vol = GetVolume(); - vol += volume; - SetVolume(vol); - } - - void AudioManager::DecreaseVolume(float32 volume) - { - float32 vol = GetVolume(); - vol -= volume; - SetVolume(vol); - } - - AudioManager::SoundChannel & AudioManager::GetChannel( - uint8 channel, - const tstring & sender, - bool & result - ) - { - auto it = mChannels.find(channel); - result = it != mChannels.end(); - if(result) - { - return it->second; - } - else - { - LOG(LogLevel::Error, - sender + _T(": Couldn't find channel '") - + string_cast(channel) + _T("'."), - STARENGINE_LOG_TAG); - } - return mEmptyChannel; - } - -#ifdef ANDROID - const SLEngineItf& AudioManager::GetEngine() const - { - return mEngine; - } - - const SLObjectItf& AudioManager::GetOutputMixObject() const - { - return mOutputMixObj; - } - - -#endif - - AudioManager::SoundChannel::SoundChannel() - : volume(1.0f) - , isMuted(false) - , sounds() - , channel(0) - , state(ChannelState::playing) - { - } - - AudioManager::SoundChannel::~SoundChannel() - { - for(auto it : sounds) - { - it->SetChannelVolume(1.0f); - it->UnsetChannel(); - } - sounds.clear(); - } - - void AudioManager::SoundChannel::SetVolume(float32 newVolume) - { - volume = Clamp(newVolume, 0.0f, 1.0f); - for(auto & it : sounds) - { - it->SetChannelVolume(volume); - } - } - - void AudioManager::SoundChannel::IncreaseVolume(float32 volume) - { - SetVolume(volume + volume); - } - - void AudioManager::SoundChannel::DecreaseVolume(float32 volume) - { - SetVolume(volume - volume); - } - - void AudioManager::SoundChannel::SetMuted(bool muted) - { - isMuted = muted; - for( auto it : sounds) - { - it->SetMuted(muted); - } - } -} +#include "AudioManager.h" +#include "../Logger.h" +#include "../Helpers/Helpers.h" +#include "../Helpers/Math.h" + +#ifdef ANDROID +#include "../Graphics/Resource.h" +#endif + +namespace star +{ + bool AudioManager::mbIsInitialized = false; + + AudioManager::AudioManager() + : Singleton() + , mMusicList() + , mMusicPathList() + , mEffectsList() + , mSoundEffectPathList() + , mBackgroundQueue() + , mQueueIterator() + , mChannels() + , mEmptyChannel() + , mCurrentSoundFile(nullptr) + , mCurrentSoundEffect(nullptr) + , mVolume(1.0f) + , mbMusicMuted(false) + , mbEffectsMuted(false) +#ifdef ANDROID + , mEngineObj(nullptr) + , mEngine(nullptr) + , mOutputMixObj(nullptr) + , mOutputMixVolume(nullptr) +#endif + { + mQueueIterator = mBackgroundQueue.begin(); + } + + AudioManager::~AudioManager() + { + for(auto & music : mMusicList) + { + delete music.second; + } + + mMusicList.clear(); + + for(auto & effect : mEffectsList) + { + delete effect.second; + } + + mEffectsList.clear(); + + mChannels.clear(); + } + + void AudioManager::Start() + { + if(mbIsInitialized) + { + return; + } + + mbIsInitialized = true; + LOG(LogLevel::Info, + _T("AudioManager::Start: Started making Audio Engine"), STARENGINE_LOG_TAG); + +#ifdef DESKTOP + int32 audio_rate(44100); + uint16 audio_format(MIX_DEFAULT_FORMAT); + int32 audio_channels(2); + int32 audio_buffers(4096); + + SDL_Init(SDL_INIT_AUDIO); + int32 flags = MIX_INIT_OGG | MIX_INIT_MP3; + int32 innited = Mix_Init(flags); + if((innited & flags) != flags) + { + LOG(LogLevel::Info, + _T("AudioManager::Start: Could not init Ogg and Mp3, reason : ") + + string_cast(Mix_GetError()), STARENGINE_LOG_TAG); + } + + if(Mix_OpenAudio(audio_rate, audio_format,audio_channels,audio_buffers)) + { + LOG(LogLevel::Info, + _T("AudioManager::Start: Could Not open Audio Mix SDL"), STARENGINE_LOG_TAG); + Stop(); + return; + } + Mix_AllocateChannels(16); + + //check What we got + int32 actual_rate, actual_channels; + uint16 actual_format; + + Mix_QuerySpec(&actual_rate,&actual_format,&actual_channels); + tstringstream buffer; + buffer << "Actual Rate : " << actual_rate; + buffer << ", Actual Format : " << actual_format; + buffer << ", Actual Channels : " << actual_channels; + buffer << std::endl; + LOG(LogLevel::Info, + _T("AudioManager::Start: SDL specs : ") + buffer.str(), STARENGINE_LOG_TAG); + Mix_Volume(-1,100); +#elif defined(ANDROID) + + SLresult lRes; + const SLuint32 lEngineMixIIDCount = 1; + const SLInterfaceID lEngineMixIIDs[] = { SL_IID_ENGINE }; + const SLboolean lEngineMixReqs[] = { SL_BOOLEAN_TRUE }; + const SLuint32 lOutputMixIIDCount= 1; + const SLInterfaceID lOutputMixIIDs[] = { SL_IID_VOLUME }; + const SLboolean lOutputMixReqs[] = { SL_BOOLEAN_FALSE}; + + lRes = slCreateEngine( + &mEngineObj, + 0, + NULL, + lEngineMixIIDCount, + lEngineMixIIDs, + lEngineMixReqs + ); + + if(lRes != SL_RESULT_SUCCESS) + { + LOG(LogLevel::Error, + _T("AudioManager::Start: Can't make Audio Engine"), STARENGINE_LOG_TAG); + Stop(); + return; + } + + lRes = (*mEngineObj)->Realize(mEngineObj, SL_BOOLEAN_FALSE); + if(lRes != SL_RESULT_SUCCESS) + { + LOG(LogLevel::Error, + _T("AudioManager::Start: Can't realize Engine"), STARENGINE_LOG_TAG); + Stop(); + return; + } + + lRes = (*mEngineObj)->GetInterface( + mEngineObj, + SL_IID_ENGINE, + &mEngine + ); + + if(lRes != SL_RESULT_SUCCESS) + { + LOG(LogLevel::Error, + _T("AudioManager::Start: Can't fetch engine interface"), STARENGINE_LOG_TAG); + Stop(); + return; + } + + lRes = (*mEngine)->CreateOutputMix( + mEngine, + &mOutputMixObj, + lOutputMixIIDCount, + lOutputMixIIDs, + lOutputMixReqs + ); + + if(lRes != SL_RESULT_SUCCESS) + { + LOG(LogLevel::Error, + _T("AudioManager::Start: Can't create outputmix"), STARENGINE_LOG_TAG); + Stop(); + return; + } + + lRes = (*mOutputMixObj)->Realize(mOutputMixObj,SL_BOOLEAN_FALSE); + if(lRes != SL_RESULT_SUCCESS) + { + LOG(LogLevel::Error, + _T("AudioManager::Start: Can't realise output object"), STARENGINE_LOG_TAG); + Stop(); + return; + } + + lRes = (*mOutputMixObj)->GetInterface( + mOutputMixObj, + SL_IID_VOLUME, + &mOutputMixVolume + ); + + if(lRes != SL_RESULT_SUCCESS) + { + LOG(LogLevel::Warning, + _T("AudioManager::Start: Can't get volume interface!"), STARENGINE_LOG_TAG); + mOutputMixVolume = nullptr; + } + LOG(LogLevel::Info, + _T("AudioManager::Start: Succesfull made Audio Engine"), STARENGINE_LOG_TAG); +#endif + } + + void AudioManager::Stop() + { + StopAllSounds(); + DeleteAllSounds(); + +#ifdef DESKTOP + Mix_CloseAudio(); + Mix_Quit(); + SDL_Quit(); +#elif defined(ANDROID) + if(mOutputMixObj != NULL) + { + (*mOutputMixObj)->Destroy(mOutputMixObj); + mOutputMixObj = NULL; + } + if(mEngineObj != NULL) + { + (*mEngineObj)->Destroy(mEngineObj); + mEngineObj = NULL; + mEngine = NULL; + } +#endif + LOG(LogLevel::Info, + _T("AudioManager::Stop: Stopped audio Engine"), STARENGINE_LOG_TAG); + } + + void AudioManager::LoadMusic(const tstring& path, const tstring& name, uint8 channel) + { + LoadMusic(path, name, 1.0f, channel); + } + + void AudioManager::LoadEffect(const tstring& path, const tstring& name, uint8 channel) + { + LoadEffect(path, name, 1.0f, channel); + } + + void AudioManager::LoadMusic( + const tstring& path, + const tstring& name, + float32 volume, + uint8 channel + ) + { + if(mMusicList.find(name) != mMusicList.end()) + { + LOG(LogLevel::Warning, + _T("AudioManager::LoadMusic: The music file '") + name + + _T("' is already loaded."), STARENGINE_LOG_TAG); + return; + } + + auto pathit = mMusicPathList.find(path); + if(pathit != mMusicPathList.end()) + { + LOG(LogLevel::Warning, + _T("AudioManager::LoadMusic: Sound File Path Already Exists"), + STARENGINE_LOG_TAG); + tstring nameold = pathit->second; + auto nameit = mMusicList.find(nameold); + if(nameit != mMusicList.end()) + { + LOG(LogLevel::Warning, + _T("AudioManager::LoadMusic: Found\ + sound file of old path, making copy for new name"), + STARENGINE_LOG_TAG); + mMusicList[name] = nameit->second; + return; + } + mMusicPathList.erase(pathit); + return; + } + + SoundFile* music = new SoundFile(path, channel); + music->SetCompleteVolume( + volume, + GetChannelVolume(channel), + GetVolume() + ); + mMusicList[name] = music; + mMusicPathList[path] = name; + return; + } + + void AudioManager::LoadEffect( + const tstring& path, + const tstring& name, + float32 volume, + uint8 channel + ) + { + if(mEffectsList.find(name) != mEffectsList.end()) + { + LOG(LogLevel::Warning, + _T("AudioManager::LoadEffect: The effect '") + name + + _T("' already exists."), STARENGINE_LOG_TAG); + return; + } + + auto pathit = mSoundEffectPathList.find(path); + if(pathit != mSoundEffectPathList.end()) + { + LOG(LogLevel::Warning, + _T("AudioManager::LoadEffect: Sound Effect Path Already Exists"), + STARENGINE_LOG_TAG); + tstring nameold = pathit->second; + auto nameit = mMusicList.find(nameold); + if(nameit!= mMusicList.end()) + { + LOG(LogLevel::Warning, + _T("AudioManager::LoadEffect: \ +Found Sound Effect of old path, making copy for new name")); + mMusicList[name] = nameit->second; + } + mSoundEffectPathList.erase(pathit); + } + + SoundEffect* effect = new SoundEffect(path, channel); + effect->SetCompleteVolume( + volume, + GetChannelVolume(channel), + GetVolume() + ); + mEffectsList[name] = effect; + mSoundEffectPathList[path] = name; + return; + } + + void AudioManager::PlayMusic( + const tstring& path, + const tstring& name, + uint8 channel, + int32 loopTimes + ) + { + if(mMusicList.find(name) == mMusicList.end()) + { + LoadMusic(path, name, channel); + } + return PlayMusic(name, loopTimes); + } + + void AudioManager::PlayMusic( + const tstring& name, + int32 loopTimes + ) + { + auto it = mMusicList.find(name); + if(it != mMusicList.end()) + { + if(mCurrentSoundFile != nullptr) mCurrentSoundFile->Stop(); + mCurrentSoundFile = mMusicList[name]; + mCurrentSoundFile->SetMuted(mbMusicMuted); + mCurrentSoundFile->Play(loopTimes); + return; + } + else + { + mCurrentSoundFile = nullptr; + star::Logger::GetInstance()-> + Log(LogLevel::Warning, + _T("AudioManager::PlayMusic: \ +AudioManager::PlayMusic: Couldn't find the song '") + name + + _T("'."), STARENGINE_LOG_TAG); + } + } + + void AudioManager::PlayEffect( + const tstring& path, + const tstring& name, + uint8 channel, + int32 loopTimes + ) + { + if(mEffectsList.find(name) == mEffectsList.end()) + { + LoadEffect(path, name, channel); + } + PlayEffect(name, loopTimes); + } + + void AudioManager::PlayEffect( + const tstring& name, + int32 loopTimes + ) + { + auto it = mEffectsList.find(name); + if(it != mEffectsList.end()) + { + mCurrentSoundEffect = mEffectsList[name]; + mCurrentSoundEffect->SetMuted(mbEffectsMuted); + mCurrentSoundEffect->Play(loopTimes); + } + else + { + star::Logger::GetInstance()-> + Log(LogLevel::Warning, + _T("AudioManager::PlayEffect: Couldn't find effect '") + name + + _T("'.")); + } + } + + void AudioManager::PlayMusic( + const tstring& path, + const tstring& name, + float32 volume, + uint8 channel, + int32 loopTimes + ) + { + if(mMusicList.find(name) == mMusicList.end()) + { + LoadMusic(path, name, channel); + } + return PlayMusic(name, volume, loopTimes); + } + + void AudioManager::PlayMusic( + const tstring& name, + float32 volume, + int32 loopTimes + ) + { + auto it = mMusicList.find(name); + if(it != mMusicList.end()) + { + if(mCurrentSoundFile != nullptr) mCurrentSoundFile->Stop(); + mCurrentSoundFile = mMusicList[name]; + mCurrentSoundFile->Play(loopTimes); + mCurrentSoundFile->SetMuted(mbMusicMuted); + mCurrentSoundFile->SetBaseVolume(volume); + return; + } + else + { + mCurrentSoundFile = nullptr; + star::Logger::GetInstance()-> + Log(LogLevel::Warning, + _T("AudioManager::PlayMusic: Couldn't find the song '") + name + + _T("'."), STARENGINE_LOG_TAG); + } + } + + void AudioManager::PlayEffect( + const tstring& path, + const tstring& name, + float32 volume, + uint8 channel, + int32 loopTimes + ) + { + if(mEffectsList.find(name) == mEffectsList.end()) + { + LoadEffect(path, name, channel); + } + PlayEffect(name, volume, loopTimes); + } + + void AudioManager::PlayEffect( + const tstring& name, + float32 volume, + int32 loopTimes + ) + { + auto it = mEffectsList.find(name); + if(it != mEffectsList.end()) + { + mCurrentSoundEffect = mEffectsList[name]; + mCurrentSoundEffect->Play(loopTimes); + mCurrentSoundEffect->SetMuted(mbEffectsMuted); + mCurrentSoundEffect->SetBaseVolume(volume); + } + else + { + star::Logger::GetInstance()-> + Log(LogLevel::Warning, + _T("AudioManager::PlayEffect: Couldn't find effect '") + name + + _T("'."), STARENGINE_LOG_TAG); + } + } + + void AudioManager::AddToBackgroundQueue(const tstring& name) + { + auto it = mMusicList.find(name); + if(it != mMusicList.end()) + { + auto music = mMusicList[name]; + music->SetMuted(mbMusicMuted); + mBackgroundQueue.push_back(music); + } + else + { + star::Logger::GetInstance()-> + Log(LogLevel::Warning, + _T("AudioManager::AddToBackgroundQueue: Couldn't find background song '") + name + + _T("'."), STARENGINE_LOG_TAG); + } + } + + void AudioManager::PlayBackgroundQueue() + { + mQueueIterator = mBackgroundQueue.begin(); + if(mQueueIterator != mBackgroundQueue.end()) + { + (*mQueueIterator)->SetMuted(mbMusicMuted); + (*mQueueIterator)->PlayQueued(0); + } + else + { + LOG(LogLevel::Warning, + _T("PlayEffect::AddToBackgroundQueue: No song in background queue."), + STARENGINE_LOG_TAG); + } + } + + void AudioManager::PlayNextSongInQueue() + { + if(mBackgroundQueue.size() == 0) + { + return; + } + + ++mQueueIterator; + if(mQueueIterator != mBackgroundQueue.end()) + { + (*mQueueIterator)->SetMuted(mbMusicMuted); + (*mQueueIterator)->PlayQueued(0); + } + } + + void AudioManager::PauseBackgroundQueue() + { + if(mBackgroundQueue.size() == 0) + { + return; + } + + if(mQueueIterator != mBackgroundQueue.end()) + { + (*mQueueIterator)->Pause(); + } + } + + void AudioManager::ResumeBackgroundQueue() + { + if(mBackgroundQueue.size() == 0) + { + return; + } + + if(mQueueIterator != mBackgroundQueue.end()) + { + (*mQueueIterator)->Resume(); + } + else + { + LOG(LogLevel::Warning, + _T("AudioManager::ResumeBackgroundQueue: \ +Sound Service : No song in background queue."), + STARENGINE_LOG_TAG); + } + } + + void AudioManager::StopBackgroundQueue() + { + if(mBackgroundQueue.size() == 0) + { + return; + } + + if(mQueueIterator != mBackgroundQueue.end()) + { + (*mQueueIterator)->Stop(); + mQueueIterator = mBackgroundQueue.begin(); + } + else + { + LOG(LogLevel::Warning, + _T("AudioManager::StopBackgroundQueue: \ +Sound Service : No song in background queue."), + STARENGINE_LOG_TAG); + } + } + + void AudioManager::PauseMusic(const tstring & name) + { + auto it = mMusicList.find(name); + if(it != mMusicList.end()) + { + it->second->Pause(); + } + else + { + LOG(LogLevel::Error, + _T("AudioManager::PauseMusic: Couldn't find '") + + name + _T("'."), STARENGINE_LOG_TAG); + } + } + + void AudioManager::ResumeMusic(const tstring & name) + { + auto it = mMusicList.find(name); + if(it != mMusicList.end()) + { + it->second->SetMuted(mbMusicMuted); + it->second->Resume(); + } + else + { + LOG(LogLevel::Error, + _T("AudioManager::ResumeMusic: Couldn't find '") + + name + _T("'."), STARENGINE_LOG_TAG); + } + } + + void AudioManager::StopMusic(const tstring & name) + { + auto it = mMusicList.find(name); + if(it != mMusicList.end()) + { + it->second->Stop(); + } + else + { + LOG(LogLevel::Error, + _T("AudioManager::StopMusic: Couldn't find '") + + name + _T("'."), STARENGINE_LOG_TAG); + } + } + + bool AudioManager::IsMusicPaused(const tstring & name) const + { + auto it = mMusicList.find(name); + if(it != mMusicList.end()) + { + return it->second->IsPaused(); + } + else + { + LOG(LogLevel::Error, + _T("AudioManager::IsMusicPaused: Couldn't find '") + + name + _T("'."), STARENGINE_LOG_TAG); + } + return false; + } + + bool AudioManager::IsMusicStopped(const tstring & name) const + { + auto it = mMusicList.find(name); + if(it != mMusicList.end()) + { + return it->second->IsStopped(); + } + else + { + LOG(LogLevel::Error, + _T("AudioManager::IsMusicStopped: Couldn't find '") + + name + _T("'."), STARENGINE_LOG_TAG); + } + return false; + } + + bool AudioManager::IsMusicPlaying(const tstring & name) const + { + auto it = mMusicList.find(name); + if(it != mMusicList.end()) + { + return it->second->IsPlaying(); + } + else + { + LOG(LogLevel::Error, + _T("AudioManager::IsMusicPlaying: Couldn't find '") + + name + _T("'."), STARENGINE_LOG_TAG); + } + return false; + } + + bool AudioManager::IsMusicLooping(const tstring & name) const + { + auto it = mMusicList.find(name); + if(it != mMusicList.end()) + { + return it->second->IsLooping(); + } + else + { + LOG(LogLevel::Error, + _T("AudioManager::IsMusicLooping: Couldn't find '") + + name + _T("'."), STARENGINE_LOG_TAG); + } + return false; + } + + void AudioManager::PauseEffect(const tstring & name) + { + auto it = mEffectsList.find(name); + if(it != mEffectsList.end()) + { + it->second->Pause(); + } + else + { + LOG(LogLevel::Error, + _T("AudioManager::PauseEffect: Couldn't find '") + + name + _T("'."), STARENGINE_LOG_TAG); + } + } + + void AudioManager::ResumeEffect(const tstring & name) + { + auto it = mEffectsList.find(name); + if(it != mEffectsList.end()) + { + it->second->SetMuted(mbEffectsMuted); + it->second->Resume(); + } + else + { + LOG(LogLevel::Error, + _T("AudioManager::ResumeEffect: Couldn't find '") + + name + _T("'."), STARENGINE_LOG_TAG); + } + } + + void AudioManager::StopEffect(const tstring & name) + { + auto it = mEffectsList.find(name); + if(it != mEffectsList.end()) + { + it->second->Stop(); + } + else + { + LOG(LogLevel::Error, + _T("AudioManager::StopEffect: Couldn't find '") + + name + _T("'."), STARENGINE_LOG_TAG); + } + } + + bool AudioManager::IsEffectPaused(const tstring & name) const + { + auto it = mEffectsList.find(name); + if(it != mEffectsList.end()) + { + return it->second->IsPaused(); + } + else + { + LOG(LogLevel::Error, + _T("AudioManager::IsEffectPaused: Couldn't find '") + + name + _T("'."), STARENGINE_LOG_TAG); + } + return false; + } + + bool AudioManager::IsEffectStopped(const tstring & name) const + { + auto it = mEffectsList.find(name); + if(it != mEffectsList.end()) + { + return it->second->IsStopped(); + } + else + { + LOG(LogLevel::Error, + _T("AudioManager::IsEffectStopped: Couldn't find '") + + name + _T("'."), STARENGINE_LOG_TAG); + } + return false; + } + + bool AudioManager::IsEffectPlaying(const tstring & name) const + { + auto it = mEffectsList.find(name); + if(it != mEffectsList.end()) + { + return it->second->IsPlaying(); + } + else + { + LOG(LogLevel::Error, + _T("AudioManager::IsEffectPlaying: Couldn't find '") + + name + _T("'."), STARENGINE_LOG_TAG); + } + return false; + } + + bool AudioManager::IsEffectLooping(const tstring & name) const + { + auto it = mEffectsList.find(name); + if(it != mEffectsList.end()) + { + return it->second->IsLooping(); + } + else + { + LOG(LogLevel::Error, + _T("AudioManager::IsEffectLooping: Couldn't find '") + + name + _T("'."), STARENGINE_LOG_TAG); + } + return false; + } + + void AudioManager::SetMusicVolume(const tstring& name, float32 volume) + { + auto it = mMusicList.find(name); + if(it != mMusicList.end()) + { + it->second->SetBaseVolume(volume); + } + else + { + LOG(LogLevel::Error, + _T("AudioManager::SetMusicVolume: Couldn't find '") + + name + _T("'."), STARENGINE_LOG_TAG); + } + } + + float32 AudioManager::GetMusicVolume(const tstring& name) const + { + auto it = mMusicList.find(name); + if(it != mMusicList.end()) + { + return it->second->GetVolume(); + } + else + { + LOG(LogLevel::Error, + _T("AudioManager::SetMusicVolume: Couldn't find '") + + name + _T("'."), STARENGINE_LOG_TAG); + } + return 0; + } + + void AudioManager::SetEffectVolume(const tstring& name, float32 volume) + { + auto it = mEffectsList.find(name); + if(it != mEffectsList.end()) + { + it->second->SetBaseVolume(volume); + } + else + { + LOG(LogLevel::Error, + _T("AudioManager::SetEffectVolume: Couldn't find '") + + name + _T("'."), STARENGINE_LOG_TAG); + } + } + + float32 AudioManager::GetEffectVolume(const tstring& name) const + { + auto it = mEffectsList.find(name); + if(it != mEffectsList.end()) + { + return it->second->GetVolume(); + } + else + { + LOG(LogLevel::Error, + _T("AudioManager::GetEffectVolume: Couldn't find '") + + name + _T("'."), STARENGINE_LOG_TAG); + } + return 0; + } + + void AudioManager::IncreaseMusicVolume(const tstring& name, float32 volume) + { + auto it = mMusicList.find(name); + if(it != mMusicList.end()) + { + it->second->IncreaseVolume(volume); + } + else + { + LOG(LogLevel::Error, + _T("AudioManager::IncreaseMusicVolume: Couldn't find '") + + name + _T("'."), STARENGINE_LOG_TAG); + } + } + + void AudioManager::DecreaseMusicVolume(const tstring& name, float32 volume) + { + auto it = mMusicList.find(name); + if(it != mMusicList.end()) + { + it->second->DecreaseVolume(volume); + } + else + { + LOG(LogLevel::Error, + _T("AudioManager::DecreaseMusicVolume: Couldn't find '") + + name + _T("'."), STARENGINE_LOG_TAG); + } + } + + void AudioManager::IncreaseEffectVolume(const tstring& name, float32 volume) + { + auto it = mEffectsList.find(name); + if(it != mEffectsList.end()) + { + it->second->IncreaseVolume(volume); + } + else + { + LOG(LogLevel::Error, + _T("AudioManager::IncreaseEffectVolume: Couldn't find '") + + name + _T("'."), STARENGINE_LOG_TAG); + } + } + void AudioManager::DecreaseEffectVolume(const tstring& name, float32 volume) + { + auto it = mEffectsList.find(name); + if(it != mEffectsList.end()) + { + it->second->DecreaseVolume(volume); + } + else + { + LOG(LogLevel::Error, + _T("AudioManager::DecreaseEffectVolume: Couldn't find '") + + name + _T("'."), STARENGINE_LOG_TAG); + } + } + + void AudioManager::MuteAllMusic(bool mute) + { + mbMusicMuted = mute; + for(auto & it : mMusicList) + { + it.second->SetMuted(mute); + } + } + + bool AudioManager::IsAllMusicMuted() const + { + return mbMusicMuted; + } + + void AudioManager::SetMusicMuted(const tstring& name, bool muted) + { + if(mbMusicMuted && !muted) + { + mbMusicMuted = false; + MuteAllMusic(false); + } + auto it = mMusicList.find(name); + if(it != mMusicList.end()) + { + it->second->SetMuted(muted); + } + else + { + LOG(LogLevel::Error, + _T("AudioManager::SetMusicMuted: Couldn't find '") + + name + _T("'."), STARENGINE_LOG_TAG); + } + } + + bool AudioManager::IsMusicMuted(const tstring& name) const + { + auto it = mMusicList.find(name); + if(it != mMusicList.end()) + { + return it->second->IsMuted(); + } + else + { + LOG(LogLevel::Error, + _T("AudioManager::IsMusicMuted: Couldn't find '") + + name + _T("'."), STARENGINE_LOG_TAG); + return false; + } + } + + void AudioManager::MuteAllEffects(bool mute) + { + mbEffectsMuted = mute; + for(auto & it : mEffectsList) + { + it.second->SetMuted(mute); + } + } + + bool AudioManager::IsAllEffectsMuted() const + { + return mbEffectsMuted; + } + + void AudioManager::SetEffectMuted(const tstring& name, bool muted) + { + if(mbEffectsMuted && !muted) + { + mbEffectsMuted = false; + MuteAllEffects(false); + } + auto it = mEffectsList.find(name); + if(it != mEffectsList.end()) + { + it->second->SetMuted(muted); + } + else + { + LOG(LogLevel::Error, + _T("AudioManager::SetEffectMuted: Couldn't find '") + + name + _T("'."), STARENGINE_LOG_TAG); + } + } + + bool AudioManager::IsEffectMuted(const tstring& name) const + { + auto it = mEffectsList.find(name); + if(it != mEffectsList.end()) + { + return it->second->IsMuted(); + } + else + { + LOG(LogLevel::Error, + _T("AudioManager::IsEffectMuted: Couldn't find '") + + name + _T("'."), STARENGINE_LOG_TAG); + return false; + } + } + + bool AudioManager::ToggleMusicMuted(const tstring& name) + { + auto it = mEffectsList.find(name); + if(it != mEffectsList.end()) + { + it->second->SetMuted(!it->second->IsMuted()); + return it->second->IsMuted(); + } + else + { + LOG(LogLevel::Error, + _T("AudioManager::ToggleMusicMuted: Couldn't find '") + + name + _T("'."), STARENGINE_LOG_TAG); + return false; + } + } + + bool AudioManager::ToggleEffectMuted(const tstring& name) + { + auto it = mMusicList.find(name); + if(it != mMusicList.end()) + { + it->second->SetMuted(!it->second->IsMuted()); + return it->second->IsMuted(); + } + else + { + LOG(LogLevel::Error, + _T("AudioManager::ToggleEffectMuted: Couldn't find '") + + name + _T("'."), STARENGINE_LOG_TAG); + return false; + } + } + + void AudioManager::AddSoundToChannel(uint8 channel, BaseSound * pSound) + { + auto & chnl = mChannels[channel]; + auto it = chnl.sounds.begin(); + auto end = chnl.sounds.end(); + for(auto sound : chnl.sounds) + { + if(sound == pSound) + { + LOG(LogLevel::Warning, + _T("AudioManager::AddSoundToChannel: Trying to add a sound twice in channel '") + + string_cast(channel) + _T("'."), STARENGINE_LOG_TAG); + return; + } + } + pSound->SetChannelVolume(chnl.volume); + chnl.sounds.push_back(pSound); + chnl.channel = channel; + switch(chnl.state) + { + case ChannelState::paused: + pSound->Pause(); + break; + case ChannelState::stopped: + pSound->Stop(); + break; + } + } + + void AudioManager::RemoveSoundFromChannel(uint8 channel, BaseSound * pSound) + { + bool result; + SoundChannel & chnl = GetChannel( + channel, + _T("AudioManager::RemoveSoundFromChannel"), + result + ); + if(result) + { + for(auto it = chnl.sounds.begin() ; + it != chnl.sounds.end() ; + ++it + ) + { + if(*it == pSound) + { + pSound->SetChannelVolume(1.0f); + chnl.sounds.erase(it); + return; + } + } + LOG(LogLevel::Warning, + _T("AudioManager::RemoveSoundFromChannel: Sound not found in channel '") + + string_cast(channel) + _T("'."), STARENGINE_LOG_TAG); + } + } + + void AudioManager::SetChannelVolume(uint8 channel, float32 volume) + { + bool result; + SoundChannel & chnl = GetChannel( + channel, + _T("AudioManager::SetChannelVolume"), + result + ); + if(result) + { + chnl.SetVolume(volume); + } + } + + float32 AudioManager::GetChannelVolume(uint8 channel) + { + bool result; + SoundChannel & chnl = GetChannel( + channel, + _T("AudioManager::GetChannelVolume"), + result + ); + if(result) + { + return chnl.volume; + } + return 0; + } + + void AudioManager::IncreaseChannelVolume(uint8 channel, float32 volume) + { + bool result; + SoundChannel & chnl = GetChannel( + channel, + _T("AudioManager::IncreaseChannelVolume"), + result + ); + if(result) + { + chnl.IncreaseVolume(volume); + } + } + + void AudioManager::DecreaseChannelVolume(uint8 channel, float32 volume) + { + bool result; + SoundChannel & chnl = GetChannel( + channel, + _T("AudioManager::DecreaseChannelVolume"), + result + ); + if(result) + { + chnl.DecreaseVolume(volume); + } + } + + void AudioManager::SetChannelMuted(uint8 channel, bool muted) + { + bool result; + SoundChannel & chnl = GetChannel( + channel, + _T("AudioManager::SetChannelMuted"), + result + ); + if(result) + { + chnl.SetMuted(muted); + } + } + + bool AudioManager::IsChannelMuted(uint8 channel) + { + bool result; + SoundChannel & chnl = GetChannel( + channel, + _T("AudioManager::IsChannelMuted"), + result + ); + if(result) + { + return chnl.isMuted; + } + return false; + } + + bool AudioManager::ToggleChannelMuted(uint8 channel) + { + bool result; + SoundChannel & chnl = GetChannel( + channel, + _T("AudioManager::ToggleChannelMuted"), + result + ); + if(result) + { + chnl.SetMuted(!chnl.isMuted); + return chnl.isMuted; + } + return false; + } + + void AudioManager::SetMusicChannel(const tstring & name, uint8 channel) + { + auto it = mMusicList.find(name); + if(it != mMusicList.end()) + { + it->second->SetChannel(channel); + } + else + { + LOG(LogLevel::Error, + _T("AudioManager::SetMusicChannel: Couldn't find '") + + name + _T("'."), STARENGINE_LOG_TAG); + } + } + + void AudioManager::UnsetMusicChannel(const tstring & name) + { + auto it = mMusicList.find(name); + if(it != mMusicList.end()) + { + it->second->UnsetChannel(); + } + else + { + LOG(LogLevel::Error, + _T("AudioManager::SetMusicChannel: Couldn't find '") + + name + _T("'."), STARENGINE_LOG_TAG); + } + } + + void AudioManager::SetEffectChannel(const tstring & name, uint8 channel) + { + auto it = mEffectsList.find(name); + if(it != mEffectsList.end()) + { + it->second->SetChannel(channel); + } + else + { + LOG(LogLevel::Error, + _T("AudioManager::SetEffectChannel: Couldn't find '") + + name + _T("'."), STARENGINE_LOG_TAG); + } + } + + void AudioManager::UnsetEffectChannel(const tstring & name) + { + auto it = mEffectsList.find(name); + if(it != mEffectsList.end()) + { + it->second->UnsetChannel(); + } + else + { + LOG(LogLevel::Error, + _T("AudioManager::UnsetEffectChannel: Couldn't find '") + + name + _T("'."), STARENGINE_LOG_TAG); + } + } + + void AudioManager::PauseChannel(uint8 channel) + { + bool result; + SoundChannel & chnl = GetChannel( + channel, + _T("AudioManager::PauseChannel"), + result + ); + if(result) + { + for(auto sound : chnl.sounds) + { + sound->Pause(); + } + chnl.state = ChannelState::paused; + } + } + + bool AudioManager::IsChannelPaused(uint8 channel) + { + bool result; + SoundChannel & chnl = GetChannel( + channel, + _T("AudioManager::IsChannelPaused"), + result + ); + if(result) + { + return chnl.state == ChannelState::paused; + } + return false; + } + + void AudioManager::ResumeChannel(uint8 channel) + { + bool result; + SoundChannel & chnl = GetChannel( + channel, + _T("AudioManager::ResumeChannel"), + result + ); + if(result) + { + for(auto sound : chnl.sounds) + { + sound->Resume(); + } + chnl.state = ChannelState::playing; + } + } + + bool AudioManager::IsChannelPlaying(uint8 channel) + { + bool result; + SoundChannel & chnl = GetChannel( + channel, + _T("AudioManager::IsChannelPlaying"), + result + ); + if(result) + { + return chnl.state == ChannelState::playing; + } + return false; + } + + void AudioManager::StopChannel(uint8 channel) + { + bool result; + SoundChannel & chnl = GetChannel( + channel, + _T("AudioManager::StopChannel"), + result + ); + if(result) + { + for(auto sound : chnl.sounds) + { + sound->Stop(); + } + chnl.state = ChannelState::stopped; + } + } + + bool AudioManager::IsChannelStopped(uint8 channel) + { + bool result; + SoundChannel & chnl = GetChannel( + channel, + _T("AudioManager::IsChannelStopped"), + result + ); + if(result) + { + return chnl.state == ChannelState::stopped; + } + return false; + } + + void AudioManager::PlayChannel(uint8 channel, int32 loopTimes) + { + bool result; + SoundChannel & chnl = GetChannel( + channel, + _T("AudioManager::PlayChannel"), + result + ); + if(result) + { + for(auto sound : chnl.sounds) + { + sound->Play(loopTimes); + } + chnl.state = ChannelState::playing; + } + } + + void AudioManager::StopAllSounds() + { + for(auto & song : mMusicList) + { + song.second->Stop(); + } + + for(auto & effect : mEffectsList) + { + effect.second->Stop(); + } + } + + void AudioManager::PauseAllSounds() + { + for(auto & song : mMusicList) + { + song.second->Pause(); + } + + for(auto & effect : mEffectsList) + { + effect.second->Pause(); + } + } + + void AudioManager::ResumeAllSounds() + { + for(auto & song : mMusicList) + { + song.second->Resume(); + } + + for(auto & effect : mEffectsList) + { + effect.second->Resume(); + } + } + + void AudioManager::DeleteAllSounds() + { + for(auto & song : mMusicList) + { + delete song.second; + } + mMusicList.clear(); + + for(auto & effect : mEffectsList) + { + delete effect.second; + } + mEffectsList.clear(); + + } + + void AudioManager::SetVolume(float32 volume) + { + mVolume = Clamp(volume, 0.0f, 1.0f); + + for(auto & song : mMusicList) + { + song.second->SetMasterVolume(volume); + } + + for(auto & effect : mEffectsList) + { + effect.second->SetMasterVolume(volume); + } + } + + float32 AudioManager::GetVolume() const + { + return mVolume; + } + + void AudioManager::IncreaseVolume(float32 volume) + { + float32 vol = GetVolume(); + vol += volume; + SetVolume(vol); + } + + void AudioManager::DecreaseVolume(float32 volume) + { + float32 vol = GetVolume(); + vol -= volume; + SetVolume(vol); + } + + AudioManager::SoundChannel & AudioManager::GetChannel( + uint8 channel, + const tstring & sender, + bool & result + ) + { + auto it = mChannels.find(channel); + result = it != mChannels.end(); + if(result) + { + return it->second; + } + else + { + LOG(LogLevel::Error, + sender + _T(": Couldn't find channel '") + + string_cast(channel) + _T("'."), + STARENGINE_LOG_TAG); + } + return mEmptyChannel; + } + +#ifdef ANDROID + const SLEngineItf& AudioManager::GetEngine() const + { + return mEngine; + } + + const SLObjectItf& AudioManager::GetOutputMixObject() const + { + return mOutputMixObj; + } + + +#endif + + AudioManager::SoundChannel::SoundChannel() + : volume(1.0f) + , isMuted(false) + , sounds() + , channel(0) + , state(ChannelState::playing) + { + } + + AudioManager::SoundChannel::~SoundChannel() + { + for(auto it : sounds) + { + it->SetChannelVolume(1.0f); + it->UnsetChannel(); + } + sounds.clear(); + } + + void AudioManager::SoundChannel::SetVolume(float32 newVolume) + { + volume = Clamp(newVolume, 0.0f, 1.0f); + for(auto & it : sounds) + { + it->SetChannelVolume(volume); + } + } + + void AudioManager::SoundChannel::IncreaseVolume(float32 volume) + { + SetVolume(volume + volume); + } + + void AudioManager::SoundChannel::DecreaseVolume(float32 volume) + { + SetVolume(volume - volume); + } + + void AudioManager::SoundChannel::SetMuted(bool muted) + { + isMuted = muted; + for( auto it : sounds) + { + it->SetMuted(muted); + } + } +} diff --git a/src/Sound/BaseSound.cpp b/src/Sound/BaseSound.cpp index 4ad25ba..4ab3c55 100755 --- a/src/Sound/BaseSound.cpp +++ b/src/Sound/BaseSound.cpp @@ -1,451 +1,451 @@ -#include "BaseSound.h" -#include "AudioManager.h" -#include "../Logger.h" -#include "../Graphics/Resource.h" -#include "../Helpers/Helpers.h" -#include "../Helpers/FilePath.h" -#include "../Helpers/Math.h" - -#ifdef ANDROID -#include "../StarEngine.h" -#endif - - -namespace star -{ -#ifdef ANDROID - const SLInterfaceID BaseSound::PLAYER_ID_ARR[] = - {SL_IID_PLAY, SL_IID_SEEK, SL_IID_VOLUME}; - const SLboolean BaseSound::PLAYER_REQ_ARR[] = - {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE}; -#endif - - BaseSound::~BaseSound() - { - } - - void BaseSound::Play(int32 loopTime) - { - mSoundState = SoundState::playing; - mbIsLooping = loopTime == -1; - } - - void BaseSound::Stop() - { - mSoundState = SoundState::stopped; - } - - void BaseSound::Pause() - { - mSoundState = SoundState::paused; - } - - void BaseSound::Resume() - { - mSoundState = SoundState::playing; - } - - bool BaseSound::IsStopped() const - { - return mSoundState == SoundState::stopped; - } - - bool BaseSound::IsPlaying() const - { - return mSoundState == SoundState::playing; - } - - bool BaseSound::IsPaused() const - { - return mSoundState == SoundState::paused; - } - - bool BaseSound::IsLooping() const - { - return mbIsLooping && IsPlaying(); - } - - void BaseSound::SetCompleteVolume( - float32 volume, - float32 channelVolume, - float32 masterVolume - ) - { - mSoundVolume.volume = volume; - mSoundVolume.channelVolume = channelVolume; - mSoundVolume.masterVolume = masterVolume; - SetVolume(mSoundVolume.GetVolume()); - } - - void BaseSound::SetBaseVolume( - float32 volume - ) - { - mSoundVolume.volume = volume; - SetVolume(mSoundVolume.GetVolume()); - } - - void BaseSound::SetChannelVolume( - float32 volume - ) - { - mSoundVolume.channelVolume = volume; - SetVolume(mSoundVolume.GetVolume()); - } - - void BaseSound::SetMasterVolume( - float32 volume - ) - { - mSoundVolume.masterVolume = volume; - SetVolume(mSoundVolume.GetVolume()); - } - - float32 BaseSound::GetBaseVolume() const - { - return mSoundVolume.volume; - } - - void BaseSound::SetVolume(float32 volume) - { -#ifdef DESKTOP - volume = Clamp(volume, 0.0f, 1.0f); - int32 vol(int32(volume * float32(MIX_MAX_VOLUME))); - SetSoundVolume(vol); -#endif - } - - void BaseSound::IncreaseVolume(float32 volume) - { - mSoundVolume.volume += volume; - mSoundVolume.volume = Clamp(mSoundVolume.volume, 0.0f, 1.0f); - SetVolume(mSoundVolume.GetVolume()); - } - - void BaseSound::DecreaseVolume(float32 volume) - { - mSoundVolume.volume -= volume; - mSoundVolume.volume = Clamp(mSoundVolume.volume, 0.0f, 1.0f); - SetVolume(mSoundVolume.GetVolume()); - } - - void BaseSound::SetChannel(uint8 channel) - { - if(!mNoChannelAssigned) - { - UnsetChannel(); - } - mChannel = channel; - mNoChannelAssigned = false; - } - - void BaseSound::UnsetChannel() - { - mNoChannelAssigned = true; - } - - uint8 BaseSound::GetChannel() const - { - return mChannel; - } - - BaseSound::BaseSound(uint8 channel) - : mbIsLooping(false) - , mNoChannelAssigned(true) -#ifdef DESKTOP - , mIsMuted(false) - , mVolume(1) -#else - , mPath(EMPTY_STRING) -#endif - , mChannel(0) - , mSoundVolume() - , mSoundState(SoundState::stopped) - - { - } - -#ifdef ANDROID - void BaseSound::CreateSoundDetails() - { - - } - - void BaseSound::CreateSound( - SLObjectItf & sound, - SLEngineItf & engine, - SLPlayItf & player, - const tstring & path - ) - { - SLresult lRes; - - Resource lResource(path); - - ResourceDescriptor lDescriptor = lResource.DeScript(); - if(lDescriptor.mDescriptor < 0) - { - LOG(LogLevel::Error, - _T("Sound: Could not open file"), STARENGINE_LOG_TAG); - return; - } - SLDataLocator_AndroidFD lDataLocatorIn; - lDataLocatorIn.locatorType = SL_DATALOCATOR_ANDROIDFD; - lDataLocatorIn.fd = lDescriptor.mDescriptor; - lDataLocatorIn.offset = lDescriptor.mStart; - lDataLocatorIn.length = lDescriptor.mLength; - - SLDataFormat_MIME lDataFormat; - lDataFormat.formatType = SL_DATAFORMAT_MIME; - lDataFormat.mimeType = NULL; - lDataFormat.containerType = SL_CONTAINERTYPE_UNSPECIFIED; - - SLDataSource lDataSource; - lDataSource.pLocator = &lDataLocatorIn; - lDataSource.pFormat = &lDataFormat; - - SLDataLocator_OutputMix lDataLocatorOut; - lDataLocatorOut.locatorType = SL_DATALOCATOR_OUTPUTMIX; - lDataLocatorOut.outputMix = AudioManager::GetInstance()->GetOutputMixObject(); - - SLDataSink lDataSink; - lDataSink.pLocator = &lDataLocatorOut; - lDataSink.pFormat = NULL; - - lRes = (*engine)->CreateAudioPlayer( - engine, - &sound, - &lDataSource, - &lDataSink, - PLAYER_ID_COUNT, - PLAYER_ID_ARR, - PLAYER_REQ_ARR - ); - - if (lRes != SL_RESULT_SUCCESS) - { - LOG(LogLevel::Error, - _T("Sound: Can't create audio player"), STARENGINE_LOG_TAG); - Stop(); - return; - } - - lRes = (*sound)->Realize(sound, SL_BOOLEAN_FALSE); - - if (lRes != SL_RESULT_SUCCESS) - { - LOG(LogLevel::Error, - _T("Sound: Can't realise audio player"), STARENGINE_LOG_TAG); - Stop(); - return; - } - - lRes = (*sound)->GetInterface(sound, SL_IID_PLAY, &player); - - if (lRes != SL_RESULT_SUCCESS) - { - LOG(LogLevel::Error, - _T("Sound: Can't get audio play interface"), STARENGINE_LOG_TAG); - Stop(); - return; - } - - if((*player)->SetCallbackEventsMask( - player, SL_PLAYSTATE_STOPPED) != SL_RESULT_SUCCESS) - { - LOG(LogLevel::Error, - _T("Sound: Can't set callback flags"), STARENGINE_LOG_TAG); - } - - CreateSoundDetails(); - - RegisterCallback(player); - } - - void BaseSound::DestroySound( - SLObjectItf & sound, - SLPlayItf & player - ) - { - if(player != NULL) - { - SLuint32 lPlayerState; - (*sound)->GetState(sound, &lPlayerState); - if(lPlayerState == SL_OBJECT_STATE_REALIZED) - { - (*player)->SetPlayState(player,SL_PLAYSTATE_PAUSED); - (*sound)->Destroy(sound); - sound = NULL; - player = NULL; - LOG(LogLevel::Error, - _T("Sound: Soundfile Destroyed"), STARENGINE_LOG_TAG); - } - } - } - - void BaseSound::ResumeSound(SLPlayItf & player) - { - SLresult lres = - (*player)->GetPlayState(player, &lres); - if(lres == SL_PLAYSTATE_PAUSED) - { - (*player)->SetPlayState(player, SL_PLAYSTATE_PLAYING); - } - } - - void BaseSound::SetSoundVolume( - SLObjectItf & sound, - SLPlayItf & player, - float32 volume - ) - { - SLVolumeItf volumeItf; - if(GetVolumeInterface(sound, player, &volumeItf)) - { - volume = Clamp(volume, 0.0f, 1.0f); - volume = (volume / 10.0f) + 0.9f; - SLmillibel actualMillibelLevel, maxMillibelLevel; - SLresult result = (*volumeItf)->GetMaxVolumeLevel( - volumeItf, - &maxMillibelLevel - ); - ASSERT_LOG(result == SL_RESULT_SUCCESS, - _T("Sound: Couldn't get the maximum volume level!"), - STARENGINE_LOG_TAG); - actualMillibelLevel = SLmillibel( - (1.0f - volume) * - float32(SL_MILLIBEL_MIN - maxMillibelLevel)) - + maxMillibelLevel; - result = (*volumeItf)->SetVolumeLevel( - volumeItf, - actualMillibelLevel - ); - ASSERT_LOG(result == SL_RESULT_SUCCESS, - _T("Sound: Couldn't set the volume!"), - STARENGINE_LOG_TAG); - } - } - - bool BaseSound::GetVolumeInterface( - const SLObjectItf & sound, - const SLPlayItf & player, - void * pInterface - ) const - { - if(player != nullptr) - { - SLuint32 lPlayerState; - (*sound)->GetState(sound, &lPlayerState); - if(lPlayerState == SL_OBJECT_STATE_REALIZED) - { - SLresult result = (*sound)->GetInterface( - sound, SL_IID_VOLUME, pInterface - ); - bool isOK = result == SL_RESULT_SUCCESS; - ASSERT_LOG(isOK, - _T("Sound: Couldn't get the interface!"), - STARENGINE_LOG_TAG); - return isOK; - } - } - return false; - } - - float32 BaseSound::GetSoundVolume( - const SLObjectItf & sound, - const SLPlayItf & player - ) const - { - SLVolumeItf volumeItf; - if(GetVolumeInterface(sound, player, &volumeItf)) - { - SLmillibel actualMillibelLevel, maxMillibelLevel; - SLresult result = result = (*volumeItf)->GetVolumeLevel( - volumeItf, - &actualMillibelLevel - ); - ASSERT_LOG(result == SL_RESULT_SUCCESS, - _T("Sound: Couldn't get the volume!"), - STARENGINE_LOG_TAG); - result = (*volumeItf)->GetMaxVolumeLevel( - volumeItf, - &maxMillibelLevel - ); - ASSERT_LOG(result == SL_RESULT_SUCCESS, - _T("Sound: Couldn't get the maximum volume level!"), - STARENGINE_LOG_TAG); - float32 posMinVol = float32(SL_MILLIBEL_MIN) * -1.0f; - float32 volume = - float32(actualMillibelLevel + posMinVol) / - float32(posMinVol + maxMillibelLevel); - return volume; - } - return 0; - } - - void BaseSound::SetSoundMuted( - SLObjectItf & sound, - SLPlayItf & player, - bool muted - ) - { - SLVolumeItf volumeItf; - if(GetVolumeInterface(sound, player, &volumeItf)) - { - SLresult result = (*volumeItf)->SetMute( - volumeItf, SLboolean(muted) - ); - ASSERT_LOG(result == SL_RESULT_SUCCESS, - _T("BaseSound::SetMuted: Couldn't set muted state!"), - STARENGINE_LOG_TAG); - } - } - - bool BaseSound::GetSoundMuted( - const SLObjectItf & sound, - const SLPlayItf & player - ) const - { - SLVolumeItf volumeItf; - if(GetVolumeInterface(sound, player, &volumeItf)) - { - SLboolean isMuted; - SLresult result = (*volumeItf)->GetMute( - volumeItf, &isMuted - ); - ASSERT_LOG(result == SL_RESULT_SUCCESS, - _T("BaseSound::SetMuted: Couldn't get muted state!"), - STARENGINE_LOG_TAG); - return bool(isMuted); - } - return false; - } -#else - void BaseSound::SetSoundMuted(bool muted) - { - mIsMuted = muted; - if(mIsMuted) - { - mVolume = GetBaseVolume(); - SetVolume(0); - } - else - { - SetVolume(mVolume); - } - } -#endif - - BaseSound::SoundVolume::SoundVolume() - : volume(1.0f) - , channelVolume(1.0f) - , masterVolume(1.0f) - { - - } - - float32 BaseSound::SoundVolume::GetVolume() const - { - return volume * channelVolume * masterVolume; - } -} +#include "BaseSound.h" +#include "AudioManager.h" +#include "../Logger.h" +#include "../Graphics/Resource.h" +#include "../Helpers/Helpers.h" +#include "../Helpers/Filepath.h" +#include "../Helpers/Math.h" + +#ifdef ANDROID +#include "../StarEngine.h" +#endif + + +namespace star +{ +#ifdef ANDROID + const SLInterfaceID BaseSound::PLAYER_ID_ARR[] = + {SL_IID_PLAY, SL_IID_SEEK, SL_IID_VOLUME}; + const SLboolean BaseSound::PLAYER_REQ_ARR[] = + {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE}; +#endif + + BaseSound::~BaseSound() + { + } + + void BaseSound::Play(int32 loopTime) + { + mSoundState = SoundState::playing; + mbIsLooping = loopTime == -1; + } + + void BaseSound::Stop() + { + mSoundState = SoundState::stopped; + } + + void BaseSound::Pause() + { + mSoundState = SoundState::paused; + } + + void BaseSound::Resume() + { + mSoundState = SoundState::playing; + } + + bool BaseSound::IsStopped() const + { + return mSoundState == SoundState::stopped; + } + + bool BaseSound::IsPlaying() const + { + return mSoundState == SoundState::playing; + } + + bool BaseSound::IsPaused() const + { + return mSoundState == SoundState::paused; + } + + bool BaseSound::IsLooping() const + { + return mbIsLooping && IsPlaying(); + } + + void BaseSound::SetCompleteVolume( + float32 volume, + float32 channelVolume, + float32 masterVolume + ) + { + mSoundVolume.volume = volume; + mSoundVolume.channelVolume = channelVolume; + mSoundVolume.masterVolume = masterVolume; + SetVolume(mSoundVolume.GetVolume()); + } + + void BaseSound::SetBaseVolume( + float32 volume + ) + { + mSoundVolume.volume = volume; + SetVolume(mSoundVolume.GetVolume()); + } + + void BaseSound::SetChannelVolume( + float32 volume + ) + { + mSoundVolume.channelVolume = volume; + SetVolume(mSoundVolume.GetVolume()); + } + + void BaseSound::SetMasterVolume( + float32 volume + ) + { + mSoundVolume.masterVolume = volume; + SetVolume(mSoundVolume.GetVolume()); + } + + float32 BaseSound::GetBaseVolume() const + { + return mSoundVolume.volume; + } + + void BaseSound::SetVolume(float32 volume) + { +#ifdef DESKTOP + volume = Clamp(volume, 0.0f, 1.0f); + int32 vol(int32(volume * float32(MIX_MAX_VOLUME))); + SetSoundVolume(vol); +#endif + } + + void BaseSound::IncreaseVolume(float32 volume) + { + mSoundVolume.volume += volume; + mSoundVolume.volume = Clamp(mSoundVolume.volume, 0.0f, 1.0f); + SetVolume(mSoundVolume.GetVolume()); + } + + void BaseSound::DecreaseVolume(float32 volume) + { + mSoundVolume.volume -= volume; + mSoundVolume.volume = Clamp(mSoundVolume.volume, 0.0f, 1.0f); + SetVolume(mSoundVolume.GetVolume()); + } + + void BaseSound::SetChannel(uint8 channel) + { + if(!mNoChannelAssigned) + { + UnsetChannel(); + } + mChannel = channel; + mNoChannelAssigned = false; + } + + void BaseSound::UnsetChannel() + { + mNoChannelAssigned = true; + } + + uint8 BaseSound::GetChannel() const + { + return mChannel; + } + + BaseSound::BaseSound(uint8 channel) + : mbIsLooping(false) + , mNoChannelAssigned(true) +#ifdef DESKTOP + , mIsMuted(false) + , mVolume(1) +#elif defined(ANDROID) + , mPath(EMPTY_STRING) +#endif + , mChannel(0) + , mSoundVolume() + , mSoundState(SoundState::stopped) + + { + } + +#ifdef ANDROID + void BaseSound::CreateSoundDetails() + { + + } + + void BaseSound::CreateSound( + SLObjectItf & sound, + SLEngineItf & engine, + SLPlayItf & player, + const tstring & path + ) + { + SLresult lRes; + + Resource lResource(path); + + ResourceDescriptor lDescriptor = lResource.DeScript(); + if(lDescriptor.mDescriptor < 0) + { + LOG(LogLevel::Error, + _T("Sound: Could not open file"), STARENGINE_LOG_TAG); + return; + } + SLDataLocator_AndroidFD lDataLocatorIn; + lDataLocatorIn.locatorType = SL_DATALOCATOR_ANDROIDFD; + lDataLocatorIn.fd = lDescriptor.mDescriptor; + lDataLocatorIn.offset = lDescriptor.mStart; + lDataLocatorIn.length = lDescriptor.mLength; + + SLDataFormat_MIME lDataFormat; + lDataFormat.formatType = SL_DATAFORMAT_MIME; + lDataFormat.mimeType = NULL; + lDataFormat.containerType = SL_CONTAINERTYPE_UNSPECIFIED; + + SLDataSource lDataSource; + lDataSource.pLocator = &lDataLocatorIn; + lDataSource.pFormat = &lDataFormat; + + SLDataLocator_OutputMix lDataLocatorOut; + lDataLocatorOut.locatorType = SL_DATALOCATOR_OUTPUTMIX; + lDataLocatorOut.outputMix = AudioManager::GetInstance()->GetOutputMixObject(); + + SLDataSink lDataSink; + lDataSink.pLocator = &lDataLocatorOut; + lDataSink.pFormat = NULL; + + lRes = (*engine)->CreateAudioPlayer( + engine, + &sound, + &lDataSource, + &lDataSink, + PLAYER_ID_COUNT, + PLAYER_ID_ARR, + PLAYER_REQ_ARR + ); + + if (lRes != SL_RESULT_SUCCESS) + { + LOG(LogLevel::Error, + _T("Sound: Can't create audio player"), STARENGINE_LOG_TAG); + Stop(); + return; + } + + lRes = (*sound)->Realize(sound, SL_BOOLEAN_FALSE); + + if (lRes != SL_RESULT_SUCCESS) + { + LOG(LogLevel::Error, + _T("Sound: Can't realise audio player"), STARENGINE_LOG_TAG); + Stop(); + return; + } + + lRes = (*sound)->GetInterface(sound, SL_IID_PLAY, &player); + + if (lRes != SL_RESULT_SUCCESS) + { + LOG(LogLevel::Error, + _T("Sound: Can't get audio play interface"), STARENGINE_LOG_TAG); + Stop(); + return; + } + + if((*player)->SetCallbackEventsMask( + player, SL_PLAYSTATE_STOPPED) != SL_RESULT_SUCCESS) + { + LOG(LogLevel::Error, + _T("Sound: Can't set callback flags"), STARENGINE_LOG_TAG); + } + + CreateSoundDetails(); + + RegisterCallback(player); + } + + void BaseSound::DestroySound( + SLObjectItf & sound, + SLPlayItf & player + ) + { + if(player != NULL) + { + SLuint32 lPlayerState; + (*sound)->GetState(sound, &lPlayerState); + if(lPlayerState == SL_OBJECT_STATE_REALIZED) + { + (*player)->SetPlayState(player,SL_PLAYSTATE_PAUSED); + (*sound)->Destroy(sound); + sound = NULL; + player = NULL; + LOG(LogLevel::Error, + _T("Sound: Soundfile Destroyed"), STARENGINE_LOG_TAG); + } + } + } + + void BaseSound::ResumeSound(SLPlayItf & player) + { + SLresult lres = + (*player)->GetPlayState(player, &lres); + if(lres == SL_PLAYSTATE_PAUSED) + { + (*player)->SetPlayState(player, SL_PLAYSTATE_PLAYING); + } + } + + void BaseSound::SetSoundVolume( + SLObjectItf & sound, + SLPlayItf & player, + float32 volume + ) + { + SLVolumeItf volumeItf; + if(GetVolumeInterface(sound, player, &volumeItf)) + { + volume = Clamp(volume, 0.0f, 1.0f); + volume = (volume / 10.0f) + 0.9f; + SLmillibel actualMillibelLevel, maxMillibelLevel; + SLresult result = (*volumeItf)->GetMaxVolumeLevel( + volumeItf, + &maxMillibelLevel + ); + ASSERT_LOG(result == SL_RESULT_SUCCESS, + _T("Sound: Couldn't get the maximum volume level!"), + STARENGINE_LOG_TAG); + actualMillibelLevel = SLmillibel( + (1.0f - volume) * + float32(SL_MILLIBEL_MIN - maxMillibelLevel)) + + maxMillibelLevel; + result = (*volumeItf)->SetVolumeLevel( + volumeItf, + actualMillibelLevel + ); + ASSERT_LOG(result == SL_RESULT_SUCCESS, + _T("Sound: Couldn't set the volume!"), + STARENGINE_LOG_TAG); + } + } + + bool BaseSound::GetVolumeInterface( + const SLObjectItf & sound, + const SLPlayItf & player, + void * pInterface + ) const + { + if(player != nullptr) + { + SLuint32 lPlayerState; + (*sound)->GetState(sound, &lPlayerState); + if(lPlayerState == SL_OBJECT_STATE_REALIZED) + { + SLresult result = (*sound)->GetInterface( + sound, SL_IID_VOLUME, pInterface + ); + bool isOK = result == SL_RESULT_SUCCESS; + ASSERT_LOG(isOK, + _T("Sound: Couldn't get the interface!"), + STARENGINE_LOG_TAG); + return isOK; + } + } + return false; + } + + float32 BaseSound::GetSoundVolume( + const SLObjectItf & sound, + const SLPlayItf & player + ) const + { + SLVolumeItf volumeItf; + if(GetVolumeInterface(sound, player, &volumeItf)) + { + SLmillibel actualMillibelLevel, maxMillibelLevel; + SLresult result = result = (*volumeItf)->GetVolumeLevel( + volumeItf, + &actualMillibelLevel + ); + ASSERT_LOG(result == SL_RESULT_SUCCESS, + _T("Sound: Couldn't get the volume!"), + STARENGINE_LOG_TAG); + result = (*volumeItf)->GetMaxVolumeLevel( + volumeItf, + &maxMillibelLevel + ); + ASSERT_LOG(result == SL_RESULT_SUCCESS, + _T("Sound: Couldn't get the maximum volume level!"), + STARENGINE_LOG_TAG); + float32 posMinVol = float32(SL_MILLIBEL_MIN) * -1.0f; + float32 volume = + float32(actualMillibelLevel + posMinVol) / + float32(posMinVol + maxMillibelLevel); + return volume; + } + return 0; + } + + void BaseSound::SetSoundMuted( + SLObjectItf & sound, + SLPlayItf & player, + bool muted + ) + { + SLVolumeItf volumeItf; + if(GetVolumeInterface(sound, player, &volumeItf)) + { + SLresult result = (*volumeItf)->SetMute( + volumeItf, SLboolean(muted) + ); + ASSERT_LOG(result == SL_RESULT_SUCCESS, + _T("BaseSound::SetMuted: Couldn't set muted state!"), + STARENGINE_LOG_TAG); + } + } + + bool BaseSound::GetSoundMuted( + const SLObjectItf & sound, + const SLPlayItf & player + ) const + { + SLVolumeItf volumeItf; + if(GetVolumeInterface(sound, player, &volumeItf)) + { + SLboolean isMuted; + SLresult result = (*volumeItf)->GetMute( + volumeItf, &isMuted + ); + ASSERT_LOG(result == SL_RESULT_SUCCESS, + _T("BaseSound::SetMuted: Couldn't get muted state!"), + STARENGINE_LOG_TAG); + return bool(isMuted); + } + return false; + } +#else + void BaseSound::SetSoundMuted(bool muted) + { + mIsMuted = muted; + if(mIsMuted) + { + mVolume = GetBaseVolume(); + SetVolume(0); + } + else + { + SetVolume(mVolume); + } + } +#endif + + BaseSound::SoundVolume::SoundVolume() + : volume(1.0f) + , channelVolume(1.0f) + , masterVolume(1.0f) + { + + } + + float32 BaseSound::SoundVolume::GetVolume() const + { + return volume * channelVolume * masterVolume; + } +} diff --git a/src/Sound/BaseSound.h b/src/Sound/BaseSound.h index 38b798f..1c99c43 100755 --- a/src/Sound/BaseSound.h +++ b/src/Sound/BaseSound.h @@ -1,160 +1,160 @@ -#pragma once - -#include "../defines.h" -#include - -#ifdef DESKTOP - #include "SDL.h" - #include "SDL_mixer.h" -#else - #include "android_native_app_glue.h" - #include - #include - #include -#endif - -namespace star -{ - class BaseSound - { - public: - virtual ~BaseSound(); - - virtual void Play(int32 loopTime = 0); - virtual void Stop(); - virtual void Pause(); - virtual void Resume(); - - bool IsStopped() const; - bool IsPlaying() const; - bool IsPaused() const; - bool IsLooping() const; - - void SetCompleteVolume( - float32 volume, - float32 channelVolume, - float32 masterVolume - ); - void SetBaseVolume( - float32 volume - ); - void SetChannelVolume( - float32 volume - ); - void SetMasterVolume( - float32 volume - ); - - float32 GetBaseVolume() const; - - void IncreaseVolume(float32 volume); - void DecreaseVolume(float32 volume); - - virtual void SetMuted(bool muted) = 0; - virtual bool IsMuted() const = 0; - - virtual void SetChannel(uint8 channel); - virtual void UnsetChannel(); - - uint8 GetChannel() const; - - protected: -#ifdef ANDROID - virtual void SetVolume(float32 volume) = 0; -#else - void SetVolume(float32 volume); -#endif - virtual float32 GetVolume() const = 0; - - BaseSound(uint8 channel); -#ifdef ANDROID - static const SLuint32 PLAYER_ID_COUNT = 3; - static const SLInterfaceID PLAYER_ID_ARR[]; - static const SLboolean PLAYER_REQ_ARR[]; - - tstring mPath; - - virtual void CreateSoundDetails(); - virtual void RegisterCallback(SLPlayItf & player) = 0; - - void CreateSound( - SLObjectItf & sound, - SLEngineItf & engine, - SLPlayItf & player, - const tstring & path - ); - - void DestroySound( - SLObjectItf & sound, - SLPlayItf & player - ); - - void ResumeSound(SLPlayItf & player); - - void SetSoundVolume( - SLObjectItf & sound, - SLPlayItf & player, - float32 volume - ); - - bool GetVolumeInterface( - const SLObjectItf & sound, - const SLPlayItf & player, - void * pInterface - ) const; - - float32 GetSoundVolume( - const SLObjectItf & sound, - const SLPlayItf & player - ) const; - - void SetSoundMuted( - SLObjectItf & sound, - SLPlayItf & player, - bool muted - ); - - bool GetSoundMuted( - const SLObjectItf & sound, - const SLPlayItf & player - ) const; - -#else - bool mIsMuted; - float32 mVolume; - - virtual void SetSoundVolume(int32 volume) = 0; - void SetSoundMuted(bool muted); -#endif - - bool mbIsLooping; - bool mNoChannelAssigned; - uint8 mChannel; - - private: - struct SoundVolume - { - float32 volume; - float32 channelVolume; - float32 masterVolume; - - SoundVolume(); - float32 GetVolume() const; - }; - - enum class SoundState : byte - { - playing = 0, - paused = 1, - stopped = 2 - }; - - SoundVolume mSoundVolume; - SoundState mSoundState; - - BaseSound(const BaseSound& yRef); - BaseSound(BaseSound&& yRef); - BaseSound& operator=(const BaseSound& yRef); - BaseSound& operator=(BaseSound&& yRef); - }; -} +#pragma once + +#include "../defines.h" +#include + +#ifdef DESKTOP + #include "SDL.h" + #include "SDL_mixer.h" +#elif defined(ANDROID) + #include "android_native_app_glue.h" + #include + #include + #include +#endif + +namespace star +{ + class BaseSound + { + public: + virtual ~BaseSound(); + + virtual void Play(int32 loopTime = 0); + virtual void Stop(); + virtual void Pause(); + virtual void Resume(); + + bool IsStopped() const; + bool IsPlaying() const; + bool IsPaused() const; + bool IsLooping() const; + + void SetCompleteVolume( + float32 volume, + float32 channelVolume, + float32 masterVolume + ); + void SetBaseVolume( + float32 volume + ); + void SetChannelVolume( + float32 volume + ); + void SetMasterVolume( + float32 volume + ); + + float32 GetBaseVolume() const; + + void IncreaseVolume(float32 volume); + void DecreaseVolume(float32 volume); + + virtual void SetMuted(bool muted) = 0; + virtual bool IsMuted() const = 0; + + virtual void SetChannel(uint8 channel); + virtual void UnsetChannel(); + + uint8 GetChannel() const; + + protected: +#ifdef ANDROID + virtual void SetVolume(float32 volume) = 0; +#else + void SetVolume(float32 volume); +#endif + virtual float32 GetVolume() const = 0; + + BaseSound(uint8 channel); +#ifdef ANDROID + static const SLuint32 PLAYER_ID_COUNT = 3; + static const SLInterfaceID PLAYER_ID_ARR[]; + static const SLboolean PLAYER_REQ_ARR[]; + + tstring mPath; + + virtual void CreateSoundDetails(); + virtual void RegisterCallback(SLPlayItf & player) = 0; + + void CreateSound( + SLObjectItf & sound, + SLEngineItf & engine, + SLPlayItf & player, + const tstring & path + ); + + void DestroySound( + SLObjectItf & sound, + SLPlayItf & player + ); + + void ResumeSound(SLPlayItf & player); + + void SetSoundVolume( + SLObjectItf & sound, + SLPlayItf & player, + float32 volume + ); + + bool GetVolumeInterface( + const SLObjectItf & sound, + const SLPlayItf & player, + void * pInterface + ) const; + + float32 GetSoundVolume( + const SLObjectItf & sound, + const SLPlayItf & player + ) const; + + void SetSoundMuted( + SLObjectItf & sound, + SLPlayItf & player, + bool muted + ); + + bool GetSoundMuted( + const SLObjectItf & sound, + const SLPlayItf & player + ) const; + +#else + bool mIsMuted; + float32 mVolume; + + virtual void SetSoundVolume(int32 volume) = 0; + void SetSoundMuted(bool muted); +#endif + + bool mbIsLooping; + bool mNoChannelAssigned; + uint8 mChannel; + + private: + struct SoundVolume + { + float32 volume; + float32 channelVolume; + float32 masterVolume; + + SoundVolume(); + float32 GetVolume() const; + }; + + enum class SoundState : byte + { + playing = 0, + paused = 1, + stopped = 2 + }; + + SoundVolume mSoundVolume; + SoundState mSoundState; + + BaseSound(const BaseSound& yRef); + BaseSound(BaseSound&& yRef); + BaseSound& operator=(const BaseSound& yRef); + BaseSound& operator=(BaseSound&& yRef); + }; +} diff --git a/src/Sound/SoundEffect.cpp b/src/Sound/SoundEffect.cpp index 974a86b..523fb41 100755 --- a/src/Sound/SoundEffect.cpp +++ b/src/Sound/SoundEffect.cpp @@ -1,268 +1,268 @@ -#include "SoundEffect.h" -#include "AudioManager.h" -#include "../Logger.h" -#include "../Graphics/Resource.h" -#include "../Helpers/Helpers.h" -#include "../Helpers/FilePath.h" -#include "../Helpers/Math.h" - -#ifdef ANDROID -#include "../StarEngine.h" -#endif - -namespace star -{ - SoundEffect::SoundEffect(const tstring& path, uint8 channel) - : BaseSound(channel) - #ifdef DESKTOP - , mpSound(nullptr) - #else - , mPlayerObjs(MAX_SAMPLES) - , mPlayers(MAX_SAMPLES) - #endif - { - #ifdef ANDROID - SLEngineItf engine = AudioManager::GetInstance()->GetEngine(); - for(int32 i = 0 ; i < MAX_SAMPLES ; ++i) - { - CreateSound(mPlayerObjs[i], engine, mPlayers[i], path); - mLoopTimes.push_back(0); - } - #else - FilePath real_path(path); - sstring sound_path = string_cast(real_path.GetFullPath()); - mpSound = Mix_LoadWAV(sound_path.c_str()); - if(!mpSound) - { - LOG(LogLevel::Error, - _T("SoundEffect: Could not load sound, reason : ") - + string_cast(Mix_GetError()), - STARENGINE_LOG_TAG); - } - #endif - SetChannel(channel); - } - - SoundEffect::~SoundEffect() - { - #ifdef DESKTOP - for(auto it : mPlayChannels) - { - Mix_HaltChannel(it); - } - mPlayChannels.clear(); - #else - for(int32 i = 0 ; i < MAX_SAMPLES ; ++i) - { - DestroySound(mPlayerObjs[i], mPlayers[i]); - } - #endif - if(!mNoChannelAssigned) - { - UnsetChannel(); - } - } - - void SoundEffect::Play(int32 loopTime) - { - BaseSound::Play(loopTime); - #ifdef DESKTOP - mPlayChannels.push_back(Mix_PlayChannel(-1, mpSound, loopTime)); - #else - for(int32 i = 0 ; i < MAX_SAMPLES ; ++i) - { - SLresult lRes; - (*mPlayers[i])->GetPlayState(mPlayers[i], &lRes); - if(lRes == SL_PLAYSTATE_STOPPED) - { - mLoopTimes[i] = loopTime; - lRes = (*mPlayers[i])->SetPlayState(mPlayers[i], SL_PLAYSTATE_PLAYING); - if (lRes != SL_RESULT_SUCCESS) - { - LOG(LogLevel::Error, - _T("SoundEffect: Can't play audio!"), STARENGINE_LOG_TAG); - Stop(); - return; - }; - return; - } - } -#endif - } - - void SoundEffect::Stop() - { - BaseSound::Stop(); -#ifdef DESKTOP - for(auto it : mPlayChannels) - { - Mix_HaltChannel(it); - } - mPlayChannels.clear(); -#else - for(int32 i = 0 ; i < MAX_SAMPLES ; ++i) - { - (*mPlayers[i])->SetPlayState(mPlayers[i], SL_PLAYSTATE_STOPPED); - } -#endif - } - - void SoundEffect::Pause() - { - BaseSound::Pause(); -#ifdef DESKTOP - for(auto it : mPlayChannels) - { - Mix_Pause(it); - } -#else - for(int32 i = 0 ; i < MAX_SAMPLES ; ++i) - { - SLresult lres = (*mPlayers[i])->GetPlayState( - mPlayers[i], &lres - ); - if(lres == SL_PLAYSTATE_PLAYING) - { - (*mPlayers[i])->SetPlayState( - mPlayers[i],SL_PLAYSTATE_PAUSED - ); - } - } -#endif - } - - void SoundEffect::Resume() - { - BaseSound::Resume(); -#ifdef DESKTOP - for(auto it : mPlayChannels) - { - Mix_Resume(it); - } -#else - for(int32 i = 0 ; i < MAX_SAMPLES ; ++i) - { - ResumeSound(mPlayers[i]); - } -#endif - } - - void SoundEffect::SetChannel(uint8 channel) - { - BaseSound::SetChannel(channel); - AudioManager::GetInstance()->AddSoundToChannel(channel, this); - } - - void SoundEffect::UnsetChannel() - { - BaseSound::UnsetChannel(); - AudioManager::GetInstance()->RemoveSoundFromChannel(mChannel, this); - } - -#ifdef ANDROID - void SoundEffect::SetVolume(float32 volume) - { - for(int32 i = 0 ; i < MAX_SAMPLES ; ++i) - { - SetSoundVolume( - mPlayerObjs[i], - mPlayers[i], - volume - ); - } - } -#endif - - float32 SoundEffect::GetVolume() const - { -#ifdef ANDROID - return GetSoundVolume(mPlayerObjs[0], mPlayers[0]); -#else - if(mIsMuted) - { - return mVolume; - } - else - { - if(mPlayChannels.size()==0)return 0; - float32 volume = float32(Mix_Volume(mPlayChannels[0], -1)); - return volume / float32(MIX_MAX_VOLUME); - } -#endif - } - - void SoundEffect::SetMuted(bool muted) - { -#ifdef ANDROID - for(int32 i = 0 ; i < MAX_SAMPLES ; ++i) - { - SetSoundMuted(mPlayerObjs[i], mPlayers[i], muted); - } -#else - SetSoundMuted(muted); -#endif - } - - bool SoundEffect::IsMuted() const - { -#ifdef ANDROID - return GetSoundMuted(mPlayerObjs[0], mPlayers[0]); -#else - return mIsMuted; -#endif - } - -#ifdef DESKTOP - void SoundEffect::SetSoundVolume(int32 volume) - { - for(auto it : mPlayChannels) - { - Mix_Volume(it, volume); - } - } -#else - void SoundEffect::RegisterCallback(SLPlayItf & player) - { - if((*player)->RegisterCallback( - player, MusicStoppedCallback, - this) != SL_RESULT_SUCCESS) - { - LOG(LogLevel::Error, - _T("SoundEffect::RegisterCallback: unable to register the class-defined callback function."), - STARENGINE_LOG_TAG); - } - } - - void SoundEffect::MusicStoppedCallback( - SLPlayItf caller, - void *pContext, - SLuint32 event - ) - { - (*caller)->SetPlayState(caller, SL_PLAYSTATE_STOPPED); - SoundEffect* eff = reinterpret_cast(pContext); - //Search for the caller in the list - for(uint32 i = 0 ; i < eff->mPlayers.size() ; ++i) - { - if(eff->mPlayers[i] == caller) - { - //If infinite loop keep playing - if(eff->mLoopTimes[i] == -1) - { - (*caller)->SetPlayState(caller, SL_PLAYSTATE_PLAYING); - } - else - { - //check if only play once otherwise keep playing - if(eff->mLoopTimes[i] != 0) - { - (*caller)->SetPlayState(caller, SL_PLAYSTATE_PLAYING); - } - --(eff->mLoopTimes[i]); - } - break; - } - } - } -#endif -} +#include "SoundEffect.h" +#include "AudioManager.h" +#include "../Logger.h" +#include "../Graphics/Resource.h" +#include "../Helpers/Helpers.h" +#include "../Helpers/Filepath.h" +#include "../Helpers/Math.h" + +#ifdef ANDROID +#include "../StarEngine.h" +#endif + +namespace star +{ + SoundEffect::SoundEffect(const tstring& path, uint8 channel) + : BaseSound(channel) + #ifdef DESKTOP + , mpSound(nullptr) + #elif defined(ANDROID) + , mPlayerObjs(MAX_SAMPLES) + , mPlayers(MAX_SAMPLES) + #endif + { + #ifdef ANDROID + SLEngineItf engine = AudioManager::GetInstance()->GetEngine(); + for(int32 i = 0 ; i < MAX_SAMPLES ; ++i) + { + CreateSound(mPlayerObjs[i], engine, mPlayers[i], path); + mLoopTimes.push_back(0); + } + #else + FilePath real_path(path); + sstring sound_path = string_cast(real_path.GetFullPath()); + mpSound = Mix_LoadWAV(sound_path.c_str()); + if(!mpSound) + { + LOG(LogLevel::Error, + _T("SoundEffect: Could not load sound, reason : ") + + string_cast(Mix_GetError()), + STARENGINE_LOG_TAG); + } + #endif + SetChannel(channel); + } + + SoundEffect::~SoundEffect() + { + #ifdef DESKTOP + for(auto it : mPlayChannels) + { + Mix_HaltChannel(it); + } + mPlayChannels.clear(); + #elif defined(ANDROID) + for(int32 i = 0 ; i < MAX_SAMPLES ; ++i) + { + DestroySound(mPlayerObjs[i], mPlayers[i]); + } + #endif + if(!mNoChannelAssigned) + { + UnsetChannel(); + } + } + + void SoundEffect::Play(int32 loopTime) + { + BaseSound::Play(loopTime); + #ifdef DESKTOP + mPlayChannels.push_back(Mix_PlayChannel(-1, mpSound, loopTime)); + #elif defined(ANDROID) + for(int32 i = 0 ; i < MAX_SAMPLES ; ++i) + { + SLresult lRes; + (*mPlayers[i])->GetPlayState(mPlayers[i], &lRes); + if(lRes == SL_PLAYSTATE_STOPPED) + { + mLoopTimes[i] = loopTime; + lRes = (*mPlayers[i])->SetPlayState(mPlayers[i], SL_PLAYSTATE_PLAYING); + if (lRes != SL_RESULT_SUCCESS) + { + LOG(LogLevel::Error, + _T("SoundEffect: Can't play audio!"), STARENGINE_LOG_TAG); + Stop(); + return; + }; + return; + } + } +#endif + } + + void SoundEffect::Stop() + { + BaseSound::Stop(); +#ifdef DESKTOP + for(auto it : mPlayChannels) + { + Mix_HaltChannel(it); + } + mPlayChannels.clear(); +#elif defined(ANDROID) + for(int32 i = 0 ; i < MAX_SAMPLES ; ++i) + { + (*mPlayers[i])->SetPlayState(mPlayers[i], SL_PLAYSTATE_STOPPED); + } +#endif + } + + void SoundEffect::Pause() + { + BaseSound::Pause(); +#ifdef DESKTOP + for(auto it : mPlayChannels) + { + Mix_Pause(it); + } +#elif defined(ANDROID) + for(int32 i = 0 ; i < MAX_SAMPLES ; ++i) + { + SLresult lres = (*mPlayers[i])->GetPlayState( + mPlayers[i], &lres + ); + if(lres == SL_PLAYSTATE_PLAYING) + { + (*mPlayers[i])->SetPlayState( + mPlayers[i],SL_PLAYSTATE_PAUSED + ); + } + } +#endif + } + + void SoundEffect::Resume() + { + BaseSound::Resume(); +#ifdef DESKTOP + for(auto it : mPlayChannels) + { + Mix_Resume(it); + } +#elif defined(ANDROID) + for(int32 i = 0 ; i < MAX_SAMPLES ; ++i) + { + ResumeSound(mPlayers[i]); + } +#endif + } + + void SoundEffect::SetChannel(uint8 channel) + { + BaseSound::SetChannel(channel); + AudioManager::GetInstance()->AddSoundToChannel(channel, this); + } + + void SoundEffect::UnsetChannel() + { + BaseSound::UnsetChannel(); + AudioManager::GetInstance()->RemoveSoundFromChannel(mChannel, this); + } + +#ifdef ANDROID + void SoundEffect::SetVolume(float32 volume) + { + for(int32 i = 0 ; i < MAX_SAMPLES ; ++i) + { + SetSoundVolume( + mPlayerObjs[i], + mPlayers[i], + volume + ); + } + } +#endif + + float32 SoundEffect::GetVolume() const + { +#ifdef ANDROID + return GetSoundVolume(mPlayerObjs[0], mPlayers[0]); +#else + if(mIsMuted) + { + return mVolume; + } + else + { + if(mPlayChannels.size()==0)return 0; + float32 volume = float32(Mix_Volume(mPlayChannels[0], -1)); + return volume / float32(MIX_MAX_VOLUME); + } +#endif + } + + void SoundEffect::SetMuted(bool muted) + { +#ifdef ANDROID + for(int32 i = 0 ; i < MAX_SAMPLES ; ++i) + { + SetSoundMuted(mPlayerObjs[i], mPlayers[i], muted); + } +#else + SetSoundMuted(muted); +#endif + } + + bool SoundEffect::IsMuted() const + { +#ifdef ANDROID + return GetSoundMuted(mPlayerObjs[0], mPlayers[0]); +#else + return mIsMuted; +#endif + } + +#ifdef DESKTOP + void SoundEffect::SetSoundVolume(int32 volume) + { + for(auto it : mPlayChannels) + { + Mix_Volume(it, volume); + } + } +#elif defined(ANDROID) + void SoundEffect::RegisterCallback(SLPlayItf & player) + { + if((*player)->RegisterCallback( + player, MusicStoppedCallback, + this) != SL_RESULT_SUCCESS) + { + LOG(LogLevel::Error, + _T("SoundEffect::RegisterCallback: unable to register the class-defined callback function."), + STARENGINE_LOG_TAG); + } + } + + void SoundEffect::MusicStoppedCallback( + SLPlayItf caller, + void *pContext, + SLuint32 event + ) + { + (*caller)->SetPlayState(caller, SL_PLAYSTATE_STOPPED); + SoundEffect* eff = reinterpret_cast(pContext); + //Search for the caller in the list + for(uint32 i = 0 ; i < eff->mPlayers.size() ; ++i) + { + if(eff->mPlayers[i] == caller) + { + //If infinite loop keep playing + if(eff->mLoopTimes[i] == -1) + { + (*caller)->SetPlayState(caller, SL_PLAYSTATE_PLAYING); + } + else + { + //check if only play once otherwise keep playing + if(eff->mLoopTimes[i] != 0) + { + (*caller)->SetPlayState(caller, SL_PLAYSTATE_PLAYING); + } + --(eff->mLoopTimes[i]); + } + break; + } + } + } +#endif +} diff --git a/src/Sound/SoundEffect.h b/src/Sound/SoundEffect.h index 0f46883..a40d5a4 100755 --- a/src/Sound/SoundEffect.h +++ b/src/Sound/SoundEffect.h @@ -1,58 +1,58 @@ -#pragma once - -#include "BaseSound.h" - -namespace star -{ - const int32 MAX_SAMPLES = 2; - - class SoundEffect : public BaseSound - { - public: - SoundEffect(const tstring& path, uint8 channel = 0); - ~SoundEffect(); - - virtual void Play(int32 loopTime = 0); - virtual void Stop(); - virtual void Pause(); - virtual void Resume(); - - virtual void SetChannel(uint8 channel); - virtual void UnsetChannel(); - - #ifdef ANDROID - void SetVolume(float32 volume); - #endif - float32 GetVolume() const; - - void SetMuted(bool muted); - bool IsMuted() const; - - private: -#ifdef DESKTOP - void SetSoundVolume(int32 volume); - - //static int32 PLAY_CHANNELS; - std::vector mPlayChannels; - Mix_Chunk * mpSound; -#else - void RegisterCallback(SLPlayItf & player); - - static void MusicStoppedCallback( - SLPlayItf caller, - void *pContext, - SLuint32 event - ); - - std::vector mPlayerObjs; - //SLObjectItf mPlayerObj; - std::vector mPlayers; - std::vector mLoopTimes; -#endif - - SoundEffect(const SoundEffect& yRef); - SoundEffect(SoundEffect&& yRef); - SoundEffect& operator=(const SoundEffect& yRef); - SoundEffect& operator=(SoundEffect&& yRef); - }; -} +#pragma once + +#include "BaseSound.h" + +namespace star +{ + const int32 MAX_SAMPLES = 2; + + class SoundEffect : public BaseSound + { + public: + SoundEffect(const tstring& path, uint8 channel = 0); + ~SoundEffect(); + + virtual void Play(int32 loopTime = 0); + virtual void Stop(); + virtual void Pause(); + virtual void Resume(); + + virtual void SetChannel(uint8 channel); + virtual void UnsetChannel(); + + #ifdef ANDROID + void SetVolume(float32 volume); + #endif + float32 GetVolume() const; + + void SetMuted(bool muted); + bool IsMuted() const; + + private: +#ifdef DESKTOP + void SetSoundVolume(int32 volume); + + //static int32 PLAY_CHANNELS; + std::vector mPlayChannels; + Mix_Chunk * mpSound; +#elif defined(ANDROID) + void RegisterCallback(SLPlayItf & player); + + static void MusicStoppedCallback( + SLPlayItf caller, + void *pContext, + SLuint32 event + ); + + std::vector mPlayerObjs; + //SLObjectItf mPlayerObj; + std::vector mPlayers; + std::vector mLoopTimes; +#endif + + SoundEffect(const SoundEffect& yRef); + SoundEffect(SoundEffect&& yRef); + SoundEffect& operator=(const SoundEffect& yRef); + SoundEffect& operator=(SoundEffect&& yRef); + }; +} diff --git a/src/Sound/SoundFile.cpp b/src/Sound/SoundFile.cpp index 2891b81..d45fe27 100755 --- a/src/Sound/SoundFile.cpp +++ b/src/Sound/SoundFile.cpp @@ -1,276 +1,276 @@ -#include "SoundFile.h" -#include "AudioManager.h" -#include "../Logger.h" -#include "../Graphics/Resource.h" -#include "../Helpers/Helpers.h" -#include "../Helpers/FilePath.h" - -#ifdef ANDROID -#include "../StarEngine.h" -#endif - -namespace star -{ - SoundFile::SoundFile(const tstring& path, uint8 channel) - : BaseSound(channel) - , mLoopTimes(0) - , mbQueuedPlay(false) -#ifdef ANDROID - , mPlayerObj(nullptr) - , mPlayer(nullptr) - , mPlayerSeek(nullptr) -#else - , mpSound(nullptr) -#endif - { -#ifdef ANDROID - SLEngineItf engine = AudioManager::GetInstance()->GetEngine(); - CreateSound(mPlayerObj, engine, mPlayer, path); -#else - FilePath real_path(path); - sstring sound_path = string_cast(real_path.GetFullPath()); - mpSound = Mix_LoadMUS(sound_path.c_str()); - if(!mpSound) - { - LOG(LogLevel::Error, - _T("SoundFile: Could not load sound, reason : ") - + string_cast(Mix_GetError()), - STARENGINE_LOG_TAG); - } -#endif - SetChannel(channel); - } - - SoundFile::~SoundFile() - { -#ifdef DESKTOP - if(mpSound != nullptr) - { - Mix_FreeMusic(mpSound); - mpSound = nullptr; - } -#else - DestroySound(mPlayerObj, mPlayer); -#endif - if(!mNoChannelAssigned) - { - UnsetChannel(); - } - } - - void SoundFile::Play(int32 looptimes) - { - BaseSound::Play(looptimes); - mLoopTimes = looptimes; - LOG(LogLevel::Info, - _T("Sound File: Playing File , Looptimes = ") + - star::string_cast(mLoopTimes), - STARENGINE_LOG_TAG); -#ifdef DESKTOP - Mix_HookMusicFinished(NULL); - Mix_PlayMusic(mpSound, mLoopTimes); -#else - SLresult lRes; - if(mLoopTimes == -1) - { - lRes = (*mPlayerSeek)->SetLoop( - mPlayerSeek, - SL_BOOLEAN_TRUE, - 0, - SL_TIME_UNKNOWN - ); - - if (lRes != SL_RESULT_SUCCESS) - { - LOG( - LogLevel::Error, - _T("Sound File: Can't set audio loop"), - STARENGINE_LOG_TAG - ); - Stop(); - return; - } - } - - lRes = (*mPlayer)->SetPlayState(mPlayer,SL_PLAYSTATE_PLAYING); - if (lRes != SL_RESULT_SUCCESS) - { - LOG(LogLevel::Error, - _T("Sound File: Can't play audio"), STARENGINE_LOG_TAG); - Stop(); - return; - }; -#endif - } - - void SoundFile::PlayQueued(int32 looptimes) - { - BaseSound::Play(looptimes); - mLoopTimes = looptimes; - mbQueuedPlay = true; - -#ifdef DESKTOP - Mix_HookMusicFinished(MusicStoppedCallback); - Mix_PlayMusic(mpSound, mLoopTimes); -#else - Play(mLoopTimes); -#endif - } - - void SoundFile::Stop() - { - BaseSound::Stop(); -#ifdef DESKTOP - Mix_PauseMusic(); - Mix_RewindMusic(); -#else - (*mPlayer)->SetPlayState(mPlayer, SL_PLAYSTATE_STOPPED); -#endif - } - - void SoundFile::Pause() - { - BaseSound::Pause(); -#ifdef DESKTOP - Mix_PauseMusic(); -#else - (*mPlayer)->SetPlayState(mPlayer, SL_PLAYSTATE_PAUSED); -#endif - } - - void SoundFile::Resume() - { - BaseSound::Resume(); -#ifdef DESKTOP - Mix_ResumeMusic(); -#else - ResumeSound(mPlayer); -#endif - } - - void SoundFile::SetChannel(uint8 channel) - { - BaseSound::SetChannel(channel); - AudioManager::GetInstance()->AddSoundToChannel(channel, this); - } - - void SoundFile::UnsetChannel() - { - BaseSound::UnsetChannel(); - AudioManager::GetInstance()->RemoveSoundFromChannel(mChannel, this); - } - -#ifdef ANDROID - void SoundFile::SetVolume(float32 volume) - { - SetSoundVolume(mPlayerObj, mPlayer, volume); - } -#endif - float32 SoundFile::GetVolume() const - { -#ifdef ANDROID - return GetSoundVolume(mPlayerObj, mPlayer); -#else - if(mIsMuted) - { - return mVolume; - } - else - { - float32 volume = float32(Mix_VolumeMusic(-1)); - return volume / float32(MIX_MAX_VOLUME); - } -#endif - } - - void SoundFile::SetMuted(bool muted) - { -#ifdef ANDROID - SetSoundMuted(mPlayerObj, mPlayer, muted); -#else - SetSoundMuted(muted); -#endif - } - - bool SoundFile::IsMuted() const - { -#ifdef ANDROID - return GetSoundMuted(mPlayerObj, mPlayer); -#else - return mIsMuted; -#endif - } - -#ifdef DESKTOP - void SoundFile::SetSoundVolume(int32 volume) - { - Mix_VolumeMusic(volume); - } - - void SoundFile::MusicStoppedCallback() - { - AudioManager::GetInstance()->PlayNextSongInQueue(); - } -#else - void SoundFile::CreateSoundDetails() - { - SLresult lRes = - (*mPlayerObj)->GetInterface( - mPlayerObj, - SL_IID_SEEK, - &mPlayerSeek - ); - if (lRes != SL_RESULT_SUCCESS) - { - LOG(LogLevel::Error, - _T("SoundFile : Can't get audio seek interface"), - STARENGINE_LOG_TAG); - Stop(); - return; - } - } - - void SoundFile::RegisterCallback(SLPlayItf & player) - { - if((*player)->RegisterCallback( - player, MusicStoppedCallback, - &player) != SL_RESULT_SUCCESS) - { - LOG(LogLevel::Error, - _T("SoundFile: Can't set callback"), STARENGINE_LOG_TAG); - } - } - - void SoundFile::MusicStoppedCallback( - SLPlayItf caller, - void *pContext,SLuint32 event - ) - { - SoundFile* file = - reinterpret_cast(pContext); - - LOG(LogLevel::Info, - _T("Sound File: Callback Entered, Looptimes = ") + - star::string_cast(file->mLoopTimes), - STARENGINE_LOG_TAG - ); - - if(file->mLoopTimes == 0) - { - SLPlayItf pPlay = file->mPlayer; - (*pPlay)->SetPlayState(pPlay, SL_PLAYSTATE_STOPPED); - if(file->mbQueuedPlay) - { - star::AudioManager::GetInstance()->PlayNextSongInQueue(); - } - } - else - { - SLPlayItf pPlay = file->mPlayer; - (*pPlay)->SetPlayState(pPlay, SL_PLAYSTATE_STOPPED); - file->mLoopTimes -= 1; - file->Play(file->mLoopTimes); - } - } -#endif -} +#include "SoundFile.h" +#include "AudioManager.h" +#include "../Logger.h" +#include "../Graphics/Resource.h" +#include "../Helpers/Helpers.h" +#include "../Helpers/Filepath.h" + +#ifdef ANDROID +#include "../StarEngine.h" +#endif + +namespace star +{ + SoundFile::SoundFile(const tstring& path, uint8 channel) + : BaseSound(channel) + , mLoopTimes(0) + , mbQueuedPlay(false) +#ifdef ANDROID + , mPlayerObj(nullptr) + , mPlayer(nullptr) + , mPlayerSeek(nullptr) +#else + , mpSound(nullptr) +#endif + { +#ifdef ANDROID + SLEngineItf engine = AudioManager::GetInstance()->GetEngine(); + CreateSound(mPlayerObj, engine, mPlayer, path); +#else + FilePath real_path(path); + sstring sound_path = string_cast(real_path.GetFullPath()); + mpSound = Mix_LoadMUS(sound_path.c_str()); + if(!mpSound) + { + LOG(LogLevel::Error, + _T("SoundFile: Could not load sound, reason : ") + + string_cast(Mix_GetError()), + STARENGINE_LOG_TAG); + } +#endif + SetChannel(channel); + } + + SoundFile::~SoundFile() + { +#ifdef DESKTOP + if(mpSound != nullptr) + { + Mix_FreeMusic(mpSound); + mpSound = nullptr; + } +#elif defined(ANDROID) + DestroySound(mPlayerObj, mPlayer); +#endif + if(!mNoChannelAssigned) + { + UnsetChannel(); + } + } + + void SoundFile::Play(int32 looptimes) + { + BaseSound::Play(looptimes); + mLoopTimes = looptimes; + LOG(LogLevel::Info, + _T("Sound File: Playing File , Looptimes = ") + + star::string_cast(mLoopTimes), + STARENGINE_LOG_TAG); +#ifdef DESKTOP + Mix_HookMusicFinished(NULL); + Mix_PlayMusic(mpSound, mLoopTimes); +#elif defined(ANDROID) + SLresult lRes; + if(mLoopTimes == -1) + { + lRes = (*mPlayerSeek)->SetLoop( + mPlayerSeek, + SL_BOOLEAN_TRUE, + 0, + SL_TIME_UNKNOWN + ); + + if (lRes != SL_RESULT_SUCCESS) + { + LOG( + LogLevel::Error, + _T("Sound File: Can't set audio loop"), + STARENGINE_LOG_TAG + ); + Stop(); + return; + } + } + + lRes = (*mPlayer)->SetPlayState(mPlayer,SL_PLAYSTATE_PLAYING); + if (lRes != SL_RESULT_SUCCESS) + { + LOG(LogLevel::Error, + _T("Sound File: Can't play audio"), STARENGINE_LOG_TAG); + Stop(); + return; + }; +#endif + } + + void SoundFile::PlayQueued(int32 looptimes) + { + BaseSound::Play(looptimes); + mLoopTimes = looptimes; + mbQueuedPlay = true; + +#ifdef DESKTOP + Mix_HookMusicFinished(MusicStoppedCallback); + Mix_PlayMusic(mpSound, mLoopTimes); +#elif defined(ANDROID) + Play(mLoopTimes); +#endif + } + + void SoundFile::Stop() + { + BaseSound::Stop(); +#ifdef DESKTOP + Mix_PauseMusic(); + Mix_RewindMusic(); +#elif defined(ANDROID) + (*mPlayer)->SetPlayState(mPlayer, SL_PLAYSTATE_STOPPED); +#endif + } + + void SoundFile::Pause() + { + BaseSound::Pause(); +#ifdef DESKTOP + Mix_PauseMusic(); +#elif defined(ANDROID) + (*mPlayer)->SetPlayState(mPlayer, SL_PLAYSTATE_PAUSED); +#endif + } + + void SoundFile::Resume() + { + BaseSound::Resume(); +#ifdef DESKTOP + Mix_ResumeMusic(); +#elif defined(ANDROID) + ResumeSound(mPlayer); +#endif + } + + void SoundFile::SetChannel(uint8 channel) + { + BaseSound::SetChannel(channel); + AudioManager::GetInstance()->AddSoundToChannel(channel, this); + } + + void SoundFile::UnsetChannel() + { + BaseSound::UnsetChannel(); + AudioManager::GetInstance()->RemoveSoundFromChannel(mChannel, this); + } + +#ifdef ANDROID + void SoundFile::SetVolume(float32 volume) + { + SetSoundVolume(mPlayerObj, mPlayer, volume); + } +#endif + float32 SoundFile::GetVolume() const + { +#ifdef ANDROID + return GetSoundVolume(mPlayerObj, mPlayer); +#else + if(mIsMuted) + { + return mVolume; + } + else + { + float32 volume = float32(Mix_VolumeMusic(-1)); + return volume / float32(MIX_MAX_VOLUME); + } +#endif + } + + void SoundFile::SetMuted(bool muted) + { +#ifdef ANDROID + SetSoundMuted(mPlayerObj, mPlayer, muted); +#else + SetSoundMuted(muted); +#endif + } + + bool SoundFile::IsMuted() const + { +#ifdef ANDROID + return GetSoundMuted(mPlayerObj, mPlayer); +#else + return mIsMuted; +#endif + } + +#ifdef DESKTOP + void SoundFile::SetSoundVolume(int32 volume) + { + Mix_VolumeMusic(volume); + } + + void SoundFile::MusicStoppedCallback() + { + AudioManager::GetInstance()->PlayNextSongInQueue(); + } +#elif defined(ANDROID) + void SoundFile::CreateSoundDetails() + { + SLresult lRes = + (*mPlayerObj)->GetInterface( + mPlayerObj, + SL_IID_SEEK, + &mPlayerSeek + ); + if (lRes != SL_RESULT_SUCCESS) + { + LOG(LogLevel::Error, + _T("SoundFile : Can't get audio seek interface"), + STARENGINE_LOG_TAG); + Stop(); + return; + } + } + + void SoundFile::RegisterCallback(SLPlayItf & player) + { + if((*player)->RegisterCallback( + player, MusicStoppedCallback, + &player) != SL_RESULT_SUCCESS) + { + LOG(LogLevel::Error, + _T("SoundFile: Can't set callback"), STARENGINE_LOG_TAG); + } + } + + void SoundFile::MusicStoppedCallback( + SLPlayItf caller, + void *pContext,SLuint32 event + ) + { + SoundFile* file = + reinterpret_cast(pContext); + + LOG(LogLevel::Info, + _T("Sound File: Callback Entered, Looptimes = ") + + star::string_cast(file->mLoopTimes), + STARENGINE_LOG_TAG + ); + + if(file->mLoopTimes == 0) + { + SLPlayItf pPlay = file->mPlayer; + (*pPlay)->SetPlayState(pPlay, SL_PLAYSTATE_STOPPED); + if(file->mbQueuedPlay) + { + star::AudioManager::GetInstance()->PlayNextSongInQueue(); + } + } + else + { + SLPlayItf pPlay = file->mPlayer; + (*pPlay)->SetPlayState(pPlay, SL_PLAYSTATE_STOPPED); + file->mLoopTimes -= 1; + file->Play(file->mLoopTimes); + } + } +#endif +} diff --git a/src/Sound/SoundFile.h b/src/Sound/SoundFile.h index 9026995..d90dda4 100755 --- a/src/Sound/SoundFile.h +++ b/src/Sound/SoundFile.h @@ -1,63 +1,63 @@ -#pragma once - -#include "BaseSound.h" - -#include - -namespace star -{ - class SoundFile final : public BaseSound - { - public: - SoundFile(const tstring& path, uint8 channel = 0); - ~SoundFile(); - - virtual void Play(int32 looptimes = 0); - void PlayQueued(int32 looptimes = 0); - virtual void Stop(); - virtual void Pause(); - virtual void Resume(); - - virtual void SetChannel(uint8 channel); - virtual void UnsetChannel(); - -#ifdef ANDROID - void SetVolume(float32 volume); -#endif - float32 GetVolume() const; - - void SetMuted(bool muted); - bool IsMuted() const; - - protected: -#ifdef DESKTOP - void SetSoundVolume(int32 volume); - static void MusicStoppedCallback(); -#else - void CreateSoundDetails(); - void RegisterCallback(SLPlayItf & player); - - static void MusicStoppedCallback( - SLPlayItf caller, - void *pContext, - SLuint32 event - ); -#endif - - private: - int32 mLoopTimes; - bool mbQueuedPlay; -#ifdef ANDROID - SLObjectItf mPlayerObj; - SLPlayItf mPlayer; - SLSeekItf mPlayerSeek; -#else - Mix_Music * mpSound; -#endif - - SoundFile(const SoundFile& yRef); - SoundFile(SoundFile&& yRef); - SoundFile& operator=(const SoundFile& yRef); - SoundFile& operator=(SoundFile&& yRef); - }; -} +#pragma once + +#include "BaseSound.h" + +#include + +namespace star +{ + class SoundFile final : public BaseSound + { + public: + SoundFile(const tstring& path, uint8 channel = 0); + ~SoundFile(); + + virtual void Play(int32 looptimes = 0); + void PlayQueued(int32 looptimes = 0); + virtual void Stop(); + virtual void Pause(); + virtual void Resume(); + + virtual void SetChannel(uint8 channel); + virtual void UnsetChannel(); + +#ifdef ANDROID + void SetVolume(float32 volume); +#endif + float32 GetVolume() const; + + void SetMuted(bool muted); + bool IsMuted() const; + + protected: +#ifdef DESKTOP + void SetSoundVolume(int32 volume); + static void MusicStoppedCallback(); +#elif defined(ANDROID) + void CreateSoundDetails(); + void RegisterCallback(SLPlayItf & player); + + static void MusicStoppedCallback( + SLPlayItf caller, + void *pContext, + SLuint32 event + ); +#endif + + private: + int32 mLoopTimes; + bool mbQueuedPlay; +#ifdef ANDROID + SLObjectItf mPlayerObj; + SLPlayItf mPlayer; + SLSeekItf mPlayerSeek; +#else + Mix_Music * mpSound; +#endif + + SoundFile(const SoundFile& yRef); + SoundFile(SoundFile&& yRef); + SoundFile& operator=(const SoundFile& yRef); + SoundFile& operator=(SoundFile&& yRef); + }; +} diff --git a/src/StarEngine.cpp b/src/StarEngine.cpp index 473c41c..5b30592 100755 --- a/src/StarEngine.cpp +++ b/src/StarEngine.cpp @@ -1,176 +1,176 @@ -#include "StarEngine.h" -#include "Graphics/GraphicsManager.h" -#include "Graphics/SpriteAnimationManager.h" -#include "Graphics/SpriteBatch.h" -#include "Graphics/FontManager.h" -#include "Graphics/ScaleSystem.h" -#include "Scenes/SceneManager.h" -#include "Input/InputManager.h" -#include "Context.h" -#include "Logger.h" -#include "Sound/AudioManager.h" -#include "Helpers/TimerManager.h" -#include "AI/Pathfinding/PathFindManager.h" -#include "Physics/Collision/CollisionManager.h" -#include "Helpers/Debug/DebugDraw.h" - -namespace star -{ - StarEngine * StarEngine::m_pEngine = nullptr; - - StarEngine::~StarEngine() - { - } - - StarEngine* StarEngine::GetInstance() - { - if(m_pEngine == nullptr) - { - m_pEngine = new StarEngine(); - } - return m_pEngine; - } - - void StarEngine::Initialize(int32 window_width, int32 window_height) - { - std::random_device seeder; - m_RandomEngine.seed(seeder()); - - //Only for windows we need to pas the window paramaters - //for android these will be fetched when setting up the OpenGL context - //within the Graphics Manager -#ifdef DESKTOP - GraphicsManager::GetInstance()->Initialize(window_width,window_height); -#endif - - AudioManager::GetInstance()->Start(); - GraphicsManager::GetInstance()->CalculateViewPort(); - SpriteBatch::GetInstance()->Initialize(); - DebugDraw::GetInstance()->Initialize(); - } - - void StarEngine::Update(const Context & context) - { - m_FPS.Update(context); - SceneManager::GetInstance()->Update(context); - GraphicsManager::GetInstance()->Update(); - InputManager::GetInstance()->EndUpdate(); - Logger::GetInstance()->Update(context); -#if defined(DEBUG) | defined(_DEBUG) - OPENGL_LOG(); -#endif - m_bInitialized = true; - } - - void StarEngine::Draw() - { - GraphicsManager::GetInstance()->StartDraw(); - if(m_bInitialized) - { - SceneManager::GetInstance()->Draw(); - } - GraphicsManager::GetInstance()->StopDraw(); - } - - void StarEngine::End() - { - FontManager::GetInstance()->EraseFonts(); - DebugDraw::DeleteSingleton(); - ScaleSystem::DeleteSingleton(); - FontManager::DeleteSingleton(); - SpriteAnimationManager::DeleteSingleton(); - TextureManager::DeleteSingleton(); - GraphicsManager::DeleteSingleton(); - SpriteBatch::DeleteSingleton(); - AudioManager::DeleteSingleton(); - PathFindManager::DeleteSingleton(); - SceneManager::DeleteSingleton(); - Logger::DeleteSingleton(); - TimeManager::DeleteSingleton(); - } - - void StarEngine::SetActive() - { - AudioManager::GetInstance()->ResumeAllSounds(); - } - - void StarEngine::SetInactive() - { - AudioManager::GetInstance()->PauseAllSounds(); - } - - int32 StarEngine::GetCurrentFPS() const - { - return m_FPS.CurrentFPS; - } - - int32 StarEngine::GetPreviousFPS() const - { - return m_FPS.PreviousFPS; - } - - void StarEngine::SetGameTitle(const tstring & title) - { - m_Title = title; - m_TitleHasUpdated = true; - } - - void StarEngine::SetGameSubTitle(const tstring & title) - { - m_SubTitle = title; - m_TitleHasUpdated = true; - } - - const tstring & StarEngine::GetGameTitle() - { - return m_Title; - } - - bool StarEngine::HasTitleUpdated() const - { - return m_TitleHasUpdated; - } - - void StarEngine::ResetTitleUpdateMark() - { - m_TitleHasUpdated = false; - } - - std::mt19937& StarEngine::GetMt19937Engine() - { - return m_RandomEngine; - } - - void StarEngine::Quit() - { -#ifdef _WIN32 - PostQuitMessage(0); -#else - ANativeActivity_finish(m_pAndroidApp->activity); -#endif - } - -#ifdef ANDROID - void StarEngine::SetAndroidApp(android_app * app) - { - m_pAndroidApp = app; - } - - android_app * StarEngine::GetAndroidApp() const - { - return m_pAndroidApp; - } -#endif - - StarEngine::StarEngine() - : m_FPS() - , m_Title(EMPTY_STRING) - , m_SubTitle(EMPTY_STRING) - , m_TitleHasUpdated(false) - , m_bInitialized (false) - , m_RandomEngine() - { - - } - -} +#include "StarEngine.h" +#include "Graphics/GraphicsManager.h" +#include "Graphics/SpriteAnimationManager.h" +#include "Graphics/SpriteBatch.h" +#include "Graphics/FontManager.h" +#include "Graphics/ScaleSystem.h" +#include "Scenes/SceneManager.h" +#include "Input/InputManager.h" +#include "Context.h" +#include "Logger.h" +#include "Sound/AudioManager.h" +#include "Helpers/TimerManager.h" +#include "AI/Pathfinding/PathFindManager.h" +#include "Physics/Collision/CollisionManager.h" +#include "Helpers/Debug/DebugDraw.h" + +namespace star +{ + StarEngine * StarEngine::m_pEngine = nullptr; + + StarEngine::~StarEngine() + { + } + + StarEngine* StarEngine::GetInstance() + { + if(m_pEngine == nullptr) + { + m_pEngine = new StarEngine(); + } + return m_pEngine; + } + + void StarEngine::Initialize(int32 window_width, int32 window_height) + { + std::random_device seeder; + m_RandomEngine.seed(seeder()); + + //Only for windows we need to pas the window paramaters + //for android these will be fetched when setting up the OpenGL context + //within the Graphics Manager +#ifdef DESKTOP + GraphicsManager::GetInstance()->Initialize(window_width,window_height); +#endif + + AudioManager::GetInstance()->Start(); + GraphicsManager::GetInstance()->CalculateViewPort(); + SpriteBatch::GetInstance()->Initialize(); + DebugDraw::GetInstance()->Initialize(); + } + + void StarEngine::Update(const Context & context) + { + m_FPS.Update(context); + SceneManager::GetInstance()->Update(context); + GraphicsManager::GetInstance()->Update(); + InputManager::GetInstance()->EndUpdate(); + Logger::GetInstance()->Update(context); +#if defined(DEBUG) | defined(_DEBUG) + OPENGL_LOG(); +#endif + m_bInitialized = true; + } + + void StarEngine::Draw() + { + GraphicsManager::GetInstance()->StartDraw(); + if(m_bInitialized) + { + SceneManager::GetInstance()->Draw(); + } + GraphicsManager::GetInstance()->StopDraw(); + } + + void StarEngine::End() + { + FontManager::GetInstance()->EraseFonts(); + DebugDraw::DeleteSingleton(); + ScaleSystem::DeleteSingleton(); + FontManager::DeleteSingleton(); + SpriteAnimationManager::DeleteSingleton(); + TextureManager::DeleteSingleton(); + GraphicsManager::DeleteSingleton(); + SpriteBatch::DeleteSingleton(); + AudioManager::DeleteSingleton(); + PathFindManager::DeleteSingleton(); + SceneManager::DeleteSingleton(); + Logger::DeleteSingleton(); + TimeManager::DeleteSingleton(); + } + + void StarEngine::SetActive() + { + AudioManager::GetInstance()->ResumeAllSounds(); + } + + void StarEngine::SetInactive() + { + AudioManager::GetInstance()->PauseAllSounds(); + } + + int32 StarEngine::GetCurrentFPS() const + { + return m_FPS.CurrentFPS; + } + + int32 StarEngine::GetPreviousFPS() const + { + return m_FPS.PreviousFPS; + } + + void StarEngine::SetGameTitle(const tstring & title) + { + m_Title = title; + m_TitleHasUpdated = true; + } + + void StarEngine::SetGameSubTitle(const tstring & title) + { + m_SubTitle = title; + m_TitleHasUpdated = true; + } + + const tstring & StarEngine::GetGameTitle() + { + return m_Title; + } + + bool StarEngine::HasTitleUpdated() const + { + return m_TitleHasUpdated; + } + + void StarEngine::ResetTitleUpdateMark() + { + m_TitleHasUpdated = false; + } + + std::mt19937& StarEngine::GetMt19937Engine() + { + return m_RandomEngine; + } + + void StarEngine::Quit() + { +#ifdef _WIN32 + PostQuitMessage(0); +#elif defined(ANDROID) + ANativeActivity_finish(m_pAndroidApp->activity); +#endif + } + +#ifdef ANDROID + void StarEngine::SetAndroidApp(android_app * app) + { + m_pAndroidApp = app; + } + + android_app * StarEngine::GetAndroidApp() const + { + return m_pAndroidApp; + } +#endif + + StarEngine::StarEngine() + : m_FPS() + , m_Title(EMPTY_STRING) + , m_SubTitle(EMPTY_STRING) + , m_TitleHasUpdated(false) + , m_bInitialized (false) + , m_RandomEngine() + { + + } + +} diff --git a/src/TimeManager.cpp b/src/TimeManager.cpp index d13e9ad..d35b1b3 100755 --- a/src/TimeManager.cpp +++ b/src/TimeManager.cpp @@ -1,6 +1,6 @@ #include "TimeManager.h" #include "Logger.h" -#include "Helpers\Helpers.h" +#include "Helpers/Helpers.h" namespace star { diff --git a/src/defines.h b/src/defines.h index 6ee5ae8..738b51f 100755 --- a/src/defines.h +++ b/src/defines.h @@ -6,7 +6,7 @@ #define MOBILE #endif -#include "Helpers\SerializedData.h" +#include "Helpers/SerializedData.h" #include "definesTypes.h" #include "definesCrossPlatform.h" diff --git a/src/definesMath.h b/src/definesMath.h index 362d1c7..c77f0fb 100755 --- a/src/definesMath.h +++ b/src/definesMath.h @@ -6,8 +6,8 @@ using std::min; using std::max; //OpenGL Math Library -#include "Helpers\glm\glm.h" -#include "Helpers\glm\ext.hpp" +#include "Helpers/glm/glm.h" +#include "Helpers/glm/ext.hpp" typedef glm::ivec2 ivec2; typedef glm::ivec3 ivec3; diff --git a/src/definesTypes.h b/src/definesTypes.h index 72bb0cc..ac1dd1c 100755 --- a/src/definesTypes.h +++ b/src/definesTypes.h @@ -16,6 +16,11 @@ typedef float float32; typedef double float64; typedef long double float128; +// byte type: Windows gets it from , Android from definesAndroid.h +#if !defined(_WIN32) && !defined(ANDROID) +typedef uint8_t byte; +#endif + #include #include #include @@ -102,6 +107,18 @@ typedef long double float128; #ifdef _WIN32 #define tfopen swfopen #define TSHFILEINFO SWSHFILEINFO + #else + // Linux: provide fopen_s-like wrapper for wide strings + #include + inline int tfopen(FILE** fp, const wchar_t* path, const wchar_t* mode) + { + // Convert wchar to char for Linux + char cpath[4096], cmode[32]; + wcstombs(cpath, path, sizeof(cpath)); + wcstombs(cmode, mode, sizeof(cmode)); + *fp = fopen(cpath, cmode); + return (*fp == nullptr) ? -1 : 0; + } #endif #else #define tstring sstring @@ -122,6 +139,13 @@ typedef long double float128; #ifdef _WIN32 #define tfopen sfopen #define TSHFILEINFO SSHFILEINFO + #else + // Linux: provide fopen_s-like wrapper + inline int tfopen(FILE** fp, const char* path, const char* mode) + { + *fp = fopen(path, mode); + return (*fp == nullptr) ? -1 : 0; + } #endif #endif @@ -134,4 +158,4 @@ struct PointerArray { U amount; T * elements; -}; +}; diff --git a/test/pong/CMakeLists.txt b/test/pong/CMakeLists.txt new file mode 100644 index 0000000..2f36ca4 --- /dev/null +++ b/test/pong/CMakeLists.txt @@ -0,0 +1,33 @@ +cmake_minimum_required(VERSION 3.14) +project(pong LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +# Find the same packages the engine uses +find_package(OpenGL REQUIRED) +find_package(GLEW REQUIRED) +find_package(PkgConfig REQUIRED) +find_package(Freetype REQUIRED) +find_package(PNG REQUIRED) + +pkg_check_modules(SDL2 REQUIRED IMPORTED_TARGET sdl2) +pkg_check_modules(SDL2_MIXER REQUIRED IMPORTED_TARGET SDL2_mixer) + +add_executable(pong main.cpp) + +# Link against the starengine static library and all its transitive deps +target_link_libraries(pong PRIVATE + starengine + OpenGL::GL + GLEW::GLEW + PkgConfig::SDL2 + PkgConfig::SDL2_MIXER + Freetype::Freetype + PNG::PNG +) + +# Engine headers live under src/ +target_include_directories(pong PRIVATE + ${CMAKE_SOURCE_DIR}/src +) diff --git a/test/pong/main.cpp b/test/pong/main.cpp new file mode 100644 index 0000000..6c058d6 --- /dev/null +++ b/test/pong/main.cpp @@ -0,0 +1,878 @@ +/** + * StarEngine Test Program — Star Pong + * + * A Pong game with start menu, AI opponents, and difficulty settings. + * Links against the starengine library (Logger, TimeManager). + * Uses SDL2 for windowing/input and OpenGL 2.1 immediate mode for rendering. + * + * Menu Controls: + * Up / Down Navigate + * Enter / Space Select + * Escape Back / Quit + * + * Game Controls: + * Player 1 (left): W / S + * Player 2 (right): Up / Down arrows (2-player mode only) + * Pause: Space + * Escape: Back to menu + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +// StarEngine headers +#include "Logger.h" +#include "TimeManager.h" +#include "defines.h" + +// --------------------------------------------------------------------------- +// Constants +// --------------------------------------------------------------------------- +static const int WINDOW_W = 800; +static const int WINDOW_H = 600; +static const float PADDLE_W = 12.0f; +static const float PADDLE_H = 80.0f; +static const float PADDLE_SPEED = 350.0f; +static const float PADDLE_MARGIN = 30.0f; +static const float BALL_SIZE = 10.0f; +static const float BALL_SPEED = 300.0f; +static const float BALL_ACCEL = 20.0f; +static const int WIN_SCORE = 7; +static const float MY_PI = 3.14159265f; + +// --------------------------------------------------------------------------- +// Enums +// --------------------------------------------------------------------------- +enum class GameScreen { + MainMenu, + DifficultySelect, + Playing, + Paused, + GameOver +}; + +enum class Difficulty { + Easy, + Medium, + Hard, + Impossible +}; + +enum class GameMode { + VsAI, + VsPlayer +}; + +// --------------------------------------------------------------------------- +// Structs +// --------------------------------------------------------------------------- +struct Paddle { + float x, y; + float halfW, halfH; + int score; +}; + +struct Ball { + float x, y; + float vx, vy; + float halfSize; + float speed; +}; + +struct AIState { + float reactionTimer; + float targetY; + float errorOffset; + float speed; + float reactionDelay; + float maxError; + bool cheats; +}; + +// --------------------------------------------------------------------------- +// Game state +// --------------------------------------------------------------------------- +static Paddle gP1, gP2; +static Ball gBall; +static AIState gAI; +static bool gRunning = true; +static GameScreen gScreen = GameScreen::MainMenu; +static GameMode gMode = GameMode::VsAI; +static Difficulty gDifficulty = Difficulty::Medium; +static int gMenuSelection = 0; +static int gDiffSelection = 1; +static std::string gWinnerText; +static float gCountdown = 0.0f; +static float gScreenShake = 0.0f; +static int gServeDir = 1; +static float gBallTrailX[8], gBallTrailY[8]; +static int gTrailIdx = 0; +static float gMenuPulse = 0.0f; + +// Digit bitmaps (5x7) +static const uint8_t DIGITS[10][7] = { + {0x1F,0x11,0x11,0x11,0x11,0x11,0x1F}, + {0x04,0x0C,0x04,0x04,0x04,0x04,0x0E}, + {0x1F,0x01,0x01,0x1F,0x10,0x10,0x1F}, + {0x1F,0x01,0x01,0x1F,0x01,0x01,0x1F}, + {0x11,0x11,0x11,0x1F,0x01,0x01,0x01}, + {0x1F,0x10,0x10,0x1F,0x01,0x01,0x1F}, + {0x1F,0x10,0x10,0x1F,0x11,0x11,0x1F}, + {0x1F,0x01,0x01,0x01,0x01,0x01,0x01}, + {0x1F,0x11,0x11,0x1F,0x11,0x11,0x1F}, + {0x1F,0x11,0x11,0x1F,0x01,0x01,0x1F}, +}; + +// Letter bitmaps (5x7) A-Z +static const uint8_t LETTERS[26][7] = { + {0x0E,0x11,0x11,0x1F,0x11,0x11,0x11}, // A + {0x1E,0x11,0x11,0x1E,0x11,0x11,0x1E}, // B + {0x0F,0x10,0x10,0x10,0x10,0x10,0x0F}, // C + {0x1E,0x11,0x11,0x11,0x11,0x11,0x1E}, // D + {0x1F,0x10,0x10,0x1E,0x10,0x10,0x1F}, // E + {0x1F,0x10,0x10,0x1E,0x10,0x10,0x10}, // F + {0x0F,0x10,0x10,0x17,0x11,0x11,0x0F}, // G + {0x11,0x11,0x11,0x1F,0x11,0x11,0x11}, // H + {0x0E,0x04,0x04,0x04,0x04,0x04,0x0E}, // I + {0x01,0x01,0x01,0x01,0x11,0x11,0x0E}, // J + {0x11,0x12,0x14,0x18,0x14,0x12,0x11}, // K + {0x10,0x10,0x10,0x10,0x10,0x10,0x1F}, // L + {0x11,0x1B,0x15,0x11,0x11,0x11,0x11}, // M + {0x11,0x19,0x15,0x13,0x11,0x11,0x11}, // N + {0x0E,0x11,0x11,0x11,0x11,0x11,0x0E}, // O + {0x1E,0x11,0x11,0x1E,0x10,0x10,0x10}, // P + {0x0E,0x11,0x11,0x11,0x15,0x12,0x0D}, // Q + {0x1E,0x11,0x11,0x1E,0x14,0x12,0x11}, // R + {0x0F,0x10,0x10,0x0E,0x01,0x01,0x1E}, // S + {0x1F,0x04,0x04,0x04,0x04,0x04,0x04}, // T + {0x11,0x11,0x11,0x11,0x11,0x11,0x0E}, // U + {0x11,0x11,0x11,0x11,0x0A,0x0A,0x04}, // V + {0x11,0x11,0x11,0x15,0x15,0x1B,0x11}, // W + {0x11,0x11,0x0A,0x04,0x0A,0x11,0x11}, // X + {0x11,0x11,0x0A,0x04,0x04,0x04,0x04}, // Y + {0x1F,0x01,0x02,0x04,0x08,0x10,0x1F}, // Z +}; + +static const uint8_t SYM_COLON[7] = {0x00,0x04,0x00,0x00,0x04,0x00,0x00}; +static const uint8_t SYM_DASH[7] = {0x00,0x00,0x00,0x1F,0x00,0x00,0x00}; +static const uint8_t SYM_EXCLAM[7] = {0x04,0x04,0x04,0x04,0x04,0x00,0x04}; +static const uint8_t SYM_PERIOD[7] = {0x00,0x00,0x00,0x00,0x00,0x00,0x04}; +static const uint8_t SYM_SLASH[7] = {0x01,0x01,0x02,0x04,0x08,0x10,0x10}; +static const uint8_t SYM_ARROW[7] = {0x04,0x02,0x1F,0x02,0x04,0x00,0x00}; + +// --------------------------------------------------------------------------- +// Drawing primitives +// --------------------------------------------------------------------------- +static void DrawRect(float cx, float cy, float hw, float hh) +{ + glBegin(GL_QUADS); + glVertex2f(cx - hw, cy - hh); + glVertex2f(cx + hw, cy - hh); + glVertex2f(cx + hw, cy + hh); + glVertex2f(cx - hw, cy + hh); + glEnd(); +} + +static void DrawGlyph(const uint8_t glyph[7], float originX, float originY, float ps) +{ + for (int row = 0; row < 7; ++row) { + uint8_t bits = glyph[row]; + for (int col = 0; col < 5; ++col) { + if (bits & (1 << (4 - col))) { + float x = originX + col * ps + ps * 0.5f; + float y = originY + row * ps + ps * 0.5f; + DrawRect(x, y, ps * 0.5f, ps * 0.5f); + } + } + } +} + +static const uint8_t* GetCharGlyph(char c) +{ + if (c >= '0' && c <= '9') return DIGITS[c - '0']; + if (c >= 'A' && c <= 'Z') return LETTERS[c - 'A']; + if (c >= 'a' && c <= 'z') return LETTERS[c - 'a']; + switch (c) { + case ':': return SYM_COLON; + case '-': return SYM_DASH; + case '!': return SYM_EXCLAM; + case '.': return SYM_PERIOD; + case '/': return SYM_SLASH; + case '>': return SYM_ARROW; + default: return nullptr; + } +} + +static float MeasureText(const char* text, float ps) +{ + float w = 0; + for (const char* p = text; *p; ++p) { + w += 5 * ps + ps; + } + if (w > 0) w -= ps; + return w; +} + +static void DrawText(const char* text, float centreX, float y, float ps) +{ + float totalW = MeasureText(text, ps); + float x = centreX - totalW * 0.5f; + for (const char* p = text; *p; ++p) { + const uint8_t* glyph = GetCharGlyph(*p); + if (glyph) { + DrawGlyph(glyph, x, y, ps); + } + x += 5 * ps + ps; + } +} + +static void DrawScore(int score, float centreX, float topY, float pixelSize) +{ + char buf[4]; + snprintf(buf, sizeof(buf), "%d", score); + DrawText(buf, centreX, topY, pixelSize); +} + +// --------------------------------------------------------------------------- +// AI logic +// --------------------------------------------------------------------------- +static void ConfigureAI(Difficulty diff) +{ + switch (diff) { + case Difficulty::Easy: + gAI.speed = 0.45f; + gAI.reactionDelay = 0.5f; + gAI.maxError = 60.0f; + gAI.cheats = false; + break; + case Difficulty::Medium: + gAI.speed = 0.7f; + gAI.reactionDelay = 0.2f; + gAI.maxError = 25.0f; + gAI.cheats = false; + break; + case Difficulty::Hard: + gAI.speed = 0.92f; + gAI.reactionDelay = 0.08f; + gAI.maxError = 8.0f; + gAI.cheats = false; + break; + case Difficulty::Impossible: + gAI.speed = 1.0f; + gAI.reactionDelay = 0.0f; + gAI.maxError = 0.0f; + gAI.cheats = true; + break; + } + gAI.reactionTimer = 0.0f; + gAI.targetY = WINDOW_H / 2.0f; + gAI.errorOffset = 0.0f; +} + +static float PredictBallY(float targetX) +{ + float bx = gBall.x, by = gBall.y; + float bvx = gBall.vx; + float bvy = gBall.vy; + + if (bvx <= 0) return WINDOW_H / 2.0f; + + float timeToReach = (targetX - bx) / bvx; + float futureY = by + bvy * timeToReach; + + float fieldH = static_cast(WINDOW_H); + // Reflect off walls + int bounces = 0; + while ((futureY < 0 || futureY > fieldH) && bounces < 20) { + if (futureY < 0) futureY = -futureY; + if (futureY > fieldH) futureY = 2.0f * fieldH - futureY; + ++bounces; + } + return std::max(0.0f, std::min(fieldH, futureY)); +} + +static void UpdateAI(float dt) +{ + gAI.reactionTimer -= dt; + if (gAI.reactionTimer <= 0.0f) { + gAI.reactionTimer = gAI.reactionDelay; + + if (gAI.cheats || gBall.vx > 0) { + gAI.targetY = PredictBallY(gP2.x); + } else { + gAI.targetY = WINDOW_H / 2.0f; + } + gAI.errorOffset = ((float)(rand() % 1000) / 500.0f - 1.0f) * gAI.maxError; + } + + float target = gAI.targetY + gAI.errorOffset; + float diff = target - gP2.y; + float aiSpeed = PADDLE_SPEED * gAI.speed; + + if (std::abs(diff) > 3.0f) { + if (diff > 0) gP2.y += std::min(aiSpeed * dt, diff); + else gP2.y += std::max(-aiSpeed * dt, diff); + } + + if (gP2.y - gP2.halfH < 0) gP2.y = gP2.halfH; + if (gP2.y + gP2.halfH > WINDOW_H) gP2.y = WINDOW_H - gP2.halfH; +} + +// --------------------------------------------------------------------------- +// Game logic +// --------------------------------------------------------------------------- +static void ResetBall(int direction) +{ + gBall.x = WINDOW_W / 2.0f; + gBall.y = WINDOW_H / 2.0f; + gBall.speed = BALL_SPEED; + gBall.vx = 0; + gBall.vy = 0; + gBall.halfSize = BALL_SIZE / 2.0f; + gServeDir = direction; + gCountdown = 1.5f; + + for (int i = 0; i < 8; ++i) { + gBallTrailX[i] = gBall.x; + gBallTrailY[i] = gBall.y; + } +} + +static void ServeBall() +{ + float angle = ((float)(rand() % 60) - 30.0f) * (MY_PI / 180.0f); + gBall.vx = cosf(angle) * gBall.speed * gServeDir; + gBall.vy = sinf(angle) * gBall.speed; +} + +static void InitGame() +{ + gP1.halfW = PADDLE_W / 2.0f; gP1.halfH = PADDLE_H / 2.0f; + gP2.halfW = PADDLE_W / 2.0f; gP2.halfH = PADDLE_H / 2.0f; + + gP1.x = PADDLE_MARGIN; + gP2.x = WINDOW_W - PADDLE_MARGIN; + gP1.y = gP2.y = WINDOW_H / 2.0f; + gP1.score = gP2.score = 0; + + if (gMode == GameMode::VsAI) { + ConfigureAI(gDifficulty); + } + ResetBall(1); +} + +static bool AABBOverlap(float ax, float ay, float ahw, float ahh, + float bx, float by, float bhw, float bhh) +{ + return std::abs(ax - bx) < (ahw + bhw) && + std::abs(ay - by) < (ahh + bhh); +} + +static void UpdatePlaying(float dt, const uint8_t* keys) +{ + // Countdown / serve + if (gCountdown > 0.0f) { + gCountdown -= dt; + if (gCountdown <= 0.0f) { + gCountdown = 0.0f; + ServeBall(); + } + return; + } + + // Player 1 + if (keys[SDL_SCANCODE_W]) gP1.y -= PADDLE_SPEED * dt; + if (keys[SDL_SCANCODE_S]) gP1.y += PADDLE_SPEED * dt; + + // Player 2 or AI + if (gMode == GameMode::VsAI) { + UpdateAI(dt); + } else { + if (keys[SDL_SCANCODE_UP]) gP2.y -= PADDLE_SPEED * dt; + if (keys[SDL_SCANCODE_DOWN]) gP2.y += PADDLE_SPEED * dt; + } + + // Clamp + auto clampPaddle = [](Paddle& p) { + if (p.y - p.halfH < 0) p.y = p.halfH; + if (p.y + p.halfH > WINDOW_H) p.y = WINDOW_H - p.halfH; + }; + clampPaddle(gP1); + clampPaddle(gP2); + + // Ball trail + gTrailIdx = (gTrailIdx + 1) % 8; + gBallTrailX[gTrailIdx] = gBall.x; + gBallTrailY[gTrailIdx] = gBall.y; + + // Ball movement + gBall.x += gBall.vx * dt; + gBall.y += gBall.vy * dt; + + // Wall bounce + if (gBall.y - gBall.halfSize < 0) { + gBall.y = gBall.halfSize; + gBall.vy = std::abs(gBall.vy); + } + if (gBall.y + gBall.halfSize > WINDOW_H) { + gBall.y = WINDOW_H - gBall.halfSize; + gBall.vy = -std::abs(gBall.vy); + } + + // Paddle collisions + auto paddleHit = [&](Paddle& p, int dir) { + if (AABBOverlap(gBall.x, gBall.y, gBall.halfSize, gBall.halfSize, + p.x, p.y, p.halfW, p.halfH)) + { + gBall.speed += BALL_ACCEL; + float relY = (gBall.y - p.y) / p.halfH; + float angle = relY * 60.0f * (MY_PI / 180.0f); + gBall.vx = cosf(angle) * gBall.speed * dir; + gBall.vy = sinf(angle) * gBall.speed; + gBall.x = p.x + (p.halfW + gBall.halfSize + 1.0f) * dir; + gScreenShake = 0.15f; + } + }; + paddleHit(gP1, 1); + paddleHit(gP2, -1); + + // Scoring + auto handleScore = [&](Paddle& scorer, int nextDir, const char* who) { + ++scorer.score; + if (scorer.score >= WIN_SCORE) { + gWinnerText = who; + gScreen = GameScreen::GameOver; + star::Logger::GetInstance()->Log(star::LogLevel::Info, + tstring(_T("Game over! ")) + _T(who) + _T(" wins!"), + STARENGINE_LOG_TAG); + } else { + ResetBall(nextDir); + } + }; + + if (gBall.x < -BALL_SIZE) { + gScreenShake = 0.25f; + const char* name = (gMode == GameMode::VsAI) ? "AI" : "PLAYER 2"; + handleScore(gP2, -1, name); + } + if (gBall.x > WINDOW_W + BALL_SIZE) { + gScreenShake = 0.25f; + handleScore(gP1, 1, "PLAYER 1"); + } +} + +// --------------------------------------------------------------------------- +// Rendering +// --------------------------------------------------------------------------- +static void RenderField() +{ + glClearColor(0.04f, 0.04f, 0.10f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + + float shakeX = 0, shakeY = 0; + if (gScreenShake > 0) { + shakeX = ((rand() % 100) / 100.0f - 0.5f) * gScreenShake * 20.0f; + shakeY = ((rand() % 100) / 100.0f - 0.5f) * gScreenShake * 20.0f; + } + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0, WINDOW_W, WINDOW_H, 0, -1, 1); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glTranslatef(shakeX, shakeY, 0); + + // Centre line + glColor3f(0.18f, 0.18f, 0.28f); + for (float y = 0; y < WINDOW_H; y += 20.0f) { + DrawRect(WINDOW_W / 2.0f, y + 5.0f, 1.5f, 5.0f); + } + + // Scores + glColor3f(0.35f, 0.35f, 0.50f); + DrawScore(gP1.score, WINDOW_W * 0.25f, 20.0f, 6.0f); + DrawScore(gP2.score, WINDOW_W * 0.75f, 20.0f, 6.0f); + + // Labels + glColor3f(0.25f, 0.25f, 0.38f); + if (gMode == GameMode::VsAI) { + DrawText("YOU", WINDOW_W * 0.25f, 80.0f, 2.5f); + DrawText("AI", WINDOW_W * 0.75f, 80.0f, 2.5f); + } else { + DrawText("P1", WINDOW_W * 0.25f, 80.0f, 2.5f); + DrawText("P2", WINDOW_W * 0.75f, 80.0f, 2.5f); + } + + // Ball trail + for (int i = 0; i < 8; ++i) { + int idx = (gTrailIdx - i + 8) % 8; + float alpha = (8 - i) / 24.0f; + float size = gBall.halfSize * (8 - i) / 10.0f; + glColor4f(1.0f, 0.7f, 0.1f, alpha); + DrawRect(gBallTrailX[idx], gBallTrailY[idx], size, size); + } + + // Ball + glColor3f(1.0f, 0.85f, 0.2f); + DrawRect(gBall.x, gBall.y, gBall.halfSize, gBall.halfSize); + + // Ball glow + glColor4f(1.0f, 0.85f, 0.2f, 0.08f); + DrawRect(gBall.x, gBall.y, gBall.halfSize * 3, gBall.halfSize * 3); + + // Paddles P1=blue P2=red + glColor3f(0.4f, 0.7f, 1.0f); + DrawRect(gP1.x, gP1.y, gP1.halfW, gP1.halfH); + glColor4f(0.4f, 0.7f, 1.0f, 0.06f); + DrawRect(gP1.x, gP1.y, gP1.halfW * 3, gP1.halfH + 5); + + glColor3f(1.0f, 0.45f, 0.4f); + DrawRect(gP2.x, gP2.y, gP2.halfW, gP2.halfH); + glColor4f(1.0f, 0.45f, 0.4f, 0.06f); + DrawRect(gP2.x, gP2.y, gP2.halfW * 3, gP2.halfH + 5); + + // Countdown + if (gCountdown > 0.0f) { + int num = (int)ceilf(gCountdown); + if (num < 1) num = 1; + if (num > 3) num = 3; + float scale = 1.0f + (gCountdown - floorf(gCountdown)) * 0.5f; + glColor4f(1.0f, 1.0f, 1.0f, 0.6f); + char buf[2] = { (char)('0' + num), 0 }; + DrawText(buf, WINDOW_W / 2.0f, WINDOW_H / 2.0f - 30.0f * scale, 8.0f * scale); + } +} + +static void RenderPauseOverlay() +{ + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glColor4f(0.0f, 0.0f, 0.0f, 0.5f); + DrawRect(WINDOW_W / 2.0f, WINDOW_H / 2.0f, WINDOW_W / 2.0f, WINDOW_H / 2.0f); + + glColor3f(1.0f, 1.0f, 1.0f); + DrawText("PAUSED", WINDOW_W / 2.0f, WINDOW_H / 2.0f - 40.0f, 5.0f); + + glColor3f(0.6f, 0.6f, 0.7f); + DrawText("PRESS SPACE TO RESUME", WINDOW_W / 2.0f, WINDOW_H / 2.0f + 20.0f, 2.5f); + DrawText("PRESS ESCAPE FOR MENU", WINDOW_W / 2.0f, WINDOW_H / 2.0f + 50.0f, 2.5f); +} + +static void RenderMainMenu() +{ + glClearColor(0.03f, 0.03f, 0.08f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0, WINDOW_W, WINDOW_H, 0, -1, 1); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + // Decorative dashed lines + float shift = fmodf(gMenuPulse * 30.0f, 20.0f); + glColor3f(0.12f, 0.12f, 0.22f); + for (float y = -20.0f + shift; y < WINDOW_H + 20; y += 20.0f) { + DrawRect(60.0f, y, 1.5f, 5.0f); + DrawRect(WINDOW_W - 60.0f, y, 1.5f, 5.0f); + } + + // Title + float titlePulse = 1.0f + sinf(gMenuPulse * 2.0f) * 0.03f; + glColor3f(1.0f, 0.85f, 0.2f); + DrawText("STAR PONG", WINDOW_W / 2.0f, 80.0f, 7.0f * titlePulse); + + // Subtitle + glColor3f(0.4f, 0.4f, 0.55f); + DrawText("POWERED BY STARENGINE", WINDOW_W / 2.0f, 150.0f, 2.0f); + + // Menu items + const char* items[] = { "1 PLAYER VS AI", "2 PLAYERS", "QUIT" }; + const int itemCount = 3; + float startY = 250.0f; + float gap = 55.0f; + + for (int i = 0; i < itemCount; ++i) { + float y = startY + i * gap; + bool selected = (i == gMenuSelection); + + if (selected) { + glColor4f(1.0f, 0.85f, 0.2f, 0.08f); + DrawRect(WINDOW_W / 2.0f, y + 14.0f, 180.0f, 20.0f); + + glColor3f(1.0f, 0.85f, 0.2f); + DrawText(">", WINDOW_W / 2.0f - 150.0f, y, 4.0f); + + glColor3f(1.0f, 0.95f, 0.7f); + } else { + glColor3f(0.5f, 0.5f, 0.6f); + } + DrawText(items[i], WINDOW_W / 2.0f, y, 3.5f); + } + + // Hint + glColor3f(0.3f, 0.3f, 0.42f); + DrawText("UP/DOWN TO SELECT ENTER TO CONFIRM", WINDOW_W / 2.0f, 520.0f, 2.0f); +} + +static void RenderDifficultyMenu() +{ + glClearColor(0.03f, 0.03f, 0.08f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0, WINDOW_W, WINDOW_H, 0, -1, 1); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + glColor3f(0.7f, 0.7f, 0.85f); + DrawText("SELECT DIFFICULTY", WINDOW_W / 2.0f, 80.0f, 5.0f); + + const char* items[] = { "EASY", "MEDIUM", "HARD", "IMPOSSIBLE" }; + const char* descs[] = { + "SLOW AI LOTS OF MISTAKES", + "BALANCED FAIR CHALLENGE", + "FAST AI VERY PRECISE", + "PERFECT NO MERCY" + }; + float colors[][3] = { + {0.3f, 0.9f, 0.3f}, + {0.9f, 0.8f, 0.2f}, + {1.0f, 0.4f, 0.2f}, + {1.0f, 0.15f, 0.15f}, + }; + const int itemCount = 4; + float startY = 180.0f; + float gap = 75.0f; + + for (int i = 0; i < itemCount; ++i) { + float y = startY + i * gap; + bool selected = (i == gDiffSelection); + + if (selected) { + glColor4f(colors[i][0], colors[i][1], colors[i][2], 0.08f); + DrawRect(WINDOW_W / 2.0f, y + 18.0f, 200.0f, 28.0f); + + glColor3f(colors[i][0], colors[i][1], colors[i][2]); + DrawText(">", WINDOW_W / 2.0f - 130.0f, y, 4.0f); + DrawText(items[i], WINDOW_W / 2.0f, y, 4.0f); + + glColor3f(colors[i][0] * 0.6f, colors[i][1] * 0.6f, colors[i][2] * 0.6f); + DrawText(descs[i], WINDOW_W / 2.0f, y + 35.0f, 2.0f); + } else { + glColor3f(0.4f, 0.4f, 0.5f); + DrawText(items[i], WINDOW_W / 2.0f, y, 3.5f); + } + } + + glColor3f(0.3f, 0.3f, 0.42f); + DrawText("ENTER TO START ESCAPE TO GO BACK", WINDOW_W / 2.0f, 520.0f, 2.0f); +} + +static void RenderGameOver() +{ + RenderField(); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glColor4f(0.0f, 0.0f, 0.0f, 0.6f); + DrawRect(WINDOW_W / 2.0f, WINDOW_H / 2.0f, WINDOW_W / 2.0f, WINDOW_H / 2.0f); + + glColor3f(1.0f, 0.85f, 0.2f); + DrawText(gWinnerText.c_str(), WINDOW_W / 2.0f, WINDOW_H / 2.0f - 60.0f, 5.0f); + + glColor3f(1.0f, 1.0f, 1.0f); + DrawText("WINS!", WINDOW_W / 2.0f, WINDOW_H / 2.0f, 5.0f); + + glColor3f(0.6f, 0.6f, 0.7f); + char scoreBuf[32]; + snprintf(scoreBuf, sizeof(scoreBuf), "%d - %d", gP1.score, gP2.score); + DrawText(scoreBuf, WINDOW_W / 2.0f, WINDOW_H / 2.0f + 55.0f, 4.0f); + + glColor3f(0.5f, 0.5f, 0.65f); + DrawText("ENTER TO PLAY AGAIN", WINDOW_W / 2.0f, WINDOW_H / 2.0f + 120.0f, 2.5f); + DrawText("ESCAPE FOR MENU", WINDOW_W / 2.0f, WINDOW_H / 2.0f + 150.0f, 2.5f); +} + +// --------------------------------------------------------------------------- +// Main +// --------------------------------------------------------------------------- +int main(int /*argc*/, char* /*argv*/[]) +{ + srand(static_cast(time(nullptr))); + + star::Logger::GetInstance()->Initialize(); + star::Logger::GetInstance()->Log(star::LogLevel::Info, + _T("Star Pong starting"), STARENGINE_LOG_TAG); + + if (SDL_Init(SDL_INIT_VIDEO) != 0) { + fprintf(stderr, "SDL_Init failed: %s\n", SDL_GetError()); + return 1; + } + + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1); + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + + SDL_Window* window = SDL_CreateWindow( + "Star Pong", + SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, + WINDOW_W, WINDOW_H, + SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN); + + if (!window) { + fprintf(stderr, "SDL_CreateWindow failed: %s\n", SDL_GetError()); + SDL_Quit(); + return 1; + } + + SDL_GLContext glCtx = SDL_GL_CreateContext(window); + if (!glCtx) { + fprintf(stderr, "SDL_GL_CreateContext failed: %s\n", SDL_GetError()); + SDL_DestroyWindow(window); + SDL_Quit(); + return 1; + } + SDL_GL_SetSwapInterval(1); + + GLenum glewErr = glewInit(); + if (glewErr != GLEW_OK) { + fprintf(stderr, "glewInit failed: %s\n", glewGetErrorString(glewErr)); + SDL_GL_DeleteContext(glCtx); + SDL_DestroyWindow(window); + SDL_Quit(); + return 1; + } + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + star::Logger::GetInstance()->Log(star::LogLevel::Info, + _T("OpenGL context created"), STARENGINE_LOG_TAG); + + star::TimeManager* timeMgr = star::TimeManager::GetInstance(); + + while (gRunning) { + timeMgr->StartMonitoring(); + + SDL_Event ev; + while (SDL_PollEvent(&ev)) { + if (ev.type == SDL_QUIT) { + gRunning = false; + } + if (ev.type == SDL_KEYDOWN && !ev.key.repeat) { + SDL_Scancode sc = ev.key.keysym.scancode; + + switch (gScreen) { + case GameScreen::MainMenu: + if (sc == SDL_SCANCODE_UP || sc == SDL_SCANCODE_W) + gMenuSelection = (gMenuSelection + 2) % 3; + if (sc == SDL_SCANCODE_DOWN || sc == SDL_SCANCODE_S) + gMenuSelection = (gMenuSelection + 1) % 3; + if (sc == SDL_SCANCODE_RETURN || sc == SDL_SCANCODE_SPACE) { + if (gMenuSelection == 0) { + gMode = GameMode::VsAI; + gScreen = GameScreen::DifficultySelect; + } else if (gMenuSelection == 1) { + gMode = GameMode::VsPlayer; + InitGame(); + gScreen = GameScreen::Playing; + } else { + gRunning = false; + } + } + if (sc == SDL_SCANCODE_ESCAPE) gRunning = false; + break; + + case GameScreen::DifficultySelect: + if (sc == SDL_SCANCODE_UP || sc == SDL_SCANCODE_W) + gDiffSelection = (gDiffSelection + 3) % 4; + if (sc == SDL_SCANCODE_DOWN || sc == SDL_SCANCODE_S) + gDiffSelection = (gDiffSelection + 1) % 4; + if (sc == SDL_SCANCODE_RETURN || sc == SDL_SCANCODE_SPACE) { + gDifficulty = static_cast(gDiffSelection); + InitGame(); + gScreen = GameScreen::Playing; + star::Logger::GetInstance()->Log(star::LogLevel::Info, + _T("Starting game vs AI"), STARENGINE_LOG_TAG); + } + if (sc == SDL_SCANCODE_ESCAPE) gScreen = GameScreen::MainMenu; + break; + + case GameScreen::Playing: + if (sc == SDL_SCANCODE_SPACE) gScreen = GameScreen::Paused; + if (sc == SDL_SCANCODE_ESCAPE) gScreen = GameScreen::MainMenu; + break; + + case GameScreen::Paused: + if (sc == SDL_SCANCODE_SPACE) gScreen = GameScreen::Playing; + if (sc == SDL_SCANCODE_ESCAPE) gScreen = GameScreen::MainMenu; + break; + + case GameScreen::GameOver: + if (sc == SDL_SCANCODE_RETURN || sc == SDL_SCANCODE_SPACE) { + InitGame(); + gScreen = GameScreen::Playing; + } + if (sc == SDL_SCANCODE_ESCAPE) gScreen = GameScreen::MainMenu; + break; + } + } + } + + const uint8_t* keys = SDL_GetKeyboardState(nullptr); + float dt = static_cast(timeMgr->DeltaTime().GetSeconds()); + if (dt > 0.05f) dt = 0.05f; + + gMenuPulse += dt; + if (gScreenShake > 0) { + gScreenShake -= dt * 2.0f; + if (gScreenShake < 0) gScreenShake = 0; + } + + switch (gScreen) { + case GameScreen::MainMenu: + RenderMainMenu(); + break; + case GameScreen::DifficultySelect: + RenderDifficultyMenu(); + break; + case GameScreen::Playing: + UpdatePlaying(dt, keys); + RenderField(); + break; + case GameScreen::Paused: + RenderField(); + RenderPauseOverlay(); + break; + case GameScreen::GameOver: + RenderGameOver(); + break; + } + + SDL_GL_SwapWindow(window); + timeMgr->StopMonitoring(); + } + + star::Logger::GetInstance()->Log(star::LogLevel::Info, + _T("Star Pong shutting down"), STARENGINE_LOG_TAG); + + star::TimeManager::DeleteSingleton(); + star::Logger::DeleteSingleton(); + + SDL_GL_DeleteContext(glCtx); + SDL_DestroyWindow(window); + SDL_Quit(); + + return 0; +}