Improve axmol site build

This commit is contained in:
halx99 2023-08-31 21:20:01 +08:00
parent b50c629307
commit 12bb1eb62a
424 changed files with 12487 additions and 13369 deletions

View File

@ -31,7 +31,7 @@ jobs:
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./docs/out/
publish_dir: ./docs/dist/
enable_jekyll: false
allow_empty_commit: false
force_orphan: true

View File

@ -1,4 +1,5 @@
# Default manifest in main script build1k.ps1
# Uncomment to overwrite $manifest in main script build1k.ps1
# $manifest = @{
# msvc = '143+';
# ndk = 'r23c+';
@ -6,24 +7,11 @@
# clang = '15.0.0+';
# gcc = '9.0.0+';
# cmake = '3.26.4+';
# nuget = '*'; # any
# glslcc = '1.8.0+';
# ninja = '1.11.1+';
# jdk = '11.0.19+';
# cmdlinetools = '7.0+'; # android cmdlinetools
# }
# add or overwrite tool version like follow
$manifest['nuget'] = '*' # any
$manifest['glslcc'] = '1.9.3+'
if ($IsMacOS) {
# refer to: https://gitlab.kitware.com/cmake/cmake/-/merge_requests/8632
# once cmake-3.28.0 released, can simply specify cmake to '3.28.0+'
$manifest['cmake'] = '3.27.20230808'
$channels['cmake'] = 'g94eae40'
}
elseif ($options.p -eq 'winuwp') {
# refer to: https://gitlab.kitware.com/cmake/cmake/-/merge_requests/8319
$manifest['cmake'] = '3.27.2+'
}
# [void]$manifest

View File

@ -37,7 +37,7 @@ endif()
# ax root path
set(_AX_ROOT ${CMAKE_CURRENT_SOURCE_DIR})
set(CMAKE_MODULE_PATH ${_AX_ROOT}/cmake/)
set(CMAKE_MODULE_PATH ${_AX_ROOT}/cmake/Modules/)
# prevent in-source-build
include(PreventInSourceBuilds)

View File

@ -10,6 +10,13 @@
- AX_USE_ALSOFT: whether use openal-soft for all platforms
- Apple platform: Use openal-soft instead system deprecated: `OpenAL.framework`
- Other platforms: Always use openal-soft even this option not enabled
- AX_USE_ANGLE: whether use compat gl as renderer backend, default: `FALSE`
- windows: whether use angleproject as GLES2 backend
- apple: whether use GLES instead Metal backend
- AX_USE_COMPAT_GL: deprecated, use AX_USE_ANGLE instead
- AX_USE_GLAD:
- Android: use glad load for GLES API loads, default `FALSE`
- Other platforms: Always use glad even this option not enabled
- AX_USE_LUAJIT: whether use luajit, default: `FALSE`, use plainlua
- AX_ENABLE_EXT_XXX for extensions
- AX_ENABLE_EXT_GUI: the traditional GUI extension, default: `TRUE`
@ -25,11 +32,6 @@
- AX_ENABLE_EXT_EFFEKSEER: the effekseer extension, default: `FALSE`
- AX_WITH_XXX: usually user don't need care it
- AX_VS_DEPLOYMENT_TARGET: specify windows store deploy target, default: `10.0.17763.0`
- AX_USE_COMPAT_GL: whether use compat gl as renderer backend, default: FALSE
- win32: whether use ANGLE GLES backend
- osx: whether use OpenGL instead Metal backend
- ios/tvos: whether use GLES instead Metal backend
- AX_GLES_PROFILE: speicify GLES profile version for GLES backend, valid value `200`, `300`
## The options for axmol apps

View File

@ -30,14 +30,6 @@
| Linux |[![Linux Build Status](https://github.com/axmolengine/axmol/workflows/linux/badge.svg)](https://github.com/axmolengine/axmol/actions?query=workflow%3Alinux)|
| macOS |[![macOS Build Status](https://github.com/axmolengine/axmol/workflows/osx/badge.svg)](https://github.com/axmolengine/axmol/actions?query=workflow%3Aosx)|
## Renderer Backends
- Metal for macOS and iOS
- OpenGL 3.3+ for Linux, macOS and Win32
- OpenGL ES 2.0+ for Android
- OpenGL ES 3.0+ for iOS
- ANGLE GLES 3.0+ for Win32 and UWP
## New MediaPlayer
The new `ui::MediaPlayer`(renamed from `ui::VideoPlayer`) render video as Texture2D with designed corss-platform MediaEngine, the MediaEngine inspired from microsoft
@ -104,7 +96,6 @@ Open [APPENDIX.md](APPENDIX.md) for additional information and see [Milestones](
## Reference links
- [build1k](https://github.com/axmolengine/build1k), the axmol prebuilt build-bot
- [axmolengine/glslcc](https://github.com/axmolengine/glslcc), a fork of glslcc for axmol new shader workflow tool
- [Some interesting related projects based on axmol](https://github.com/axmolengine/axmol/discussions/694)
- [Axmols contributing guide](https://github.com/axmolengine/axmol/discussions/411)
- [Official Cocos2d-x](https://github.com/cocos2d/cocos2d-x)

View File

@ -23,14 +23,6 @@
| Linux |[![Linux Build Status](https://github.com/axmolengine/axmol/workflows/linux/badge.svg)](https://github.com/axmolengine/axmol/actions?query=workflow%3Alinux)|
| macOS |[![macOS Build Status](https://github.com/axmolengine/axmol/workflows/osx/badge.svg)](https://github.com/axmolengine/axmol/actions?query=workflow%3Aosx)|
## 渲染后端
- Metal: macOS, iOS
- OpenGL 3.3+: Linux, macOS, Win32
- OpenGL ES 2.0+: Android
- OpenGL ES 3.0+: iOS
- ANGLE GLES 3.0+: Win32, WinUWP
## 新的媒体播放器
新的媒体播放器`ui::MediaPlayer`(原命: `ui::VideoPlayer`) 将视频渲染为纹理使得游戏对视频渲染控制更加灵活就像普通UI一样而无需考虑层级问题。这得益于重新升级的跨平台`MediaEngine`, 灵感来自微软的媒体基础库(Microsoft Media Foundation): `IMFMediaEngine`目前已支持axmol引擎支持的所有平台。
@ -82,7 +74,6 @@
### 参考链接
- axmol引擎预编译库生成工具: [build1k](https://github.com/axmolengine/build1k),
- axmol专用shader编译工具: [axmolengine/glslcc](https://github.com/axmolengine/glslcc),
- 一些基于axmol引擎的开源项目: https://github.com/axmolengine/axmol/discussions/694
- official v4: https://gitee.com/mirrors/cocos2d-x
- Git快速手册: https://github.com/axmolengine/axmol/discussions/411

View File

@ -1,244 +0,0 @@
cmake_policy(PUSH)
cmake_policy(SET CMP0057 NEW)
##############################################################
## enable shader lang by shader compiler: glslcc
macro(glslcc_option variable value)
if(NOT DEFINED ${variable})
set(${variable} ${value} CACHE STATIC "" FORCE)
endif()
endmacro()
glslcc_option(GLSLCC_FRAG_SOURCE_FILE_EXTENSIONS ".frag;.fsh")
glslcc_option(GLSLCC_VERT_SOURCE_FILE_EXTENSIONS ".vert;.vsh")
glslcc_option(GLSLCC_OUT_DIR ${CMAKE_BINARY_DIR}/runtime/axslc)
glslcc_option(GLSLCC_FIND_PROG_ROOT "")
find_program(GLSLCC_EXE NAMES glslcc
PATHS ${GLSLCC_FIND_PROG_ROOT}
)
if (NOT GLSLCC_EXE)
message(STATUS, "glslcc not found.")
message(FATAL_ERROR "Please run setup.ps1 again to download glslcc, and run CMake again.")
endif()
message(STATUS "GLSLCC_OUT_DIR=${GLSLCC_OUT_DIR}")
message(STATUS "GLSLCC_FIND_PROG_ROOT=${GLSLCC_FIND_PROG_ROOT}")
message(STATUS "GLSLCC_FRAG_SOURCE_FILE_EXTENSIONS=${GLSLCC_FRAG_SOURCE_FILE_EXTENSIONS}")
message(STATUS "GLSLCC_VERT_SOURCE_FILE_EXTENSIONS=${GLSLCC_VERT_SOURCE_FILE_EXTENSIONS}")
# PROPERTY: include direcotries (optional)
define_property(SOURCE PROPERTY GLSLCC_INCLUDE_DIRS
BRIEF_DOCS "Compiled shader include directories"
FULL_DOCS "Compiled shader include directories, seperated with comma")
# PROPERTY: defines (optional) TODO: rename to PREPROCESSOR_LIST
define_property(SOURCE PROPERTY GLSLCC_DEFINES
BRIEF_DOCS "Compiled shader defines"
FULL_DOCS "Compiled shader defines, seperated with comma")
# PROPERTY: output1 (optional) TODO: rename to PREPROCESSOR_LIST
define_property(SOURCE PROPERTY GLSLCC_OUTPUT1
BRIEF_DOCS "Compiled shader output1 additional defines"
FULL_DOCS "Compiled shader output1 additional defines, seperated with comma")
# PROPERTY: glscc output (optional)
define_property(SOURCE PROPERTY GLSLCC_OUTPUT
BRIEF_DOCS "The compiled sources shader output path list"
FULL_DOCS "The compiled shaders output list, seperated with comma")
# Find shader sources in specified directory
# syntax: ax_find_shaders(dir shader_sources [RECURSE])
# examples:
# - ax_find_shaders("${CMAKE_CURRENT_LIST_DIR}/core/renderer/shaders" runtime_shader_sources)
# - ax_find_shaders("${CMAKE_CURRENT_LIST_DIR}/Source" custom_shader_sources RECURSE)
function (ax_find_shaders dir varName)
set(options RECURSE)
cmake_parse_arguments(opt "${options}" "" "" ${ARGN})
set(SC_FILTERS "")
foreach(fileext ${GLSLCC_FRAG_SOURCE_FILE_EXTENSIONS})
list(APPEND SC_FILTERS "${dir}/*${fileext}")
endforeach()
foreach(fileext ${GLSLCC_VERT_SOURCE_FILE_EXTENSIONS})
list(APPEND SC_FILTERS "${dir}/*${fileext}")
endforeach()
if (opt_RECURSE)
file(GLOB_RECURSE out_files ${SC_FILTERS})
else()
file(GLOB out_files ${SC_FILTERS})
endif()
set(${varName} ${out_files} PARENT_SCOPE)
endfunction()
# This function allow make shader files (.frag, .vert) compiled with glslcc
# usage:
# - ax_target_compile_shaders(axmol FILES source_files): output compiled shader to ${CMAKE_BINARY_DIR}/runtime/axslc/xxx_fs
# - ax_target_compile_shaders(axmol FILES source_files CUSTOM): output compiled shader to ${CMAKE_BINARY_DIR}/runtime/axslc/custom/xxx_fs
# - ax_target_compile_shaders(axmol FILES source_files CVAR): the shader will compiled to c hex header for embed include by C/C++ use
# Use global variable to control shader file extension:
# - GLSLCC_FRAG_SOURCE_FILE_EXTENSIONS: default is .frag;.fsh
# - GLSLCC_VERT_SOURCE_FILE_EXTENSIONS: default is .vert;.vsh
#
function (ax_target_compile_shaders target_name)
set(options RUNTIME CVAR CUSTOM)
set(multiValueArgs FILES)
cmake_parse_arguments(opt "${options}" "" "${multiValueArgs}" ${ARGN})
foreach(SC_FILE ${opt_FILES})
get_filename_component(FILE_EXT ${SC_FILE} LAST_EXT)
get_filename_component(FILE_NAME ${SC_FILE} NAME_WE)
string(TOLOWER "${FILE_EXT}" FILE_EXT)
set(SC_DEFINES "")
# silent when compile shader success
set(SC_FLAGS "--silent" "--err-format=msvc")
# shader lang
set(SC_PROFILE "")
if(AX_GLES_PROFILE)
# version 300 es
if (AX_GLES_PROFILE EQUAL 300)
set(OUT_LANG "ESSL")
set(SC_PROFILE "300")
else()
# GLSL2 use glsl100 syntax es profile alka essl100
set(OUT_LANG "ESSL")
set(SC_PROFILE "100")
set(SC_DEFINES "GLES2")
endif()
list(APPEND SC_FLAGS "--lang=gles" "--profile=${SC_PROFILE}")
elseif (AX_USE_GL)
# version 330
set(OUT_LANG "GLSL")
set(SC_PROFILE "330")
list(APPEND SC_FLAGS "--lang=glsl" "--profile=${SC_PROFILE}")
elseif (AX_USE_METAL)
set(OUT_LANG "MSL")
list(APPEND SC_FLAGS "--lang=msl")
set(SC_DEFINES "METAL")
endif()
# automap, no-suffix since 1.18.1 released by axmolengine
list(APPEND SC_FLAGS "--automap" "--no-suffix")
# defines
get_source_file_property(SOURCE_SC_DEFINES ${SC_FILE} GLSLCC_DEFINES)
if (NOT (SOURCE_SC_DEFINES STREQUAL "NOTFOUND"))
set(SC_DEFINES "${SC_DEFINES},${SOURCE_SC_DEFINES}")
endif()
if (SC_DEFINES)
list(APPEND SC_FLAGS "\"--defines=${SC_DEFINES}\"")
endif()
# includes
get_source_file_property(INC_DIRS ${SC_FILE} GLSLCC_INCLUDE_DIRS)
if (INC_DIRS STREQUAL "NOTFOUND")
set(INC_DIRS "")
endif()
list(APPEND INC_DIRS "${_AX_ROOT}/core/renderer/shaders")
list(APPEND SC_FLAGS "--include-dirs=${INC_DIRS}")
if (opt_CVAR)
list(APPEND SC_FLAGS "--cvar=shader_rt_${FILE_NAME}")
endif()
# sgs, because Apple Metal lack of shader uniform reflect so use --sgs --refelect
if (AX_USE_METAL)
list(APPEND SC_FLAGS "--sgs" "--reflect")
endif()
# input
if (${FILE_EXT} IN_LIST GLSLCC_FRAG_SOURCE_FILE_EXTENSIONS)
list(APPEND SC_FLAGS "--frag=${SC_FILE}")
set(SC_TYPE "fs")
elseif(${FILE_EXT} IN_LIST GLSLCC_VERT_SOURCE_FILE_EXTENSIONS)
set(SC_TYPE "vs")
list(APPEND SC_FLAGS "--vert=${SC_FILE}")
else()
message(FATAL_ERROR "Invalid shader source, the file extesion must be one of .frag;.vert")
endif()
# output
set(OUT_DIR ${GLSLCC_OUT_DIR})
if(opt_CUSTOM)
set(OUT_DIR "${OUT_DIR}/custom")
endif()
if (NOT (IS_DIRECTORY ${OUT_DIR}))
file(MAKE_DIRECTORY ${OUT_DIR})
endif()
set(SC_OUTPUT "${OUT_DIR}/${FILE_NAME}_${SC_TYPE}")
set(SC_COMMENT "Compiling shader ${SC_FILE} for ${OUT_LANG}${SC_PROFILE} ...")
get_source_file_property(SOURCE_SC_OUTPUT1 ${SC_FILE} GLSLCC_OUTPUT1)
string(REPLACE ";" " " FULL_COMMAND_LINE "${GLSLCC_EXE};${SC_FLAGS} ...")
if(SOURCE_SC_OUTPUT1 STREQUAL "NOTFOUND") # single output
list(APPEND SC_FLAGS "--output=${SC_OUTPUT}")
set_source_files_properties(${SC_FILE} DIRECTORY ${CMAKE_BINARY_DIR} PROPERTIES GLSLCC_OUTPUT ${SC_OUTPUT})
add_custom_command(
MAIN_DEPENDENCY ${SC_FILE} OUTPUT ${SC_OUTPUT} COMMAND ${GLSLCC_EXE} ${SC_FLAGS}
COMMENT "${SC_COMMENT}"
)
else() # dual outputs
set(SC_DEFINES1 "${SC_DEFINES},${SOURCE_SC_OUTPUT1}")
set(SC_FLAGS1 ${SC_FLAGS})
list(REMOVE_ITEM SC_FLAGS1 "\"--defines=${SC_DEFINES}\"")
list(APPEND SC_FLAGS1 "\"--defines=${SC_DEFINES1}\"")
list(APPEND SC_FLAGS "--output=${SC_OUTPUT}")
set(SC_OUTPUT1 "${SC_OUTPUT}_1")
list(APPEND SC_FLAGS1 "--output=${SC_OUTPUT1}")
string(REPLACE ";" " " FULL_COMMAND_LINE1 "${GLSLCC_EXE};${SC_FLAGS1} ...")
set_source_files_properties(${SC_FILE} DIRECTORY ${CMAKE_BINARY_DIR} PROPERTIES GLSLCC_OUTPUT "${SC_OUTPUT};${SC_OUTPUT1}")
add_custom_command(
MAIN_DEPENDENCY ${SC_FILE}
OUTPUT ${SC_OUTPUT} ${SC_OUTPUT1}
COMMAND ${GLSLCC_EXE} ${SC_FLAGS}
COMMAND ${GLSLCC_EXE} ${SC_FLAGS1}
COMMENT "${SC_COMMENT}"
)
endif()
endforeach()
target_sources(${target_name} PRIVATE ${opt_FILES})
endfunction()
function(ax_target_embed_compiled_shaders target_name rc_output)
set(multiValueArgs FILES)
cmake_parse_arguments(opt "" "" "${multiValueArgs}" ${ARGN})
set(app_all_shaders_json "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n")
set(app_all_shaders_json "${app_all_shaders_json}<Project DefaultTargets=\"Build\" ToolsVersion=\"12.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n")
set(app_all_shaders_json "${app_all_shaders_json} <ItemGroup>\n")
foreach(shader ${opt_FILES})
get_source_file_property(compiled_shaders ${shader} DIRECTORY ${CMAKE_BINARY_DIR} GLSLCC_OUTPUT)
if(compiled_shaders STREQUAL "NOTFOUND")
message(FATAL_ERROR "Not found property GLSLCC_OUTPUT of file: ${shader}")
endif()
foreach(compiled_shader ${compiled_shaders})
set(app_all_shaders_json "${app_all_shaders_json} <None Include=\"${compiled_shader}\">\n")
set(app_all_shaders_json "${app_all_shaders_json} <Link>Content\\axslc\\%(FileName)%(Extension)</Link>\n")
set(app_all_shaders_json "${app_all_shaders_json} <DeploymentContent Condition=\"'\$(Configuration)|\$(Platform)'=='Debug|x64'\">true</DeploymentContent>\n")
set(app_all_shaders_json "${app_all_shaders_json} <DeploymentContent Condition=\"'\$(Configuration)|\$(Platform)'=='Release|x64'\">true</DeploymentContent>\n")
set(app_all_shaders_json "${app_all_shaders_json} <DeploymentContent Condition=\"'\$(Configuration)|\$(Platform)'=='MinSizeRel|x64'\">true</DeploymentContent>\n")
set(app_all_shaders_json "${app_all_shaders_json} <DeploymentContent Condition=\"'\$(Configuration)|\$(Platform)'=='RelWithDebInfo|x64'\">true</DeploymentContent>\n")
set(app_all_shaders_json "${app_all_shaders_json} </None>\n")
endforeach()
endforeach()
set(app_all_shaders_json "${app_all_shaders_json} </ItemGroup>\n</Project>\n")
set(props_file "${rt_output}/axslc.props")
write_file("${props_file}" "${app_all_shaders_json}")
set_target_properties(${target_name} PROPERTIES VS_USER_PROPS "${props_file}")
endfunction()
cmake_policy(POP)

View File

@ -201,7 +201,7 @@ function(ax_copy_target_dll ax_target)
)
# Copy windows angle binaries
if (WIN32 AND AX_GLES_PROFILE)
if (WIN32 AND AX_USE_ANGLE)
add_custom_command(TARGET ${ax_target} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
${_AX_ROOT}/${_AX_THIRDPARTY_NAME}/angle/prebuilt/${platform_name}/${ARCH_ALIAS}/libGLESv2.dll
@ -398,33 +398,10 @@ function(ax_setup_app_config app_name)
)
endif()
# auto looking app shaders source dir and add to glslcc compile-list
get_target_property(app_shaders_dir ${app_name} SOURCE_DIR)
set(app_shaders_dir "${app_shaders_dir}/Source/shaders")
ax_find_shaders(${app_shaders_dir} app_shaders RECURSE)
if (app_shaders)
list(LENGTH app_shaders app_shaders_count)
message(STATUS "${app_shaders_count} shader sources found in ${app_shaders_dir}")
# compile app shader to ${CMAKE_BINARY_DIR}/runtime/axslc/custom/
ax_target_compile_shaders(${app_name} FILES ${app_shaders} CUSTOM)
source_group("Source Files/Source/shaders" FILES ${app_shaders})
else()
message(STATUS "No shader found in ${app_shaders_dir}")
endif()
if (IS_DIRECTORY ${GLSLCC_OUT_DIR})
get_target_property(rt_output ${app_name} RUNTIME_OUTPUT_DIRECTORY)
if ((WIN32 AND (NOT WINRT)) OR LINUX)
ax_sync_target_res(${app_name} LINK_TO "${rt_output}/${CMAKE_CFG_INTDIR}/axslc" FOLDERS ${GLSLCC_OUT_DIR} SYM_LINK 1 SYNC_TARGET_ID axslc)
elseif(APPLE)
# once cmake-3.28.0 released, uncomment follow line instead above 2 lines
set_target_properties(${app_name} PROPERTIES XCODE_EMBED_RESOURCES_PATH ${GLSLCC_OUT_DIR})
elseif(WINRT)
set(app_all_shaders)
list(APPEND app_all_shaders ${ax_builtin_shaders})
list(APPEND app_all_shaders ${app_shaders})
ax_target_embed_compiled_shaders(${app_name} ${rt_output} FILES ${app_all_shaders})
if((WIN32 AND (NOT WINRT)) OR LINUX)
if (IS_DIRECTORY ${GLSLCC_OUT_DIR})
get_target_property(rt_output ${app_name} RUNTIME_OUTPUT_DIRECTORY)
ax_sync_target_res(${APP_NAME} LINK_TO "${rt_output}/${CMAKE_CFG_INTDIR}/axslc" FOLDERS ${GLSLCC_OUT_DIR} SYM_LINK 1 SYNC_TARGET_ID axslc)
endif()
endif()
endfunction()

View File

@ -17,27 +17,19 @@ cmake_policy(SET CMP0072 NEW)
set(ENGINE_BINARY_PATH ${PROJECT_BINARY_DIR}/engine)
if(CMAKE_TOOLCHAIN_FILE)
message(STATUS "Using toolchain file:" ${CMAKE_TOOLCHAIN_FILE})
message(STATUS "using toolchain file:" ${CMAKE_TOOLCHAIN_FILE})
endif()
find_program(PYTHON_COMMAND NAMES python3 python2 python)
find_program(_AX_COMMAND NAME axmol
PATHS ${_AX_ROOT}/tools/console/bin $ENV{AX_CONSOLE_ROOT})
# the default behavior of build module
option(AX_ENABLE_EXT_LUA "Build lua libraries" ON)
# hold the extensions list to auto link to app
set(_AX_EXTENSION_LIBS "" CACHE INTERNAL "extensions for auto link to target application")
# configure android GLSLCC compile output, this is the first include cmake module
if (ANDROID)
file(TO_NATIVE_PATH "${PROJECT_SOURCE_DIR}/proj.android/build/runtime/axslc" _GLSLCC_OUT_DIR)
set(GLSLCC_OUT_DIR "${_GLSLCC_OUT_DIR}" CACHE STRING "" FORCE)
message(AUTHOR_WARNING "Set GLSLCC_OUT_DIR to ${GLSLCC_OUT_DIR} for android")
endif()
# import minimal AXGLSLCC.cmake for shader compiler support
# the function: ax_target_compile_shaders avaiable from it
set(GLSLCC_FIND_PROG_ROOT "${_AX_ROOT}/tools/external/glslcc")
include(AXGLSLCC)
# include helper functions
include(AXBuildHelpers)
@ -63,4 +55,25 @@ message(STATUS "CMAKE_MODULE_PATH:" ${CMAKE_MODULE_PATH})
# delete binary dir if you hope a full clean re-build
message(STATUS "PROJECT_BINARY_DIR:" ${PROJECT_BINARY_DIR})
message(STATUS "ENGINE_BINARY_PATH:" ${ENGINE_BINARY_PATH})
message(STATUS "PYTHON_PATH:" ${PYTHON_COMMAND})
message(STATUS "_AX_COMMAND_PATH:" ${_AX_COMMAND})
message(STATUS "ARCH_ALIAS:" ${ARCH_ALIAS})
if(_AX_COMMAND)
get_filename_component(ax_console_dir ${_AX_COMMAND} DIRECTORY)
set(_AX_LUAJIT_ROOT ${ax_console_dir}/../plugins/plugin_luacompile/bin)
message(STATUS "_AX_LUAJIT_ROOT:" ${_AX_LUAJIT_ROOT})
if("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Windows")
find_program(LUAJIT32_COMMAND NAMES luajit-win32 PATHS ${_AX_LUAJIT_ROOT}/32bit NO_SYSTEM_ENVIRONMENT_PATH)
find_program(LUAJIT64_COMMAND NAMES luajit-win32 PATHS ${_AX_LUAJIT_ROOT}/64bit NO_SYSTEM_ENVIRONMENT_PATH)
elseif("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Linux")
find_program(LUAJIT32_COMMAND NAMES luajit-linux PATHS ${_AX_LUAJIT_ROOT}/32bit NO_SYSTEM_ENVIRONMENT_PATH)
find_program(LUAJIT64_COMMAND NAMES luajit-linux PATHS ${_AX_LUAJIT_ROOT}/64bit NO_SYSTEM_ENVIRONMENT_PATH)
endif()
endif()
if(WINDOWS OR LINUX)
message(STATUS "LUAJIT32_COMMAND:" ${LUAJIT32_COMMAND})
message(STATUS "LUAJIT64_COMMAND:" ${LUAJIT64_COMMAND})
endif()

View File

@ -127,13 +127,13 @@ function(use_ax_compile_define target)
if(APPLE)
target_compile_definitions(${target} PUBLIC __APPLE__)
target_compile_definitions(${target} PUBLIC USE_FILE32API)
if(AX_USE_GL)
if(AX_USE_ANGLE)
target_compile_definitions(${target}
PUBLIC AX_USE_GL=1
PUBLIC AX_GLES_PROFILE=${AX_GLES_PROFILE}
PUBLIC AX_USE_ANGLE=1
PUBLIC GL_SILENCE_DEPRECATION=1
)
endif()
if(IOS)
if(TVOS)
target_compile_definitions(${target} PUBLIC AX_TARGET_OS_TVOS)
@ -146,10 +146,9 @@ function(use_ax_compile_define target)
ax_config_pred(${target} AX_ENABLE_VLC_MEDIA)
target_compile_definitions(${target} PUBLIC _GNU_SOURCE)
elseif(ANDROID)
target_compile_definitions(${target} PUBLIC AX_GLES_PROFILE=${AX_GLES_PROFILE})
target_compile_definitions(${target} PUBLIC USE_FILE32API)
elseif(WINDOWS)
target_compile_definitions(${target} PUBLIC AX_GLES_PROFILE=${AX_GLES_PROFILE})
ax_config_pred(${target} AX_USE_ANGLE)
ax_config_pred(${target} AX_ENABLE_VLC_MEDIA)
target_compile_definitions(${target}
PUBLIC WIN32

View File

@ -11,7 +11,7 @@ macro(ax_depend)
endif()
elseif(LINUX)
# need review those libs: X11 Xi Xrandr Xxf86vm Xinerama Xcursor rt m
list(APPEND PLATFORM_SPECIFIC_LIBS dl X11 Xi Xrandr Xxf86vm Xinerama Xcursor rt m)
list(APPEND PLATFORM_SPECIFIC_LIBS dl X11 Xi Xrandr Xxf86vm Xinerama Xcursor rt m bsd)
if(_AX_HAVE_VLC)
list(APPEND PLATFORM_SPECIFIC_LIBS vlc vlccore)
endif()

View File

@ -0,0 +1,149 @@
cmake_policy(PUSH)
cmake_policy(SET CMP0057 NEW)
##############################################################
## enable shader lang by shader compiler: glslcc
find_program(GLSLCC_EXE NAMES glslcc
PATHS ${_AX_ROOT}/tools/external/glslcc
)
if (NOT GLSLCC_EXE)
message("glslcc not found.")
message(FATAL_ERROR "Please run setup.ps1 again to download glslcc, and run CMake again.")
endif()
macro(glslcc_option variable value)
if(NOT DEFINED ${variable})
set(${variable} ${value})
endif()
endmacro()
glslcc_option(GLSLCC_FRAG_SOURCE_FILE_EXTENSIONS .frag;.fsh)
glslcc_option(GLSLCC_VERT_SOURCE_FILE_EXTENSIONS .vert;.vsh)
glslcc_option(GLSLCC_OUT_DIR ${CMAKE_BINARY_DIR}/runtime/axslc)
glslcc_option(GLSLCC_OUT_SUFFIX "")
glslcc_option(GLSLCC_FLAT_UBOS TRUE)
message(STATUS "GLSLCC_FRAG_SOURCE_FILE_EXTENSIONS=${GLSLCC_FRAG_SOURCE_FILE_EXTENSIONS}")
message(STATUS "GLSLCC_VERT_SOURCE_FILE_EXTENSIONS=${GLSLCC_VERT_SOURCE_FILE_EXTENSIONS}")
message(STATUS "GLSLCC_OUT_SUFFIX=${GLSLCC_OUT_SUFFIX}")
message(STATUS "GLSLCC_FLAT_UBOS=${GLSLCC_FLAT_UBOS}")
# PROPERTY: include direcotries (optional)
define_property(SOURCE PROPERTY GLSLCC_INCLUDE_DIRS
BRIEF_DOCS "Compiled shader include directories"
FULL_DOCS "Compiled shader include directories, seperated with comma")
# Find shader sources in specified directory
# syntax: ax_find_shaders(dir shader_sources [RECURSE])
# examples:
# - ax_find_shaders("${CMAKE_CURRENT_LIST_DIR}/core/renderer/shaders" runtime_shader_sources)
# - ax_find_shaders("${CMAKE_CURRENT_LIST_DIR}/Source" custom_shader_sources RECURSE)
function (ax_find_shaders dir varName)
set(options RECURSE)
cmake_parse_arguments(opt "${options}" "" "" ${ARGN})
set(SC_FILTERS "")
foreach(fileext ${GLSLCC_FRAG_SOURCE_FILE_EXTENSIONS})
list(APPEND SC_FILTERS "${dir}/*${fileext}")
endforeach()
foreach(fileext ${GLSLCC_VERT_SOURCE_FILE_EXTENSIONS})
list(APPEND SC_FILTERS "${dir}/*${fileext}")
endforeach()
if (opt_RECURSE)
file(GLOB_RECURSE out_files ${SC_FILTERS})
else()
file(GLOB out_files ${SC_FILTERS})
endif()
set(${varName} ${out_files} PARENT_SCOPE)
endfunction()
# This function allow make shader files (.frag, .vert) compiled with glslcc
# usage:
# - ax_target_compile_shaders(axmol FILES source_files): output compiled shader to ${CMAKE_BINARY_DIR}/runtime/shaders/${SC_LANG}/xxx_fs
# - ax_target_compile_shaders(axmol FILES source_files CUSTOM): output compiled shader to ${CMAKE_BINARY_DIR}/runtime/shaders/${SC_LANG}/xxx_fs
# - ax_target_compile_shaders(axmol FILES source_files CVAR): the shader will compiled to c hex header for embed include by C/C++ use
# Use global variable to control shader file extension:
# - GLSLCC_FRAG_SOURCE_FILE_EXTENSIONS: default is .frag;.fsh
# - GLSLCC_VERT_SOURCE_FILE_EXTENSIONS: default is .vert;.vsh
#
function (ax_target_compile_shaders target_name)
set(options RUNTIME CVAR)
set(multiValueArgs FILES)
cmake_parse_arguments(opt "${options}" "" "${multiValueArgs}" ${ARGN})
foreach(SC_FILE ${opt_FILES})
get_filename_component(FILE_EXT ${SC_FILE} LAST_EXT)
get_filename_component(FILE_NAME ${SC_FILE} NAME_WE)
string(TOLOWER "${FILE_EXT}" FILE_EXT)
# silent when compile shader success
set(SC_FLAGS "--silent" "--err-format=msvc")
# shader lang
set(SC_PROFILE "")
if(ANDROID OR WINRT OR AX_USE_ANGLE)
# version 300 es
set(OUT_LANG "ESSL")
set(SC_PROFILE "300")
list(APPEND SC_FLAGS "--lang=gles" "--profile=${SC_PROFILE}")
elseif (WIN32 OR LINUX)
# version 330
set(OUT_LANG "GLSL")
set(SC_PROFILE "330")
list(APPEND SC_FLAGS "--lang=glsl" "--profile=${SC_PROFILE}")
elseif (APPLE)
set(OUT_LANG "MSL")
list(APPEND SC_FLAGS "--lang=msl" "--defines=METAL")
endif()
# includes
get_source_file_property(INC_DIRS ${SC_FILE} GLSLCC_INCLUDE_DIRS)
if (INC_DIRS STREQUAL "NOTFOUND")
set(INC_DIRS "")
endif()
list(APPEND INC_DIRS "${_AX_ROOT}/core/renderer/shaders")
list(APPEND SC_FLAGS "--include-dirs=${INC_DIRS}")
# flat-ubs
if(${GLSLCC_FLAT_UBOS})
list(APPEND SC_FLAGS "--flatten-ubos")
endif()
# input
if (${FILE_EXT} IN_LIST GLSLCC_FRAG_SOURCE_FILE_EXTENSIONS)
list(APPEND SC_FLAGS "--frag=${SC_FILE}")
set(TYPE "fs")
elseif(${FILE_EXT} IN_LIST GLSLCC_VERT_SOURCE_FILE_EXTENSIONS)
set(TYPE "vs")
list(APPEND SC_FLAGS "--vert=${SC_FILE}")
else()
message(FATAL_ERROR "Invalid shader source, the file extesion must be one of .frag;.vert")
endif()
# output
set(OUT_DIR ${GLSLCC_OUT_DIR})
if (NOT (IS_DIRECTORY ${OUT_DIR}))
file(MAKE_DIRECTORY ${OUT_DIR})
endif()
if (NOT opt_CVAR)
list(APPEND SC_FLAGS "--output=${OUT_DIR}/${FILE_NAME}${GLSLCC_OUT_SUFFIX}" )
# glscc will auto insert ${FILE_NAME}_vs.bin or ${FILE_NAME}_fs.bin
# so we set OUTPUT to match with it, otherwise will cause cause incremental build to work incorrectly.
set(SC_OUTPUT "${OUT_DIR}/${FILE_NAME}_${TYPE}${GLSLCC_OUT_SUFFIX}")
else()
set(SC_OUTPUT "${OUT_DIR}/${FILE_NAME}_${TYPE}${GLSLCC_OUT_SUFFIX}.h")
list(APPEND SC_FLAGS "${OUT_FILE}" "--cvar=shader_rt_${FILE_NAME}" "--output=${SC_OUTPUT}")
endif()
set(SC_COMMENT "Compiling shader ${SC_FILE} for ${OUT_LANG}${SC_PROFILE} to ${SC_OUTPUT} ...")
string(REPLACE ";" " " FULL_COMMAND_LINE "${GLSLCC_EXE};${SC_FLAGS} ...")
add_custom_command(
MAIN_DEPENDENCY ${SC_FILE} OUTPUT ${SC_OUTPUT} COMMAND ${GLSLCC_EXE} ${SC_FLAGS}
COMMENT "${FULL_COMMAND_LINE}"
)
endforeach()
target_sources(${target_name} PRIVATE ${opt_FILES})
endfunction()
cmake_policy(POP)

View File

@ -9,6 +9,8 @@ endif()
function(ax_link_cxx_prebuilt APP_NAME AX_ROOT_DIR AX_PREBUILT_DIR)
load_cache("${AX_ROOT_DIR}/${AX_PREBUILT_DIR}" EXCLUDE thirdparty_LIB_DEPENDS)
message(STATUS "AX_USE_ANGLE=${AX_USE_ANGLE}")
message(STATUS "AX_ENABLE_MSEDGE_WEBVIEW2=${AX_ENABLE_MSEDGE_WEBVIEW2}")
message(STATUS "AX_ENABLE_MFMEDIA=${AX_ENABLE_MFMEDIA}")
@ -23,7 +25,7 @@ function(ax_link_cxx_prebuilt APP_NAME AX_ROOT_DIR AX_PREBUILT_DIR)
message(STATUS "AX_ENABLE_EXT_EFFEKSEER=${AX_ENABLE_EXT_EFFEKSEER}")
message(STATUS "AX_ENABLE_EXT_LUA=${AX_ENABLE_EXT_LUA}")
target_compile_definitions(${APP_NAME} PUBLIC AX_GLES_PROFILE=${AX_GLES_PROFILE})
ax_config_pred(${APP_NAME} AX_USE_ANGLE)
ax_config_pred(${APP_NAME} AX_ENABLE_MFMEDIA)
ax_config_pred(${APP_NAME} AX_ENABLE_MSEDGE_WEBVIEW2)
@ -180,7 +182,7 @@ function(ax_link_cxx_prebuilt APP_NAME AX_ROOT_DIR AX_PREBUILT_DIR)
endif()
# Copy windows angle binaries
if (AX_GLES_PROFILE)
if (AX_USE_ANGLE)
add_custom_command(TARGET ${APP_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
${AX_ROOT_DIR}/thirdparty/angle/prebuilt/${platform_name}/${ARCH_ALIAS}/libGLESv2.dll
@ -204,10 +206,6 @@ function(ax_link_cxx_prebuilt APP_NAME AX_ROOT_DIR AX_PREBUILT_DIR)
endif()
endif()
endif()
# prebuilt, need copy axslc folder to target output directory
get_target_property(rt_output ${APP_NAME} RUNTIME_OUTPUT_DIRECTORY)
ax_sync_target_res(${APP_NAME} LINK_TO "${rt_output}/${CMAKE_CFG_INTDIR}/axslc" FOLDERS ${GLSLCC_OUT_DIR} SYNC_TARGET_ID axslc)
endfunction(ax_link_cxx_prebuilt)
function(ax_link_lua_prebuilt APP_NAME AX_ROOT_DIR AX_PREBUILT_DIR)

View File

@ -80,9 +80,9 @@ elseif(ANDROID)
set(platform_spec_path android/${ANDROID_ABI})
elseif(WINDOWS)
if (NOT WINRT)
set(platform_name win32)
set(platform_name win)
else()
set(platform_name winuwp)
set(platform_name uwp)
endif()
set(platform_spec_path ${platform_name}/${ARCH_ALIAS})
elseif(MACOSX)
@ -97,8 +97,8 @@ set(platform_spec_path "${_path_prefix}${platform_spec_path}")
### axpkg url
set (axpkg_ver v58)
set (axpkg_base_url "https://github.com/axmolengine/build1k/releases/download/${axpkg_ver}" CACHE STRING "" FORCE)
set (axpkg_ver v56)
set (axpkg_base_url "https://github.com/axmolengine/buildware/releases/download/${axpkg_ver}" CACHE STRING "" FORCE)
function(axpkg_require package_name dir)
if(NOT IS_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/prebuilt)

View File

@ -95,7 +95,7 @@ void AnimationCache::parseVersion1(const ValueMap& animations)
if (frameNames.empty())
{
AXLOG(
"axmol: AnimationCache: Animation '%s' found in dictionary without any frames - cannot add to "
"cocos2d: AnimationCache: Animation '%s' found in dictionary without any frames - cannot add to "
"animation cache.",
anim.first.c_str());
continue;
@ -111,7 +111,7 @@ void AnimationCache::parseVersion1(const ValueMap& animations)
if (!spriteFrame)
{
AXLOG(
"axmol:AnimationCache: Animation '%s' refers to frame '%s' which is not currently in the "
"cocos2d: AnimationCache: Animation '%s' refers to frame '%s' which is not currently in the "
"SpriteFrameCache. This frame will not be added to the animation.",
anim.first.c_str(), frameName.asString().c_str());
@ -125,7 +125,7 @@ void AnimationCache::parseVersion1(const ValueMap& animations)
if (frames.empty())
{
AXLOG(
"axmol:AnimationCache: None of the frames for animation '%s' were found in the SpriteFrameCache. "
"cocos2d: AnimationCache: None of the frames for animation '%s' were found in the SpriteFrameCache. "
"Animation is not being added to the Animation Cache.",
anim.first.c_str());
continue;
@ -133,7 +133,7 @@ void AnimationCache::parseVersion1(const ValueMap& animations)
else if (frames.size() != frameNameSize)
{
AXLOG(
"axmol:AnimationCache: An animation in your dictionary refers to a frame which is not in the "
"cocos2d: AnimationCache: An animation in your dictionary refers to a frame which is not in the "
"SpriteFrameCache. Some or all of the frames for the animation '%s' may be missing.",
anim.first.c_str());
}
@ -161,7 +161,7 @@ void AnimationCache::parseVersion2(const ValueMap& animations)
if (frameArray.empty())
{
AXLOG(
"axmol:AnimationCache: Animation '%s' found in dictionary without any frames - cannot add to "
"cocos2d: AnimationCache: Animation '%s' found in dictionary without any frames - cannot add to "
"animation cache.",
name.c_str());
continue;
@ -179,7 +179,7 @@ void AnimationCache::parseVersion2(const ValueMap& animations)
if (!spriteFrame)
{
AXLOG(
"axmol:AnimationCache: Animation '%s' refers to frame '%s' which is not currently in the "
"cocos2d: AnimationCache: Animation '%s' refers to frame '%s' which is not currently in the "
"SpriteFrameCache. This frame will not be added to the animation.",
name.c_str(), spriteFrameName.c_str());

View File

@ -92,9 +92,9 @@ bool AtlasNode::initWithTexture(Texture2D* texture, int tileWidth, int tileHeigh
return true;
}
bool AtlasNode::setProgramState(backend::ProgramState* programState, bool ownPS /*= false*/)
bool AtlasNode::setProgramState(backend::ProgramState* programState, bool needsRetain)
{
if (Node::setProgramState(programState, ownPS))
if (Node::setProgramState(programState, needsRetain))
{
auto& pipelineDescriptor = _quadCommand.getPipelineDescriptor();
pipelineDescriptor.programState = _programState;

View File

@ -99,7 +99,7 @@ public:
void setQuadsToDraw(ssize_t quadsToDraw);
size_t getQuadsToDraw() const;
bool setProgramState(backend::ProgramState* programState, bool ownPS = false) override;
bool setProgramState(backend::ProgramState* programState, bool needsRetain = true) override;
AtlasNode() = default;
virtual ~AtlasNode();

View File

@ -498,8 +498,8 @@ void Camera::apply()
void Camera::applyViewport()
{
_director->getRenderer()->setViewPort(_defaultViewport.x, _defaultViewport.y, _defaultViewport.width,
_defaultViewport.height);
_director->getRenderer()->setViewPort(_defaultViewport.x, _defaultViewport.y, _defaultViewport.w,
_defaultViewport.h);
}
int Camera::getRenderOrder() const

View File

@ -178,11 +178,11 @@ void DrawNode::updateShaderInternal(CustomCommand& cmd,
void DrawNode::setVertexLayout(CustomCommand& cmd)
{
auto* programState = cmd.getPipelineDescriptor().programState;
programState->validateSharedVertexLayout(backend::VertexLayoutType::DrawNode);
programState->validateSharedVertexLayout(VertexLayoutHelper::setupDrawNode);
}
void DrawNode::freeShaderInternal(CustomCommand& cmd)
{
{
auto& pipelinePS = cmd.getPipelineDescriptor().programState;
AX_SAFE_RELEASE_NULL(pipelinePS);
}
@ -244,6 +244,7 @@ void DrawNode::draw(Renderer* renderer, const Mat4& transform, uint32_t flags)
{
updateBlendState(_customCommandLine);
updateUniforms(transform, _customCommandLine);
_customCommandLine.setLineWidth(_lineWidth);
_customCommandLine.init(_globalZOrder);
renderer->addCommand(&_customCommandLine);
}

View File

@ -60,7 +60,7 @@ FontAtlas::FontAtlas(Font* theFont) : _font(theFont)
if (outlineSize > 0)
{
_strideShift = 1;
_pixelFormat = AX_GLES_PROFILE != 200 ? backend::PixelFormat::RG8 : backend::PixelFormat::LA8;
_pixelFormat = backend::PixelFormat::LA8;
_currentPageDataSize = CacheTextureWidth * CacheTextureHeight << _strideShift;
#if defined(AX_USE_METAL)
@ -72,7 +72,7 @@ FontAtlas::FontAtlas(Font* theFont) : _font(theFont)
else
{
_strideShift = 0;
_pixelFormat = AX_GLES_PROFILE != 200 ? backend::PixelFormat::R8 : backend::PixelFormat::A8;
_pixelFormat = backend::PixelFormat::A8;
_currentPageDataSize = CacheTextureWidth * CacheTextureHeight;
}

View File

@ -34,11 +34,10 @@
#include "2d/Label.h"
#include "platform/FileUtils.h"
#include "base/format.h"
NS_AX_BEGIN
hlookup::string_map<FontAtlas*> FontAtlasCache::_atlasMap;
#define ATLAS_MAP_KEY_PREFIX_BUFFER_SIZE 255
void FontAtlasCache::purgeCachedData()
{
@ -55,25 +54,33 @@ void FontAtlasCache::purgeCachedData()
FontAtlas* FontAtlasCache::getFontAtlasTTF(const _ttfConfig* config)
{
auto& realFontFilename = config->fontFilePath;
bool useDistanceField = config->distanceFieldEnabled;
int outlineSize = useDistanceField ? 0 : config->outlineSize;
auto realFontFilename = config->fontFilePath; // resolves real file path, to prevent storing multiple atlases for the same file.
bool useDistanceField = config->distanceFieldEnabled;
if (config->outlineSize > 0)
{
useDistanceField = false;
}
std::string key;
char keyPrefix[ATLAS_MAP_KEY_PREFIX_BUFFER_SIZE];
snprintf(keyPrefix, ATLAS_MAP_KEY_PREFIX_BUFFER_SIZE, useDistanceField ? "df %.2f %d " : "%.2f %d ",
config->fontSize, config->outlineSize);
std::string atlasName(keyPrefix);
atlasName += realFontFilename;
std::string atlasName =
config->distanceFieldEnabled
? fmt::format("df {:.2f} {} {}", config->fontSize, outlineSize, realFontFilename)
: fmt::format("{:.2f} {} {}", config->fontSize, outlineSize, realFontFilename);
auto it = _atlasMap.find(atlasName);
if (it == _atlasMap.end())
{
auto font = FontFreeType::create(realFontFilename, config->fontSize, config->glyphs, config->customGlyphs,
useDistanceField, static_cast<float>(outlineSize));
useDistanceField, (float)config->outlineSize);
if (font)
{
auto tempAtlas = font->newFontAtlas();
if (tempAtlas)
return _atlasMap.emplace(std::move(atlasName), tempAtlas).first->second;
{
return _atlasMap.emplace(atlasName, tempAtlas).first->second;
}
}
}
else
@ -89,9 +96,11 @@ FontAtlas* FontAtlasCache::getFontAtlasFNT(std::string_view fontFileName)
FontAtlas* FontAtlasCache::getFontAtlasFNT(std::string_view fontFileName, std::string_view subTextureKey)
{
const auto& realFontFilename = fontFileName;
auto atlasName = fmt::format("{} {}", subTextureKey, realFontFilename);
const auto it = _atlasMap.find(atlasName);
const auto realFontFilename = fontFileName; // resolves real file path, to prevent storing multiple atlases for the same file.
std::string atlasName{subTextureKey};
atlasName.append(" ", 1).append(realFontFilename);
const auto it = _atlasMap.find(atlasName);
if (it == _atlasMap.end())
{
const auto font = FontFNT::create(realFontFilename, subTextureKey);
@ -100,7 +109,10 @@ FontAtlas* FontAtlasCache::getFontAtlasFNT(std::string_view fontFileName, std::s
{
const auto tempAtlas = font->newFontAtlas();
if (tempAtlas)
return _atlasMap.emplace(std::move(atlasName), tempAtlas).first->second;
{
_atlasMap[atlasName] = tempAtlas;
return _atlasMap[atlasName];
}
}
}
else
@ -111,10 +123,11 @@ FontAtlas* FontAtlasCache::getFontAtlasFNT(std::string_view fontFileName, std::s
FontAtlas* FontAtlasCache::getFontAtlasFNT(std::string_view fontFileName, const Rect& imageRect, bool imageRotated)
{
// resolves real file path, to prevent storing multiple atlases for the same file.
const auto& realFontFilename = fontFileName;
auto atlasName = fmt::format("{:.2f} {:.2f} {}", imageRect.origin.x, imageRect.origin.y, realFontFilename);
const auto realFontFilename = fontFileName; // resolves real file path, to prevent storing multiple atlases for the same file.
char keyPrefix[ATLAS_MAP_KEY_PREFIX_BUFFER_SIZE];
snprintf(keyPrefix, ATLAS_MAP_KEY_PREFIX_BUFFER_SIZE, "%.2f %.2f ", imageRect.origin.x, imageRect.origin.y);
std::string atlasName(keyPrefix);
atlasName += realFontFilename;
const auto it = _atlasMap.find(atlasName);
if (it == _atlasMap.end())
@ -125,7 +138,10 @@ FontAtlas* FontAtlasCache::getFontAtlasFNT(std::string_view fontFileName, const
{
const auto tempAtlas = font->newFontAtlas();
if (tempAtlas)
return _atlasMap.emplace(std::move(atlasName), tempAtlas).first->second;
{
_atlasMap[atlasName] = tempAtlas;
return _atlasMap[atlasName];
}
}
}
else
@ -152,7 +168,10 @@ FontAtlas* FontAtlasCache::getFontAtlasCharMap(std::string_view plistFile)
{
auto tempAtlas = font->newFontAtlas();
if (tempAtlas)
return _atlasMap.emplace(atlasName, tempAtlas).first->second;
{
hlookup::set_item(_atlasMap, atlasName, tempAtlas); // _atlasMap[atlasName] = tempAtlas;
return tempAtlas;
}
}
}
else
@ -163,7 +182,9 @@ FontAtlas* FontAtlasCache::getFontAtlasCharMap(std::string_view plistFile)
FontAtlas* FontAtlasCache::getFontAtlasCharMap(Texture2D* texture, int itemWidth, int itemHeight, int startCharMap)
{
auto atlasName = fmt::format("name:{}_{}_{}_{}", reinterpret_cast<uintptr_t>(texture->getBackendTexture()), itemWidth, itemHeight, startCharMap);
char key[ATLAS_MAP_KEY_PREFIX_BUFFER_SIZE];
snprintf(key, sizeof(key), "name:%p_%d_%d_%d", texture->getBackendTexture(), itemWidth, itemHeight, startCharMap);
std::string atlasName = key;
auto it = _atlasMap.find(atlasName);
if (it == _atlasMap.end())
@ -174,7 +195,10 @@ FontAtlas* FontAtlasCache::getFontAtlasCharMap(Texture2D* texture, int itemWidth
{
auto tempAtlas = font->newFontAtlas();
if (tempAtlas)
return _atlasMap.emplace(std::move(atlasName), tempAtlas).first->second;
{
_atlasMap[atlasName] = tempAtlas;
return _atlasMap[atlasName];
}
}
}
else
@ -188,7 +212,10 @@ FontAtlas* FontAtlasCache::getFontAtlasCharMap(std::string_view charMapFile,
int itemHeight,
int startCharMap)
{
auto atlasName = fmt::format("{} {} {} {}", itemWidth, itemHeight, startCharMap, charMapFile);
char keyPrefix[ATLAS_MAP_KEY_PREFIX_BUFFER_SIZE];
snprintf(keyPrefix, ATLAS_MAP_KEY_PREFIX_BUFFER_SIZE, "%d %d %d ", itemWidth, itemHeight, startCharMap);
std::string atlasName(keyPrefix);
atlasName += charMapFile;
auto it = _atlasMap.find(atlasName);
if (it == _atlasMap.end())
@ -199,7 +226,10 @@ FontAtlas* FontAtlasCache::getFontAtlasCharMap(std::string_view charMapFile,
{
auto tempAtlas = font->newFontAtlas();
if (tempAtlas)
return _atlasMap.emplace(std::move(atlasName), tempAtlas).first->second;
{
_atlasMap[atlasName] = tempAtlas;
return _atlasMap[atlasName];
}
}
}
else
@ -232,7 +262,10 @@ bool FontAtlasCache::releaseFontAtlas(FontAtlas* atlas)
void FontAtlasCache::reloadFontAtlasFNT(std::string_view fontFileName, const Rect& imageRect, bool imageRotated)
{
auto atlasName = fmt::format("{:.2f} {:.2f} {}", imageRect.origin.x, imageRect.origin.y, fontFileName);
char keyPrefix[ATLAS_MAP_KEY_PREFIX_BUFFER_SIZE];
snprintf(keyPrefix, ATLAS_MAP_KEY_PREFIX_BUFFER_SIZE, "%.2f %.2f ", imageRect.origin.x, imageRect.origin.y);
std::string atlasName(keyPrefix);
atlasName += fontFileName;
auto it = _atlasMap.find(atlasName);
if (it != _atlasMap.end())
@ -246,7 +279,9 @@ void FontAtlasCache::reloadFontAtlasFNT(std::string_view fontFileName, const Rec
{
auto tempAtlas = font->newFontAtlas();
if (tempAtlas)
_atlasMap.emplace(std::move(atlasName), tempAtlas);
{
_atlasMap[atlasName] = tempAtlas;
}
}
}
@ -257,15 +292,16 @@ void FontAtlasCache::reloadFontAtlasFNT(std::string_view fontFileName, const Vec
void FontAtlasCache::unloadFontAtlasTTF(std::string_view fontFileName)
{
for (auto iter = _atlasMap.begin(); iter != _atlasMap.end();)
auto item = _atlasMap.begin();
while (item != _atlasMap.end())
{
if (iter->first.find(fontFileName) != std::string::npos)
if (item->first.find(fontFileName) != std::string::npos)
{
AX_SAFE_RELEASE_NULL(iter->second);
iter = _atlasMap.erase(iter);
continue;
AX_SAFE_RELEASE_NULL(item->second);
item = _atlasMap.erase(item);
}
++iter;
else
item++;
}
}

View File

@ -31,6 +31,7 @@ THE SOFTWARE.
#include "base/UTF8.h"
#include "freetype/ftmodapi.h"
#include "platform/FileUtils.h"
#include "platform/FileStream.h"
#include "ft2build.h"
#include FT_FREETYPE_H
@ -71,25 +72,25 @@ static unsigned long ft_stream_read_callback(FT_Stream stream,
unsigned char* buf,
unsigned long size)
{
auto fstm = (IFileStream*)stream->descriptor.pointer;
if (!fstm)
auto fd = (FileStream*)stream->descriptor.pointer;
if (!fd)
return 1;
if (!size && offset >= stream->size)
return 1;
if (stream->pos != offset)
fstm->seek(offset, SEEK_SET);
fd->seek(offset, SEEK_SET);
if (buf)
return fstm->read(buf, static_cast<unsigned int>(size));
return fd->read(buf, static_cast<unsigned int>(size));
return 0;
}
static void ft_stream_close_callback(FT_Stream stream)
{
const auto* fstrm = (IFileStream*)stream->descriptor.pointer;
delete fstrm;
const auto* fd = (FileStream*)stream->descriptor.pointer;
delete fd;
stream->size = 0;
stream->descriptor.pointer = nullptr;
}
@ -205,7 +206,7 @@ bool FontFreeType::loadFontFace(std::string_view fontPath, float fontSize)
if (fullPath.empty())
return false;
auto fs = FileUtils::getInstance()->openFileStream(fullPath, IFileStream::Mode::READ);
auto fs = FileUtils::getInstance()->openFileStream(fullPath, FileStream::Mode::READ);
if (!fs)
{
return false;

View File

@ -117,19 +117,17 @@ bool GridBase::initWithSize(const Vec2& gridSize, Texture2D* texture, bool flipp
uint32_t totalSize = (VERTEX_POSITION_SIZE + VERTEX_TEXCOORD_SIZE) * sizeof(float);
const auto& attributeInfo = _programState->getProgram()->getActiveAttributes();
auto iter = attributeInfo.find("a_position");
auto layout = _programState->getMutableVertexLayout();
if (iter != attributeInfo.end())
{
layout->setAttrib("a_position", iter->second.location, backend::VertexFormat::FLOAT3, 0, false);
_programState->setVertexAttrib("a_position", iter->second.location, backend::VertexFormat::FLOAT3, 0, false);
}
iter = attributeInfo.find("a_texCoord");
if (iter != attributeInfo.end())
{
layout->setAttrib("a_texCoord", iter->second.location, backend::VertexFormat::FLOAT2, texcoordOffset,
_programState->setVertexAttrib("a_texCoord", iter->second.location, backend::VertexFormat::FLOAT2, texcoordOffset,
false);
}
layout->setStride(totalSize);
_programState->setVertexStride(totalSize);
calculateVertexPoints();
updateBlendState();
@ -243,7 +241,7 @@ void GridBase::afterDraw(ax::Node* /*target*/)
renderer->addCallbackCommand([director, renderer, this]() -> void {
director->setProjection(_directorProjection);
const auto& vp = Camera::getDefaultViewport();
renderer->setViewPort(vp.x, vp.y, vp.width, vp.height);
renderer->setViewPort(vp.x, vp.y, vp.w, vp.h);
renderer->setRenderTarget(_oldRenderTarget);
});

View File

@ -676,12 +676,12 @@ static Texture2D* _getTexture(Label* label)
void Label::setVertexLayout()
{
_programState->validateSharedVertexLayout(backend::VertexLayoutType::Sprite);
_programState->validateSharedVertexLayout(VertexLayoutHelper::setupSprite);
}
bool Label::setProgramState(backend::ProgramState* programState, bool ownPS /*= false*/)
bool Label::setProgramState(backend::ProgramState* programState, bool needsRetain)
{
if (Node::setProgramState(programState, ownPS))
if (Node::setProgramState(programState, needsRetain))
{
updateUniformLocations();
for (auto&& batch : _batchCommands)
@ -691,9 +691,9 @@ bool Label::setProgramState(backend::ProgramState* programState, bool ownPS /*=
setVertexLayout();
auto& quadPipeline = _quadCommand.getPipelineDescriptor();
auto& quadPipeline = _quadCommand.getPipelineDescriptor();
quadPipeline.programState = _programState;
return true;
}
return false;
@ -717,9 +717,13 @@ void Label::updateShaderProgram()
{
case ax::LabelEffect::NORMAL:
if (_useDistanceField)
{
programType = backend::ProgramType::LABEL_DISTANCE_NORMAL;
}
else if (_useA8Shader)
{
programType = backend::ProgramType::LABEL_NORMAL;
}
else
{
auto texture = _getTexture(this);
@ -731,26 +735,32 @@ void Label::updateShaderProgram()
}
break;
case ax::LabelEffect::OUTLINE:
programType =
_useDistanceField ? backend::ProgramType::LABEL_DISTANCE_OUTLINE : backend::ProgramType::LABLE_OUTLINE;
break;
{
programType = backend::ProgramType::LABLE_OUTLINE;
}
break;
case ax::LabelEffect::GLOW:
if (_useDistanceField)
programType = backend::ProgramType::LABLE_DISTANCE_GLOW;
{
programType = backend::ProgramType::LABLE_DISTANCEFIELD_GLOW;
}
break;
default:
return;
}
}
this->setProgramStateByProgramId(programType);
auto* program = backend::Program::getBuiltinProgram(programType);
setProgramState(new backend::ProgramState(program), false);
updateUniformLocations();
for (auto&& batch : _batchCommands)
{
updateBatchCommand(batch);
}
auto& quadPipeline = _quadCommand.getPipelineDescriptor();
auto& quadPipeline = _quadCommand.getPipelineDescriptor();
quadPipeline.programState = _programState;
}
@ -1282,8 +1292,10 @@ bool Label::setTTFConfigInternal(const TTFConfig& ttfConfig)
if (_fontConfig.outlineSize > 0)
{
_useA8Shader = false;
_currLabelEffect = LabelEffect::OUTLINE;
_fontConfig.distanceFieldEnabled = false;
_useDistanceField = false;
_useA8Shader = false;
_currLabelEffect = LabelEffect::OUTLINE;
updateShaderProgram();
}
else
@ -1384,16 +1396,11 @@ void Label::enableOutline(const Color4B& outlineColor, int outlineSize /* = -1 *
_effectColorF.b = outlineColor.b / 255.0f;
_effectColorF.a = outlineColor.a / 255.0f;
if (!_useDistanceField)
{ // not SDF, request font atlas from feetype
if (outlineSize > 0 && _fontConfig.outlineSize != outlineSize)
{
_fontConfig.outlineSize = outlineSize;
setTTFConfig(_fontConfig);
}
if (outlineSize > 0 && _fontConfig.outlineSize != outlineSize)
{
_fontConfig.outlineSize = outlineSize;
setTTFConfig(_fontConfig);
}
else
updateShaderProgram();
}
else if (_effectColorF != outlineColor || _outlineSize != outlineSize)
{
@ -1801,6 +1808,7 @@ void Label::updateEffectUniforms(BatchCommand& batch,
{
int effectType = 0;
Vec4 effectColor(_effectColorF.r, _effectColorF.g, _effectColorF.b, _effectColorF.a);
// draw shadow
if (_shadowEnabled)
{
@ -1813,33 +1821,24 @@ void Label::updateEffectUniforms(BatchCommand& batch,
renderer->addCommand(&batch.shadowCommand);
}
if (_useDistanceField)
{ // distance outline
effectColor.w = _outlineSize > 0 ? _outlineSize : _fontConfig.outlineSize;
batch.textCommand.getPipelineDescriptor().programState->setUniform(_effectColorLocation, &effectColor,
sizeof(Vec4));
}
else
// draw outline
{
// draw outline
{
effectType = 1;
updateBuffer(textureAtlas, batch.outLineCommand);
auto* programStateOutline = batch.outLineCommand.getPipelineDescriptor().programState;
programStateOutline->setUniform(_effectColorLocation, &effectColor, sizeof(Vec4));
programStateOutline->setUniform(_effectTypeLocation, &effectType, sizeof(effectType));
batch.outLineCommand.init(_globalZOrder);
renderer->addCommand(&batch.outLineCommand);
}
effectType = 1;
updateBuffer(textureAtlas, batch.outLineCommand);
auto* programStateOutline = batch.outLineCommand.getPipelineDescriptor().programState;
programStateOutline->setUniform(_effectColorLocation, &effectColor, sizeof(Vec4));
programStateOutline->setUniform(_effectTypeLocation, &effectType, sizeof(effectType));
batch.outLineCommand.init(_globalZOrder);
renderer->addCommand(&batch.outLineCommand);
}
// draw text
{
effectType = 0;
auto* programStateText = batch.textCommand.getPipelineDescriptor().programState;
// draw text
{
effectType = 0;
auto* programStateText = batch.textCommand.getPipelineDescriptor().programState;
programStateText->setUniform(_effectColorLocation, &effectColor, sizeof(effectColor));
programStateText->setUniform(_effectTypeLocation, &effectType, sizeof(effectType));
}
programStateText->setUniform(_effectColorLocation, &effectColor, sizeof(effectColor));
programStateText->setUniform(_effectTypeLocation, &effectType, sizeof(effectType));
}
}
break;
@ -2013,7 +2012,7 @@ void Label::visit(Renderer* renderer, const Mat4& parentTransform, uint32_t pare
// Label overflow shrink fix #566
if (_overflow == Overflow::SHRINK && this->getRenderingFontSize() < _originalFontSize)
rescaleWithOriginalFontSize();
updateContent();
}

View File

@ -674,7 +674,7 @@ public:
*/
float getAdditionalKerning() const;
bool setProgramState(backend::ProgramState* programState, bool ownPS = false) override;
bool setProgramState(backend::ProgramState* programState, bool needsRetain = true) override;
FontAtlas* getFontAtlas() { return _fontAtlas; }

View File

@ -221,9 +221,9 @@ void MotionStreak::setTexture(Texture2D* texture)
}
}
bool MotionStreak::setProgramState(backend::ProgramState* programState, bool ownPS /*= false*/)
bool MotionStreak::setProgramState(backend::ProgramState* programState, bool needsRetain)
{
if (Node::setProgramState(programState, ownPS))
if (Node::setProgramState(programState, needsRetain))
{
AXASSERT(programState, "argument should not be nullptr");
auto& pipelineDescriptor = _customCommand.getPipelineDescriptor();
@ -235,24 +235,23 @@ bool MotionStreak::setProgramState(backend::ProgramState* programState, bool own
// setup custom vertex layout for V2F_T2F_C4B
const auto& attributeInfo = _programState->getProgram()->getActiveAttributes();
auto iter = attributeInfo.find("a_position");
auto layout = _programState->getMutableVertexLayout();
if (iter != attributeInfo.end())
{
layout->setAttrib("a_position", iter->second.location, backend::VertexFormat::FLOAT2, 0, false);
_programState->setVertexAttrib("a_position", iter->second.location, backend::VertexFormat::FLOAT2, 0, false);
}
iter = attributeInfo.find("a_texCoord");
if (iter != attributeInfo.end())
{
layout->setAttrib("a_texCoord", iter->second.location, backend::VertexFormat::FLOAT2,
_programState->setVertexAttrib("a_texCoord", iter->second.location, backend::VertexFormat::FLOAT2,
2 * sizeof(float), false);
}
iter = attributeInfo.find("a_color");
if (iter != attributeInfo.end())
{
layout->setAttrib("a_color", iter->second.location, backend::VertexFormat::UBYTE4,
_programState->setVertexAttrib("a_color", iter->second.location, backend::VertexFormat::UBYTE4,
4 * sizeof(float), true);
}
layout->setStride(4 * sizeof(float) + 4 * sizeof(uint8_t));
_programState->setVertexStride(4 * sizeof(float) + 4 * sizeof(uint8_t));
updateProgramStateTexture(_texture);
return true;

View File

@ -156,7 +156,7 @@ public:
_startingPositionInitialized = bStartingPositionInitialized;
}
bool setProgramState(backend::ProgramState* programState, bool ownPS = false) override;
bool setProgramState(backend::ProgramState* programState, bool needsRetain) override;
MotionStreak();
virtual ~MotionStreak();

View File

@ -45,7 +45,6 @@ THE SOFTWARE.
#include "2d/Component.h"
#include "renderer/Material.h"
#include "math/TransformUtils.h"
#include "renderer/backend/ProgramManager.h"
#include "renderer/backend/ProgramStateRegistry.h"
#if AX_NODE_RENDER_SUBPIXEL
@ -2229,33 +2228,22 @@ void Node::setProgramStateWithRegistry(uint32_t programType, Texture2D* texture)
{
auto samplerFlags = texture ? texture->getSamplerFlags() : 0;
auto programState = backend::ProgramStateRegistry::getInstance()->newProgramState(programType, samplerFlags);
setProgramState(programState, true);
setProgramState(programState, false);
}
bool Node::setProgramState(backend::ProgramState* programState, bool ownPS/* = false*/)
bool Node::setProgramState(backend::ProgramState* programState, bool needsRetain)
{
if (_programState != programState)
{
AX_SAFE_RELEASE(_programState);
_programState = programState;
if (!ownPS)
if (needsRetain)
AX_SAFE_RETAIN(_programState);
return !!_programState;
}
return false;
}
backend::ProgramState* Node::setProgramStateByProgramId(uint64_t programId)
{
auto prog = ProgramManager::getInstance()->loadProgram(programId);
if (prog)
{
this->setProgramState(new ProgramState(prog), true);
return _programState;
}
return nullptr;
}
void Node::updateProgramStateTexture(Texture2D* texture)
{
if (texture == nullptr || texture->getBackendTexture() == nullptr || _programState == nullptr)

View File

@ -1828,14 +1828,7 @@ public:
* Sets ProgramState with retain
* @param programState
*/
virtual bool setProgramState(backend::ProgramState* programState, bool ownPS = false);
/**
* Sets ProgramState by programId
* @param progId the program id or programType used to create programState
* @return ProgramState* (nullable)
*/
backend::ProgramState* setProgramStateByProgramId(uint64_t progId);
virtual bool setProgramState(backend::ProgramState* programState, bool needsRetain = true);
backend::ProgramState* getProgramState() const;

View File

@ -418,7 +418,7 @@ void PlistSpriteSheetLoader::reloadSpriteFramesWithDictionary(ValueMap& dict,
if (!ow || !oh)
{
AXLOGWARN(
"axmol:WARNING: originalWidth/Height not found on the SpriteFrame. AnchorPoint won't work as "
"cocos2d: WARNING: originalWidth/Height not found on the SpriteFrame. AnchorPoint won't work as "
"expected. Regenerate the .plist");
}
// abs ow/oh

View File

@ -57,16 +57,15 @@ backend::ProgramState* initPipelineDescriptor(ax::CustomCommand& command,
pipelieDescriptor.programState = programState;
// set custom vertexLayout according to V2F_C4B_T2F structure
auto vertexLayout = programState->getMutableVertexLayout();
vertexLayout->setAttrib("a_position", program->getAttributeLocation(backend::Attribute::POSITION),
backend::VertexFormat::FLOAT2, 0, false);
vertexLayout->setAttrib("a_texCoord", program->getAttributeLocation(backend::Attribute::TEXCOORD),
backend::VertexFormat::FLOAT2,
offsetof(V2F_C4B_T2F, texCoords), false);
vertexLayout->setAttrib("a_color", program->getAttributeLocation(backend::Attribute::COLOR),
programState->setVertexAttrib("a_position", program->getAttributeLocation(backend::Attribute::POSITION),
backend::VertexFormat::FLOAT2, 0, false);
programState->setVertexAttrib("a_texCoord", program->getAttributeLocation(backend::Attribute::TEXCOORD),
backend::VertexFormat::FLOAT2,
offsetof(V2F_C4B_T2F, texCoords), false);
programState->setVertexAttrib("a_color", program->getAttributeLocation(backend::Attribute::COLOR),
backend::VertexFormat::UBYTE4,
offsetof(V2F_C4B_T2F, colors), true);
vertexLayout->setStride(sizeof(V2F_C4B_T2F));
programState->setVertexStride(sizeof(V2F_C4B_T2F));
if (ridal)
{
@ -108,7 +107,7 @@ bool ProgressTimer::initWithSprite(Sprite* sp)
// TODO: Use ProgramState Vector to Node
AX_SAFE_RELEASE(_programState2);
setProgramState(initPipelineDescriptor(_customCommand, true, _locMVP1, _locTex1), true);
setProgramState(initPipelineDescriptor(_customCommand, true, _locMVP1, _locTex1), false);
_programState2 = initPipelineDescriptor(_customCommand2, false, _locMVP2, _locTex2);
return true;

View File

@ -159,7 +159,7 @@ bool RenderTexture::initWithWidthAndHeight(int w,
PixelFormat depthStencilFormat,
bool sharedRenderTarget)
{
AXASSERT(format == backend::PixelFormat::RGBA8 || format == PixelFormat::RGB8 || format == PixelFormat::RGBA4, "only RGB and RGBA formats are valid for a render texture");
AXASSERT(format != backend::PixelFormat::A8, "only RGB and RGBA formats are valid for a render texture");
bool ret = false;
do
@ -588,7 +588,7 @@ void RenderTexture::onEnd()
_director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, _oldTransMatrix);
Renderer* renderer = _director->getRenderer();
renderer->setViewPort(_oldViewport.x, _oldViewport.y, _oldViewport.width, _oldViewport.height);
renderer->setViewPort(_oldViewport.x, _oldViewport.y, _oldViewport.w, _oldViewport.h);
renderer->setRenderTarget(_oldRenderTarget);
}

View File

@ -325,6 +325,23 @@ Sprite::~Sprite()
* Texture methods
*/
/*
* This array is the data of a white image with 2 by 2 dimension.
* It's used for creating a default texture when sprite's texture is set to nullptr.
* Supposing codes as follows:
*
* auto sp = new Sprite();
* sp->init(); // Texture was set to nullptr, in order to make opacity and color to work correctly, we need to create
* a 2x2 white texture.
*
* The test is in "TestCpp/SpriteTest/Sprite without texture".
*/
static unsigned char cc_2x2_white_image[] = {
// RGBA8888
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
#define AX_2x2_WHITE_IMAGE_KEY "/cc_2x2_white_image"
// MARK: texture
void Sprite::setTexture(std::string_view filename)
{
@ -341,7 +358,7 @@ void Sprite::setTexture(std::string_view filename)
void Sprite::setVertexLayout()
{
AXASSERT(_programState, "programState should not be nullptr");
_programState->validateSharedVertexLayout(backend::VertexLayoutType::Sprite);
_programState->validateSharedVertexLayout(VertexLayoutHelper::setupSprite);
}
void Sprite::setProgramState(uint32_t type)
@ -349,10 +366,10 @@ void Sprite::setProgramState(uint32_t type)
setProgramStateWithRegistry(type, _texture);
}
bool Sprite::setProgramState(backend::ProgramState* programState, bool ownPS/* = false*/)
bool Sprite::setProgramState(backend::ProgramState* programState, bool needsRetain)
{
AXASSERT(programState, "argument should not be nullptr");
if (Node::setProgramState(programState, ownPS))
if (Node::setProgramState(programState, needsRetain))
{
auto& pipelineDescriptor = _trianglesCommand.getPipelineDescriptor();
pipelineDescriptor.programState = _programState;
@ -377,7 +394,18 @@ void Sprite::setTexture(Texture2D* texture)
if (texture == nullptr)
{
// Gets the texture by key firstly.
texture = _director->getTextureCache()->getWhiteTexture();
texture = _director->getTextureCache()->getTextureForKey(AX_2x2_WHITE_IMAGE_KEY);
// If texture wasn't in cache, create it from RAW data.
if (texture == nullptr)
{
Image* image = new Image();
bool AX_UNUSED isOK = image->initWithRawData(cc_2x2_white_image, sizeof(cc_2x2_white_image), 2, 2, 8);
AXASSERT(isOK, "The 2x2 empty texture was created unsuccessfully.");
texture = _director->getTextureCache()->addImage(image, AX_2x2_WHITE_IMAGE_KEY);
AX_SAFE_RELEASE(image);
}
}
bool needsUpdatePS =

View File

@ -425,7 +425,7 @@ public:
/**
* Set or Attach new ProgramState
*/
bool setProgramState(backend::ProgramState* programState, bool ownPS = false) override;
bool setProgramState(backend::ProgramState* programState, bool needsRetain = true) override;
/**
* Sets the weak reference of the TextureAtlas when the sprite is rendered using via SpriteBatchNode.

View File

@ -124,13 +124,13 @@ void SpriteBatchNode::setUniformLocation()
void SpriteBatchNode::setVertexLayout()
{
AXASSERT(_programState, "programState should not be nullptr");
_programState->validateSharedVertexLayout(backend::VertexLayoutType::Sprite);
_programState->validateSharedVertexLayout(VertexLayoutHelper::setupSprite);
}
bool SpriteBatchNode::setProgramState(backend::ProgramState* programState, bool ownPS/* = false*/)
bool SpriteBatchNode::setProgramState(backend::ProgramState* programState, bool needsRetain)
{
AXASSERT(programState, "programState should not be nullptr");
if (Node::setProgramState(programState, ownPS))
if (Node::setProgramState(programState, needsRetain))
{
auto& pipelineDescriptor = _quadCommand.getPipelineDescriptor();
pipelineDescriptor.programState = _programState;

View File

@ -213,7 +213,7 @@ public:
*/
virtual std::string getDescription() const override;
bool setProgramState(backend::ProgramState* programState, bool ownPS = false) override;
bool setProgramState(backend::ProgramState* programState, bool needsRetain = true) override;
/** Inserts a quad at a certain index into the texture atlas. The Sprite won't be added into the children array.
* This method should be called only when you are dealing with very big AtlasSprite and when most of the Sprite

View File

@ -40,7 +40,6 @@
#include "renderer/Renderer.h"
#include "renderer/backend/Buffer.h"
#include "renderer/backend/Program.h"
#include "renderer/RenderConsts.h"
#include "math/Mat4.h"
using namespace std;
@ -68,9 +67,9 @@ std::string s_uniformSamplerName[] = {
void Mesh::resetLightUniformValues()
{
const auto& conf = Configuration::getInstance();
constexpr int maxDirLight = AX_MAX_DIRECTIONAL_LIGHT;
constexpr int maxPointLight = AX_MAX_POINT_LIGHT;
constexpr int maxSpotLight = AX_MAX_SPOT_LIGHT;
int maxDirLight = conf->getMaxSupportDirLightInShader();
int maxPointLight = conf->getMaxSupportPointLightInShader();
int maxSpotLight = conf->getMaxSupportSpotLightInShader();
_dirLightUniformColorValues.assign(maxDirLight, Vec3::ZERO);
_dirLightUniformDirValues.assign(maxDirLight, Vec3::ZERO);
@ -90,15 +89,28 @@ void Mesh::resetLightUniformValues()
_spotLightUniformRangeInverseValues.assign(maxSpotLight, 0.0f);
}
// Generate a dummy texture when the texture file is missing
static Texture2D* getDummyTexture()
{
auto texture = Director::getInstance()->getTextureCache()->getTextureForKey("/dummyTexture");
if (!texture)
{
#ifdef NDEBUG
unsigned char data[] = {0, 0, 0, 0}; // 1*1 transparent picture
#else
unsigned char data[] = {255, 0, 0, 255}; // 1*1 red picture
#endif
Image* image = new Image();
image->initWithRawData(data, sizeof(data), 1, 1, sizeof(unsigned char));
texture = Director::getInstance()->getTextureCache()->addImage(image, "/dummyTexture");
image->release();
}
return texture;
}
Mesh::Mesh()
: _skin(nullptr)
, _visible(true)
, _instancing(false)
, _instanceTransformBuffer(nullptr)
, _instanceTransformBufferDirty(false)
, _instanceCount(0)
, _dynamicInstancing(false)
, _instanceMatrixCache(nullptr)
, meshIndexFormat(CustomCommand::IndexFormat::U_SHORT)
, _meshIndexData(nullptr)
, _blend(BlendFunc::ALPHA_NON_PREMULTIPLIED)
@ -109,60 +121,12 @@ Mesh::Mesh()
Mesh::~Mesh()
{
for (auto&& tex : _textures)
{
AX_SAFE_RELEASE(tex.second);
for (auto&& ins : _instances)
AX_SAFE_RELEASE(ins);
}
AX_SAFE_RELEASE(_skin);
AX_SAFE_RELEASE(_meshIndexData);
AX_SAFE_RELEASE(_material);
AX_SAFE_RELEASE(_instanceTransformBuffer);
AX_SAFE_DELETE_ARRAY(_instanceMatrixCache);
}
void Mesh::enableInstancing(bool instance, int count)
{
_instancing = instance;
_instanceCount = count;
}
void Mesh::setInstanceCount(int count) {
AXASSERT(_instancing, "Instancing should be enabled on this mesh.");
_instanceCount = count;
}
void Mesh::addInstanceChild(Node* child)
{
AX_SAFE_RETAIN(child);
_instances.push_back(child);
_instanceTransformDirty = true;
if (_instances.size() > _instanceCount)
{
_instanceCount *= 2;
_instanceTransformBufferDirty = true;
}
}
void Mesh::shrinkToFitInstances()
{
if (_instanceCount > _instances.size())
{
_instanceCount = _instances.size();
_instanceTransformBufferDirty = true;
}
}
void Mesh::rebuildInstances()
{
_instanceTransformDirty = true;
}
void Mesh::setDynamicInstancing(bool dynamic)
{
_dynamicInstancing = dynamic;
}
backend::Buffer* Mesh::getVertexBuffer() const
@ -317,7 +281,7 @@ void Mesh::setTexture(Texture2D* tex, NTextureData::Usage usage, bool cacheFileN
// it doesn't matter if the material is already set or not
// This functionality is added for compatibility issues
if (tex == nullptr)
tex = Director::getInstance()->getTextureCache()->getDummyTexture();
tex = getDummyTexture();
AX_SAFE_RETAIN(tex);
AX_SAFE_RELEASE(_textures[usage]);
@ -397,7 +361,7 @@ void Mesh::setMaterial(Material* material)
auto& attributes = program->getActiveAttributes();
auto meshVertexData = _meshIndexData->getMeshVertexData();
auto attributeCount = meshVertexData->getMeshVertexAttribCount();
//AXASSERT(attributes.size() <= attributeCount, "missing attribute data");
AXASSERT(attributes.size() <= attributeCount, "missing attribute data");
}
#endif
// TODO
@ -441,57 +405,6 @@ void Mesh::draw(Renderer* renderer,
if (isTransparent)
flags |= Node::FLAGS_RENDER_AS_3D;
if (_instancing && _instanceCount > 0)
{
if (!_instanceTransformBuffer || _instanceTransformBufferDirty)
{
AX_SAFE_RELEASE(_instanceTransformBuffer);
AX_SAFE_DELETE_ARRAY(_instanceMatrixCache);
_instanceTransformBuffer = backend::Device::getInstance()->newBuffer(
_instanceCount * 64, backend::BufferType::VERTEX, backend::BufferUsage::DYNAMIC);
_instanceMatrixCache = new float[_instanceCount * 16];
for (int i = 0; i < _instanceCount; i++)
{
_instanceMatrixCache[i * 16 + 0] = 1.0f;
_instanceMatrixCache[i * 16 + 1] = 0.0f;
_instanceMatrixCache[i * 16 + 2] = 0.0f;
_instanceMatrixCache[i * 16 + 3] = 0.0f;
_instanceMatrixCache[i * 16 + 4] = 0.0f;
_instanceMatrixCache[i * 16 + 5] = 1.0f;
_instanceMatrixCache[i * 16 + 6] = 0.0f;
_instanceMatrixCache[i * 16 + 7] = 0.0f;
_instanceMatrixCache[i * 16 + 8] = 0.0f;
_instanceMatrixCache[i * 16 + 9] = 0.0f;
_instanceMatrixCache[i * 16 + 10] = 1.0f;
_instanceMatrixCache[i * 16 + 11] = 0.0f;
_instanceMatrixCache[i * 16 + 12] = 0.0f;
_instanceMatrixCache[i * 16 + 13] = 0.0f;
_instanceMatrixCache[i * 16 + 14] = 0.0f;
_instanceMatrixCache[i * 16 + 15] = 1.0f;
}
// Fill the buffer with identity matrix.
_instanceTransformBuffer->updateData(_instanceMatrixCache, _instanceCount * 64);
_instanceTransformBufferDirty = false;
}
if (_instanceTransformDirty || _dynamicInstancing)
{
_instanceTransformDirty = false;
int memOffset = 0;
for (auto& _ : _instances)
{
auto& mat = _->getNodeToParentTransform();
std::copy(mat.m, mat.m + 16, _instanceMatrixCache + 16 * memOffset++);
}
_instanceTransformBuffer->updateSubData(_instanceMatrixCache, 0, _instanceCount * 64);
}
}
// TODO
// _meshCommand.init(globalZ,
// _material,
@ -533,13 +446,6 @@ void Mesh::draw(Renderer* renderer,
command.setTransparent(isTransparent);
command.set3D(!_material->isForce2DQueue());
command.setWireframe(wireframe);
if (_instancing && _instances.size() > 0)
{
command.setDrawType(CustomCommand::DrawType::ELEMENT_INSTANCE);
command.setInstanceBuffer(_instanceTransformBuffer, _instances.size());
}
else if (_instancing)
return;
}
_meshIndexData->setPrimitiveType(_material->_drawPrimitive);
@ -642,9 +548,9 @@ void Mesh::setLightUniforms(Pass* pass, Scene* scene, const Vec4& color, unsigne
AXASSERT(scene, "Invalid scene");
const auto& conf = Configuration::getInstance();
constexpr int maxDirLight = AX_MAX_DIRECTIONAL_LIGHT;
constexpr int maxPointLight = AX_MAX_POINT_LIGHT;
constexpr int maxSpotLight = AX_MAX_SPOT_LIGHT;
int maxDirLight = conf->getMaxSupportDirLightInShader();
int maxPointLight = conf->getMaxSupportPointLightInShader();
int maxSpotLight = conf->getMaxSupportSpotLightInShader();
auto& lights = scene->getLights();
auto bindings = pass->getVertexAttributeBinding();

View File

@ -35,7 +35,6 @@
#include "math/Math.h"
#include "renderer/MeshCommand.h"
#include "renderer/CustomCommand.h"
#include "renderer/backend/Backend.h"
NS_AX_BEGIN
@ -243,36 +242,6 @@ public:
std::string getTextureFileName() { return _texFile; }
void setInstanceCount(int count = 0);
/** Enables instancing for this Mesh Renderer, keep in mind that
a special vertex shader has to be used, make sure that your shader
has a mat4 attribute set on the location of total vertex attributes +1
*/
void enableInstancing(bool instance, int count = 0);
/** Set this to true and instancing objects within this mesh renderer
will be recalculated each frame, use it when you plan to move objects,
Otherwise, transforms will be built once for better performance.
* to update transforms on demand use `rebuildInstances()` */
void setDynamicInstancing(bool dynamic);
/** Adds a child to use it's transformations for instancing.
* The child is in the space of this Node, keep in mind that
the node isn't added to the scene graph, it is instead retained
and it's parent is set to this node, updates and actions will not run.
* the reason for this is performance.
*
* @param child, The child to use for instancing.
*/
void addInstanceChild(Node* child);
/** shrinks the instance transform buffer after many steps of expansion to increase performance. */
void shrinkToFitInstances();
/** rebuilds the instance transform buffer next frame. */
void rebuildInstances();
Mesh();
virtual ~Mesh();
@ -285,15 +254,6 @@ protected:
MeshSkin* _skin; // skin
bool _visible; // is the submesh visible
bool _instancing;
backend::Buffer* _instanceTransformBuffer;
bool _instanceTransformDirty;
bool _instanceTransformBufferDirty;
int _instanceCount;
std::vector<Node*> _instances;
float* _instanceMatrixCache;
bool _dynamicInstancing;
CustomCommand::IndexFormat meshIndexFormat;
std::string _name;

View File

@ -40,7 +40,6 @@ MeshMaterialCache* MeshMaterialCache::_cacheInstance = nullptr;
std::unordered_map<std::string, MeshMaterial*> MeshMaterial::_materials;
MeshMaterial* MeshMaterial::_unLitMaterial = nullptr;
MeshMaterial* MeshMaterial::_unLitInstanceMaterial = nullptr;
MeshMaterial* MeshMaterial::_unLitNoTexMaterial = nullptr;
MeshMaterial* MeshMaterial::_vertexLitMaterial = nullptr;
MeshMaterial* MeshMaterial::_diffuseMaterial = nullptr;
@ -56,7 +55,6 @@ MeshMaterial* MeshMaterial::_quadTextureMaterial = nullptr;
MeshMaterial* MeshMaterial::_quadColorMaterial = nullptr;
backend::ProgramState* MeshMaterial::_unLitMaterialProgState = nullptr;
backend::ProgramState* MeshMaterial::_unLitInstanceMaterialProgState = nullptr;
backend::ProgramState* MeshMaterial::_unLitNoTexMaterialProgState = nullptr;
backend::ProgramState* MeshMaterial::_vertexLitMaterialProgState = nullptr;
backend::ProgramState* MeshMaterial::_diffuseMaterialProgState = nullptr;
@ -105,14 +103,6 @@ void MeshMaterial::createBuiltInMaterial()
_unLitMaterial->_type = MeshMaterial::MaterialType::UNLIT;
}
program = backend::Program::getBuiltinProgram(backend::ProgramType::POSITION_TEXTURE_3D_INSTANCE);
_unLitInstanceMaterialProgState = new backend::ProgramState(program);
_unLitInstanceMaterial = new MeshMaterial();
if (_unLitInstanceMaterial && _unLitInstanceMaterial->initWithProgramState(_unLitInstanceMaterialProgState))
{
_unLitInstanceMaterial->_type = MeshMaterial::MaterialType::UNLIT_INSTANCE;
}
program = backend::Program::getBuiltinProgram(backend::ProgramType::POSITION_3D);
_unLitNoTexMaterialProgState = new backend::ProgramState(program);
_unLitNoTexMaterial = new MeshMaterial();
@ -240,10 +230,6 @@ MeshMaterial* MeshMaterial::createBuiltInMaterial(MaterialType type, bool skinne
material = skinned ? _unLitMaterialSkin : _unLitMaterial;
break;
case MeshMaterial::MaterialType::UNLIT_INSTANCE:
material = skinned ? /* TODO: implement instanced hardware skinning */ nullptr : _unLitInstanceMaterial;
break;
case MeshMaterial::MaterialType::UNLIT_NOTEX:
material = _unLitNoTexMaterial;
break;

View File

@ -58,7 +58,6 @@ public:
{
// Built in materials
UNLIT, // unlit material
UNLIT_INSTANCE, // unlit instance material
UNLIT_NOTEX, // unlit material (without texture)
VERTEX_LIT, // vertex lit
DIFFUSE, // diffuse (pixel lighting)
@ -71,18 +70,6 @@ public:
CUSTOM, // Create from a material file
};
/**
* Instanced Material types, there are mainly two types of materials. Built-in materials and Custom materials.
*/
enum class InstanceMaterialType
{
NO_INSTANCING, // disabled instancing
UNLIT_INSTANCE, // unlit instance material
// Custom material
CUSTOM, // Create from a material file
};
/**
* Get material type
* @return Material type
@ -137,7 +124,6 @@ protected:
MaterialType _type;
static std::unordered_map<std::string, MeshMaterial*> _materials; // cached material
static MeshMaterial* _unLitMaterial;
static MeshMaterial* _unLitInstanceMaterial;
static MeshMaterial* _unLitNoTexMaterial;
static MeshMaterial* _vertexLitMaterial;
static MeshMaterial* _diffuseMaterial;
@ -153,7 +139,6 @@ protected:
static MeshMaterial* _quadColorMaterial;
static backend::ProgramState* _unLitMaterialProgState;
static backend::ProgramState* _unLitInstanceMaterialProgState;
static backend::ProgramState* _unLitNoTexMaterialProgState;
static backend::ProgramState* _vertexLitMaterialProgState;
static backend::ProgramState* _diffuseMaterialProgState;

View File

@ -692,63 +692,6 @@ void MeshRenderer::setModelTexture(std::string_view modelPath, std::string_view
}
}
void MeshRenderer::enableInstancing(MeshMaterial::InstanceMaterialType instanceMat, int count)
{
switch (instanceMat)
{
case MeshMaterial::InstanceMaterialType::UNLIT_INSTANCE:
{
auto mat = MeshMaterial::createBuiltInMaterial(MeshMaterial::MaterialType::UNLIT_INSTANCE, false);
enableInstancing(mat, count);
}
}
}
void MeshRenderer::enableInstancing(MeshMaterial* instanceMat, int count)
{
for (auto&& mesh : _meshes)
{
mesh->enableInstancing(true, MAX(1, count));
mesh->setMaterial(instanceMat);
}
}
void MeshRenderer::disableInstancing()
{
for (auto&& mesh : _meshes)
mesh->enableInstancing(false, 0);
}
void MeshRenderer::setDynamicInstancing(bool dynamic)
{
for (auto&& mesh : _meshes)
mesh->setDynamicInstancing(dynamic);
}
void MeshRenderer::addInstanceChild(Node* child, bool active)
{
for (auto&& mesh : _meshes)
{
mesh->addInstanceChild(child);
if (active)
addChild(child);
else
child->setParent(this);
}
}
void MeshRenderer::shrinkToFitInstances()
{
for (auto&& mesh : _meshes)
mesh->shrinkToFitInstances();
}
void MeshRenderer::rebuildInstances()
{
for (auto&& mesh : _meshes)
mesh->rebuildInstances();
}
void MeshRenderer::setTexture(std::string_view texFile)
{
auto tex = _director->getTextureCache()->addImage(texFile);
@ -892,9 +835,9 @@ void MeshRenderer::draw(Renderer* renderer, const Mat4& transform, uint32_t flag
}
}
bool MeshRenderer::setProgramState(backend::ProgramState* programState, bool ownPS/* = false*/)
bool MeshRenderer::setProgramState(backend::ProgramState* programState, bool needsRetain)
{
if (Node::setProgramState(programState, ownPS))
if (Node::setProgramState(programState, needsRetain))
{
for (auto&& state : _meshes)
{

View File

@ -38,7 +38,6 @@
#include "3d/AABB.h"
#include "3d/Bundle3DData.h"
#include "3d/MeshVertexIndexData.h"
#include "3d/MeshMaterial.h"
NS_AX_BEGIN
@ -130,7 +129,7 @@ public:
// overrides
/** Sets ProgramState, attributes should be bound by the user */
bool setProgramState(backend::ProgramState* programState, bool ownPS = false) override;
bool setProgramState(backend::ProgramState* programState, bool needsRetain = true) override;
/*
* Get AABB
@ -251,50 +250,6 @@ public:
static AABB getAABBRecursivelyImp(Node* node);
/** Enables instancing for this Mesh Renderer, keep in mind that
a special vertex shader has to be used, make sure that your shader
has a mat4 attribute set on the location of total vertex attributes +1
@param instanceMat Prebuilt material made to work with instancing.
@param count Count of Instances, 0 to enable auto expanstion, but you
should call `shrinkToFitInstances` after adding children to maximize performance.*/
void enableInstancing(MeshMaterial::InstanceMaterialType instanceMat, int count = 0);
/* Enables instancing for this Mesh Renderer, keep in mind that
/ a special vertex shader has to be used, make sure that your shader
/ has a mat4 attribute set on the location of total vertex attributes +1
@param instanceMat Custom material that supports instancing.
@param count Count of Instances, 0 to enable auto expanstion, but you
should call `shrinkToFitInstances` after adding children to maximize performance.*/
void enableInstancing(MeshMaterial* instanceMat, int count = 0);
// Disables instancing for this Mesh Renderer.
void disableInstancing();
/** Set this to true and instancing objects within this mesh renderer
will be recalculated each frame, use it when you plan to move objects,
Otherwise, transforms will be built once for better performance.
* to update transforms on demand use `rebuildInstances()` */
void setDynamicInstancing(bool dynamic);
/** Adds a child to use it's transformations for instancing.
* The child is in the space of this Node, keep in mind that
the node isn't added to the scene graph, it is instead retained
and it's parent is set to this node, updates and actions will not run.
* the reason for this is performance.
*
* @param child, The child to use for instancing.
* @param active, Child will run updates & actions but performance issues may arise.
*/
void addInstanceChild(Node* child, bool active = false);
/** shrinks the instance transform buffer after many steps of expansion to increase performance. */
void shrinkToFitInstances();
/** rebuilds the instance transform buffer next frame. */
void rebuildInstances();
protected:
/** set specific mesh texture, for private use (create mesh stage) only */
Texture2D* setMeshTexture(Mesh* mesh,

View File

@ -121,7 +121,8 @@ bool MotionStreak3D::initWithFade(float fade, float minSeg, float stroke, const
_blendFunc = BlendFunc::ALPHA_NON_PREMULTIPLIED;
// shader state
this->setProgramStateByProgramId(ProgramType::POSITION_TEXTURE_COLOR);
auto* program = backend::Program::getBuiltinProgram(backend::ProgramType::POSITION_TEXTURE_COLOR);
setProgramState(new backend::ProgramState(program), false);
_customCommand.getPipelineDescriptor().programState = _programState;

View File

@ -64,7 +64,8 @@ bool Skybox::init()
_customCommand.setAfterCallback(AX_CALLBACK_0(Skybox::onAfterDraw, this));
// create and set our custom shader
setProgramStateByProgramId(backend::ProgramType::SKYBOX_3D);
auto* program = backend::Program::getBuiltinProgram(backend::ProgramType::SKYBOX_3D);
setProgramState(new backend::ProgramState(program), false);
auto& pipelineDescriptor = _customCommand.getPipelineDescriptor();

View File

@ -106,7 +106,8 @@ void ax::Terrain::setLightDir(const Vec3& lightDir)
bool Terrain::initProperties()
{
setProgramStateByProgramId(ProgramType::TERRAIN_3D);
auto* program = backend::Program::getBuiltinProgram(backend::ProgramType::TERRAIN_3D);
setProgramState(new backend::ProgramState(program), false);
_stateBlock.depthWrite = true;
_stateBlock.depthTest = true;

View File

@ -90,17 +90,15 @@ bool VertexAttribBinding::init(MeshIndexData* meshIndexData, Pass* pass, MeshCom
// Parse and set attributes
parseAttributes();
int offset = 0;
auto vertexLayout = _programState->getMutableVertexLayout();
for (auto k = 0; k < attributeCount; k++)
{
auto meshattribute = meshVertexData->getMeshVertexAttrib(k);
setVertexAttribPointer(vertexLayout, shaderinfos::getAttributeName(meshattribute.vertexAttrib),
meshattribute.type, false,
setVertexAttribPointer(shaderinfos::getAttributeName(meshattribute.vertexAttrib), meshattribute.type, false,
offset, 1 << k);
offset += meshattribute.getAttribSizeBytes();
}
vertexLayout->setStride(offset);
_programState->setVertexStride(offset);
AXASSERT(offset == meshVertexData->getSizePerVertex(), "vertex layout mismatch!");
@ -135,8 +133,7 @@ const backend::AttributeBindInfo* VertexAttribBinding::getVertexAttribValue(std:
return nullptr;
}
void VertexAttribBinding::setVertexAttribPointer(VertexLayout* vertexLayout,
std::string_view name,
void VertexAttribBinding::setVertexAttribPointer(std::string_view name,
backend::VertexFormat type,
bool normalized,
int offset,
@ -146,7 +143,7 @@ void VertexAttribBinding::setVertexAttribPointer(VertexLayout* vertexLayout,
if (v)
{
// AXLOG("axmol: set attribute '%s' location: %d, offset: %d", name.c_str(), v->location, offset);
vertexLayout->setAttrib(name, v->location, type, offset, normalized);
_programState->setVertexAttrib(name, v->location, type, offset, normalized);
_vertexAttribsFlags |= flag;
}
else

View File

@ -107,7 +107,7 @@ private:
VertexAttribBinding& operator=(const VertexAttribBinding&);
bool init(MeshIndexData* meshIndexData, Pass* pass, MeshCommand*);
void setVertexAttribPointer(VertexLayout* vertexLayout, std::string_view name,
void setVertexAttribPointer(std::string_view name,
backend::VertexFormat type,
bool normalized,
int offset,

View File

@ -32,59 +32,30 @@
# include_guard (GLOBAL)
# The version number
set(_AX_VERSION 2.0)
set(_AX_VERSION 1.1)
if(NOT DEFINED _AX_CORE_LIB)
set(_AX_CORE_LIB axmol CACHE INTERNAL "The axmol core lib name" )
endif()
cmake_policy(SET CMP0127 NEW)
project(ax_libs)
if(WIN32)
# explicit set source charset to utf-8 for windows targets
add_compile_options("$<$<C_COMPILER_ID:MSVC>:/utf-8>")
add_compile_options("$<$<CXX_COMPILER_ID:MSVC>:/utf-8>")
if (NOT WINRT)
option (AX_USE_ANGLE "Use google angle renderer" OFF)
else()
set (AX_USE_ANGLE TRUE CACHE BOOL "Use google angle renderer" FORCE)
endif()
include(CMakeDependentOption)
# by default: use angle on win32
cmake_dependent_option(AX_USE_COMPAT_GL "Whether use compatibility GL as render backend" ON "WIN32" OFF)
# choosing render backend for all target platforms: win32, winuwp, ios, tvos, android, linux, osx
if(APPLE AND (NOT AX_USE_COMPAT_GL))
set(AX_USE_METAL ON CACHE BOOL "" FORCE)
set(AX_USE_GL OFF CACHE BOOL "" FORCE)
else() # win32, winuwp, android, linux: OpenGL
set(AX_USE_GL ON CACHE BOOL "" FORCE)
set(AX_USE_METAL OFF CACHE BOOL "" FORCE)
endif()
# macos, linux or (win32, ios, tvos and NOT AX_USE_COMPAT_GL) not use GLES profile
set(_GLES_PROFILE 0) # _GLES_PROFILE is the default GLES profile
if(ANDROID) # android force use GLES profile
set(_GLES_PROFILE 200)
elseif(WINRT) # winuwp fore use GLES profile
set(_GLES_PROFILE 300)
elseif((NOT MACOSX) AND (NOT LINUX)) # win32, ios, tvos
if(AX_USE_COMPAT_GL)
set(_GLES_PROFILE 300)
if (NOT AX_USE_ANGLE) # check deprecated option: AX_USE_COMPAT_GL
if (NOT WINRT)
option (AX_USE_COMPAT_GL "Use google angle renderer" OFF)
else()
set (AX_USE_COMPAT_GL TRUE CACHE BOOL "Use google angle renderer" ON)
endif()
set (AX_USE_ANGLE ${AX_USE_COMPAT_GL} CACHE BOOL "Use google angle renderer" FORCE)
endif()
if(_GLES_PROFILE)
set(AX_GLES_PROFILE ${_GLES_PROFILE} CACHE STRING "")
if (NOT (AX_GLES_PROFILE EQUAL 200 OR AX_GLES_PROFILE EQUAL 300))
message(FATAL_ERROR "${MACOSX} Invalid GLES profile ${AX_GLES_PROFILE}, must be 200 or 300, default ${_GLES_PROFILE}")
endif()
else() # force disable GLES profile
set(AX_GLES_PROFILE 0 CACHE STRING "" FORCE)
endif()
# print renderer backend profile
message(AUTHOR_WARNING "AX_USE_GL=${AX_USE_GL}, AX_USE_METAL=${AX_USE_METAL}, AX_GLES_PROFILE=${AX_GLES_PROFILE}")
message(STATUS "WINRT=${WINRT}")
option (AX_ENABLE_MFMEDIA "Enabling microsoft media foundation" ON)
@ -98,10 +69,11 @@ endif()
if (LINUX)
include(CheckIncludeFile)
check_include_file(vlc/vlc.h _AX_HAVE_VLC)
option (AX_ENABLE_VLC_MEDIA "Enabling vlc media on linux" ON)
elseif(WINDOWS AND (NOT WINRT))
option (AX_ENABLE_VLC_MEDIA "Enabling vlc media on windows" OFF)
endif()
cmake_dependent_option(AX_ENABLE_VLC_MEDIA "Enabling vlc media" ON "_AX_HAVE_VLC" OFF)
message(STATUS "AX_ENABLE_VLC_MEDIA=${AX_ENABLE_VLC_MEDIA}")
if(NOT APPLE)
@ -112,6 +84,7 @@ endif()
option(AX_UPDATE_BUILD_VERSION "Update build version" ON)
# default value for axmol extensions modules to Build
# total supported extensions count: 12
# extensions dependicies: COCOSTUDIO may depend on spine & dragonBones if they are present in buildset
@ -132,9 +105,16 @@ option(AX_ENABLE_EXT_FAIRYGUI "Build extension FairyGUI" ON)
option(AX_ENABLE_EXT_LIVE2D "Build extension Live2D" OFF)
option(AX_ENABLE_EXT_EFFEKSEER "Build extension Effekseer" OFF)
cmake_dependent_option(AX_ENABLE_EXT_IMGUI "Build extension ImGui" ON "(WINDOWS AND NOT WINRT) OR MACOSX OR LINUX OR ANDROID" OFF)
if((WINDOWS AND NOT WINRT) OR MACOSX OR LINUX OR ANDROID)
option(AX_ENABLE_EXT_IMGUI "Build extension ImGui" ON)
else()
set(AX_ENABLE_EXT_IMGUI OFF)
endif()
option(AX_DISABLE_GLES2 "Whether disable GLES2 support" OFF)
if (ANDROID)
set(AX_USE_GLAD TRUE CACHE BOOL "Use glad for android GLESv3 support" FORCE)
add_definitions(-DAX_USE_GLAD=1)
endif()
if(XCODE)
# set(CMAKE_BUILD_WITH_INSTALL_RPATH YES)
@ -153,36 +133,6 @@ if (WIN32)
endif()
endif()
# axmolver.h
find_package(Git)
if(AX_UPDATE_BUILD_VERSION AND GIT_FOUND AND EXISTS "${_AX_ROOT}/.git")
# Get the current working branch and its latest abbreviated commit hash
EXECUTE_PROCESS(COMMAND ${GIT_EXECUTABLE} -C "${_AX_ROOT}" rev-list --count HEAD
TIMEOUT 5
OUTPUT_VARIABLE AX_BUILD_NUM
OUTPUT_STRIP_TRAILING_WHITESPACE)
EXECUTE_PROCESS(COMMAND ${GIT_EXECUTABLE} -C "${_AX_ROOT}" branch --show-current
TIMEOUT 5
OUTPUT_VARIABLE AX_GIT_BRANCH
OUTPUT_STRIP_TRAILING_WHITESPACE)
EXECUTE_PROCESS(COMMAND ${GIT_EXECUTABLE} -C "${_AX_ROOT}" rev-parse --short=7 HEAD
TIMEOUT 5
OUTPUT_VARIABLE AX_GIT_COMMIT_HASH
OUTPUT_STRIP_TRAILING_WHITESPACE)
else()
set(AX_GIT_BRANCH "UNKNOWN")
set(AX_GIT_COMMIT_HASH "unknown")
endif()
configure_file(
"${CMAKE_CURRENT_LIST_DIR}/axmolver.h.in"
"${CMAKE_CURRENT_LIST_DIR}/axmolver.h")
# early experimental features
# include(CMakeDependentOption)
# cmake_dependent_option(AX_ENABLE_EARLY_FEATURES
# "Build the tests when we are the root project" ON
# "NOT (AX_GIT_BRANCH STREQUAL \"dev\")" OFF)
include(2d/CMakeLists.txt)
include(3d/CMakeLists.txt)
include(platform/CMakeLists.txt)
@ -240,44 +190,6 @@ list(APPEND _AX_SRC ${_AX_HEADER})
add_library(${_AX_CORE_LIB} ${_AX_SRC})
ax_find_shaders(${_AX_ROOT}/core/renderer/shaders BUILTIN_SHADER_SOURCES)
set(ax_builtin_shaders ${BUILTIN_SHADER_SOURCES} CACHE STATIC "" FORCE)
# configure engine builtin light num
if (NOT DEFINED AX_MAX_DIRECTIONAL_LIGHT)
set(AX_MAX_DIRECTIONAL_LIGHT 1)
endif()
if (NOT DEFINED AX_MAX_POINT_LIGHT)
set(AX_MAX_POINT_LIGHT 1)
endif()
if (NOT DEFINED AX_MAX_SPOT_LIGHT)
set (AX_MAX_SPOT_LIGHT 1)
endif()
configure_file(
"${CMAKE_CURRENT_LIST_DIR}/renderer/RenderConsts.h.in"
"${CMAKE_CURRENT_LIST_DIR}/renderer/RenderConsts.h" @ONLY)
# SKINPOSITION_NORMAL_TEXTURE_3D: skinPositionNormalTexture.vert, colorNormalTexture.frag, LightDefs
# POSITION_NORMAL_TEXTURE_3D: skinPositionNormalTexture.vert, colorNormalTexture.frag, LightDefs
# POSITION_NORMAL_3D: positionNormalTexture.vert, colorNormal.frag, LightDefs
# POSITION_BUMPEDNORMAL_TEXTURE_3D: positionNormalTexture.vert, colorNormalTexture.frag, lightNormMapDef
# SKINPOSITION_BUMPEDNORMAL_TEXTURE_3D: skinPositionNormalTexture_vert, colorNormalTexture.frag, lightNormMapDef
set_source_files_properties(
${_AX_ROOT}/core/renderer/shaders/colorNormal.frag
${_AX_ROOT}/core/renderer/shaders/colorNormalTexture.frag
${_AX_ROOT}/core/renderer/shaders/positionNormalTexture.vert
${_AX_ROOT}/core/renderer/shaders/skinPositionNormalTexture.vert
PROPERTIES GLSLCC_DEFINES
"MAX_DIRECTIONAL_LIGHT_NUM=${AX_MAX_DIRECTIONAL_LIGHT},MAX_POINT_LIGHT_NUM=${AX_MAX_POINT_LIGHT},MAX_SPOT_LIGHT_NUM=${AX_MAX_SPOT_LIGHT}"
)
set_source_files_properties(
${_AX_ROOT}/core/renderer/shaders/colorNormalTexture.frag
${_AX_ROOT}/core/renderer/shaders/positionNormalTexture.vert
${_AX_ROOT}/core/renderer/shaders/skinPositionNormalTexture.vert
PROPERTIES GLSLCC_OUTPUT1 "USE_NORMAL_MAPPING=1"
)
ax_target_compile_shaders(${_AX_CORE_LIB} FILES ${BUILTIN_SHADER_SOURCES})
if (WINRT)
target_compile_options(${_AX_CORE_LIB} PUBLIC /ZW)
endif()
@ -365,6 +277,29 @@ if(ANDROID)
add_subdirectory(${_AX_ROOT}/core/platform/android ${ENGINE_BINARY_PATH}/core/cpp-android)
endif()
find_package(Git)
if(AX_UPDATE_BUILD_VERSION AND GIT_FOUND AND EXISTS "${_AX_ROOT}/.git")
# Get the current working branch and its latest abbreviated commit hash
EXECUTE_PROCESS(COMMAND ${GIT_EXECUTABLE} -C "${_AX_ROOT}" rev-list --count HEAD
TIMEOUT 5
OUTPUT_VARIABLE AX_BUILD_NUM
OUTPUT_STRIP_TRAILING_WHITESPACE)
EXECUTE_PROCESS(COMMAND ${GIT_EXECUTABLE} -C "${_AX_ROOT}" branch --show-current
TIMEOUT 5
OUTPUT_VARIABLE AX_GIT_BRANCH
OUTPUT_STRIP_TRAILING_WHITESPACE)
EXECUTE_PROCESS(COMMAND ${GIT_EXECUTABLE} -C "${_AX_ROOT}" rev-parse --short=7 HEAD
TIMEOUT 5
OUTPUT_VARIABLE AX_GIT_COMMIT_HASH
OUTPUT_STRIP_TRAILING_WHITESPACE)
else()
set(AX_GIT_BRANCH "UNKNOWN")
set(AX_GIT_COMMIT_HASH "unknown")
endif()
configure_file(
"${CMAKE_CURRENT_LIST_DIR}/axmolver.h.in"
"${CMAKE_CURRENT_LIST_DIR}/axmolver.h")
#if(XCODE)
# # Later versions of Xcode clang want to compile C++17 with aligned allocation turned on and this is only supported on iOS 11.0+
# # TODO: Only turn this off if ${CMAKE_XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET} < 11.0

View File

@ -28,7 +28,7 @@
#include <stdint.h>
#include <string>
#include "platform/IFileStream.h"
#include "platform/FileStream.h"
NS_AX_BEGIN

View File

@ -29,7 +29,7 @@
#include <stdint.h>
#import <AudioToolbox/ExtendedAudioFile.h>
#include "audio/AudioDecoder.h"
#include "platform/IFileStream.h"
#include "platform/FileStream.h"
NS_AX_BEGIN
@ -98,7 +98,7 @@ private:
static SInt64 getSizeCallback(void* inClientData);
ExtAudioFileRef _extRef;
std::unique_ptr<IFileStream> _fileStream;
std::unique_ptr<ax::FileStream> _fileStream;
SInt64 _streamSize;
AudioFileID _audioFileId;

View File

@ -59,29 +59,29 @@ NS_AX_BEGIN
#if !AX_USE_MPG123
static size_t minimp3_read_r(void* buf, size_t size, void* user_data)
{
return ((IFileStream*)user_data)->read(buf, size);
return ((FileStream*)user_data)->read(buf, size);
}
static int minimp3_seek_r(uint64_t position, void* user_data)
{
return ((IFileStream*)user_data)->seek(position, SEEK_SET) < 0 ? -1 : 0;
return ((FileStream*)user_data)->seek(position, SEEK_SET) < 0 ? -1 : 0;
}
#else
static bool __mp3Inited = false;
static ssize_t mpg123_read_r(void* handle, void* buffer, size_t count)
{
return ((IFileStream*)handle)->read(buffer, count);
return ((FileStream*)handle)->read(buffer, count);
}
static off_t mpg123_lseek_r(void* handle, off_t offset, int whence)
{
return ((IFileStream*)handle)->seek(offset, whence);
return ((FileStream*)handle)->seek(offset, whence);
}
void mpg123_close_r(void* handle)
{
((IFileStream*)handle)->close();
((FileStream*)handle)->close();
}
#endif
bool AudioDecoderMp3::lazyInit()
@ -131,7 +131,7 @@ bool AudioDecoderMp3::open(std::string_view fullPath)
#if !AX_USE_MPG123
do
{
_fileStream = FileUtils::getInstance()->openFileStream(fullPath, IFileStream::Mode::READ);
_fileStream = FileUtils::getInstance()->openFileStream(fullPath, FileStream::Mode::READ);
if (!_fileStream)
{
ALOGE("Trouble with minimp3(1): %s\n", strerror(errno));

View File

@ -83,7 +83,7 @@ protected:
static bool lazyInit();
static void destroy();
std::unique_ptr<IFileStream> _fileStream{};
std::unique_ptr<FileStream> _fileStream{};
mp3dec_handle_t _handle;
friend class AudioDecoderManager;

View File

@ -39,25 +39,25 @@ NS_AX_BEGIN
static size_t ov_fread_r(void* buffer, size_t element_size, size_t element_count, void* handle)
{
auto* fs = static_cast<IFileStream*>(handle);
auto* fs = static_cast<FileStream*>(handle);
return fs->read(buffer, static_cast<uint32_t>(element_size * element_count));
}
static int ov_fseek_r(void* handle, ogg_int64_t offset, int whence)
{
auto* fs = static_cast<IFileStream*>(handle);
auto* fs = static_cast<FileStream*>(handle);
return fs->seek(offset, whence) < 0 ? -1 : 0;
}
static long ov_ftell_r(void* handle)
{
auto* fs = static_cast<IFileStream*>(handle);
auto* fs = static_cast<FileStream*>(handle);
return fs->tell();
}
static int ov_fclose_r(void* handle)
{
auto* fs = static_cast<IFileStream*>(handle);
auto* fs = static_cast<FileStream*>(handle);
delete fs;
return 0;
}
@ -71,7 +71,7 @@ AudioDecoderOgg::~AudioDecoderOgg()
bool AudioDecoderOgg::open(std::string_view fullPath)
{
auto fs = FileUtils::getInstance()->openFileStream(fullPath, IFileStream::Mode::READ).release();
auto fs = FileUtils::getInstance()->openFileStream(fullPath, FileStream::Mode::READ).release();
if (!fs)
{
ALOGE("Trouble with ogg(1): %s\n", strerror(errno));

View File

@ -80,7 +80,7 @@ static bool wav_scan_chunk(WAV_FILE* wavf, uint32_t chunkID, void* header, void*
}
static bool wav_open(std::string_view fullPath, WAV_FILE* wavf)
{
wavf->Stream = FileUtils::getInstance()->openFileStream(fullPath, IFileStream::Mode::READ);
wavf->Stream = FileUtils::getInstance()->openFileStream(fullPath, FileStream::Mode::READ);
if (!wavf->Stream)
return false;

View File

@ -116,7 +116,7 @@ struct WAV_FILE
WAV_FILE_HEADER FileHeader;
AUDIO_SOURCE_FORMAT SourceFormat;
uint32_t PcmDataOffset;
std::unique_ptr<IFileStream> Stream{};
std::unique_ptr<FileStream> Stream{};
};
/**

View File

@ -178,7 +178,6 @@ THE SOFTWARE.
#include "platform/Common.h"
#include "platform/Device.h"
#include "platform/FileUtils.h"
#include "platform/FileStream.h"
#include "platform/Image.h"
#include "platform/PlatformConfig.h"
#include "platform/PlatformMacros.h"

View File

@ -3,12 +3,12 @@
/* Define the axmol version */
// 0x00 HI ME LO
// 00 03 08 00
#define AX_VERSION_MAJOR 2
#define AX_VERSION_MAJOR 1
#define AX_VERSION_MINOR 0
#define AX_VERSION_PATCH 0
/* Define the axmol version string, easy for script parsing */
#define AX_VERSION_STR "2.0.0"
#define AX_VERSION_STR "1.0.0"
/* Define axmol version helper macros */
#define AX_VERSION_MAKE(a,b,c) ((a << 16) | (b << 8) | (c & 0xff))

View File

@ -15,6 +15,7 @@ elseif(LINUX OR WINDOWS)
endif()
set(_AX_BASE_HEADER
base/posix_io.h
base/astc.h
base/pvr.h
base/format.h
@ -136,5 +137,6 @@ set(_AX_BASE_SRC
base/pvr.cpp
base/s3tc.cpp
base/astc.cpp
base/posix_io.cpp
${_AX_BASE_SPECIFIC_SRC}
)

View File

@ -117,11 +117,11 @@ std::string Configuration::getInfo() const
void Configuration::gatherGPUInfo()
{
auto _deviceInfo = backend::Device::getInstance()->getDeviceInfo();
AXLOG("Supported extensions: %s", _deviceInfo->getExtension());
_valueDict["vendor"] = Value(_deviceInfo->getVendor());
_valueDict["renderer"] = Value(_deviceInfo->getRenderer());
_valueDict["version"] = Value(_deviceInfo->getVersion());
_valueDict["glsl"] = Value(_deviceInfo->getShaderVersion());
_valueDict["max_texture_size"] = Value(_deviceInfo->getMaxTextureSize());
_valueDict["max_vertex_attributes"] = Value(_deviceInfo->getMaxAttributes());
@ -167,7 +167,7 @@ void Configuration::gatherGPUInfo()
_supportsOESDepth24 = _deviceInfo->checkForFeatureSupported(backend::FeatureType::DEPTH24);
_valueDict["supports_OES_depth24"] = Value(_supportsOESDepth24);
// _glExtensions = _deviceInfo->getExtension();
_glExtensions = _deviceInfo->getExtension();
}
Configuration* Configuration::getInstance()
@ -186,6 +186,11 @@ void Configuration::destroyInstance()
AX_SAFE_RELEASE_NULL(s_sharedConfiguration);
}
bool Configuration::checkForGLExtension(std::string_view searchName) const
{
return _glExtensions.find(searchName) != std::string::npos;
}
//
// getters for specific variables.
// Maintained for backward compatibility reasons only.
@ -271,7 +276,7 @@ bool Configuration::supportsMapBuffer() const
// is always implemented in OpenGL.
// XXX: Warning. On iOS this is always `true`. Avoiding the comparison.
#if AX_GLES_PROFILE && !defined(__APPLE__)
#if defined(AX_USE_GLES) && !defined(__APPLE__)
return _supportsOESMapBuffer;
#else
return true;

View File

@ -200,6 +200,13 @@ public:
/** get 3d animate quality */
Animate3DQuality getAnimate3DQuality() const;
/** Returns whether or not an OpenGL extension is supported.
*
* @param searchName A given search name.
* @return Is true if an OpenGL extension is supported.
*/
bool checkForGLExtension(std::string_view searchName) const;
/** Initialize method.
*
* @return Is true if initialize success.

View File

@ -1451,7 +1451,7 @@ void Console::commandUpload(socket_native_type fd)
static std::string writablePath = FileUtils::getInstance()->getWritablePath();
std::string filepath = writablePath + std::string(buf);
auto fs = FileUtils::getInstance()->openFileStream(filepath, IFileStream::Mode::WRITE);
auto fs = FileUtils::getInstance()->openFileStream(filepath, FileStream::Mode::WRITE);
if (!fs)
{
const char err[] = "can't create file!\n";

View File

@ -1028,7 +1028,7 @@ void Director::reset()
AsyncTaskPool::destroyInstance();
backend::ProgramManager::destroyInstance();
// axmol specific data structures
// cocos2d-x specific data structures
UserDefault::destroyInstance();
resetMatrixStack();

View File

@ -179,7 +179,7 @@ Color4F operator/(Color4F lhs, float rhs);
/**
* Hue Saturation Value color space composed of 4 floats.
* @since axmol-1.0.0b7
*
*
* Implementation source: https://gist.github.com/fairlight1337/4935ae72bcbcc1ba5c72
*/
struct AX_DLL HSV
@ -518,7 +518,7 @@ struct AX_DLL BlendFunc
*
* @note If any of these enums are edited and/or reordered, update Texture2D.m.
*/
enum class TextVAlignment
enum class AX_DLL TextVAlignment
{
TOP,
CENTER,
@ -530,7 +530,7 @@ enum class TextVAlignment
*
* @note If any of these enums are edited and/or reordered, update Texture2D.m.
*/
enum class TextHAlignment
enum class AX_DLL TextHAlignment
{
LEFT,
CENTER,
@ -660,42 +660,21 @@ public:
extern const std::string AX_DLL STD_STRING_EMPTY;
extern const ssize_t AX_DLL AX_INVALID_INDEX;
struct RectI
struct AX_DLL Viewport
{
RectI() { this->x = this->y = this->w = this->h = 0; }
int x;
int y;
union
{
struct
{
int width;
int height;
};
struct
{
int w;
int h;
};
};
inline bool operator==(const RectI& v) const
{
return this->x == v.x && this->y == v.y && this->width == v.width && this->height == v.height;
}
inline RectI& set(int x, int y, int w, int h)
{
this->x = x;
this->y = y;
this->width = w;
this->height = h;
return *this;
}
int x = 0;
int y = 0;
unsigned int w = 0;
unsigned int h = 0;
};
using Viewport = RectI;
using ScissorRect = RectI; // both GL & Metal is integer type, GL: int, Metal: NSUInteger
struct AX_DLL ScissorRect
{
float x = 0;
float y = 0;
float width = 0;
float height = 0;
};
using TextureUsage = backend::TextureUsage;
using PixelFormat = backend::PixelFormat;

View File

@ -52,6 +52,8 @@ THE SOFTWARE.
#include "pugixml/pugixml.hpp"
#include "base/Utils.h"
#include "PosixFileStream.h"
#define USER_DEFAULT_PLAIN_MODE 0
#if !USER_DEFAULT_PLAIN_MODE
@ -134,8 +136,11 @@ void UserDefault::closeFileMapping()
{
_rwmmap.reset();
#if !USER_DEFAULT_PLAIN_MODE
if (_fileStream.isOpen())
_fileStream.close();
if (_fd != -1)
{
posix_close(_fd);
_fd = -1;
}
#endif
}
@ -379,27 +384,29 @@ void UserDefault::lazyInit()
_filePath = FileUtils::getInstance()->getNativeWritableAbsolutePath() + USER_DEFAULT_FILENAME;
// construct file mapping
if (!_fileStream.open(_filePath, IFileStream::Mode::OVERLAPPED))
_fd = posix_open(_filePath.c_str(), O_OVERLAP_FLAGS);
if (_fd == -1)
{
log("[Warning] UserDefault::init open storage file '%s' failed!", _filePath.c_str());
return;
}
int filesize = static_cast<int>(_fileStream.size());
int filesize = static_cast<int>(posix_lseek64(_fd, 0, SEEK_END));
posix_lseek64(_fd, 0, SEEK_SET);
if (filesize < _curMapSize)
{ // construct a empty file mapping
if (!_fileStream.resize(_curMapSize))
if (posix_ftruncate(_fd, _curMapSize) == -1)
{
log("[Warning] UserDefault::init failed to truncate '%s'.", _filePath.c_str());
return;
}
_rwmmap = std::make_shared<mio::mmap_sink>(_fileStream.nativeHandle(), 0, _curMapSize);
posix_lseek(_fd, _curMapSize, SEEK_SET);
_rwmmap = std::make_shared<mio::mmap_sink>(posix_fd2fh(_fd), 0, _curMapSize);
}
else
{ /// load to memory _values
_rwmmap = std::make_shared<mio::mmap_sink>(_fileStream.nativeHandle(), 0,
mio::map_entire_file);
_rwmmap = std::make_shared<mio::mmap_sink>(posix_fd2fh(_fd), 0, mio::map_entire_file);
if (_rwmmap->is_mapped())
{ // no error
yasio::ibstream_view ibs(_rwmmap->data(), _rwmmap->length());
@ -490,10 +497,11 @@ void UserDefault::flush()
while (obs.length() > _curMapSize)
_curMapSize <<= 1; // X2
if (!_fileStream.resize(_curMapSize))
ax::log("[Warning] UserDefault::flush failed to truncate '%s'.", _filePath.c_str());
if (posix_ftruncate(_fd, _curMapSize) == -1)
log("[Warning] UserDefault::flush failed to truncate '%s'.", _filePath.c_str());
_rwmmap->map(_fileStream.nativeHandle(), 0, _curMapSize, error);
posix_lseek(_fd, _curMapSize, SEEK_SET);
_rwmmap->map(posix_fd2fh(_fd), 0, _curMapSize, error);
}
if (!error && _rwmmap->is_mapped())

View File

@ -33,7 +33,6 @@ THE SOFTWARE.
#include <unordered_map>
#include "mio/mio.hpp"
#include "yasio/string_view.hpp"
#include "platform/FileStream.h"
/**
* @addtogroup base
@ -279,7 +278,7 @@ protected:
static UserDefault* _userDefault;
std::string _filePath;
FileStream _fileStream; // the file handle for data persistence
int _fd = -1; // the file handle for data persistence
std::shared_ptr<mio::mmap_sink> _rwmmap;
int _curMapSize = 4096; // init mapsize is 4K
int _realSize = 0; // real data size without key/value entities count field

View File

@ -422,23 +422,19 @@ std::string getDataMD5Hash(const Data& data)
std::string computeDigest(std::string_view data, std::string_view algorithm, bool toHex)
{
const EVP_MD* md = nullptr;
unsigned char mdValue[EVP_MAX_MD_SIZE] = {0};
unsigned int mdLen = 0;
OpenSSL_add_all_digests();
const EVP_MD* md = EVP_get_digestbyname(algorithm.data());
md = EVP_get_digestbyname(algorithm.data());
if (!md || data.empty())
return std::string{};
EVP_MD_CTX* mdctx = EVP_MD_CTX_create();
auto ok = EVP_DigestInit(mdctx, md);
if (!ok)
{
EVP_MD_CTX_destroy(mdctx);
return std::string{};
}
EVP_DigestInit_ex(mdctx, md, nullptr);
EVP_DigestUpdate(mdctx, data.data(), data.size());
EVP_DigestFinal(mdctx, mdValue, &mdLen);
EVP_DigestFinal_ex(mdctx, mdValue, &mdLen);
EVP_MD_CTX_destroy(mdctx);
return toHex ? bin2hex(std::string_view{(const char*)mdValue, (size_t)mdLen})
@ -658,14 +654,23 @@ const Mat4& getAdjustMatrix()
return adjustMatrix;
}
Mat3 getNormalMat3OfMat4(const Mat4& mat)
std::vector<float> getNormalMat3OfMat4(const Mat4& mat)
{
std::vector<float> normalMat(9);
Mat4 mvInverse = mat;
mvInverse.m[12] = mvInverse.m[13] = mvInverse.m[14] = 0.0f;
mvInverse.inverse();
mvInverse.transpose();
return Mat3{mvInverse.m[0], mvInverse.m[1], mvInverse.m[2], mvInverse.m[4], mvInverse.m[5],
mvInverse.m[6], mvInverse.m[8], mvInverse.m[9], mvInverse.m[10]};
normalMat[0] = mvInverse.m[0];
normalMat[1] = mvInverse.m[1];
normalMat[2] = mvInverse.m[2];
normalMat[3] = mvInverse.m[4];
normalMat[4] = mvInverse.m[5];
normalMat[5] = mvInverse.m[6];
normalMat[6] = mvInverse.m[8];
normalMat[7] = mvInverse.m[9];
normalMat[8] = mvInverse.m[10];
return normalMat;
}
std::vector<int> parseIntegerList(std::string_view intsString)

View File

@ -36,7 +36,6 @@ THE SOFTWARE.
#include "base/Data.h"
#include "renderer/backend/Types.h"
#include "math/Mat4.h"
#include "math/Mat3.h"
/** @file ccUtils.h
Misc free functions
@ -227,7 +226,7 @@ AX_DLL const Mat4& getAdjustMatrix();
/**
Get the Normal Matrix of matrixMV
*/
AX_DLL Mat3 getNormalMat3OfMat4(const Mat4& mat);
AX_DLL std::vector<float> getNormalMat3OfMat4(const Mat4& mat);
/**
@brief Parses a list of space-separated integers.

View File

@ -32,6 +32,7 @@
#else // from our embedded sources
# include "unzip.h"
#endif
#include "ioapi_mem.h"
#include <ioapi.h>
#include <memory>
@ -70,16 +71,16 @@ inline void ZipUtils::decodeEncodedPvr(unsigned int* data, ssize_t len)
// check if key was set
// make sure to call caw_setkey_part() for all 4 key parts
AXASSERT(s_uEncryptedPvrKeyParts[0] != 0,
"axmol:CCZ file is encrypted but key part 0 is not set. Did you call "
"Cocos2D: CCZ file is encrypted but key part 0 is not set. Did you call "
"ZipUtils::setPvrEncryptionKeyPart(...)?");
AXASSERT(s_uEncryptedPvrKeyParts[1] != 0,
"axmol:CCZ file is encrypted but key part 1 is not set. Did you call "
"Cocos2D: CCZ file is encrypted but key part 1 is not set. Did you call "
"ZipUtils::setPvrEncryptionKeyPart(...)?");
AXASSERT(s_uEncryptedPvrKeyParts[2] != 0,
"axmol:CCZ file is encrypted but key part 2 is not set. Did you call "
"Cocos2D: CCZ file is encrypted but key part 2 is not set. Did you call "
"ZipUtils::setPvrEncryptionKeyPart(...)?");
AXASSERT(s_uEncryptedPvrKeyParts[3] != 0,
"axmol:CCZ file is encrypted but key part 3 is not set. Did you call "
"Cocos2D: CCZ file is encrypted but key part 3 is not set. Did you call "
"ZipUtils::setPvrEncryptionKeyPart(...)?");
// create long key
@ -466,7 +467,7 @@ int ZipUtils::inflateCCZBuffer(const unsigned char* buffer, ssize_t bufferLen, u
unsigned long destlen = len;
size_t source = (size_t)buffer + sizeof(*header);
int ret = uncompress(*out, &destlen, (Bytef*)source, static_cast<uLong>(bufferLen - sizeof(*header)));
int ret = uncompress(*out, &destlen, (Bytef*)source, bufferLen - sizeof(*header));
if (ret != Z_OK)
{
@ -497,8 +498,8 @@ int ZipUtils::inflateCCZFile(const char* path, unsigned char** out)
void ZipUtils::setPvrEncryptionKeyPart(int index, unsigned int value)
{
AXASSERT(index >= 0, "axmol:key part index cannot be less than 0");
AXASSERT(index <= 3, "axmol:key part index cannot be greater than 3");
AXASSERT(index >= 0, "Cocos2d: key part index cannot be less than 0");
AXASSERT(index <= 3, "Cocos2d: key part index cannot be greater than 3");
if (s_uEncryptedPvrKeyParts[index] != value)
{
@ -527,59 +528,58 @@ static const std::string emptyFilename("");
struct ZipEntryInfo
{
unz_file_pos pos;
uint64_t uncompressed_size;
uint64_t offset;
uLong uncompressed_size;
};
struct ZipFilePrivate
{
ZipFilePrivate()
{
functionOverrides.zopen64_file = ZipFile_open_file_func;
functionOverrides.zopendisk64_file = ZipFile_opendisk_file_func;
functionOverrides.zopen_file = ZipFile_open_file_func;
functionOverrides.zopendisk_file = ZipFile_opendisk_file_func;
functionOverrides.zread_file = ZipFile_read_file_func;
functionOverrides.zwrite_file = ZipFile_write_file_func;
functionOverrides.ztell64_file = ZipFile_tell_file_func;
functionOverrides.zseek64_file = ZipFile_seek_file_func;
functionOverrides.ztell_file = ZipFile_tell_file_func;
functionOverrides.zseek_file = ZipFile_seek_file_func;
functionOverrides.zclose_file = ZipFile_close_file_func;
functionOverrides.zerror_file = ZipFile_error_file_func;
functionOverrides.opaque = this;
}
// unzip overrides to support IFileStream
static uint64_t ZipFile_tell_file_func(voidpf opaque, voidpf stream)
// unzip overrides to support FileStream
static long ZipFile_tell_file_func(voidpf opaque, voidpf stream)
{
if (stream == nullptr)
return -1;
auto* fs = (IFileStream*)stream;
auto* fs = (FileStream*)stream;
return fs->tell();
}
static long ZipFile_seek_file_func(voidpf opaque, voidpf stream, uint64_t offset, int origin)
static long ZipFile_seek_file_func(voidpf opaque, voidpf stream, uint32_t offset, int origin)
{
if (stream == nullptr)
return -1;
auto* fs = (IFileStream*)stream;
auto* fs = (FileStream*)stream;
return fs->seek(offset, origin) != -1 ? 0 : -1; // must return 0 for success or -1 for error
return fs->seek((int32_t)offset, origin); // must return 0 for success or -1 for error
}
static voidpf ZCALLBACK ZipFile_open_file_func(voidpf opaque, const void* filename, int mode)
static voidpf ZipFile_open_file_func(voidpf opaque, const char* filename, int mode)
{
IFileStream::Mode fsMode;
FileStream::Mode fsMode;
if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER) == ZLIB_FILEFUNC_MODE_READ)
fsMode = IFileStream::Mode::READ;
fsMode = FileStream::Mode::READ;
else if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
fsMode = IFileStream::Mode::APPEND;
fsMode = FileStream::Mode::APPEND;
else if (mode & ZLIB_FILEFUNC_MODE_CREATE)
fsMode = IFileStream::Mode::WRITE;
fsMode = FileStream::Mode::WRITE;
else
return nullptr;
return FileUtils::getInstance()->openFileStream((const char*)filename, fsMode).release();
return FileUtils::getInstance()->openFileStream(filename, fsMode).release();
}
static voidpf ZipFile_opendisk_file_func(voidpf opaque, voidpf stream, uint32_t number_disk, int mode)
@ -609,7 +609,8 @@ struct ZipFilePrivate
if (stream == nullptr)
return (uint32_t)-1;
return static_cast<IFileStream*>(stream)->read(buf, size);
auto* fs = (FileStream*)stream;
return fs->read(buf, size);
}
static uint32_t ZipFile_write_file_func(voidpf opaque, voidpf stream, const void* buf, uint32_t size)
@ -617,7 +618,8 @@ struct ZipFilePrivate
if (stream == nullptr)
return (uint32_t)-1;
return static_cast<IFileStream*>(stream)->write(buf, size);
auto* fs = (FileStream*)stream;
return fs->write(buf, size);
}
static int ZipFile_close_file_func(voidpf opaque, voidpf stream)
@ -625,13 +627,13 @@ struct ZipFilePrivate
if (stream == nullptr)
return -1;
auto* fs = (IFileStream*)stream;
auto* fs = (FileStream*)stream;
const auto result = fs->close(); // 0 for success, -1 for error
delete fs;
return result;
}
// THis isn't supported by IFileStream, so just check if the stream is null and open
// THis isn't supported by FileStream, so just check if the stream is null and open
static int ZipFile_error_file_func(voidpf opaque, voidpf stream)
{
if (stream == nullptr)
@ -639,7 +641,7 @@ struct ZipFilePrivate
return -1;
}
auto* fs = (IFileStream*)stream;
auto* fs = (FileStream*)stream;
if (fs->isOpen())
{
@ -653,21 +655,27 @@ struct ZipFilePrivate
std::string zipFileName;
unzFile zipFile;
std::mutex zipFileMtx;
std::unique_ptr<ourmemory_s> memfs;
// std::unordered_map is faster if available on the platform
typedef hlookup::string_map<struct ZipEntryInfo> FileListContainer;
FileListContainer fileList;
zlib_filefunc64_def functionOverrides{};
zlib_filefunc_def functionOverrides{};
};
ZipFile* ZipFile::createFromFile(std::string_view zipFile, std::string_view filter)
ZipFile* ZipFile::createWithBuffer(const void* buffer, unsigned int size)
{
auto zip = new ZipFile();
if (zip->initWithFile(zipFile, filter))
ZipFile* zip = new ZipFile();
if (zip->initWithBuffer(buffer, size))
{
return zip;
delete zip;
return nullptr;
}
else
{
delete zip;
return nullptr;
}
}
ZipFile::ZipFile() : _data(new ZipFilePrivate())
@ -675,6 +683,13 @@ ZipFile::ZipFile() : _data(new ZipFilePrivate())
_data->zipFile = nullptr;
}
ZipFile::ZipFile(std::string_view zipFile, std::string_view filter) : _data(new ZipFilePrivate())
{
_data->zipFileName = zipFile;
_data->zipFile = unzOpen2(zipFile.data(), &_data->functionOverrides);
setFilter(filter);
}
ZipFile::~ZipFile()
{
if (_data && _data->zipFile)
@ -685,13 +700,6 @@ ZipFile::~ZipFile()
AX_SAFE_DELETE(_data);
}
bool ZipFile::initWithFile(std::string_view zipFile, std::string_view filter)
{
_data->zipFileName = zipFile;
_data->zipFile = unzOpen2_64(zipFile.data(), &_data->functionOverrides);
return setFilter(filter);
}
bool ZipFile::setFilter(std::string_view filter)
{
bool ret = false;
@ -719,7 +727,10 @@ bool ZipFile::setFilter(std::string_view filter)
// cache info about filtered files only (like 'assets/')
if (filter.empty() || currentFileName.substr(0, filter.length()) == filter)
{
_data->fileList[currentFileName] = ZipEntryInfo{posInfo, (uint64_t)fileInfo.uncompressed_size, 0};
ZipEntryInfo entry;
entry.pos = posInfo;
entry.uncompressed_size = (uLong)fileInfo.uncompressed_size;
_data->fileList[currentFileName] = entry;
}
}
// next file - also get the information about it
@ -779,6 +790,45 @@ std::vector<std::string> ZipFile::listFiles(std::string_view pathname) const
return std::vector<std::string>{fileSet.begin(), fileSet.end()};
}
unsigned char* ZipFile::getFileData(std::string_view fileName, ssize_t* size)
{
unsigned char* buffer = nullptr;
if (size)
*size = 0;
do
{
AX_BREAK_IF(!_data->zipFile);
AX_BREAK_IF(fileName.empty());
auto it = _data->fileList.find(fileName);
AX_BREAK_IF(it == _data->fileList.end());
ZipEntryInfo& fileInfo = it->second;
std::unique_lock<std::mutex> lck(_data->zipFileMtx);
int nRet = unzGoToFilePos(_data->zipFile, &fileInfo.pos);
AX_BREAK_IF(UNZ_OK != nRet);
nRet = unzOpenCurrentFile(_data->zipFile);
AX_BREAK_IF(UNZ_OK != nRet);
buffer = (unsigned char*)malloc(fileInfo.uncompressed_size);
int AX_UNUSED nSize =
unzReadCurrentFile(_data->zipFile, buffer, static_cast<unsigned int>(fileInfo.uncompressed_size));
AXASSERT(nSize == 0 || nSize == (int)fileInfo.uncompressed_size, "the file size is wrong");
if (size)
{
*size = fileInfo.uncompressed_size;
}
unzCloseCurrentFile(_data->zipFile);
} while (0);
return buffer;
}
bool ZipFile::getFileData(std::string_view fileName, ResizableBuffer* buffer)
{
bool res = false;
@ -846,32 +896,59 @@ int ZipFile::getCurrentFileInfo(std::string* filename, unz_file_info_s* info)
return ret;
}
ZipEntryInfo* ZipFile::vopen(std::string_view fileName)
bool ZipFile::initWithBuffer(const void* buffer, unsigned int size)
{
auto it = _data->fileList.find(fileName);
if (it != _data->fileList.end())
return &it->second;
if (!buffer || size == 0)
return false;
return nullptr;
zlib_filefunc_def memory_file = {0};
std::unique_ptr<ourmemory_t> memfs(
new ourmemory_t{(char*)const_cast<void*>(buffer), static_cast<uint32_t>(size), 0, 0, 0});
fill_memory_filefunc(&memory_file, memfs.get());
_data->zipFile = unzOpen2(nullptr, &memory_file);
if (!_data->zipFile)
return false;
_data->memfs = std::move(memfs);
setFilter(emptyFilename);
return true;
}
int ZipFile::vread(ZipEntryInfo* entry, void* buf, unsigned int size)
bool ZipFile::zfopen(std::string_view fileName, ZipFileStream* zfs)
{
if (!zfs)
return false;
auto it = _data->fileList.find(fileName);
if (it != _data->fileList.end())
{
zfs->entry = &it->second;
zfs->offset = 0;
return true;
}
zfs->entry = nullptr;
zfs->offset = -1;
return false;
}
int ZipFile::zfread(ZipFileStream* zfs, void* buf, unsigned int size)
{
int n = 0;
do
{
AX_BREAK_IF(entry == nullptr || entry->offset >= entry->uncompressed_size);
AX_BREAK_IF(zfs == nullptr || zfs->offset >= zfs->entry->uncompressed_size);
std::unique_lock<std::mutex> lck(_data->zipFileMtx);
int nRet = unzGoToFilePos(_data->zipFile, &entry->pos);
int nRet = unzGoToFilePos(_data->zipFile, &zfs->entry->pos);
AX_BREAK_IF(UNZ_OK != nRet);
nRet = unzOpenCurrentFile(_data->zipFile);
unzSeek64(_data->zipFile, entry->offset, SEEK_SET);
unzSeek64(_data->zipFile, zfs->offset, SEEK_SET);
n = unzReadCurrentFile(_data->zipFile, buf, size);
if (n > 0)
entry->offset += n;
zfs->offset += n;
unzCloseCurrentFile(_data->zipFile);
@ -880,10 +957,10 @@ int ZipFile::vread(ZipEntryInfo* entry, void* buf, unsigned int size)
return n;
}
int64_t ZipFile::vseek(ZipEntryInfo* entry, int64_t offset, int origin)
int32_t ZipFile::zfseek(ZipFileStream* zfs, int32_t offset, int origin)
{
int64_t result = -1;
if (entry)
int32_t result = -1;
if (zfs != nullptr)
{
switch (origin)
{
@ -891,16 +968,18 @@ int64_t ZipFile::vseek(ZipEntryInfo* entry, int64_t offset, int origin)
result = offset;
break;
case SEEK_CUR:
result = entry->offset + offset;
result = zfs->offset + offset;
break;
case SEEK_END:
result = (int32_t)entry->uncompressed_size + offset;
result = (int32_t)zfs->entry->uncompressed_size + offset;
break;
default:;
}
if (result >= 0)
entry->offset = result;
{
zfs->offset = result;
}
else
result = -1;
}
@ -908,18 +987,65 @@ int64_t ZipFile::vseek(ZipEntryInfo* entry, int64_t offset, int origin)
return result;
}
void ZipFile::vclose(ZipEntryInfo* entry)
void ZipFile::zfclose(ZipFileStream* zfs)
{
if (entry != nullptr)
entry->offset = 0;
if (zfs != nullptr && zfs->entry != nullptr)
{
zfs->entry = nullptr;
zfs->offset = -1;
}
}
int64_t ZipFile::vsize(ZipEntryInfo* entry)
long long ZipFile::zfsize(ZipFileStream* zfs)
{
if (entry != nullptr)
return entry->uncompressed_size;
if (zfs != nullptr && zfs->entry != nullptr)
{
return zfs->entry->uncompressed_size;
}
return 0;
return -1;
}
unsigned char* ZipFile::getFileDataFromZip(std::string_view zipFilePath, std::string_view filename, ssize_t* size)
{
unsigned char* buffer = nullptr;
unzFile file = nullptr;
*size = 0;
do
{
AX_BREAK_IF(zipFilePath.empty());
file = unzOpen(zipFilePath.data());
AX_BREAK_IF(!file);
// minizip 1.2.0 is same with other platforms
int ret = unzLocateFile(file, filename.data(), nullptr);
AX_BREAK_IF(UNZ_OK != ret);
char filePathA[260];
unz_file_info_s fileInfo;
ret = unzGetCurrentFileInfo(file, &fileInfo, filePathA, sizeof(filePathA), nullptr, 0, nullptr, 0);
AX_BREAK_IF(UNZ_OK != ret);
ret = unzOpenCurrentFile(file);
AX_BREAK_IF(UNZ_OK != ret);
buffer = (unsigned char*)malloc(fileInfo.uncompressed_size);
int AX_UNUSED readedSize = unzReadCurrentFile(file, buffer, static_cast<unsigned>(fileInfo.uncompressed_size));
AXASSERT(readedSize == 0 || readedSize == (int)fileInfo.uncompressed_size, "the file size is wrong");
*size = fileInfo.uncompressed_size;
unzCloseCurrentFile(file);
} while (0);
if (file)
{
unzClose(file);
}
return buffer;
}
NS_AX_END

View File

@ -224,6 +224,11 @@ private:
struct ZipEntryInfo;
struct ZipFilePrivate;
struct ZipFileStream
{
ZipEntryInfo* entry;
int32_t offset;
};
/**
* Zip file - reader helper class.
*
@ -235,12 +240,18 @@ struct ZipFilePrivate;
class AX_DLL ZipFile
{
public:
static ZipFile* createFromFile(std::string_view zipFile, std::string_view filter = ""sv);
/**
* Constructor, open zip file and store file list.
*
* @param zipFile Zip file name
* @param filter The first part of file names, which should be accessible.
* For example, "assets/". Other files will be missed.
*
* @since v2.0.5
*/
ZipFile(std::string_view zipFile, std::string_view filter = std::string());
virtual ~ZipFile();
bool initWithFile(std::string_view zipFile, std::string_view filter = ""sv);
/**
* Regenerate accessible file list based on a new filter string.
*
@ -270,6 +281,17 @@ public:
*/
std::vector<std::string> listFiles(std::string_view pathname) const;
/**
* Get resource file data from a zip file.
* @param fileName File name
* @param[out] size If the file read operation succeeds, it will be the data size, otherwise 0.
* @return Upon success, a pointer to the data is returned, otherwise nullptr.
* @warning Recall: you are responsible for calling free() on any Non-nullptr pointer returned.
*
* @since v2.0.5
*/
unsigned char* getFileData(std::string_view fileName, ssize_t* size);
/**
* Get resource file data from a zip file.
* @param fileName File name
@ -281,19 +303,34 @@ public:
std::string getFirstFilename();
std::string getNextFilename();
static ZipFile* createWithBuffer(const void* buffer, unsigned int size);
/**
* zipFile Streaming support, !!!important, the file in zip must no compress level, otherwise
* stream seek doesn't work.
*/
ZipEntryInfo* vopen(std::string_view fileName);
int vread(ZipEntryInfo*, void* buf, unsigned int size);
int64_t vseek(ZipEntryInfo*, int64_t offset, int origin);
void vclose(ZipEntryInfo*);
int64_t vsize(ZipEntryInfo*);
bool zfopen(std::string_view fileName, ZipFileStream* zfs);
int zfread(ZipFileStream* zfs, void* buf, unsigned int size);
int32_t zfseek(ZipFileStream* zfs, int32_t offset, int origin);
void zfclose(ZipFileStream* zfs);
long long zfsize(ZipFileStream* zfs);
/**
* Gets resource file data from a zip file.
*
* @param[in] filename The resource file name which contains the relative path of the zip file.
* @param[out] size If the file read operation succeeds, it will be the data size, otherwise 0.
* @return Upon success, a pointer to the data is returned, otherwise nullptr.
* @warning Recall: you are responsible for calling free() on any Non-nullptr pointer returned.
*/
AX_DEPRECATED()
static unsigned char* getFileDataFromZip(std::string_view zipFilePath, std::string_view filename, ssize_t* size);
private:
/* Only used internal for createWithBuffer() */
ZipFile();
bool initWithBuffer(const void* buffer, unsigned int size);
int getCurrentFileInfo(std::string* filename, unz_file_info_s* info);
/** Internal data like zip file pointer / file list array and so on */

View File

@ -81,40 +81,10 @@ inline void split_cb(_CStr s, size_t slen, typename std::remove_pointer<_CStr>::
func(_Start, _End);
}
template <typename _CStr, typename _Fty>
inline void split_of_cb(_CStr s, size_t slen, typename std::remove_const<_CStr>::type const delims, _Fty&& func)
{
auto _Start = s; // the start of every string
auto _Ptr = s; // source string iterator
auto _End = s + slen;
auto _Delim = *delims;
while ((_Ptr = strpbrk(_Ptr, delims)))
{
if (_Ptr >= _End)
break;
if (_Start <= _Ptr)
{
func(_Start, _Ptr, _Delim);
_Delim = *_Ptr;
}
_Start = _Ptr + 1;
++_Ptr;
}
if (_Start <= _End)
func(_Start, _End, _Delim);
}
template <typename _Fn>
inline void split_cb(std::string_view s, char delim, _Fn&& func)
{
split_cb(s.data(), s.length(), delim, std::move(func));
}
template <typename _Fn>
inline void split_of_cb(std::string_view s, const char* delims, _Fn&& func)
{
split_of_cb(s.data(), s.length(), delims, std::move(func));
}
} // namespace axstd

22
core/base/posix_io.cpp Normal file
View File

@ -0,0 +1,22 @@
#include "posix_io.h"
#if defined(_WIN32)
extern "C" int _ftruncate(int fd, int64_t size)
{
auto handle = (HANDLE)_get_osfhandle(fd);
if (handle == INVALID_HANDLE_VALUE)
return -1;
LARGE_INTEGER offset;
offset.QuadPart = size;
do
{
if (!::SetFilePointerEx(handle, offset, nullptr, FILE_BEGIN))
break;
if (!::SetEndOfFile(handle))
break;
return 0;
} while (false);
errno = GetLastError();
return -1;
}
#endif

52
core/base/posix_io.h Normal file
View File

@ -0,0 +1,52 @@
#pragma once
#if defined(_WIN32)
# include <errno.h>
# include <io.h>
# include <direct.h>
#else
# include <unistd.h>
# include <errno.h>
#endif
#include <fcntl.h>
#if defined(_WIN32)
extern "C" int _ftruncate(int fd, int64_t size);
# include "ntcvt/ntcvt.hpp"
# define O_READ_FLAGS O_BINARY | O_RDONLY, S_IREAD
# define O_WRITE_FLAGS O_CREAT | O_RDWR | O_BINARY | O_TRUNC, S_IWRITE | S_IREAD
# define O_APPEND_FLAGS O_APPEND | O_CREAT | O_RDWR | O_BINARY, S_IWRITE | S_IREAD
# define O_OVERLAP_FLAGS O_CREAT | O_RDWR | O_BINARY, S_IWRITE | S_IREAD
# define posix_open_cxx(path, ...) ::_wopen(ntcvt::from_chars(path).c_str(), ##__VA_ARGS__)
# define posix_open(path, ...) ::_wopen(ntcvt::from_chars(path).c_str(), ##__VA_ARGS__)
# define posix_close ::_close
# define posix_lseek ::_lseek
# define posix_read ::_read
# define posix_write ::_write
# define posix_fd2fh(fd) reinterpret_cast<HANDLE>(_get_osfhandle(fd))
# define posix_ftruncate(fd, size) ::_ftruncate(fd, size)
# define posix_ftruncate64 posix_ftruncate
# define posix_lseek64 ::_lseeki64
#else
# define O_READ_FLAGS O_RDONLY
# define O_WRITE_FLAGS O_CREAT | O_RDWR | O_TRUNC, S_IRWXU
# define O_APPEND_FLAGS O_APPEND | O_CREAT | O_RDWR, S_IRWXU
# define O_OVERLAP_FLAGS O_CREAT | O_RDWR, S_IRWXU
# define posix_open_cxx(path, ...) ::open(path.data(), ##__VA_ARGS__)
# define posix_open ::open
# define posix_close ::close
# define posix_lseek ::lseek
# define posix_read ::read
# define posix_write ::write
# define posix_fd2fh(fd) (fd)
# define posix_ftruncate ::ftruncate
# if defined(__APPLE__)
# define posix_lseek64 ::lseek
# define posix_ftruncate64 ::ftruncate
# else
# define posix_lseek64 ::lseek64
# define posix_ftruncate64 ::ftruncate64
# endif
#endif

View File

@ -1,5 +1,6 @@
set(_AX_MATH_HEADER
math/Vec2.h
math/Mat3.h
math/Mat4.h
math/Quaternion.h
math/TransformUtils.h
@ -17,6 +18,7 @@ set(_AX_MATH_HEADER
set(_AX_MATH_SRC
math/AffineTransform.cpp
math/Vertex.cpp
math/Mat3.cpp
math/Mat4.cpp
math/MathUtil.cpp
math/Quaternion.cpp

709
core/math/Mat3.cpp Normal file
View File

@ -0,0 +1,709 @@
#include "Mat3.h"
NS_AX_MATH_BEGIN
Mat3::Mat3()
{
loadIdentity();
}
Mat3::Mat3(float m[9])
{
this->m[0] = m[0];
this->m[1] = m[1];
this->m[2] = m[2];
this->m[3] = m[3];
this->m[4] = m[4];
this->m[5] = m[5];
this->m[6] = m[6];
this->m[7] = m[7];
this->m[8] = m[8];
}
float Mat3::get(int i, int j)
{
switch (i)
{
case 0:
switch (j)
{
case 0:
return m[0];
case 1:
return m[1];
case 2:
return m[2];
}
case 1:
switch (j)
{
case 0:
return m[3];
case 1:
return m[4];
case 2:
return m[5];
}
case 2:
switch (j)
{
case 0:
return m[6];
case 1:
return m[7];
case 2:
return m[8];
}
}
return 0.0f;
// throw new JmeException("Invalid indices into matrix.");
}
ax::Vec3 Mat3::getColumn(int i)
{
ax::Vec3 store;
switch (i)
{
case 0:
store.x = m[0];
store.y = m[3];
store.z = m[6];
break;
case 1:
store.x = m[1];
store.y = m[4];
store.z = m[7];
break;
case 2:
store.x = m[2];
store.y = m[5];
store.z = m[8];
break;
default:;
// logger.warning("Invalid column index.");
// throw new JmeException("Invalid column index. " + i);
}
return store;
}
ax::Vec3 Mat3::getRow(int i)
{
ax::Vec3 store;
switch (i)
{
case 0:
store.x = m[0];
store.y = m[1];
store.z = m[2];
break;
case 1:
store.x = m[3];
store.y = m[4];
store.z = m[5];
break;
case 2:
store.x = m[6];
store.y = m[7];
store.z = m[8];
break;
default:;
// throw new JmeException("Invalid row index. " + i);
}
return store;
}
std::string Mat3::toString()
{
return "";
}
void Mat3::setColumn(int i, const ax::Vec3& column)
{
switch (i)
{
case 0:
m[0] = column.x;
m[3] = column.y;
m[6] = column.z;
break;
case 1:
m[1] = column.x;
m[4] = column.y;
m[7] = column.z;
break;
case 2:
m[2] = column.x;
m[5] = column.y;
m[8] = column.z;
break;
default:;
// logger.warning("Invalid column index.");
// throw new JmeException("Invalid column index. " + i);
}
}
void Mat3::setRow(int i, const ax::Vec3& row)
{
switch (i)
{
case 0:
m[0] = row.x;
m[1] = row.y;
m[2] = row.z;
break;
case 1:
m[3] = row.x;
m[4] = row.y;
m[5] = row.z;
break;
case 2:
m[6] = row.x;
m[7] = row.y;
m[8] = row.z;
break;
default:;
// logger.warning("Invalid row index.");
// throw new JmeException("Invalid row index. " + i);
}
}
void Mat3::set(int i, int j, float value)
{
switch (i)
{
case 0:
switch (j)
{
case 0:
m[0] = value;
return;
case 1:
m[1] = value;
return;
case 2:
m[2] = value;
return;
}
case 1:
switch (j)
{
case 0:
m[3] = value;
return;
case 1:
m[4] = value;
return;
case 2:
m[5] = value;
return;
}
case 2:
switch (j)
{
case 0:
m[6] = value;
return;
case 1:
m[7] = value;
return;
case 2:
m[8] = value;
return;
}
}
// logger.warning("Invalid matrix index.");
// throw new JmeException("Invalid indices into matrix.");
}
void Mat3::set(float matrix[3][3])
{
// if (matrix.length != 3 || matrix[0].length != 3) {
// throw new JmeException("Array must be of size 9.");
// }
m[0] = matrix[0][0];
m[1] = matrix[0][1];
m[2] = matrix[0][2];
m[3] = matrix[1][0];
m[4] = matrix[1][1];
m[5] = matrix[1][2];
m[6] = matrix[2][0];
m[7] = matrix[2][1];
m[8] = matrix[2][2];
}
void Mat3::set(const ax::Vec3& uAxis, const ax::Vec3& vAxis, const ax::Vec3& wAxis)
{
m[0] = uAxis.x;
m[3] = uAxis.y;
m[6] = uAxis.z;
m[1] = vAxis.x;
m[4] = vAxis.y;
m[7] = vAxis.z;
m[2] = wAxis.x;
m[5] = wAxis.y;
m[8] = wAxis.z;
}
void Mat3::set(float matrix[9], bool rowMajor)
{
// if (matrix.length != 9)
// throw new JmeException("Array must be of size 9.");
if (rowMajor)
{
m[0] = matrix[0];
m[1] = matrix[1];
m[2] = matrix[2];
m[3] = matrix[3];
m[4] = matrix[4];
m[5] = matrix[5];
m[6] = matrix[6];
m[7] = matrix[7];
m[8] = matrix[8];
}
else
{
m[0] = matrix[0];
m[1] = matrix[3];
m[2] = matrix[6];
m[3] = matrix[1];
m[4] = matrix[4];
m[5] = matrix[7];
m[6] = matrix[2];
m[7] = matrix[5];
m[8] = matrix[8];
}
}
void Mat3::loadIdentity()
{
m[1] = m[2] = m[3] = m[5] = m[6] = m[7] = 0;
m[0] = m[4] = m[8] = 1;
}
bool Mat3::isIdentity()
{
return (m[0] == 1 && m[1] == 0 && m[2] == 0) && (m[3] == 0 && m[4] == 1 && m[5] == 0) &&
(m[6] == 0 && m[7] == 0 && m[8] == 1);
}
void Mat3::rotateX(float angle)
{
rotateX(std::sin(angle), std::cos(angle));
}
void Mat3::rotateY(float angle)
{
rotateY(std::sin(angle), std::cos(angle));
}
void Mat3::rotateZ(float angle)
{
rotateZ(std::sin(angle), std::cos(angle));
}
void Mat3::rotateX(float s, float c)
{
Mat3 temp;
temp.createRotationX(s, c);
mult(temp);
}
void Mat3::rotateY(float s, float c)
{
Mat3 temp;
temp.createRotationY(s, c);
mult(temp);
}
void Mat3::rotateZ(float s, float c)
{
Mat3 temp;
temp.createRotationZ(s, c);
mult(temp);
}
void Mat3::createRotation(const ax::Vec3& axis, float fSin, float fCos)
{
float x = axis.x;
float y = axis.y;
float z = axis.z;
// Make sure the input axis is normalized.
float n = x * x + y * y + z * z;
if (n != 1.0f)
{
// Not normalized.
n = sqrt(n);
// Prevent divide too close to zero.
if (n > 0.000001f)
{
n = 1.0f / n;
x *= n;
y *= n;
z *= n;
}
}
float fOneMinusCos = ((float)1.0) - fCos;
float fX2 = x * x;
float fY2 = y * y;
float fZ2 = z * z;
float fXYM = x * y * fOneMinusCos;
float fXZM = x * z * fOneMinusCos;
float fYZM = y * z * fOneMinusCos;
float fXSin = x * fSin;
float fYSin = y * fSin;
float fZSin = z * fSin;
m[0] = fX2 * fOneMinusCos + fCos;
m[1] = fXYM - fZSin;
m[2] = fXZM + fYSin;
m[3] = fXYM + fZSin;
m[4] = fY2 * fOneMinusCos + fCos;
m[5] = fYZM - fXSin;
m[6] = fXZM - fYSin;
m[7] = fYZM + fXSin;
m[8] = fZ2 * fOneMinusCos + fCos;
}
void Mat3::createRotationX(float s, float c)
{
m[4] = c;
m[5] = s;
m[7] = -s;
m[8] = c;
}
void Mat3::createRotationY(float s, float c)
{
m[0] = c;
m[2] = -s;
m[6] = s;
m[8] = c;
}
void Mat3::createRotationZ(float s, float c)
{
m[0] = c;
m[1] = s;
m[3] = -s;
m[4] = c;
}
Mat3& Mat3::mult(const Mat3& mat, Mat3& product) const
{
float temp00, temp01, temp02;
float temp10, temp11, temp12;
float temp20, temp21, temp22;
temp00 = m[0] * mat.m[0] + m[1] * mat.m[3] + m[2] * mat.m[6];
temp01 = m[0] * mat.m[1] + m[1] * mat.m[4] + m[2] * mat.m[7];
temp02 = m[0] * mat.m[2] + m[1] * mat.m[5] + m[2] * mat.m[8];
temp10 = m[3] * mat.m[0] + m[4] * mat.m[3] + m[5] * mat.m[6];
temp11 = m[3] * mat.m[1] + m[4] * mat.m[4] + m[5] * mat.m[7];
temp12 = m[3] * mat.m[2] + m[4] * mat.m[5] + m[5] * mat.m[8];
temp20 = m[6] * mat.m[0] + m[7] * mat.m[3] + m[8] * mat.m[6];
temp21 = m[6] * mat.m[1] + m[7] * mat.m[4] + m[8] * mat.m[7];
temp22 = m[6] * mat.m[2] + m[7] * mat.m[5] + m[8] * mat.m[8];
product.m[0] = temp00;
product.m[1] = temp01;
product.m[2] = temp02;
product.m[3] = temp10;
product.m[4] = temp11;
product.m[5] = temp12;
product.m[6] = temp20;
product.m[7] = temp21;
product.m[8] = temp22;
return product;
}
ax::Vec3 Mat3::mult(const ax::Vec3& vec) const
{
ax::Vec3 product;
float x = vec.x;
float y = vec.y;
float z = vec.z;
product.x = m[0] * x + m[1] * y + m[2] * z;
product.y = m[3] * x + m[4] * y + m[5] * z;
product.z = m[6] * x + m[7] * y + m[8] * z;
return product;
}
Mat3& Mat3::multLocal(float scale)
{
m[0] *= scale;
m[1] *= scale;
m[2] *= scale;
m[3] *= scale;
m[4] *= scale;
m[5] *= scale;
m[6] *= scale;
m[7] *= scale;
m[8] *= scale;
return *this;
}
Mat3& Mat3::addLocal(const Mat3& mat)
{
m[0] += mat.m[0];
m[1] += mat.m[1];
m[2] += mat.m[2];
m[3] += mat.m[3];
m[4] += mat.m[4];
m[5] += mat.m[5];
m[6] += mat.m[6];
m[7] += mat.m[7];
m[8] += mat.m[8];
return *this;
}
Mat3& Mat3::transposeLocal()
{
float tmp[9];
get(tmp, false);
set(tmp, true);
return *this;
}
Mat3 Mat3::invertNew(void)
{
Mat3 store;
float det = determinant();
if (std::abs(det) <= 0)
return store.zero();
store.m[0] = m[4] * m[8] - m[5] * m[7];
store.m[1] = m[2] * m[7] - m[1] * m[8];
store.m[2] = m[1] * m[5] - m[2] * m[4];
store.m[3] = m[5] * m[6] - m[3] * m[8];
store.m[4] = m[0] * m[8] - m[2] * m[6];
store.m[5] = m[2] * m[3] - m[0] * m[5];
store.m[6] = m[3] * m[7] - m[4] * m[6];
store.m[7] = m[1] * m[6] - m[0] * m[7];
store.m[8] = m[0] * m[4] - m[1] * m[3];
store.multLocal(1 / det);
return store;
}
Mat3& Mat3::invertLocal()
{
float det = determinant();
if (std::abs(det) <= FLT_EPSILON)
return zero();
float f00 = m[4] * m[8] - m[5] * m[7];
float f01 = m[2] * m[7] - m[1] * m[8];
float f02 = m[1] * m[5] - m[2] * m[4];
float f10 = m[5] * m[6] - m[3] * m[8];
float f11 = m[0] * m[8] - m[2] * m[6];
float f12 = m[2] * m[3] - m[0] * m[5];
float f20 = m[3] * m[7] - m[4] * m[6];
float f21 = m[1] * m[6] - m[0] * m[7];
float f22 = m[0] * m[4] - m[1] * m[3];
m[0] = f00;
m[1] = f01;
m[2] = f02;
m[3] = f10;
m[4] = f11;
m[5] = f12;
m[6] = f20;
m[7] = f21;
m[8] = f22;
multLocal(1 / det);
return *this;
}
Mat3 Mat3::adjoint()
{
Mat3 store;
store.m[0] = m[4] * m[8] - m[5] * m[7];
store.m[1] = m[2] * m[7] - m[1] * m[8];
store.m[2] = m[1] * m[5] - m[2] * m[4];
store.m[3] = m[5] * m[6] - m[3] * m[8];
store.m[4] = m[0] * m[8] - m[2] * m[6];
store.m[5] = m[2] * m[3] - m[0] * m[5];
store.m[6] = m[3] * m[7] - m[4] * m[6];
store.m[7] = m[1] * m[6] - m[0] * m[7];
store.m[8] = m[0] * m[4] - m[1] * m[3];
return store;
}
float Mat3::determinant()
{
float fCo00 = m[4] * m[8] - m[5] * m[7];
float fCo10 = m[5] * m[6] - m[3] * m[8];
float fCo20 = m[3] * m[7] - m[4] * m[6];
float fDet = m[0] * fCo00 + m[1] * fCo10 + m[2] * fCo20;
return fDet;
}
Mat3& Mat3::zero()
{
m[0] = m[1] = m[2] = m[3] = m[4] = m[5] = m[6] = m[7] = m[8] = 0.0f;
return *this;
}
Mat3 Mat3::transposeNew()
{
float temp[9] = {m[0], m[3], m[6], m[1], m[4], m[7], m[2], m[5], m[8]};
return Mat3(temp);
}
bool Mat3::equals(const Mat3& o) const
{
return memcmp(&o, this, sizeof(o)) == 0;
}
void Mat3::fromStartEndVectors(ax::Vec3 start, ax::Vec3 end)
{
ax::Vec3 v;
float e, h, f;
ax::Vec3::cross(start, end, &v);
e = start.dot(end);
f = (e < 0) ? -e : e;
// if "from" and "to" vectors are nearly parallel
if (f > 1.0f - FLT_EPSILON)
{
ax::Vec3 u;
ax::Vec3 x;
float c1, c2, c3; /* coefficients for later use */
int i, j;
x.x = (start.x > 0.0) ? start.x : -start.x;
x.y = (start.y > 0.0) ? start.y : -start.y;
x.z = (start.z > 0.0) ? start.z : -start.z;
if (x.x < x.y)
{
if (x.x < x.z)
{
x.x = 1.0f;
x.y = x.z = 0.0f;
}
else
{
x.z = 1.0f;
x.x = x.y = 0.0f;
}
}
else
{
if (x.y < x.z)
{
x.y = 1.0f;
x.x = x.z = 0.0f;
}
else
{
x.z = 1.0f;
x.x = x.y = 0.0f;
}
}
u.x = x.x - start.x;
u.y = x.y - start.y;
u.z = x.z - start.z;
v.x = x.x - end.x;
v.y = x.y - end.y;
v.z = x.z - end.z;
c1 = 2.0f / u.dot(u);
c2 = 2.0f / v.dot(v);
c3 = c1 * c2 * u.dot(v);
for (i = 0; i < 3; i++)
{
for (j = 0; j < 3; j++)
{
float val = -c1 * (&u.x)[i] * (&u.x)[j] - c2 * (&v.x)[i] * (&v.x)[j] + c3 * (&v.x)[i] * (&u.x)[j];
set(i, j, val);
}
float val = get(i, i);
set(i, i, val + 1.0f);
}
}
else
{
// the most common case, unless "start"="end", or "start"=-"end"
float hvx, hvz, hvxy, hvxz, hvyz;
h = 1.0f / (1.0f + e);
hvx = h * v.x;
hvz = h * v.z;
hvxy = hvx * v.y;
hvxz = hvx * v.z;
hvyz = hvz * v.y;
set(0, 0, e + hvx * v.x);
set(0, 1, hvxy - v.z);
set(0, 2, hvxz + v.y);
set(1, 0, hvxy + v.z);
set(1, 1, e + h * v.y * v.y);
set(1, 2, hvyz - v.x);
set(2, 0, hvxz - v.y);
set(2, 1, hvyz + v.x);
set(2, 2, e + hvz * v.z);
}
}
void Mat3::scale(const ax::Vec3& scale)
{
m[0] *= scale.x;
m[3] *= scale.x;
m[6] *= scale.x;
m[1] *= scale.y;
m[4] *= scale.y;
m[7] *= scale.y;
m[2] *= scale.z;
m[5] *= scale.z;
m[8] *= scale.z;
}
bool Mat3::equalIdentity(const Mat3& mat)
{
if (std::abs(mat.m[0] - 1) > 1e-4)
return false;
if (std::abs(mat.m[4] - 1) > 1e-4)
return false;
if (std::abs(mat.m[8] - 1) > 1e-4)
return false;
if (std::abs(mat.m[1]) > 1e-4)
return false;
if (std::abs(mat.m[2]) > 1e-4)
return false;
if (std::abs(mat.m[3]) > 1e-4)
return false;
if (std::abs(mat.m[5]) > 1e-4)
return false;
if (std::abs(mat.m[6]) > 1e-4)
return false;
if (std::abs(mat.m[7]) > 1e-4)
return false;
return true;
}
NS_AX_MATH_END

View File

@ -1,73 +1,572 @@
#include "math/MathBase.h"
/**
* Mat3 defines a 3x3 matrix. Matrix data is maintained
* internally and is accessible via the get and set methods. Convenience methods
* are used for matrix operations as well as generating a matrix from a given
* set of values.
* @autohr HALX99 2016
* @author Mark Powell
* @author Joshua Slack
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#pragma once
#ifndef _CCMAT3_H_
# define _CCMAT3_H_
# include "base/Macros.h"
# include "math/Vec3.h"
# include "math/Vec4.h"
NS_AX_MATH_BEGIN
// both metal and GLSL3/ESSL3 mat3 is identical to mat3x4,
// so provide this helper struct to construct mat3 match with GPU
struct Mat3
class Mat3
{
#if AX_GLES_PROFILE != 200
enum Index
public:
float m[9];
/**
* Constructor instantiates a new Mat3 object. The initial
* values for the matrix is that of the identity matrix.
*
*/
Mat3();
/**
* constructs a matrix with the given values.
*
* @param m[0]
* 0x0 in the matrix.
* @param m[1]
* 0x1 in the matrix.
* @param m[2]
* 0x2 in the matrix.
* @param m[3]
* 1x0 in the matrix.
* @param m[4]
* 1x1 in the matrix.
* @param m[5]
* 1x2 in the matrix.
* @param m[6]
* 2x0 in the matrix.
* @param m[7]
* 2x1 in the matrix.
* @param m[8]
* 2x2 in the matrix.
*/
Mat3(float m[9]);
/**
* get retrieves a value from the matrix at the given position.
* If the position is invalid a JmeException is thrown.
*
* @param i
* the row index.(0,1,2)
* @param j
* the colum index(0,1,2)
* @return the value at (i, j).
*/
float get(int i, int j);
/**
* get(float[]) returns the matrix in row-major or column-major
* order.
*
* @param data
* The array to return the data into. This array can be 9 or 16
* floats in size. Only the upper 3x3 are assigned to in the case
* of a 16 element array.
* @param rowMajor
* True for row major storage in the array (translation in
* elements 3, 7, 11 for a 4x4), false for column major
* (translation in elements 12, 13, 14 for a 4x4).
*/
template <size_t _Length>
void get(float (&data)[_Length], bool rowMajor)
{
_M00 = 0,
_M01 = 1,
_M02 = 2,
_M10 = 4,
_M11 = 5,
_M12 = 6,
_M20 = 8,
_M21 = 9,
_M22 = 10
};
#else
enum Index
{
_M00 = 0,
_M01 = 1,
_M02 = 2,
_M10 = 3,
_M11 = 4,
_M12 = 5,
_M20 = 6,
_M21 = 7,
_M22 = 8
};
#endif
Mat3() = default;
Mat3(float m00, float m01, float m02, float m10, float m11, float m12, float m20, float m21, float m22)
{
this->set(m00, m01, m02, m10, m11, m12, m20, m21, m22);
if (_Length == 9)
{
if (rowMajor)
{
data[0] = m[0];
data[1] = m[1];
data[2] = m[2];
data[3] = m[3];
data[4] = m[4];
data[5] = m[5];
data[6] = m[6];
data[7] = m[7];
data[8] = m[8];
}
else
{
data[0] = m[0];
data[1] = m[3];
data[2] = m[6];
data[3] = m[1];
data[4] = m[4];
data[5] = m[7];
data[6] = m[2];
data[7] = m[5];
data[8] = m[8];
}
}
else if (_Length == 16)
{
if (rowMajor)
{
data[0] = m[0];
data[1] = m[1];
data[2] = m[2];
data[4] = m[3];
data[5] = m[4];
data[6] = m[5];
data[8] = m[6];
data[9] = m[7];
data[10] = m[8];
}
else
{
data[0] = m[0];
data[1] = m[3];
data[2] = m[6];
data[4] = m[1];
data[5] = m[4];
data[6] = m[7];
data[8] = m[2];
data[9] = m[5];
data[10] = m[8];
}
}
else
{
// throw new JmeException("Array size must be 9 or 16 in Mat3.get().");
}
}
void set(float m00, float m01, float m02, float m10, float m11, float m12, float m20, float m21, float m22)
/**
* getColumn returns one of three columns specified by the
* parameter. This column is returned as a ax::Vec3 object.
*
* @param i
* the column to retrieve. Must be between 0 and 2.
* @param store
* the vector object to store the result in. if null, a new one
* is created.
* @return the column specified by the index.
*/
ax::Vec3 getColumn(int i);
/**
* getRow returns one of three rows as specified by the
* parameter. This row is returned as a ax::Vec3 object.
*
* @param i
* the row to retrieve. Must be between 0 and 2.
* @param store
* the vector object to store the result in. if null, a new one
* is created.
* @return the row specified by the index.
*/
ax::Vec3 getRow(int i);
std::string toString();
/**
*
* setColumn sets a particular column of this matrix to that
* represented by the provided vector.
*
* @param i
* the column to set.
* @param column
* the data to set.
*/
void setColumn(int i, const ax::Vec3& column);
/**
*
* setRow sets a particular row of this matrix to that
* represented by the provided vector.
*
* @param i
* the row to set.
* @param row
* the data to set.
*/
void setRow(int i, const ax::Vec3& row);
/**
* set places a given value into the matrix at the given
* position. If the position is invalid a JmeException is
* thrown.
*
* @param i
* the row index.
* @param j
* the colum index.
* @param value
* the value for (i, j).
*/
void set(int i, int j, float value);
/**
*
* set sets the values of the matrix to those supplied by the
* 3x3 two dimenion array.
*
* @param matrix
* the new values of the matrix.
* @throws JmeException
* if the array is not of size 9.
*/
void set(float matrix[3][3]);
/**
* Recreate Matrix using the provided axis.
*
* @param uAxis
* ax::Vec3
* @param vAxis
* ax::Vec3
* @param wAxis
* ax::Vec3
*/
void set(const ax::Vec3& uAxis, const ax::Vec3& vAxis, const ax::Vec3& wAxis);
/**
* set sets the values of this matrix from an array of values
* assuming that the data is rowMajor order;
*
* @param matrix
* the matrix to set the value to.
*/
void set(float matrix[9]) { set(matrix, true); }
/**
* set sets the values of this matrix from an array of values;
*
* @param matrix
* the matrix to set the value to.
* @param rowMajor
* whether the incoming data is in row or column major order.
*/
void set(float matrix[9], bool rowMajor);
/**
*
* set defines the values of the matrix based on a supplied
* Quaternion. It should be noted that all previous values will
* be overridden.
*
* @param quaternion
* the quaternion to create a rotational matrix from.
*/
void set(const ax::Quaternion& quaternion)
{
m[_M00] = m00;
m[_M01] = m01;
m[_M02] = m02;
// 0 3 = 0 * 4 + 3 = 3
m[_M10] = m10;
m[_M11] = m11;
m[_M12] = m12;
// 1 3 = 1 * 4 + 3 = 7
m[_M20] = m20;
m[_M21] = m21;
m[_M22] = m22;
// 2 3 = 2 * 4 + 3 = 11
// quaternion.toRotationMatrix(this);
}
float* operator[](size_t rowIndex)
/**
* loadIdentity sets this matrix to the identity matrix. Where
* all values are zero except those along the diagonal which are one.
*
*/
void loadIdentity();
/**
*
* @return true if this matrix is identity
*/
bool isIdentity();
/**
* Creates a matrix describing a rotation around the x-axis.
*
* @param angle The angle of rotation (in radians).
* @param dst A matrix to store the result in.
*/
void rotateX(float angle);
/**
* Creates a matrix describing a rotation around the y-axis.
*
* @param angle The angle of rotation (in radians).
* @param dst A matrix to store the result in.
*/
void rotateY(float angle);
/**
* Creates a matrix describing a rotation around the z-axis.
*
* @param angle The angle of rotation (in radians).
* @param dst A matrix to store the result in.
*/
void rotateZ(float angle);
/**
* Creates a matrix describing a rotation around the x-axis.
*
* @param angle The angle of rotation (in radians).
* @param dst A matrix to store the result in.
*/
void rotateX(float s, float c);
/**
* Creates a matrix describing a rotation around the y-axis.
*
* @param angle The angle of rotation (in radians).
* @param dst A matrix to store the result in.
*/
void rotateY(float s, float c);
/**
* Creates a matrix describing a rotation around the z-axis.
*
* @param angle The angle of rotation (in radians).
* @param dst A matrix to store the result in.
*/
void rotateZ(float s, float c);
/**
* fromAngleAxis sets this matrix4f to the values specified by
* an angle and an axis of rotation. This method creates an object, so use
* fromAngleNormalAxis if your axis is already normalized.
* axisangle3D旋转矩阵
*
* @param angle
* the angle to rotate (in radians).
* @param axis
* the axis of rotation.
*/
void createRotation(const ax::Vec3& axis, float angle)
{
#if AX_GLES_PROFILE != 200
assert(rowIndex < 3);
return &m[rowIndex * 4];
#else
assert(rowIndex < 2);
return &m[rowIndex * 3];
#endif
createRotation(axis, std::sin(angle), std::cos(angle));
}
#if AX_GLES_PROFILE != 200
float m[12] = {};
#else
float m[9] = {};
#endif
/**
* fromAngleNormalAxis sets this matrix4f to the values
* specified by an angle and a normalized axis of rotation.
*
* @param angle
* the angle to rotate (in radians).
* @param axis
* the axis of rotation (already normalized).
*/
void createRotation(const ax::Vec3& axis, float fSin, float fCos);
/**
* Creates a matrix describing a rotation around the x-axis.
*
* @param angle The angle of rotation (in radians).
* @param dst A matrix to store the result in.
*/
void createRotationX(float s, float c);
/**
* Creates a matrix describing a rotation around the y-axis.
*
* @param angle The angle of rotation (in radians).
* @param dst A matrix to store the result in.
*/
void createRotationY(float s, float c);
/**
* Creates a matrix describing a rotation around the z-axis.
*
* @param angle The angle of rotation (in radians).
* @param dst A matrix to store the result in.
*/
void createRotationZ(float s, float c);
/**
* Creates a scale matrix.
*
* @param scale The amount to scale.
* @param dst A matrix to store the result in.
*/
void createScale(const ax::Vec3& scale);
/**
* Creates a scale matrix.
*
* @param xScale The amount to scale along the x-axis.
* @param yScale The amount to scale along the y-axis.
* @param zScale The amount to scale along the z-axis.
* @param dst A matrix to store the result in.
*/
void createScale(float xScale, float yScale, float zScale);
/**
* Creates a translation matrix.
*
* @param translation The translation.
* @param dst A matrix to store the result in.
*/
void createTranslation(const ax::Vec3& translation);
/**
* Creates a translation matrix.
*
* @param xTranslation The translation on the x-axis.
* @param yTranslation The translation on the y-axis.
* @param zTranslation The translation on the z-axis.
* @param dst A matrix to store the result in.
*/
void createTranslation(float xTranslation, float yTranslation, float zTranslation);
/**
* mult multiplies this matrix by a given matrix. The result
* matrix is returned as a new object.
*
* @param mat
* the matrix to multiply this matrix by.
* @param product
* the matrix to store the result in. if null, a new Mat3 is
* created. It is safe for mat and product to be the same object.
* @return a Mat3 object containing the result of this operation
*/
Mat3& mult(const Mat3& mat) { return mult(mat, *this); }
Mat3& mult(const Mat3& mat, Mat3& product) const;
/**
* Multiplies this 3x3 matrix by the 1x3 Vector vec and stores the result in
* product.
*
* @param vec
* The ax::Vec3 to multiply.
* @return The given product vector.
*/
ax::Vec3 mult(const ax::Vec3& vec) const;
Mat3& premultAlpha(float alpha) { return multLocal(alpha); }
/**
* multLocal multiplies this matrix internally by a given float
* scale factor.
*
* @param scale
* the value to scale by.
* @return this Mat3
*/
Mat3& multLocal(float scale);
/**
* add adds the values of a parameter matrix to this matrix.
*
* @param mat
* the matrix to add to this.
*/
Mat3& addLocal(const Mat3& mat);
/**
* mult multiplies this matrix by a given matrix. The result
* matrix is saved in the current matrix. If the given matrix is null,
* nothing happens. The current matrix is returned. This is equivalent to
* this*=mat
*
* @param mat
* the matrix to multiply this matrix by.
* @return This matrix, after the multiplication
*/
/*void multLocal() {
return mult(mat, this);
}*/
/**
* Transposes this matrix in place. Returns this matrix for chaining
*
* @return This matrix after transpose
*/
Mat3& transposeLocal();
/**
* Inverts this matrix and stores it in the given store.
*
* @return The store
*/
Mat3 invertNew(void);
/**
* Inverts this matrix locally.
*
* @return this
*/
Mat3& invertLocal();
/**
* Places the adjoint of this matrix in store (creates store if null.)
*
* @param store
* The matrix to store the result in. If null, a new matrix is
* created.
* @return store
*/
Mat3 adjoint();
/**
* determinant generates the determinate of this matrix.
*
* @return the determinate
*/
float determinant();
/**
* Sets all of the values in this matrix to zero.
*
* @return this matrix
*/
Mat3& zero();
/**
* transposeNew returns a transposed version of this matrix.
*
* @return The new Mat3 object.
*/
Mat3 transposeNew();
/**
* are these two matrices the same? they are is they both have the same mXX
* values.
*
* @param o
* the object to compare for equality
* @return true if they are equal
*/
bool equals(const Mat3& o) const;
/**
* A function for creating a rotation matrix that rotates a vector called
* "start" into another vector called "end".
*
* @param start
* normalized non-zero starting vector
* @param end
* normalized non-zero ending vector
* @see "Tomas M?ller, John Hughes /"Efficiently Building a Matrix to Rotate
* / One Vector to Another/" Journal of Graphics Tools, 4(4):1-4, 1999"
*/
void fromStartEndVectors(ax::Vec3 start, ax::Vec3 end);
/**
* scale scales the operation performed by this matrix on a
* per-component basis.
*
* @param scale
* The scale applied to each of the X, Y and Z output values.
*/
void scale(const ax::Vec3& scale);
static bool equalIdentity(const Mat3& mat);
};
NS_AX_MATH_END
#endif

View File

@ -41,20 +41,6 @@ NavMeshDebugDraw::NavMeshDebugDraw()
auto* program = backend::Program::getBuiltinProgram(backend::ProgramType::POSITION_COLOR);
_programState = new backend::ProgramState(program);
_locMVP = _programState->getUniformLocation("u_MVPMatrix");
// the POSITION_COLOR default vertex layout is: V3F_C4B, so we need modify it
auto vertexLayout = _programState->getMutableVertexLayout();
vertexLayout->setAttrib("a_position",
_programState->getAttributeLocation(backend::Attribute::POSITION),
backend::VertexFormat::FLOAT3,
offsetof(V3F_C4F, position),
false);
vertexLayout->setAttrib("a_color",
_programState->getAttributeLocation(backend::Attribute::COLOR),
backend::VertexFormat::FLOAT4,
offsetof(V3F_C4F, color),
false);
vertexLayout->setStride(sizeof(V3F_C4F));
}
void NavMeshDebugDraw::initCustomCommand(CustomCommand& command)
@ -210,6 +196,11 @@ void NavMeshDebugDraw::draw(Renderer* renderer)
initCustomCommand(command);
command.setBeforeCallback(AX_CALLBACK_0(NavMeshDebugDraw::onBeforeEachCommand, this, iter->depthMask));
if (iter->type == backend::PrimitiveType::LINE)
{
command.setLineWidth(iter->size);
}
command.setVertexBuffer(_vertexBuffer);
command.setPrimitiveType(iter->type);
command.setVertexDrawInfo(iter->start, iter->end - iter->start);

View File

@ -159,7 +159,7 @@ public:
}
}
// open file
_fs = FileUtils::getInstance()->openFileStream(_tempFileName, IFileStream::Mode::APPEND);
_fs = FileUtils::getInstance()->openFileStream(_tempFileName, FileStream::Mode::APPEND);
if (!_fs)
{
_errCode = DownloadTask::ERROR_OPEN_FILE_FAILED;
@ -172,7 +172,7 @@ public:
// init md5 state
_checksumFileName = _tempFileName + ".chksum";
_fsMd5 = FileUtils::getInstance()->openFileStream(_checksumFileName, IFileStream::Mode::OVERLAPPED);
_fsMd5 = FileUtils::getInstance()->openFileStream(_checksumFileName, FileStream::Mode::OVERLAPPED);
if(!_fsMd5) {
_errCode = DownloadTask::ERROR_OPEN_FILE_FAILED;
_errCodeInternal = 0;
@ -333,10 +333,10 @@ private:
std::string _tempFileName;
std::string _checksumFileName;
std::vector<unsigned char> _buf;
std::unique_ptr<IFileStream> _fs{};
std::unique_ptr<FileStream> _fs{};
// calculate md5 in downloading time support
std::unique_ptr<IFileStream> _fsMd5{}; // store md5 state realtime
std::unique_ptr<FileStream> _fsMd5{}; // store md5 state realtime
MD5state_st _md5State;
void _initInternal()
@ -1047,7 +1047,7 @@ void DownloaderCURL::_onDownloadFinished(DownloadTask& task, int checkState)
if (checkState & kCheckSumStateSucceed) // No need download
{
auto fsOrigin = pFileUtils->openFileStream(coTask._fileName, IFileStream::Mode::READ);
auto fsOrigin = pFileUtils->openFileStream(coTask._fileName, FileStream::Mode::READ);
if (fsOrigin)
{
fsOrigin->seek(0, SEEK_END);

View File

@ -104,17 +104,18 @@ elseif(APPLE)
platform/ios/InputView-ios.mm
)
if(AX_USE_GL)
if(NOT AX_USE_ANGLE)
set(_AX_PLATFORM_SPECIFIC_HEADER
${_AX_PLATFORM_SPECIFIC_HEADER}
platform/ios/ES3Renderer-ios.h
platform/ios/ES2Renderer-ios.h
platform/ios/ES2Renderer-ios.h
platform/ios/ESRenderer-ios.h
platform/ios/GL-ios.h
platform/ios/OpenGL_Internal-ios.h
)
set(_AX_PLATFORM_SPECIFIC_SRC
${_AX_PLATFORM_SPECIFIC_SRC}
platform/ios/ES3Renderer-ios.m
platform/ios/ES2Renderer-ios.m
)
endif()
endif()
@ -161,8 +162,8 @@ set(_AX_PLATFORM_HEADER
platform/PlatformMacros.h
platform/SAXParser.h
platform/StdC.h
platform/IFileStream.h
platform/FileStream.h
platform/PosixFileStream.h
)
set(_AX_PLATFORM_SRC
@ -172,4 +173,5 @@ set(_AX_PLATFORM_SRC
platform/FileUtils.cpp
platform/Image.cpp
platform/FileStream.cpp
platform/PosixFileStream.cpp
)

View File

@ -2,392 +2,6 @@
// Copyright (c) 2020 C4games Ltd
#include "platform/FileStream.h"
#if AX_TARGET_PLATFORM == AX_PLATFORM_ANDROID
# include "platform/android/FileUtils-android.h"
# include "base/ZipUtils.h"
#endif
#include <sys/stat.h>
#include <assert.h>
#if defined(_WIN32)
# include "ntcvt/ntcvt.hpp"
#else
# include <unistd.h>
# include <errno.h>
# include <fcntl.h>
# define O_READ_FLAGS O_RDONLY, 0
# define O_WRITE_FLAGS O_CREAT | O_RDWR | O_TRUNC, S_IRWXU
# define O_APPEND_FLAGS O_APPEND | O_CREAT | O_RDWR, S_IRWXU
# define O_OVERLAP_FLAGS O_CREAT | O_RDWR, S_IRWXU
# define posix_open_cxx(path, ...) ::open(path.data(), ##__VA_ARGS__)
# define posix_open ::open
# define posix_close ::close
# define posix_lseek ::lseek
# define posix_read ::read
# define posix_write ::write
# define posix_fd2fh(fd) (fd)
# define posix_ftruncate ::ftruncate
# if defined(__APPLE__)
# define posix_lseek64 ::lseek
# define posix_ftruncate64 ::ftruncate
# else
# define posix_lseek64 ::lseek64
# define posix_ftruncate64 ::ftruncate64
# endif
#endif
NS_AX_BEGIN
struct PXIoF
{
int (*read)(const PXFileHandle& fh, void*, unsigned int);
int (*write)(const PXFileHandle& fh, const void*, unsigned int);
int64_t (*seek)(const PXFileHandle& fh, int64_t, int);
int (*close)(PXFileHandle& fh);
int64_t (*size)(const PXFileHandle& fh);
int (*resize)(const PXFileHandle& fh, int64_t);
};
static int64_t axrt_lowio_seek(const PXFileHandle& fh, int64_t offst, int origin);
struct __axrt_seek_guard
{
__axrt_seek_guard(const PXFileHandle& fh)
: place(axrt_lowio_seek(fh, 0, SEEK_CUR)), end(axrt_lowio_seek(fh, 0, SEEK_END)), fhh(fh)
{}
~__axrt_seek_guard() { axrt_lowio_seek(fhh, place, SEEK_SET); }
__axrt_seek_guard(__axrt_seek_guard const&) = delete;
__axrt_seek_guard& operator=(__axrt_seek_guard const&) = delete;
const PXFileHandle& fhh;
int64_t place;
int64_t end;
};
static inline int __axrt_errno_or(int ec)
{
auto value = errno;
if (!value)
errno = value = ec;
return value;
}
#if defined(_WIN32)
# define __axrt_truncate_file(fh, size) ::SetEndOfFile(fh)
# if !defined(WINAPI_FAMILY) || WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP
# define __axrt_create_file(path, omode, smode, cflags, fflags, fattrs) \
CreateFileW(path, omode, smode, nullptr, cflags, fflags | fattrs, nullptr)
# else
static HANDLE __axrt_create_file(LPCWSTR path, DWORD omode, DWORD smode, DWORD cflags, DWORD fflags, DWORD fattrs)
{
if (!(fflags | fattrs))
return CreateFile2(path, omode, smode, cflags, nullptr);
else
{
CREATEFILE2_EXTENDED_PARAMETERS params = {0};
params.dwSize = sizeof(params);
params.dwFileFlags = fflags;
params.dwFileAttributes = fattrs;
return CreateFile2(path, omode, smode, cflags, &params);
}
}
# endif
# define _LOWIO_SH_DENYNO (FILE_SHARE_READ | FILE_SHARE_WRITE)
static bool axrt_lowio_open(std::string_view path, IFileStream::Mode mode, PXFileHandle& fh)
{
static constexpr DWORD __axrt_open_mode2options[][5] = {
// readonly
{GENERIC_READ, _LOWIO_SH_DENYNO, OPEN_EXISTING, 0, 0},
// write
{GENERIC_READ | GENERIC_WRITE, _LOWIO_SH_DENYNO, CREATE_ALWAYS, 0, FILE_ATTRIBUTE_NORMAL},
// append
{GENERIC_READ | GENERIC_WRITE, _LOWIO_SH_DENYNO, OPEN_ALWAYS, 0, FILE_ATTRIBUTE_NORMAL},
// overlap
{GENERIC_READ | GENERIC_WRITE, _LOWIO_SH_DENYNO, OPEN_ALWAYS, 0, FILE_ATTRIBUTE_NORMAL},
};
auto wFileName = ntcvt::from_chars(path);
const auto opts = __axrt_open_mode2options[(int)mode & 0b11];
fh.osfh = __axrt_create_file(wFileName.c_str(), opts[0], opts[1], opts[2], opts[3], opts[4]);
if (fh.osfh != INVALID_HANDLE_VALUE)
{
fh.append = mode == IFileStream::Mode::APPEND;
return true;
}
return false;
}
static int axrt_lowio_read(const PXFileHandle& fh, void* buf, unsigned int size)
{
DWORD dwBytesRead = 0;
if (::ReadFile(fh.osfh, buf, size, &dwBytesRead, nullptr))
return static_cast<int>(dwBytesRead);
errno = EACCES;
return -1;
}
static int axrt_lowio_write(const PXFileHandle& fh, const void* buf, unsigned int size)
{
if (fh.append)
::SetFilePointer(fh.osfh, 0, 0, FILE_END);
DWORD dwBytesWrite = 0;
if (::WriteFile(fh.osfh, buf, size, &dwBytesWrite, nullptr))
return static_cast<int>(dwBytesWrite);
errno = EACCES;
return -1;
}
static int64_t axrt_lowio_seek(const PXFileHandle& fh, int64_t offst, int origin)
{
LARGE_INTEGER seekpos, newpos;
seekpos.QuadPart = offst;
if (SetFilePointerEx(fh.osfh, seekpos, &newpos, origin))
return newpos.QuadPart;
errno = EINVAL;
return -1;
}
static int64_t axrt_lowio_size(const PXFileHandle& fh)
{
LARGE_INTEGER endpos;
return ::GetFileSizeEx(fh.osfh, &endpos) ? endpos.QuadPart : 0;
}
static int axrt_lowio_close(PXFileHandle& fh)
{
if (fh.osfh != INVALID_HANDLE_VALUE)
{
CloseHandle(fh.osfh);
fh.osfh = INVALID_HANDLE_VALUE;
}
return 0;
}
#else
# define __axrt_truncate_file(fh, size) (posix_ftruncate64(fh, size) == 0)
static bool axrt_lowio_open(std::string_view path, IFileStream::Mode mode, PXFileHandle& fh)
{
static constexpr int __axrt_open_mode2options[][3] = {
{O_READ_FLAGS},
{O_WRITE_FLAGS},
{O_APPEND_FLAGS},
{O_OVERLAP_FLAGS},
};
const auto opts = __axrt_open_mode2options[(int)mode & 0b11];
fh.osfh = posix_open_cxx(path, opts[0], opts[1]);
return fh.osfh != -1;
}
static int axrt_lowio_read(const PXFileHandle& fh, void* buf, unsigned int size)
{
return static_cast<int>(posix_read(fh.osfh, buf, size));
}
static int axrt_lowio_write(const PXFileHandle& fh, const void* buf, unsigned int size)
{
return static_cast<int>(posix_write(fh.osfh, buf, size));
}
static int64_t axrt_lowio_seek(const PXFileHandle& fh, int64_t offst, int origin)
{
return posix_lseek64(fh.osfh, offst, origin);
}
static int64_t axrt_lowio_size(const PXFileHandle& fh)
{
// Get current file position and seek to end
__axrt_seek_guard seek_guard(fh);
return seek_guard.end != -1 ? seek_guard.end : 0;
}
static int axrt_lowio_close(PXFileHandle& fh)
{
int fd = fh.osfh;
if (fd != -1)
{
fh.osfh = -1;
return posix_close(fd);
}
return 0;
}
#endif
static int axrt_lowio_resize(const PXFileHandle& fh, int64_t size)
{
// Get current file position and seek to end
__axrt_seek_guard seek_guard(fh);
if (seek_guard.place == -1 || seek_guard.end == -1)
{
// EINVAL otherwise (ex: too large of a offset)
return __axrt_errno_or(EINVAL);
}
// move pointer to new sizes
int64_t const new_end = axrt_lowio_seek(fh, size, SEEK_SET);
if (new_end == -1)
return errno;
if (!__axrt_truncate_file(fh.osfh, size))
return __axrt_errno_or(EACCES);
// Shorten the file by truncating it, ensure restore place don't grater than new file size
int64_t const extend = size - seek_guard.end;
if (extend < 0 && seek_guard.place > new_end)
seek_guard.place = new_end;
return 0;
}
static const PXIoF axrt_lowio_iof = {axrt_lowio_read, axrt_lowio_write, axrt_lowio_seek,
axrt_lowio_close, axrt_lowio_size, axrt_lowio_resize};
#if AX_TARGET_PLATFORM == AX_PLATFORM_ANDROID
static int axrt_dummy_write(const PXFileHandle& /*fh*/, const void* /*buf*/, unsigned int /*size*/)
{
return -1;
}
static int axrt_dummy_resize(const PXFileHandle& /*fh*/, int64_t /*newsize*/)
{
return -1;
}
// android AssetManager wrappers
static int axrt_asset_read(const PXFileHandle& fh, void* buf, unsigned int size)
{
return AAsset_read(fh.aasset, buf, size);
}
static int64_t axrt_asset_seek(const PXFileHandle& fh, int64_t offst, int origin)
{
return AAsset_seek(fh.aasset, offst, origin);
}
static int64_t axrt_asset_size(const PXFileHandle& fh)
{
return AAsset_getLength64(fh.aasset);
}
static int axrt_asset_close(PXFileHandle& fh)
{
if (fh.aasset != nullptr)
{
AAsset_close(fh.aasset);
fh.aasset = nullptr;
}
return 0;
}
static const PXIoF axrt_asset_iof = {axrt_asset_read, axrt_dummy_write, axrt_asset_seek,
axrt_asset_close, axrt_asset_size, axrt_dummy_resize};
// android obb
static int axrt_obb_read(const PXFileHandle& fh, void* buf, unsigned int size)
{
return FileUtilsAndroid::getObbFile()->vread(fh.zentry, buf, size);
}
static int64_t axrt_obb_seek(const PXFileHandle& fh, int64_t offset, int origin)
{
return FileUtilsAndroid::getObbFile()->vseek(fh.zentry, offset, origin);
}
static int64_t axrt_obb_size(const PXFileHandle& fh)
{
return FileUtilsAndroid::getObbFile()->vsize(fh.zentry);
}
static int axrt_obb_close(PXFileHandle& fh)
{
FileUtilsAndroid::getObbFile()->vclose(fh.zentry);
return 0;
}
static const PXIoF axrt_obb_iof = {axrt_obb_read, axrt_dummy_write, axrt_obb_seek,
axrt_obb_close, axrt_obb_size, axrt_dummy_resize};
#endif
FileStream::~FileStream()
{
internalClose();
}
bool FileStream::open(std::string_view path, IFileStream::Mode mode)
{
#if AX_TARGET_PLATFORM != AX_PLATFORM_ANDROID
if (axrt_lowio_open(path, mode, _handle))
this->_iof = &axrt_lowio_iof;
#else // Android
if (path[0] != '/')
{ // from package, always readonly
size_t position = path.find("assets/");
// "assets/" is at the beginning of the path and we don't want it
const auto relativePath = 0 == position ? path.substr(sizeof("assets/") - 1) : path;
auto obb = FileUtilsAndroid::getObbFile();
if (obb && (_handle.zentry = obb->vopen(relativePath)))
{
this->_iof = &axrt_obb_iof;
}
else
{
AAssetManager* asMgr = FileUtilsAndroid::getAssetManager();
_handle.aasset = AAssetManager_open(asMgr, relativePath.data(), AASSET_MODE_UNKNOWN);
if (_handle.aasset)
this->_iof = &axrt_asset_iof;
}
}
else
{ // otherwise, as a absolutely path
if (axrt_lowio_open(path, mode, _handle))
this->_iof = &axrt_lowio_iof;
}
#endif
return !!this->_iof;
}
osfhnd_t FileStream::nativeHandle() const
{
return _iof == &axrt_lowio_iof ? _handle.osfh : (osfhnd_t)-1;
}
int FileStream::internalClose()
{
if (_iof)
{
int ret = _iof->close(_handle);
_iof = nullptr;
return ret;
}
return 0;
}
int FileStream::close()
{
return internalClose();
}
int64_t FileStream::seek(int64_t offset, int origin) const
{
assert(_iof);
return _iof->seek(_handle, offset, origin);
}
int FileStream::read(void* buf, unsigned int size) const
{
assert(_iof);
return _iof->read(_handle, buf, size);
}
int FileStream::write(const void* buf, unsigned int size) const
{
assert(_iof);
return _iof->write(_handle, buf, size);
}
int64_t FileStream::size() const
{
assert(_iof);
return _iof->size(_handle);
}
bool FileStream::resize(int64_t size) const
{
assert(_iof);
return _iof->resize(_handle, size) == 0;
}
bool FileStream::isOpen() const
{
return !!_iof;
}
NS_AX_END

View File

@ -2,88 +2,94 @@
// Copyright (c) 2020 C4games Ltd
#pragma once
#include "platform/IFileStream.h"
#include "platform/PlatformConfig.h"
#include <string>
#include <functional>
#include "platform/PlatformConfig.h"
#include "platform/PlatformMacros.h"
#if AX_TARGET_PLATFORM == AX_PLATFORM_ANDROID
# include <android/asset_manager.h>
#endif
NS_AX_BEGIN
struct ZipEntryInfo;
union PXFileHandle
{
void* value;
#if defined(_WIN32)
struct
{
osfhnd_t osfh; // underlying OS file HANDLE
bool append; // append mode?
};
#else
osfhnd_t osfh = -1; // underlying OS file HANDLE
#endif
#if AX_TARGET_PLATFORM == AX_PLATFORM_ANDROID
AAsset* aasset;
ZipEntryInfo* zentry;
#endif
};
struct PXIoF;
class AX_DLL FileStream : public IFileStream
class AX_DLL FileStream
{
public:
FileStream() = default;
virtual ~FileStream();
virtual ~FileStream() = default;
FileStream(const FileStream& other) = delete;
FileStream(FileStream&& other) noexcept
: IFileStream(std::move(other)), _handle(std::move(other._handle)), _iof(other._iof)
enum class Mode
{
other.reset();
}
READ,
WRITE,
APPEND,
OVERLAPPED,
};
FileStream& operator=(const FileStream& other) = delete;
/**
* Open a file
* @param path file to open
* @param mode File open mode, being READ | WRITE | APPEND
* @return true if successful, false if not
*/
virtual bool open(std::string_view path, FileStream::Mode mode) = 0;
FileStream& operator=(FileStream&& other) noexcept
{
if (this == &other)
return *this;
IFileStream::operator=(std::move(other));
_handle = std::move(other._handle);
_iof = other._iof;
/**
* Close a file stream
* @return 0 if successful, -1 if not
*/
virtual int close() = 0;
other.reset();
/**
* Seek to position in a file stream
* @param offset how many bytes to move within the stream
* @param origin SEEK_SET | SEEK_CUR | SEEK_END
* @return 0 if successful, -1 if not
*/
virtual int seek(int64_t offset, int origin) = 0;
return *this;
}
/**
* Read data from file stream
* @param buf pointer to data
* @param size the amount of data to read in bytes
* @return amount of data read successfully, -1 if error
*/
virtual int read(void* buf, unsigned int size) = 0;
bool open(std::string_view path, IFileStream::Mode mode) override;
int close() override;
/**
* Write data to file stream
* @param buf pointer to data
* @param size the amount of data to write in bytes
* @return amount of data written successfully, -1 if error
*/
virtual int write(const void* buf, unsigned int size) = 0;
int64_t seek(int64_t offset, int origin) const override;
int read(void* buf, unsigned int size) const override;
int write(const void* buf, unsigned int size) const override;
int64_t size() const override;
bool resize(int64_t size) const override;
bool isOpen() const override;
/**
* Get the current position in the file stream
* @return current position, -1 if error
*/
virtual int64_t tell() = 0;
osfhnd_t nativeHandle() const override;
/**
* Get the size of the file stream
* @return stream size, -1 if error (Mode::WRITE and Mode::APPEND may return -1)
*/
virtual int64_t size() = 0;
private:
int internalClose();
void reset() { _iof = nullptr; }
/**
* Get status of file stream
* @return true if open, false if closed
*/
virtual bool isOpen() const = 0;
PXFileHandle _handle{};
const PXIoF* _iof{nullptr};
/*
* Get native handle if support
* @returns nullptr if not a local disk file
* Windows: HANDLE
* Other: file descriptor
*/
virtual void* getNativeHandle() const { return nullptr; }
virtual operator bool() const { return isOpen(); }
protected:
FileStream(){};
};
NS_AX_END

View File

@ -35,7 +35,7 @@ THE SOFTWARE.
#include "base/Macros.h"
#include "base/Director.h"
#include "platform/SAXParser.h"
#include "platform/FileStream.h"
#include "platform/PosixFileStream.h"
#ifdef MINIZIP_FROM_SYSTEM
# include <minizip/unzip.h>
@ -476,11 +476,7 @@ void FileUtils::setDelegate(FileUtils* delegate)
s_sharedFileUtils = delegate;
}
#if AX_TARGET_PLATFORM == AX_PLATFORM_WIN32 || AX_TARGET_PLATFORM == AX_PLATFORM_LINUX
std::string FileUtils::s_exeDir;
#endif
FileUtils::FileUtils() : _writablePath() {}
FileUtils::FileUtils() : _writablePath("") {}
FileUtils::~FileUtils() {}
@ -521,12 +517,12 @@ bool FileUtils::writeBinaryToFile(const void* data, size_t dataSize, std::string
auto* fileUtils = FileUtils::getInstance();
do
{
auto fileStream = fileUtils->openFileStream(fullPath, IFileStream::Mode::WRITE);
auto fileStream = fileUtils->openFileStream(fullPath, FileStream::Mode::WRITE);
// Read the file from hardware
AX_BREAK_IF(!fileStream);
bool ok = fileStream->write(data, static_cast<unsigned int>(dataSize)) == dataSize;
return ok;
fileStream->write(data, static_cast<unsigned int>(dataSize));
return true;
} while (0);
return false;
@ -587,12 +583,11 @@ FileUtils::Status FileUtils::getContents(std::string_view filename, ResizableBuf
const auto fullPath = fileUtils->fullPathForFilename(filename);
FileStream fileStream;
fileStream.open(fullPath, IFileStream::Mode::READ);
auto fileStream = fileUtils->openFileStream(fullPath, FileStream::Mode::READ);
if (!fileStream)
return Status::OpenFailed;
const auto size = fileStream.size();
const auto size = fileStream->size();
if (size < 0)
{
return Status::ObtainSizeFailed;
@ -604,7 +599,10 @@ FileUtils::Status FileUtils::getContents(std::string_view filename, ResizableBuf
}
buffer->resize((size_t)size);
const auto sizeRead = fileStream.read(buffer->buffer(), (unsigned)size);
fileStream->seek(0, SEEK_SET);
const auto sizeRead = fileStream->read(buffer->buffer(), (unsigned)size);
if (sizeRead < size)
{
buffer->resize(sizeRead);
@ -635,7 +633,8 @@ void FileUtils::writeValueVectorToFile(ValueVector vecData,
std::move(callback), std::move(vecData));
}
std::string FileUtils::getPathForFilename(std::string_view filename, std::string_view searchPath) const
std::string FileUtils::getPathForFilename(std::string_view filename,
std::string_view searchPath) const
{
auto file = filename;
std::string_view file_path = hlookup::empty_sv;
@ -655,7 +654,8 @@ std::string FileUtils::getPathForFilename(std::string_view filename, std::string
return path;
}
std::string FileUtils::getPathForDirectory(std::string_view dir, std::string_view searchPath) const
std::string FileUtils::getPathForDirectory(std::string_view dir,
std::string_view searchPath) const
{
return std::string{searchPath}.append(dir);
}
@ -1007,7 +1007,7 @@ void FileUtils::renameFile(std::string_view oldfullpath,
{
performOperationOffthread(
[oldpath = std::string{oldfullpath}, newpath = std::string{newfullpath}]() {
return FileUtils::getInstance()->renameFile(oldpath, newpath);
return FileUtils::getInstance()->renameFile(oldpath, newpath);
},
std::move(callback));
}
@ -1032,17 +1032,17 @@ void FileUtils::listFilesRecursivelyAsync(std::string_view dirPath,
auto fullPath = fullPathForDirectory(dirPath);
performOperationOffthread(
[path = std::string{fullPath}]() {
std::vector<std::string> retval;
FileUtils::getInstance()->listFilesRecursively(path, &retval);
return retval;
std::vector<std::string> retval;
FileUtils::getInstance()->listFilesRecursively(path, &retval);
return retval;
},
std::move(callback));
}
std::unique_ptr<IFileStream> FileUtils::openFileStream(std::string_view filePath, IFileStream::Mode mode)
std::unique_ptr<FileStream> FileUtils::openFileStream(std::string_view filePath, FileStream::Mode mode)
{
FileStream fs;
return fs.open(filePath, mode) ? std::make_unique<FileStream>(std::move(fs)) : nullptr;
PosixFileStream fs;
return fs.open(filePath, mode) ? std::make_unique<PosixFileStream>(std::move(fs)) : nullptr;
}
/* !!!Notes for c++fs
@ -1065,17 +1065,17 @@ std::vector<std::string> FileUtils::listFiles(std::string_view dirPath) const
{
#if (AX_TARGET_PLATFORM == AX_PLATFORM_WIN32)
/*
* Because the object memory model of std::u8string is identical to std::string
* so we use force cast to std::string without `memory alloc & copy`, the ASM code will be:
* 00F03204 lea eax,[ebp-28h]
* 00F03207 lea ecx,[edi+20h]
* 00F0320A push eax
* 008E320B call std::filesystem::path::u8string (08E1C40h)
* 008E3210 mov esi,eax
* 008E3212 mov byte ptr [ebp-4],6
*/
* Because the object memory model of std::u8string is identical to std::string
* so we use force cast to std::string without `memory alloc & copy`, the ASM code will be:
* 00F03204 lea eax,[ebp-28h]
* 00F03207 lea ecx,[edi+20h]
* 00F0320A push eax
* 008E320B call std::filesystem::path::u8string (08E1C40h)
* 008E3210 mov esi,eax
* 008E3212 mov byte ptr [ebp-4],6
*/
auto pathU8Str = entry.path().u8string();
auto& pathStr = *reinterpret_cast<std::string*>(&pathU8Str);
auto& pathStr = *reinterpret_cast<std::string*>(&pathU8Str);
std::replace(pathStr.begin(), pathStr.end(), '\\', '/');
#else
std::string pathStr = entry.path().string();
@ -1102,7 +1102,7 @@ void FileUtils::listFilesRecursively(std::string_view dirPath, std::vector<std::
if (isDir || entry.is_regular_file())
{
#if (AX_TARGET_PLATFORM == AX_PLATFORM_WIN32)
auto pathU8Str = entry.path().u8string();
auto pathU8Str = entry.path().u8string();
auto& pathStr = *reinterpret_cast<std::string*>(&pathU8Str);
std::replace(pathStr.begin(), pathStr.end(), '\\', '/');
#else

View File

@ -34,7 +34,7 @@ THE SOFTWARE.
#include <mutex>
#include <memory>
#include "platform/IFileStream.h"
#include "platform/FileStream.h"
#include "platform/PlatformMacros.h"
#include "base/Types.h"
#include "base/Value.h"
@ -374,13 +374,6 @@ public:
*/
virtual std::string getNativeWritableAbsolutePath() const = 0;
#if AX_TARGET_PLATFORM == AX_PLATFORM_WIN32 || AX_TARGET_PLATFORM == AX_PLATFORM_LINUX
/*
* Gets application executable root directory
* @Note: Only present on targets: win32 and linux
*/
static std::string& getAppRoot() { return s_exeDir; }
#endif
/**
* Sets writable path.
*/
@ -775,7 +768,7 @@ public:
* @param mode The mode to open the file in, being READ | WRITE | APPEND
* @return Returns a pointer to the file stream
*/
virtual std::unique_ptr<IFileStream> openFileStream(std::string_view filePath, IFileStream::Mode mode);
virtual std::unique_ptr<FileStream> openFileStream(std::string_view filePath, FileStream::Mode mode);
protected:
/**
@ -802,9 +795,11 @@ protected:
* @param searchPath The search path.
* @return The full path of the file. It will return an empty string if the full path of the file doesn't exist.
*/
virtual std::string getPathForFilename(std::string_view filename, std::string_view searchPath) const;
virtual std::string getPathForFilename(std::string_view filename,
std::string_view searchPath) const;
virtual std::string getPathForDirectory(std::string_view dir, std::string_view searchPath) const;
virtual std::string getPathForDirectory(std::string_view dir,
std::string_view searchPath) const;
/**
* Gets full path for the directory and the filename.
@ -867,12 +862,6 @@ protected:
*/
std::string _writablePath;
#if AX_TARGET_PLATFORM == AX_PLATFORM_WIN32 || AX_TARGET_PLATFORM == AX_PLATFORM_LINUX
/*
* The dir of executable file, only present targets: win32, linux
*/
static std::string s_exeDir;
#endif
/**
* The singleton pointer of FileUtils.
*/
@ -888,14 +877,24 @@ protected:
static void performOperationOffthread(T&& action, R&& callback, ARGS&&... args)
{
// As axmol uses c++17+, we will use std::bind to leverage move sematics to
// Visual Studio 2013 does not support using std::bind to forward template parameters into
// a lambda. To get around this, we will just copy these arguments via lambda capture
#if defined(_MSC_VER) && _MSC_VER < 1900
auto lambda = [action, callback, args...]() {
Director::getInstance()->getScheduler()->runOnAxmolThread(std::bind(callback, action(args...)));
};
#else
// As cocos2d-x uses c++11, we will use std::bind to leverage move sematics to
// move our arguments into our lambda, to potentially avoid copying.
auto lambda = std::bind(
[](const T& actionIn, const R& callbackIn, const ARGS&... argsIn) {
Director::getInstance()->getScheduler()->runOnAxmolThread(std::bind(callbackIn, actionIn(argsIn...)));
Director::getInstance()->getScheduler()->runOnAxmolThread(
std::bind(callbackIn, actionIn(argsIn...)));
},
std::forward<T>(action), std::forward<R>(callback), std::forward<ARGS>(args)...);
#endif
AsyncTaskPool::getInstance()->enqueue(
AsyncTaskPool::TaskType::TASK_IO, [](void*) {}, nullptr, std::move(lambda));
}

View File

@ -40,11 +40,11 @@ THE SOFTWARE.
#elif AX_TARGET_PLATFORM == AX_PLATFORM_LINUX
# include "platform/linux/GL-linux.h"
#elif AX_TARGET_PLATFORM == AX_PLATFORM_IOS
# if defined(AX_USE_GL)
# if AX_USE_ANGLE
# include "platform/ios/GL-ios.h"
# endif
#elif AX_TARGET_PLATFORM == AX_PLATFORM_MAC
# if defined(AX_USE_GL)
# if AX_USE_ANGLE
# include "platform/mac/GL-mac.h"
# endif
#endif
@ -81,13 +81,6 @@ THE SOFTWARE.
# if !defined(GL_RGBA32F_EXT)
# define GL_RGBA32F_EXT 0x8814
# endif
# if !defined(GL_LUMINANCE)
# define GL_LUMINANCE 0x1909
# endif
# if !defined(GL_LUMINANCE_ALPHA)
# define GL_LUMINANCE_ALPHA 0x190A
# endif
#endif
/// @endcond

View File

@ -250,8 +250,8 @@ void GLView::setViewPortInPoints(float x, float y, float w, float h)
Viewport vp;
vp.x = (int)(x * _scaleX + _viewPortRect.origin.x);
vp.y = (int)(y * _scaleY + _viewPortRect.origin.y);
vp.width = (unsigned int)(w * _scaleX);
vp.height = (unsigned int)(h * _scaleY);
vp.w = (unsigned int)(w * _scaleX);
vp.h = (unsigned int)(h * _scaleY);
Camera::setDefaultViewport(vp);
}

View File

@ -1,118 +0,0 @@
// Copyright (c) 2018-2019 HALX99
// Copyright (c) 2020 C4games Ltd
#pragma once
#include <string>
#include "platform/PlatformConfig.h"
#include "platform/PlatformMacros.h"
NS_AX_BEGIN
/**
* @addtogroup platform
* @{
*/
#if defined(_WIN32)
using osfhnd_t = void*;
#else
using osfhnd_t = int;
#endif
class AX_DLL IFileStream
{
public:
virtual ~IFileStream() = default;
enum class Mode
{
READ,
WRITE,
APPEND,
OVERLAPPED,
};
/**
* Open a file
* @param path file to open
* @param mode File open mode, being READ, WRITE, APPEND
* @return true if successful, false if not
*/
virtual bool open(std::string_view path, IFileStream::Mode mode) = 0;
/**
* Close a file stream
* @return 0 if successful, -1 if not
*/
virtual int close() = 0;
/**
* Seek to position in a file stream
* @param offset how many bytes to move within the stream
* @param origin SEEK_SET, SEEK_CUR, SEEK_END
* @return offset from file begining
*/
virtual int64_t seek(int64_t offset, int origin) const = 0;
/**
* Read data from file stream
* @param buf pointer to data
* @param size the amount of data to read in bytes
* @return amount of data read successfully, -1 if error
*/
virtual int read(void* buf, unsigned int size) const = 0;
/**
* Write data to file stream
* @param buf pointer to data
* @param size the amount of data to write in bytes
* @return amount of data written successfully, -1 if error
*/
virtual int write(const void* buf, unsigned int size) const = 0;
/**
* Get the current position in the file stream
* @return current position, -1 if error
*/
inline int64_t tell() const { return seek(0, SEEK_CUR); }
/**
* Get the size of the file stream
* @return stream size, -1 if error (Mode::WRITE and Mode::APPEND may return -1)
*/
virtual int64_t size() const = 0;
/*
* Resize file
*/
virtual bool resize(int64_t /*size*/) const
{
errno = ENOTSUP;
return false;
}
/**
* Get status of file stream
* @return true if open, false if closed
*/
virtual bool isOpen() const = 0;
/*
* Get native handle if support
* @returns -1 if not a local disk file or file not open
* Windows: HANDLE
* Other: file descriptor
*/
virtual osfhnd_t nativeHandle() const { return (osfhnd_t)-1; }
virtual operator bool() const { return isOpen(); }
protected:
IFileStream(){};
};
// end of support group
/** @} */
NS_AX_END

View File

@ -434,7 +434,7 @@ void pngWriteCallback(png_structp png_ptr, png_bytep data, size_t length)
if (png_ptr == NULL)
return;
auto fileStream = (IFileStream*)png_get_io_ptr(png_ptr);
FileStream* fileStream = (FileStream*)png_get_io_ptr(png_ptr);
const auto check = fileStream->write(data, static_cast<unsigned int>(length));
@ -1641,7 +1641,7 @@ bool Image::initWithPVRv3Data(uint8_t* data, ssize_t dataLen, bool ownData)
if (!testFormatForPvr3TCSupport(pixelFormat))
{
AXLOG(
"axmol:WARNING: Unsupported PVR Pixel Format: 0x%016llX. Re-encode it with a OpenGL pixel format "
"cocos2d: WARNING: Unsupported PVR Pixel Format: 0x%016llX. Re-encode it with a OpenGL pixel format "
"variant",
static_cast<unsigned long long>(pixelFormat));
return false;
@ -1650,7 +1650,7 @@ bool Image::initWithPVRv3Data(uint8_t* data, ssize_t dataLen, bool ownData)
if (v3_pixel_formathash.find(pixelFormat) == v3_pixel_formathash.end())
{
AXLOG(
"axmol:WARNING: Unsupported PVR Pixel Format: 0x%016llX. Re-encode it with a OpenGL pixel format "
"cocos2d: WARNING: Unsupported PVR Pixel Format: 0x%016llX. Re-encode it with a OpenGL pixel format "
"variant",
static_cast<unsigned long long>(pixelFormat));
return false;
@ -1662,7 +1662,7 @@ bool Image::initWithPVRv3Data(uint8_t* data, ssize_t dataLen, bool ownData)
if (!info.bpp)
{
AXLOG(
"axmol:WARNING: Unsupported PVR Pixel Format: 0x%016llX. Re-encode it with a OpenGL pixel format "
"cocos2d: WARNING: Unsupported PVR Pixel Format: 0x%016llX. Re-encode it with a OpenGL pixel format "
"variant",
static_cast<unsigned long long>(pixelFormat));
return false;
@ -2313,7 +2313,7 @@ bool Image::saveToFile(std::string_view filename, bool isToRGB)
if (isCompressed() || (_pixelFormat != backend::PixelFormat::RGB8 && _pixelFormat != backend::PixelFormat::RGBA8))
{
AXLOG(
"axmol:Image: saveToFile is only support for backend::PixelFormat::RGB8 or backend::PixelFormat::RGBA8 "
"cocos2d: Image: saveToFile is only support for backend::PixelFormat::RGB8 or backend::PixelFormat::RGBA8 "
"uncompressed data for now");
return false;
}
@ -2348,7 +2348,7 @@ bool Image::saveImageToPNG(std::string_view filePath, bool isToRGB)
png_infop info_ptr;
png_bytep* row_pointers;
auto outStream = FileUtils::getInstance()->openFileStream(filePath, IFileStream::Mode::WRITE);
auto outStream = FileUtils::getInstance()->openFileStream(filePath, FileStream::Mode::WRITE);
AX_BREAK_IF(nullptr == outStream);
@ -2491,6 +2491,7 @@ bool Image::saveImageToJPG(std::string_view filePath)
{
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
std::unique_ptr<FileStream> outfile; /* target file */
JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */
int row_stride; /* physical row width in image buffer */
@ -2498,7 +2499,7 @@ bool Image::saveImageToJPG(std::string_view filePath)
/* Now we can initialize the JPEG compression object. */
jpeg_create_compress(&cinfo);
auto outfile = FileUtils::getInstance()->openFileStream(filePath, IFileStream::Mode::WRITE);
outfile = FileUtils::getInstance()->openFileStream(filePath, FileStream::Mode::WRITE);
AX_BREAK_IF(nullptr == outfile);
unsigned char* outputBuffer = nullptr;
@ -2525,6 +2526,7 @@ bool Image::saveImageToJPG(std::string_view filePath)
jpeg_finish_compress(&cinfo);
jpeg_destroy_compress(&cinfo);
outfile.reset();
if (outputBuffer)
{
free(outputBuffer);
@ -2567,6 +2569,7 @@ bool Image::saveImageToJPG(std::string_view filePath)
jpeg_finish_compress(&cinfo);
outfile->write(outputBuffer, static_cast<unsigned int>(outputSize));
outfile.reset();
if (outputBuffer)
{

View File

@ -109,43 +109,63 @@ THE SOFTWARE.
#endif // AX_PLATFORM_WIN32
/*
The google/angle is library which translate native graphics API to GLES3+ APIs
The google/angle is library which translate native graphics API to GLES2+ APIs
repo: https://github.com/google/angle
windows: d3d9/d3d11/Desktop GL/Vulkan
macOS/iOS: Metal
Android: GLES/Vulkan
Linux: Desktop GL/Vulkan
*/
// 0: indicate: not use GLES
// mac/iOS/android use system builtin GL/GLES, not ANGLE
// Windows: use ANGLE GLES
#ifndef AX_GLES_PROFILE
# if defined(__ANDROID__)
# define AX_GLES_PROFILE 200
# elif (AX_TARGET_PLATFORM == AX_PLATFORM_WINRT)
# define AX_GLES_PROFILE 300
# else
# define AX_GLES_PROFILE 0
# endif
#ifndef AX_USE_ANGLE
# define AX_USE_ANGLE 0
#endif
#define AX_GLES_PROFILE_DEN 100
#if ((AX_TARGET_PLATFORM == AX_PLATFORM_ANDROID) || (AX_TARGET_PLATFORM == AX_PLATFORM_IOS) || \
(AX_TARGET_PLATFORM == AX_PLATFORM_WINRT))
#if ((AX_TARGET_PLATFORM == AX_PLATFORM_ANDROID) || (AX_TARGET_PLATFORM == AX_PLATFORM_IOS) || (AX_TARGET_PLATFORM == AX_PLATFORM_WINRT))
# define AX_PLATFORM_MOBILE
#else
# define AX_PLATFORM_PC
#endif
#if defined(__APPLE__)
# if !defined(AX_USE_GL)
#if (AX_TARGET_PLATFORM == AX_PLATFORM_MAC)
# if !AX_USE_ANGLE
# define AX_USE_METAL
# endif
#else // win32,linux,winuwp,android
# if !defined(AX_USE_GL)
# else
# define AX_USE_GL
# endif
#elif (AX_TARGET_PLATFORM == AX_PLATFORM_IOS)
# if !AX_USE_ANGLE
# define AX_USE_METAL
# else
# define AX_USE_GL
# define AX_USE_GLES
# endif
#elif (AX_TARGET_PLATFORM == AX_PLATFORM_ANDROID)
# define AX_USE_GL
# define AX_USE_GLES
#elif (AX_TARGET_PLATFORM == AX_PLATFORM_WIN32)
# define AX_USE_GL
# if AX_USE_ANGLE
# define AX_USE_GLES
# endif
#elif (AX_TARGET_PLATFORM == AX_PLATFORM_WINRT)
# define AX_USE_GL
# if !defined(AX_USE_ANGLE)
# define AX_USE_ANGLE 1
# endif
# define AX_USE_GLES
#else
# define AX_USE_GL
#endif
#if defined(AX_USE_GL)
# if !defined(__ANDROID__)
# undef AX_USE_GLAD
# define AX_USE_GLAD 1
# else
# if !defined(AX_USE_GLAD)
# define AX_USE_GLAD 0
# endif
# endif
#endif
/// @endcond

View File

@ -0,0 +1,249 @@
// Copyright (c) 2018-2019 HALX99.
// Copyright (c) 2020 C4games Ltd
#include "platform/PosixFileStream.h"
#if AX_TARGET_PLATFORM == AX_PLATFORM_ANDROID
# include "base/ZipUtils.h"
#endif
#include <sys/stat.h>
#include <assert.h>
NS_AX_BEGIN
struct PXIoF
{
int (*read)(PXFileHandle& handle, void*, unsigned int);
int64_t (*seek)(PXFileHandle& handle, int64_t, int);
int (*close)(PXFileHandle& handle);
long long (*size)(PXFileHandle& handle);
};
static int pfs_posix_open(std::string_view path, FileStream::Mode mode, PXFileHandle& handle)
{
switch (mode)
{
case FileStream::Mode::READ:
handle._fd = posix_open_cxx(path, O_READ_FLAGS);
break;
case FileStream::Mode::WRITE:
handle._fd = posix_open_cxx(path, O_WRITE_FLAGS);
break;
case FileStream::Mode::APPEND:
handle._fd = posix_open_cxx(path, O_APPEND_FLAGS);
break;
case FileStream::Mode::OVERLAPPED:
handle._fd = posix_open_cxx(path, O_OVERLAP_FLAGS);
break;
default:
handle._fd = -1;
}
return handle._fd;
}
// posix standard wrappers
static int pfs_posix_read(PXFileHandle& handle, void* buf, unsigned int size)
{
return static_cast<int>(posix_read(handle._fd, buf, size));
}
static int64_t pfs_posix_seek(PXFileHandle& handle, int64_t offst, int origin)
{
return posix_lseek64(handle._fd, offst, origin);
}
static int pfs_posix_close(PXFileHandle& handle)
{
int fd = handle._fd;
if (fd != -1)
{
handle._fd = -1;
return posix_close(fd);
}
return 0;
}
static long long pfs_posix_size(PXFileHandle& handle)
{
#if defined(_WIN32)
return _filelengthi64(handle._fd);
#else
struct stat st;
if (fstat(handle._fd, &st) == 0)
return st.st_size;
return -1;
#endif
}
static PXIoF pfs_posix_iof = {pfs_posix_read, pfs_posix_seek, pfs_posix_close, pfs_posix_size};
#if AX_TARGET_PLATFORM == AX_PLATFORM_ANDROID
// android AssetManager wrappers
static int pfs_asset_read(PXFileHandle& handle, void* buf, unsigned int size)
{
return AAsset_read(handle._asset, buf, size);
}
static int64_t pfs_asset_seek(PXFileHandle& handle, int64_t offst, int origin)
{
return AAsset_seek(handle._asset, offst, origin);
}
static int pfs_asset_close(PXFileHandle& handle)
{
if (handle._asset != nullptr)
{
AAsset_close(handle._asset);
handle._asset = nullptr;
}
return 0;
}
static long long pfs_asset_size(PXFileHandle& handle)
{
return AAsset_getLength64(handle._asset);
}
static PXIoF pfs_asset_iof = {pfs_asset_read, pfs_asset_seek, pfs_asset_close, pfs_asset_size};
// android obb
static int pfs_obb_read(PXFileHandle& handle, void* buf, unsigned int size)
{
return FileUtilsAndroid::getObbFile()->zfread(&handle._zfs, buf, size);
}
static int64_t pfs_obb_seek(PXFileHandle& handle, int64_t offset, int origin)
{
return FileUtilsAndroid::getObbFile()->zfseek(&handle._zfs, offset, origin);
}
static int pfs_obb_close(PXFileHandle& handle)
{
FileUtilsAndroid::getObbFile()->zfclose(&handle._zfs);
return 0;
}
static long long pfs_obb_size(PXFileHandle& handle)
{
return FileUtilsAndroid::getObbFile()->zfsize(&handle._zfs);
}
static PXIoF pfs_obb_iof = {pfs_obb_read, pfs_obb_seek, pfs_obb_close, pfs_obb_size};
#endif
PosixFileStream::~PosixFileStream()
{
internalClose();
}
bool PosixFileStream::open(std::string_view path, FileStream::Mode mode)
{
bool ok = false;
#if AX_TARGET_PLATFORM != AX_PLATFORM_ANDROID
ok = pfs_posix_open(path, mode, _handle) != -1;
#else // Android
if (path[0] != '/')
{ // from package, always readonly
std::string relativePath;
size_t position = path.find("assets/");
if (0 == position)
{
// "assets/" is at the beginning of the path and we don't want it
relativePath = path.substr(sizeof("assets/") - 1);
}
else
{
relativePath = path;
}
auto obb = FileUtilsAndroid::getObbFile();
ok = obb != nullptr && obb->zfopen(relativePath, &_handle._zfs);
if (ok)
{
this->_iof = &pfs_obb_iof;
}
else
{
AAssetManager* asMgr = FileUtilsAndroid::getAssetManager();
AAsset* asset = AAssetManager_open(asMgr, relativePath.c_str(), AASSET_MODE_UNKNOWN);
ok = !!asset;
if (ok)
{
_handle._asset = asset;
// setup file read/seek/close at here
this->_iof = &pfs_asset_iof;
}
}
}
else
{ // otherwise, as a absolutely path
ok = pfs_posix_open(path, mode, _handle) != -1;
}
#endif
if (ok && !_iof)
_iof = &pfs_posix_iof;
return ok;
}
void* PosixFileStream::getNativeHandle() const
{
#if AX_TARGET_PLATFORM != AX_PLATFORM_ANDROID
if (_handle._fd != -1)
return (void*)posix_fd2fh(_handle._fd);
#endif
return nullptr;
}
int PosixFileStream::internalClose()
{
if (_iof)
{
int ret = _iof->close(_handle);
reset();
return ret;
}
return 0;
}
int PosixFileStream::close()
{
return internalClose();
}
int PosixFileStream::seek(int64_t offset, int origin)
{
const auto result = _iof->seek(_handle, static_cast<int32_t>(offset),
origin); // this returns -1 for error, and resulting offset on success
return result < 0 ? -1 : 0; // return 0 for success
}
int PosixFileStream::read(void* buf, unsigned int size)
{
return _iof->read(_handle, buf, size);
}
int PosixFileStream::write(const void* buf, unsigned int size)
{
return static_cast<int>(posix_write(_handle._fd, buf, size));
}
int64_t PosixFileStream::tell()
{
return _iof->seek(_handle, 0, SEEK_CUR);
}
int64_t PosixFileStream::size()
{
return _iof->size(_handle);
}
bool PosixFileStream::isOpen() const
{
#if AX_TARGET_PLATFORM != AX_PLATFORM_ANDROID
return _handle._fd != -1;
#else
return _handle._fd != -1 && _handle._asset != nullptr;
#endif
}
void PosixFileStream::reset()
{
memset(&_handle, 0, sizeof(_handle));
_handle._fd = -1;
_iof = nullptr;
}
NS_AX_END

View File

@ -0,0 +1,91 @@
// Copyright (c) 2018-2019 HALX99
// Copyright (c) 2020 C4games Ltd
#pragma once
#include "platform/FileStream.h"
#include "platform/PlatformConfig.h"
#include "base/posix_io.h"
#include <string>
#include <functional>
#include "platform/PlatformMacros.h"
#if AX_TARGET_PLATFORM == AX_PLATFORM_ANDROID
# include "platform/android/FileUtils-android.h"
# include <jni.h>
# include <android/asset_manager.h>
# include <android/asset_manager_jni.h>
# include "base/ZipUtils.h"
#endif
NS_AX_BEGIN
struct UnzFileStream;
union PXFileHandle
{
int _fd = -1;
#if AX_TARGET_PLATFORM == AX_PLATFORM_ANDROID
AAsset* _asset;
ZipFileStream _zfs;
#endif
};
struct PXIoF;
class AX_DLL PosixFileStream : public FileStream
{
public:
PosixFileStream() = default;
virtual ~PosixFileStream();
PosixFileStream(const PosixFileStream& other) = delete;
PosixFileStream(PosixFileStream&& other) noexcept
: FileStream(std::move(other)), _handle(std::move(other._handle)), _iof(other._iof)
{
other.reset();
}
PosixFileStream& operator=(const PosixFileStream& other) = delete;
PosixFileStream& operator=(PosixFileStream&& other) noexcept
{
if (this == &other)
return *this;
FileStream::operator=(std::move(other));
_handle = std::move(other._handle);
_iof = other._iof;
other.reset();
return *this;
}
enum class Mode
{
READ,
WRITE,
APPEND,
};
bool open(std::string_view path, FileStream::Mode mode) override;
int close() override;
int seek(int64_t offset, int origin) override;
int read(void* buf, unsigned int size) override;
int write(const void* buf, unsigned int size) override;
int64_t tell() override;
int64_t size() override;
bool isOpen() const override;
void* getNativeHandle() const override;
private:
int internalClose();
void reset();
PXFileHandle _handle{};
const PXIoF* _iof{};
};
NS_AX_END

View File

@ -18,6 +18,10 @@ add_library(${target_name} STATIC
${${target_name}_src}
)
if (AX_USE_GLAD)
target_compile_definitions(${target_name} PRIVATE AX_USE_GLAD=1)
endif()
target_include_directories(${target_name}
PRIVATE ..
PRIVATE ../..

View File

@ -99,7 +99,7 @@ bool FileUtilsAndroid::init()
std::string assetsPath(getApkPath());
if (assetsPath.find("/obb/") != std::string::npos)
{
obbfile = ZipFile::createFromFile(assetsPath);
obbfile = new ZipFile(assetsPath);
}
return FileUtils::init();
@ -303,6 +303,64 @@ std::vector<std::string> FileUtilsAndroid::listFiles(std::string_view dirPath) c
return fileList;
}
FileUtils::Status FileUtilsAndroid::getContents(std::string_view filename, ResizableBuffer* buffer) const
{
static const std::string apkprefix("assets/");
if (filename.empty())
return FileUtils::Status::NotExists;
auto fullPath = fullPathForFilename(filename);
if (fullPath[0] == '/')
return FileUtils::getContents(fullPath, buffer);
std::string relativePath;
size_t position = fullPath.find(apkprefix);
if (0 == position)
{
// "assets/" is at the beginning of the path and we don't want it
relativePath += fullPath.substr(apkprefix.size());
}
else
{
relativePath = fullPath;
}
if (obbfile)
{
if (obbfile->getFileData(relativePath, buffer))
return FileUtils::Status::OK;
}
if (nullptr == assetmanager)
{
LOGD("... FileUtilsAndroid::assetmanager is nullptr");
return FileUtils::Status::NotInitialized;
}
AAsset* asset = AAssetManager_open(assetmanager, relativePath.c_str(), AASSET_MODE_UNKNOWN);
if (nullptr == asset)
{
LOGD("AAssetManager_open %s failed", relativePath.c_str());
return FileUtils::Status::OpenFailed;
}
auto size = AAsset_getLength(asset);
buffer->resize(size);
int readsize = AAsset_read(asset, buffer->buffer(), size);
AAsset_close(asset);
if (readsize < size)
{
if (readsize >= 0)
buffer->resize(readsize);
return FileUtils::Status::ReadFailed;
}
return FileUtils::Status::OK;
}
std::string FileUtilsAndroid::getWritablePath() const
{
return getNativeWritableAbsolutePath();

View File

@ -64,6 +64,8 @@ public:
/* override functions */
bool init() override;
virtual FileUtils::Status getContents(std::string_view filename, ResizableBuffer* buffer) const override;
virtual std::string getWritablePath() const override;
std::string getNativeWritableAbsolutePath() const override;
virtual bool isAbsolutePath(std::string_view strPath) const override;

View File

@ -28,56 +28,143 @@ THE SOFTWARE.
#include "platform/PlatformConfig.h"
#include "glad/gl.h"
#if AX_USE_GLAD
#undef GL_DEPTH_STENCIL
#undef GL_DEPTH24_STENCIL8
#undef GL_UNSIGNED_INT_24_8
#undef glClearDepth
#undef glMapBuffer
#undef glUnmapBuffer
#undef glBindVertexArray
#undef glDeleteVertexArrays
#undef glGenVertexArrays
#if defined(GL_VERSION_ES_CM_1_0)
# undef glIsRenderbuffer
# undef glBindRenderbuffer
# undef glDeleteRenderbuffers
# undef glGenRenderbuffers
# undef glRenderbufferStorage
# undef glIsFramebuffer
# undef glBindFramebuffer
# undef glDeleteFramebuffers
# undef glGenFramebuffers
# undef glCheckFramebufferStatus
# undef glFramebufferRenderbuffer
# undef glFramebufferTexture2D
# undef glGetFramebufferAttachmentParameteriv
# undef glGenerateMipmap
#endif
# include "glad/gl.h"
# undef GL_DEPTH_STENCIL
# undef GL_DEPTH24_STENCIL8
# undef GL_UNSIGNED_INT_24_8
# undef glClearDepth
# undef glMapBuffer
# undef glUnmapBuffer
# undef glBindVertexArray
# undef glDeleteVertexArrays
# undef glGenVertexArrays
# if defined(GL_VERSION_ES_CM_1_0)
# undef glIsRenderbuffer
# undef glBindRenderbuffer
# undef glDeleteRenderbuffers
# undef glGenRenderbuffers
# undef glRenderbufferStorage
# undef glIsFramebuffer
# undef glBindFramebuffer
# undef glDeleteFramebuffers
# undef glGenFramebuffers
# undef glCheckFramebufferStatus
# undef glFramebufferRenderbuffer
# undef glFramebufferTexture2D
# undef glGetFramebufferAttachmentParameteriv
# undef glGenerateMipmap
# endif
# define GL_DEPTH_STENCIL GL_DEPTH_STENCIL_OES
# define GL_DEPTH24_STENCIL8 GL_DEPTH24_STENCIL8_OES
# define GL_UNSIGNED_INT_24_8 GL_UNSIGNED_INT_24_8_OES
# define glClearDepth glClearDepthf
# define glMapBuffer glMapBufferOES
# define glUnmapBuffer glUnmapBufferOES
# define glBindVertexArray glBindVertexArrayOES
# define glDeleteVertexArrays glDeleteVertexArraysOES
# define glGenVertexArrays glGenVertexArraysOES
# if defined(GL_VERSION_ES_CM_1_0)
# define glIsRenderbuffer glIsRenderbufferOES
# define glBindRenderbuffer glBindRenderbufferOES
# define glDeleteRenderbuffers glDeleteRenderbuffersOES
# define glGenRenderbuffers glGenRenderbuffersOES
# define glRenderbufferStorage glRenderbufferStorageOES
# define glIsFramebuffer glIsFramebufferOES
# define glBindFramebuffer glBindFramebufferOES
# define glDeleteFramebuffers glDeleteFramebuffersOES
# define glGenFramebuffers glGenFramebuffersOES
# define glCheckFramebufferStatus glCheckFramebufferStatusOES
# define glFramebufferRenderbuffer glFramebufferRenderbufferOES
# define glFramebufferTexture2D glFramebufferTexture2DOES
# define glGetFramebufferAttachmentParameteriv glGetFramebufferAttachmentParameterivOES
# define glGenerateMipmap glGenerateMipmapOES
# endif
#else
# define glClearDepth glClearDepthf
# define glDeleteVertexArrays glDeleteVertexArraysOES
# define glGenVertexArrays glGenVertexArraysOES
# define glBindVertexArray glBindVertexArrayOES
# define glMapBuffer glMapBufferOES
# define glUnmapBuffer glUnmapBufferOES
# define GL_DEPTH24_STENCIL8 GL_DEPTH24_STENCIL8_OES
# define GL_DEPTH_STENCIL GL_DEPTH_STENCIL_OES
# define GL_UNSIGNED_INT_24_8 GL_UNSIGNED_INT_24_8_OES
# define GL_WRITE_ONLY GL_WRITE_ONLY_OES
// GL_GLEXT_PROTOTYPES isn't defined in glplatform.h on android ndk r7
// we manually define it here
# include <GLES2/gl2platform.h>
# ifndef GL_GLEXT_PROTOTYPES
# define GL_GLEXT_PROTOTYPES 1
# endif
// normal process
# include <GLES2/gl2.h>
# include <GLES2/gl2ext.h>
// gl2.h doesn't define GLchar on Android
typedef char GLchar;
// android defines GL_BGRA_EXT but not GL_BRGA
# ifndef GL_BGRA
# define GL_BGRA 0x80E1
# endif
// declare here while define in EGLView_android.cpp
extern PFNGLGENVERTEXARRAYSOESPROC glGenVertexArraysOESEXT;
extern PFNGLBINDVERTEXARRAYOESPROC glBindVertexArrayOESEXT;
extern PFNGLDELETEVERTEXARRAYSOESPROC glDeleteVertexArraysOESEXT;
# define glGenVertexArraysOES glGenVertexArraysOESEXT
# define glBindVertexArrayOES glBindVertexArrayOESEXT
# define glDeleteVertexArraysOES glDeleteVertexArraysOESEXT
/* gles3/gl */
# if !defined(GL_SRGB8)
# define GL_SRGB8 0x8C41
# endif
# if !defined(GL_SRGB8_ALPHA8)
# define GL_SRGB8_ALPHA8 0x8C43
# endif
# if !defined(GL_COMPRESSED_RGB8_ETC2)
# define GL_COMPRESSED_RGB8_ETC2 0x9274
# endif
# if !defined(GL_COMPRESSED_SRGB8_ETC2)
# define GL_COMPRESSED_SRGB8_ETC2 0x9275
# endif
# if !defined(GL_COMPRESSED_RGBA8_ETC2_EAC)
# define GL_COMPRESSED_RGBA8_ETC2_EAC 0x9278
# endif
# if !defined(GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC)
# define GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 0x9279
# endif
/* gles2/glext */
# ifndef GL_EXT_texture_compression_s3tc_srgb
# define GL_EXT_texture_compression_s3tc_srgb 1
# define GL_COMPRESSED_SRGB_S3TC_DXT1_EXT 0x8C4C
# define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT 0x8C4D
# define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT 0x8C4E
# define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT 0x8C4F
# endif /* GL_EXT_texture_compression_s3tc_srgb */
// works on device which support OpenGLES 3.0
# if !defined(GL_RG)
# define GL_RG 0x8227
# endif
# if !defined(GL_RG8)
# define GL_RG8 0x822B
# endif
#define GL_DEPTH_STENCIL GL_DEPTH_STENCIL_OES
#define GL_DEPTH24_STENCIL8 GL_DEPTH24_STENCIL8_OES
#define GL_UNSIGNED_INT_24_8 GL_UNSIGNED_INT_24_8_OES
#define glClearDepth glClearDepthf
#define glMapBuffer glMapBufferOES
#define glUnmapBuffer glUnmapBufferOES
#define glBindVertexArray glBindVertexArrayOES
#define glDeleteVertexArrays glDeleteVertexArraysOES
#define glGenVertexArrays glGenVertexArraysOES
#if defined(GL_VERSION_ES_CM_1_0)
# define glIsRenderbuffer glIsRenderbufferOES
# define glBindRenderbuffer glBindRenderbufferOES
# define glDeleteRenderbuffers glDeleteRenderbuffersOES
# define glGenRenderbuffers glGenRenderbuffersOES
# define glRenderbufferStorage glRenderbufferStorageOES
# define glIsFramebuffer glIsFramebufferOES
# define glBindFramebuffer glBindFramebufferOES
# define glDeleteFramebuffers glDeleteFramebuffersOES
# define glGenFramebuffers glGenFramebuffersOES
# define glCheckFramebufferStatus glCheckFramebufferStatusOES
# define glFramebufferRenderbuffer glFramebufferRenderbufferOES
# define glFramebufferTexture2D glFramebufferTexture2DOES
# define glGetFramebufferAttachmentParameteriv glGetFramebufferAttachmentParameterivOES
# define glGenerateMipmap glGenerateMipmapOES
#endif

View File

@ -27,24 +27,28 @@ THE SOFTWARE.
#include "base/Director.h"
#include "base/Macros.h"
#include "platform/android/jni/JniHelper.h"
#include "platform/GL.h"
#include "GL.h"
#include <stdlib.h>
#include <android/log.h>
// <EGL/egl.h> exists since android 2.3
#include <EGL/egl.h>
PFNGLGENVERTEXARRAYSOESPROC glGenVertexArraysOESEXT = 0;
PFNGLBINDVERTEXARRAYOESPROC glBindVertexArrayOESEXT = 0;
PFNGLDELETEVERTEXARRAYSOESPROC glDeleteVertexArraysOESEXT = 0;
#define DEFAULT_MARGIN_ANDROID 30.0f
#define WIDE_SCREEN_ASPECT_RATIO_ANDROID 2.0f
void initExtensions()
{
glGenVertexArraysOESEXT = (PFNGLGENVERTEXARRAYSOESPROC)eglGetProcAddress("glGenVertexArraysOES");
glBindVertexArrayOESEXT = (PFNGLBINDVERTEXARRAYOESPROC)eglGetProcAddress("glBindVertexArrayOES");
glDeleteVertexArraysOESEXT = (PFNGLDELETEVERTEXARRAYSOESPROC)eglGetProcAddress("glDeleteVertexArraysOES");
}
NS_AX_BEGIN
void GLViewImpl::loadGLES2()
{
auto glesVer = gladLoaderLoadGLES2();
if (glesVer)
ax::print("Load GLES success, version: %d", glesVer);
else
throw std::runtime_error("Load GLES fail");
}
GLViewImpl* GLViewImpl::createWithRect(std::string_view viewName, const Rect& rect, float frameZoomFactor, bool resizable)
{
@ -84,6 +88,7 @@ GLViewImpl* GLViewImpl::createWithFullScreen(std::string_view viewName)
GLViewImpl::GLViewImpl()
{
initExtensions();
}
GLViewImpl::~GLViewImpl() {}

View File

@ -35,7 +35,6 @@ class AX_DLL GLViewImpl : public GLView
{
public:
// static function
static void loadGLES2();
static GLViewImpl* create(std::string_view viewname);
static GLViewImpl* createWithRect(std::string_view viewName, const Rect& rect, float frameZoomFactor = 1.0f, bool resizable = false);
static GLViewImpl* createWithFullScreen(std::string_view viewName);

Some files were not shown because too many files have changed in this diff Show More