mirror of https://github.com/axmolengine/axmol.git
Improve axmol site build
This commit is contained in:
parent
b50c629307
commit
12bb1eb62a
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
|
@ -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()
|
|
@ -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()
|
|
@ -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
|
|
@ -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()
|
|
@ -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)
|
|
@ -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)
|
|
@ -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)
|
|
@ -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());
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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++;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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; }
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 =
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
152
core/3d/Mesh.cpp
152
core/3d/Mesh.cpp
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include "platform/IFileStream.h"
|
||||
#include "platform/FileStream.h"
|
||||
|
||||
NS_AX_BEGIN
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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{};
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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}
|
||||
)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -1028,7 +1028,7 @@ void Director::reset()
|
|||
AsyncTaskPool::destroyInstance();
|
||||
backend::ProgramManager::destroyInstance();
|
||||
|
||||
// axmol specific data structures
|
||||
// cocos2d-x specific data structures
|
||||
UserDefault::destroyInstance();
|
||||
resetMatrixStack();
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
619
core/math/Mat3.h
619
core/math/Mat3.h
|
@ -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.
|
||||
* 绕轴axis(非单位向量)旋转angle(弧度)角的3D旋转矩阵
|
||||
*
|
||||
* @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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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, ¶ms);
|
||||
}
|
||||
}
|
||||
# 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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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 ../..
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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() {}
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue