[deploy] Merge pull request #47 from KiwanoEngine/dev

Remove tinyxml2 & add pugixml
This commit is contained in:
Haibo 2020-01-28 16:10:31 +08:00 committed by GitHub
commit 3da3cc6022
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
257 changed files with 44812 additions and 35550 deletions

108
.clang-format Normal file
View File

@ -0,0 +1,108 @@
# Clang-format version v9.0.0
---
Language: Cpp
BasedOnStyle: Google
ColumnLimit: 120
##
## Indent Style
##
IndentWidth: 4
AccessModifierOffset: -4
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
TabWidth: 4
UseTab: Never
IndentCaseLabels: false
NamespaceIndentation: None
##
## Align Style
##
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: true
AlignConsecutiveDeclarations: true
AlignEscapedNewlinesLeft: true
AlignOperands: true
AlignTrailingComments: true
PointerAlignment: Left
##
## SingleLine Style
##
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: Empty
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: true
BinPackArguments: true
BinPackParameters: true
BreakBeforeBraces: Allman
BraceWrapping:
AfterClass: true
AfterControlStatement: true
AfterEnum: true
AfterFunction: true
AfterNamespace: true
AfterObjCDeclaration: true
AfterStruct: true
AfterUnion: true
BeforeCatch: true
BeforeElse: true
IndentBraces: true
BreakBeforeBinaryOperators: NonAssignment
BreakBeforeTernaryOperators: true
CommentPragmas: "^ IWYU pragma:"
ConstructorInitializerAllOnOneLineOrOnePerLine: false
##
## Others
##
BreakConstructorInitializers: BeforeComma
BreakInheritanceList: BeforeComma
ReflowComments: true
SortIncludes: false
Cpp11BracedListStyle: false
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
ForEachMacros: [foreach, Q_FOREACH, BOOST_FOREACH]
IncludeCategories:
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
Priority: 2
- Regex: '^(<|"(gtest|isl|json)/)'
Priority: 3
- Regex: ".*"
Priority: 1
IndentWrappedFunctionNames: false
KeepEmptyLinesAtTheStartOfBlocks: true
MacroBlockBegin: ""
MacroBlockEnd: ""
MaxEmptyLinesToKeep: 1
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
SpaceAfterCStyleCast: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 2
SpacesInAngles: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Cpp11

View File

@ -14,10 +14,10 @@ insert_final_newline = true
charset = gb2312 charset = gb2312
# 4 space indentation # 4 space indentation
indent_style = tab indent_style = space
indent_size = 4 indent_size = 4
# Matches the exact files # Matches the exact files
[*.{json,xml}] [*.{json,xml}]
indent_style = space indent_style = space
indent_size = 2 indent_size = 2

66
README-zh.md Normal file
View File

@ -0,0 +1,66 @@
![Kiwano Logo](https://github.com/Nomango/Kiwano/raw/master/logo/logo_text_h.png)
# Kiwano 游戏引擎
[![Build status](https://ci.appveyor.com/api/projects/status/frqh09om9ldaklr9/branch/master?svg=true)](https://ci.appveyor.com/project/Nomango/kiwano/branch/master)
[![GitHub release](https://img.shields.io/github/release/nomango/kiwano)](https://github.com/Nomango/Kiwano/releases/latest)
[![GitHub license](https://img.shields.io/github/license/nomango/kiwano)](https://github.com/Nomango/Kiwano/blob/master/LICENSE)
[English](./README.md) | 简体中文
## 介绍
Kiwano 是一个使用 C++ 开发的 2D 游戏引擎,目前仅支持 Windows 平台。
Kiwano-Core 是一个提供了一系列实用工具的游戏无关库,它的目的是简化 C++ 开发过程。
这个仓库仍处于开发过程中,我创建这个仓库用来学习游戏引擎知识和开发自己的小游戏。
你可以到 [Kiwano Demos](https://github.com/kiwanogame/KiwanoDemos) 仓库查看和学习如何使用 Kiwano 引擎实现小游戏。
欢迎您任何形式的贡献。
## 功能
* 舞台和角色管理
* 舞台过渡动画
* 动作行为
* 按钮等简易UI元素
* 音频支持
* 网络通信支持
* 数据持久化
* 物理引擎 (基于 Box2D)
* GUI 引擎 (基于 ImGui)
## 安装
### 开发环境
- Win8 或更高 (推荐 Win10)
- Visual Studio 2015 或更高
### 通过 NuGet 安装
1. 打开你的 Visual Studio 解决方案
2. 在解决方案资源管理器, 右击 `引用` 并选择 `管理 NuGet 程序包`
3. 选择 `浏览` 选项卡, 搜索 `kiwano`, 选中列表中的包然后点击 `安装`
4. 开始使用 Kiwano 进行开发吧!
### 通过源代码安装
1. 从 Github 仓库克隆或下载源代码
2. 打开你的 Visual Studio 解决方案, 在解决方案资源管理器中右键你的解决方案, 选择 `添加` => `现有项`
3. 选中源代码目录下 /projects 文件夹中所有的 `.vcxproj` 文件,并确认添加
4. 右键你的项目,打开 `属性`, 选中 C\C++ => 常规, 并将源代码文件夹下的 src 目录添加到 `附加包含目录`
5. 右键你的项目 `引用` 并选择 `添加引用`, 选中 `kiwano` 项目和其他你需要的项目
6. 开始使用 Kiwano 进行开发吧!
## 开发计划
* 跨平台支持
* 粒子系统
## 社交媒体
* 网站: [kiwanoengine.com](https://kiwanoengine.com)
* QQ群: 608406540

View File

@ -6,6 +6,8 @@
[![GitHub release](https://img.shields.io/github/release/nomango/kiwano)](https://github.com/Nomango/Kiwano/releases/latest) [![GitHub release](https://img.shields.io/github/release/nomango/kiwano)](https://github.com/Nomango/Kiwano/releases/latest)
[![GitHub license](https://img.shields.io/github/license/nomango/kiwano)](https://github.com/Nomango/Kiwano/blob/master/LICENSE) [![GitHub license](https://img.shields.io/github/license/nomango/kiwano)](https://github.com/Nomango/Kiwano/blob/master/LICENSE)
English | [简体中文](./README-zh.md)
## Introduction ## Introduction
Kiwano is a open-source 2D C++ game engine, only support win32 platform. Kiwano is a open-source 2D C++ game engine, only support win32 platform.
@ -20,12 +22,13 @@ More docs and examples will be added later.
## Features ## Features
* Scene management * Scene management
* Transitions between scenes * Transitions between scenes
* Actions behaviours * Action behaviours
* Buttons and menus * Buttons and menus
* Texture atlas support * Texture atlas support
* Audio support * Audio support
* Custom data storage * Custom data storage
* Direct2D based * Physical engine (based on Box2D)
* GUI system (based on ImGui)
## Install ## Install
@ -51,8 +54,7 @@ More docs and examples will be added later.
6. Now you can build your own applications based on Kiwano source code ! 6. Now you can build your own applications based on Kiwano source code !
## Next plan ## Next plan
* GUI system * Cross-platform
* Physical engine
* Particle system * Particle system
## Contact ## Contact

View File

@ -19,7 +19,6 @@ pull_requests:
environment: environment:
global: global:
time_out_mins: 5 time_out_mins: 5
job_to_deploy: 6 # 3(images) * 1(platform) * 2(configuration)
flag_to_deploy: false flag_to_deploy: false
appveyor_api_token: appveyor_api_token:
secure: UJFCbRNHMOqQg3e3Kv/ZnaIqqwXAt+5HDldetaZsZ5E= secure: UJFCbRNHMOqQg3e3Kv/ZnaIqqwXAt+5HDldetaZsZ5E=
@ -46,13 +45,12 @@ for:
only: only:
- master - master
environment: environment:
matrix: matrix:
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
VS_PLATFORM_TOOLSET: v142
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
VS_PLATFORM_TOOLSET: v141
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
VS_PLATFORM_TOOLSET: v140 global:
job_to_deploy: 6 # 3(images) * 1(platform) * 2(configuration)
- -
branches: branches:
except: except:
@ -62,7 +60,8 @@ for:
environment: environment:
matrix: matrix:
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
VS_PLATFORM_TOOLSET: v142 global:
job_to_deploy: 2 # 1(images) * 1(platform) * 2(configuration)
configuration: configuration:
- Debug - Debug
@ -90,9 +89,9 @@ after_build:
artifacts: artifacts:
- path: projects/output/**/*.lib - path: projects/output/**/*.lib
name: $(appveyor_project_name)-v$(appveyor_build_version)-$(VS_PLATFORM_TOOLSET).$(platform).$(configuration) name: PublishedLibraries
- path: projects/output/**/*.pdb - path: projects/output/**/*.pdb
name: $(appveyor_project_name)-v$(appveyor_build_version)-$(VS_PLATFORM_TOOLSET).$(platform).$(configuration) name: PublishedSymbols
before_deploy: before_deploy:
- ps: .\scripts\appveyor\coapp_make.ps1 - ps: .\scripts\appveyor\coapp_make.ps1
@ -100,9 +99,9 @@ before_deploy:
deploy: deploy:
- provider: GitHub - provider: GitHub
repository: KiwanoEngine/Kiwano repository: KiwanoEngine/Kiwano
tag: v$(appveyor_build_version) tag: v$(APPVEYOR_BUILD_VERSION)
release: v$(appveyor_build_version) release: v$(APPVEYOR_BUILD_VERSION)
description: Kiwano-v$(appveyor_build_version) releases. description: Kiwano-v$(APPVEYOR_BUILD_VERSION) releases.
auth_token: auth_token:
secure: pDsK6i03d4qRjtrNXcbhLpAquso/muJWgDSWJHnxP7b6p54kXEvptB67J+1kJOhq secure: pDsK6i03d4qRjtrNXcbhLpAquso/muJWgDSWJHnxP7b6p54kXEvptB67J+1kJOhq
artifact: /.*\.nupkg/ artifact: /.*\.nupkg/

View File

@ -33,7 +33,6 @@
<ClInclude Include="..\..\..\src\3rd-party\curl\typecheck-gcc.h"> <ClInclude Include="..\..\..\src\3rd-party\curl\typecheck-gcc.h">
<Filter>include</Filter> <Filter>include</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\..\src\3rd-party\curl\tinyxml2.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Library Include="..\..\..\src\3rd-party\curl\libs\libcurl.lib"> <Library Include="..\..\..\src\3rd-party\curl\libs\libcurl.lib">

View File

@ -1,97 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClInclude Include="..\..\..\src\3rd-party\tinyxml2\tinyxml2.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\..\src\3rd-party\tinyxml2\tinyxml2.cpp" />
</ItemGroup>
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{AB47E875-85E5-4105-A71E-88930EAAB910}</ProjectGuid>
<RootNamespace>libtinyxml2</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>false</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<OutDir>$(SolutionDir)\output\$(PlatformToolset)\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)\build\$(PlatformToolset)\$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>$(SolutionDir)\output\$(PlatformToolset)\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)\build\$(PlatformToolset)\$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<TreatWarningAsError>true</TreatWarningAsError>
<DebugInformationFormat>None</DebugInformationFormat>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<AdditionalIncludeDirectories>../../../src/3rd-party;</AdditionalIncludeDirectories>
<MinimalRebuild>false</MinimalRebuild>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<BufferSecurityCheck>false</BufferSecurityCheck>
<TreatWarningAsError>true</TreatWarningAsError>
<DebugInformationFormat>None</DebugInformationFormat>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<AdditionalIncludeDirectories>../../../src/3rd-party;</AdditionalIncludeDirectories>
<MinimalRebuild>false</MinimalRebuild>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>false</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -1,9 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="..\..\..\src\3rd-party\tinyxml2\tinyxml2.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\..\src\3rd-party\tinyxml2\tinyxml2.h" />
</ItemGroup>
</Project>

View File

@ -14,8 +14,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "kiwano-physics", "kiwano-ph
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "3rd-party", "3rd-party", "{2D8919F2-8922-4B3F-8F68-D4127C6BCBB7}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "3rd-party", "3rd-party", "{2D8919F2-8922-4B3F-8F68-D4127C6BCBB7}"
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libtinyxml2", "3rd-party\tinyxml2\libtinyxml2.vcxproj", "{AB47E875-85E5-4105-A71E-88930EAAB910}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libimgui", "3rd-party\imgui\libimgui.vcxproj", "{7FA1E56D-62AC-47D1-97D1-40B302724198}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libimgui", "3rd-party\imgui\libimgui.vcxproj", "{7FA1E56D-62AC-47D1-97D1-40B302724198}"
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libcurl", "3rd-party\curl\libcurl.vcxproj", "{A9ABACC7-75A1-46BA-8E48-4105346D9719}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libcurl", "3rd-party\curl\libcurl.vcxproj", "{A9ABACC7-75A1-46BA-8E48-4105346D9719}"
@ -49,10 +47,6 @@ Global
{DF599AFB-744F-41E5-AF0C-2146F90575C8}.Debug|Win32.Build.0 = Debug|Win32 {DF599AFB-744F-41E5-AF0C-2146F90575C8}.Debug|Win32.Build.0 = Debug|Win32
{DF599AFB-744F-41E5-AF0C-2146F90575C8}.Release|Win32.ActiveCfg = Release|Win32 {DF599AFB-744F-41E5-AF0C-2146F90575C8}.Release|Win32.ActiveCfg = Release|Win32
{DF599AFB-744F-41E5-AF0C-2146F90575C8}.Release|Win32.Build.0 = Release|Win32 {DF599AFB-744F-41E5-AF0C-2146F90575C8}.Release|Win32.Build.0 = Release|Win32
{AB47E875-85E5-4105-A71E-88930EAAB910}.Debug|Win32.ActiveCfg = Debug|Win32
{AB47E875-85E5-4105-A71E-88930EAAB910}.Debug|Win32.Build.0 = Debug|Win32
{AB47E875-85E5-4105-A71E-88930EAAB910}.Release|Win32.ActiveCfg = Release|Win32
{AB47E875-85E5-4105-A71E-88930EAAB910}.Release|Win32.Build.0 = Release|Win32
{7FA1E56D-62AC-47D1-97D1-40B302724198}.Debug|Win32.ActiveCfg = Debug|Win32 {7FA1E56D-62AC-47D1-97D1-40B302724198}.Debug|Win32.ActiveCfg = Debug|Win32
{7FA1E56D-62AC-47D1-97D1-40B302724198}.Debug|Win32.Build.0 = Debug|Win32 {7FA1E56D-62AC-47D1-97D1-40B302724198}.Debug|Win32.Build.0 = Debug|Win32
{7FA1E56D-62AC-47D1-97D1-40B302724198}.Release|Win32.ActiveCfg = Release|Win32 {7FA1E56D-62AC-47D1-97D1-40B302724198}.Release|Win32.ActiveCfg = Release|Win32
@ -70,7 +64,6 @@ Global
HideSolutionNode = FALSE HideSolutionNode = FALSE
EndGlobalSection EndGlobalSection
GlobalSection(NestedProjects) = preSolution GlobalSection(NestedProjects) = preSolution
{AB47E875-85E5-4105-A71E-88930EAAB910} = {2D8919F2-8922-4B3F-8F68-D4127C6BCBB7}
{7FA1E56D-62AC-47D1-97D1-40B302724198} = {2D8919F2-8922-4B3F-8F68-D4127C6BCBB7} {7FA1E56D-62AC-47D1-97D1-40B302724198} = {2D8919F2-8922-4B3F-8F68-D4127C6BCBB7}
{A9ABACC7-75A1-46BA-8E48-4105346D9719} = {2D8919F2-8922-4B3F-8F68-D4127C6BCBB7} {A9ABACC7-75A1-46BA-8E48-4105346D9719} = {2D8919F2-8922-4B3F-8F68-D4127C6BCBB7}
{0CBA9295-F14D-4966-A7C4-1DD68158176C} = {2D8919F2-8922-4B3F-8F68-D4127C6BCBB7} {0CBA9295-F14D-4966-A7C4-1DD68158176C} = {2D8919F2-8922-4B3F-8F68-D4127C6BCBB7}

View File

@ -9,15 +9,20 @@
<ClInclude Include="..\..\src\kiwano\2d\action\ActionWalk.h" /> <ClInclude Include="..\..\src\kiwano\2d\action\ActionWalk.h" />
<ClInclude Include="..\..\src\kiwano\2d\action\ActionTween.h" /> <ClInclude Include="..\..\src\kiwano\2d\action\ActionTween.h" />
<ClInclude Include="..\..\src\kiwano\2d\action\Animation.h" /> <ClInclude Include="..\..\src\kiwano\2d\action\Animation.h" />
<ClInclude Include="..\..\src\kiwano\2d\Button.h" />
<ClInclude Include="..\..\src\kiwano\2d\Frame.h" /> <ClInclude Include="..\..\src\kiwano\2d\Frame.h" />
<ClInclude Include="..\..\src\kiwano\2d\GifSprite.h" /> <ClInclude Include="..\..\src\kiwano\2d\GifSprite.h" />
<ClInclude Include="..\..\src\kiwano\core\common.h" /> <ClInclude Include="..\..\src\kiwano\core\Common.h" />
<ClInclude Include="..\..\src\kiwano\core\Director.h" />
<ClInclude Include="..\..\src\kiwano\core\event\Event.h" /> <ClInclude Include="..\..\src\kiwano\core\event\Event.h" />
<ClInclude Include="..\..\src\kiwano\core\event\EventType.h" /> <ClInclude Include="..\..\src\kiwano\core\event\EventType.h" />
<ClInclude Include="..\..\src\kiwano\core\event\KeyEvent.h" /> <ClInclude Include="..\..\src\kiwano\core\event\KeyEvent.h" />
<ClInclude Include="..\..\src\kiwano\core\event\MouseEvent.h" /> <ClInclude Include="..\..\src\kiwano\core\event\MouseEvent.h" />
<ClInclude Include="..\..\src\kiwano\core\event\WindowEvent.h" /> <ClInclude Include="..\..\src\kiwano\core\event\WindowEvent.h" />
<ClInclude Include="..\..\src\kiwano\core\Keys.h" />
<ClInclude Include="..\..\src\kiwano\core\Library.h" /> <ClInclude Include="..\..\src\kiwano\core\Library.h" />
<ClInclude Include="..\..\src\kiwano\core\Singleton.h" />
<ClInclude Include="..\..\src\kiwano\core\Time.h" />
<ClInclude Include="..\..\src\kiwano\kiwano.h" /> <ClInclude Include="..\..\src\kiwano\kiwano.h" />
<ClInclude Include="..\..\src\kiwano\config.h" /> <ClInclude Include="..\..\src\kiwano\config.h" />
<ClInclude Include="..\..\src\kiwano\macros.h" /> <ClInclude Include="..\..\src\kiwano\macros.h" />
@ -36,7 +41,6 @@
<ClInclude Include="..\..\src\kiwano\core\Component.h" /> <ClInclude Include="..\..\src\kiwano\core\Component.h" />
<ClInclude Include="..\..\src\kiwano\core\EventDispatcher.h" /> <ClInclude Include="..\..\src\kiwano\core\EventDispatcher.h" />
<ClInclude Include="..\..\src\kiwano\core\EventListener.h" /> <ClInclude Include="..\..\src\kiwano\core\EventListener.h" />
<ClInclude Include="..\..\src\kiwano\core\keys.h" />
<ClInclude Include="..\..\src\kiwano\core\Logger.h" /> <ClInclude Include="..\..\src\kiwano\core\Logger.h" />
<ClInclude Include="..\..\src\kiwano\core\ObjectBase.h" /> <ClInclude Include="..\..\src\kiwano\core\ObjectBase.h" />
<ClInclude Include="..\..\src\kiwano\core\RefCounter.h" /> <ClInclude Include="..\..\src\kiwano\core\RefCounter.h" />
@ -44,7 +48,6 @@
<ClInclude Include="..\..\src\kiwano\core\SmartPtr.hpp" /> <ClInclude Include="..\..\src\kiwano\core\SmartPtr.hpp" />
<ClInclude Include="..\..\src\kiwano\core\Timer.h" /> <ClInclude Include="..\..\src\kiwano\core\Timer.h" />
<ClInclude Include="..\..\src\kiwano\core\TimerManager.h" /> <ClInclude Include="..\..\src\kiwano\core\TimerManager.h" />
<ClInclude Include="..\..\src\kiwano\core\time.h" />
<ClInclude Include="..\..\src\kiwano\math\constants.h" /> <ClInclude Include="..\..\src\kiwano\math\constants.h" />
<ClInclude Include="..\..\src\kiwano\math\ease.h" /> <ClInclude Include="..\..\src\kiwano\math\ease.h" />
<ClInclude Include="..\..\src\kiwano\math\math.h" /> <ClInclude Include="..\..\src\kiwano\math\math.h" />
@ -54,36 +57,33 @@
<ClInclude Include="..\..\src\kiwano\math\scalar.h" /> <ClInclude Include="..\..\src\kiwano\math\scalar.h" />
<ClInclude Include="..\..\src\kiwano\math\Vec2.hpp" /> <ClInclude Include="..\..\src\kiwano\math\Vec2.hpp" />
<ClInclude Include="..\..\src\kiwano\platform\Application.h" /> <ClInclude Include="..\..\src\kiwano\platform\Application.h" />
<ClInclude Include="..\..\src\kiwano\platform\Director.h" />
<ClInclude Include="..\..\src\kiwano\platform\FileSystem.h" /> <ClInclude Include="..\..\src\kiwano\platform\FileSystem.h" />
<ClInclude Include="..\..\src\kiwano\platform\Input.h" /> <ClInclude Include="..\..\src\kiwano\platform\Input.h" />
<ClInclude Include="..\..\src\kiwano\platform\win32\ComPtr.hpp" /> <ClInclude Include="..\..\src\kiwano\platform\win32\ComPtr.hpp" />
<ClInclude Include="..\..\src\kiwano\platform\win32\helper.h" /> <ClInclude Include="..\..\src\kiwano\platform\win32\helper.h" />
<ClInclude Include="..\..\src\kiwano\platform\win32\libraries.h" /> <ClInclude Include="..\..\src\kiwano\platform\win32\libraries.h" />
<ClInclude Include="..\..\src\kiwano\platform\Window.h" /> <ClInclude Include="..\..\src\kiwano\platform\Window.h" />
<ClInclude Include="..\..\src\kiwano\renderer\Brush.h" /> <ClInclude Include="..\..\src\kiwano\render\Brush.h" />
<ClInclude Include="..\..\src\kiwano\renderer\Color.h" /> <ClInclude Include="..\..\src\kiwano\render\Color.h" />
<ClInclude Include="..\..\src\kiwano\renderer\Font.h" /> <ClInclude Include="..\..\src\kiwano\render\DirectX\D2DDeviceResources.h" />
<ClInclude Include="..\..\src\kiwano\renderer\Geometry.h" /> <ClInclude Include="..\..\src\kiwano\render\DirectX\D3D10DeviceResources.h" />
<ClInclude Include="..\..\src\kiwano\renderer\GeometrySink.h" /> <ClInclude Include="..\..\src\kiwano\render\DirectX\D3D11DeviceResources.h" />
<ClInclude Include="..\..\src\kiwano\renderer\GifImage.h" /> <ClInclude Include="..\..\src\kiwano\render\DirectX\D3DDeviceResourcesBase.h" />
<ClInclude Include="..\..\src\kiwano\renderer\StrokeStyle.h" /> <ClInclude Include="..\..\src\kiwano\render\DirectX\FontCollectionLoader.h" />
<ClInclude Include="..\..\src\kiwano\renderer\TextStyle.hpp" /> <ClInclude Include="..\..\src\kiwano\render\DirectX\helper.h" />
<ClInclude Include="..\..\src\kiwano\renderer\Texture.h" /> <ClInclude Include="..\..\src\kiwano\render\DirectX\TextRenderer.h" />
<ClInclude Include="..\..\src\kiwano\renderer\TextureCache.h" /> <ClInclude Include="..\..\src\kiwano\render\Font.h" />
<ClInclude Include="..\..\src\kiwano\renderer\LayerArea.h" /> <ClInclude Include="..\..\src\kiwano\render\Geometry.h" />
<ClInclude Include="..\..\src\kiwano\renderer\Renderer.h" /> <ClInclude Include="..\..\src\kiwano\render\GeometrySink.h" />
<ClInclude Include="..\..\src\kiwano\renderer\RenderTarget.h" /> <ClInclude Include="..\..\src\kiwano\render\GifImage.h" />
<ClInclude Include="..\..\src\kiwano\renderer\TextLayout.h" /> <ClInclude Include="..\..\src\kiwano\render\LayerArea.h" />
<ClInclude Include="..\..\src\kiwano\renderer\win32\D2DDeviceResources.h" /> <ClInclude Include="..\..\src\kiwano\render\RenderContext.h" />
<ClInclude Include="..\..\src\kiwano\renderer\win32\D3D10DeviceResources.h" /> <ClInclude Include="..\..\src\kiwano\render\Renderer.h" />
<ClInclude Include="..\..\src\kiwano\renderer\win32\D3D11DeviceResources.h" /> <ClInclude Include="..\..\src\kiwano\render\StrokeStyle.h" />
<ClInclude Include="..\..\src\kiwano\renderer\win32\D3DDeviceResourcesBase.h" /> <ClInclude Include="..\..\src\kiwano\render\TextLayout.h" />
<ClInclude Include="..\..\src\kiwano\renderer\win32\FontCollectionLoader.h" /> <ClInclude Include="..\..\src\kiwano\render\TextStyle.hpp" />
<ClInclude Include="..\..\src\kiwano\renderer\win32\helper.h" /> <ClInclude Include="..\..\src\kiwano\render\Texture.h" />
<ClInclude Include="..\..\src\kiwano\renderer\win32\TextRenderer.h" /> <ClInclude Include="..\..\src\kiwano\render\TextureCache.h" />
<ClInclude Include="..\..\src\kiwano\ui\Button.h" />
<ClInclude Include="..\..\src\kiwano\ui\Menu.h" />
<ClInclude Include="..\..\src\kiwano\utils\LocalStorage.h" /> <ClInclude Include="..\..\src\kiwano\utils\LocalStorage.h" />
<ClInclude Include="..\..\src\kiwano\utils\ResourceCache.h" /> <ClInclude Include="..\..\src\kiwano\utils\ResourceCache.h" />
<ClInclude Include="..\..\src\kiwano\utils\UserData.h" /> <ClInclude Include="..\..\src\kiwano\utils\UserData.h" />
@ -96,6 +96,7 @@
<ClCompile Include="..\..\src\kiwano\2d\action\ActionWalk.cpp" /> <ClCompile Include="..\..\src\kiwano\2d\action\ActionWalk.cpp" />
<ClCompile Include="..\..\src\kiwano\2d\action\ActionTween.cpp" /> <ClCompile Include="..\..\src\kiwano\2d\action\ActionTween.cpp" />
<ClCompile Include="..\..\src\kiwano\2d\action\Animation.cpp" /> <ClCompile Include="..\..\src\kiwano\2d\action\Animation.cpp" />
<ClCompile Include="..\..\src\kiwano\2d\Button.cpp" />
<ClCompile Include="..\..\src\kiwano\2d\Canvas.cpp" /> <ClCompile Include="..\..\src\kiwano\2d\Canvas.cpp" />
<ClCompile Include="..\..\src\kiwano\2d\DebugActor.cpp" /> <ClCompile Include="..\..\src\kiwano\2d\DebugActor.cpp" />
<ClCompile Include="..\..\src\kiwano\2d\Frame.cpp" /> <ClCompile Include="..\..\src\kiwano\2d\Frame.cpp" />
@ -111,6 +112,7 @@
<ClCompile Include="..\..\src\kiwano\2d\Transition.cpp" /> <ClCompile Include="..\..\src\kiwano\2d\Transition.cpp" />
<ClCompile Include="..\..\src\kiwano\core\AsyncTask.cpp" /> <ClCompile Include="..\..\src\kiwano\core\AsyncTask.cpp" />
<ClCompile Include="..\..\src\kiwano\core\Component.cpp" /> <ClCompile Include="..\..\src\kiwano\core\Component.cpp" />
<ClCompile Include="..\..\src\kiwano\core\Director.cpp" />
<ClCompile Include="..\..\src\kiwano\core\EventDispatcher.cpp" /> <ClCompile Include="..\..\src\kiwano\core\EventDispatcher.cpp" />
<ClCompile Include="..\..\src\kiwano\core\EventListener.cpp" /> <ClCompile Include="..\..\src\kiwano\core\EventListener.cpp" />
<ClCompile Include="..\..\src\kiwano\core\event\Event.cpp" /> <ClCompile Include="..\..\src\kiwano\core\event\Event.cpp" />
@ -122,35 +124,34 @@
<ClCompile Include="..\..\src\kiwano\core\ObjectBase.cpp" /> <ClCompile Include="..\..\src\kiwano\core\ObjectBase.cpp" />
<ClCompile Include="..\..\src\kiwano\core\RefCounter.cpp" /> <ClCompile Include="..\..\src\kiwano\core\RefCounter.cpp" />
<ClCompile Include="..\..\src\kiwano\core\Resource.cpp" /> <ClCompile Include="..\..\src\kiwano\core\Resource.cpp" />
<ClCompile Include="..\..\src\kiwano\core\Time.cpp" />
<ClCompile Include="..\..\src\kiwano\core\Timer.cpp" /> <ClCompile Include="..\..\src\kiwano\core\Timer.cpp" />
<ClCompile Include="..\..\src\kiwano\core\TimerManager.cpp" /> <ClCompile Include="..\..\src\kiwano\core\TimerManager.cpp" />
<ClCompile Include="..\..\src\kiwano\core\time.cpp" />
<ClCompile Include="..\..\src\kiwano\platform\Application.cpp" /> <ClCompile Include="..\..\src\kiwano\platform\Application.cpp" />
<ClCompile Include="..\..\src\kiwano\platform\Director.cpp" />
<ClCompile Include="..\..\src\kiwano\platform\FileSystem.cpp" /> <ClCompile Include="..\..\src\kiwano\platform\FileSystem.cpp" />
<ClCompile Include="..\..\src\kiwano\platform\Input.cpp" /> <ClCompile Include="..\..\src\kiwano\platform\Input.cpp" />
<ClCompile Include="..\..\src\kiwano\platform\win32\libraries.cpp" /> <ClCompile Include="..\..\src\kiwano\platform\win32\libraries.cpp" />
<ClCompile Include="..\..\src\kiwano\platform\win32\StackWalker.cpp" /> <ClCompile Include="..\..\src\kiwano\platform\win32\StackWalker.cpp" />
<ClCompile Include="..\..\src\kiwano\platform\win32\WindowImpl.cpp" />
<ClCompile Include="..\..\src\kiwano\platform\Window.cpp" /> <ClCompile Include="..\..\src\kiwano\platform\Window.cpp" />
<ClCompile Include="..\..\src\kiwano\renderer\Brush.cpp" /> <ClCompile Include="..\..\src\kiwano\render\Brush.cpp" />
<ClCompile Include="..\..\src\kiwano\renderer\Color.cpp" /> <ClCompile Include="..\..\src\kiwano\render\Color.cpp" />
<ClCompile Include="..\..\src\kiwano\renderer\Font.cpp" /> <ClCompile Include="..\..\src\kiwano\render\DirectX\D2DDeviceResources.cpp" />
<ClCompile Include="..\..\src\kiwano\renderer\Geometry.cpp" /> <ClCompile Include="..\..\src\kiwano\render\DirectX\D3D10DeviceResources.cpp" />
<ClCompile Include="..\..\src\kiwano\renderer\GeometrySink.cpp" /> <ClCompile Include="..\..\src\kiwano\render\DirectX\D3D11DeviceResources.cpp" />
<ClCompile Include="..\..\src\kiwano\renderer\GifImage.cpp" /> <ClCompile Include="..\..\src\kiwano\render\DirectX\FontCollectionLoader.cpp" />
<ClCompile Include="..\..\src\kiwano\renderer\Texture.cpp" /> <ClCompile Include="..\..\src\kiwano\render\DirectX\TextRenderer.cpp" />
<ClCompile Include="..\..\src\kiwano\renderer\TextureCache.cpp" /> <ClCompile Include="..\..\src\kiwano\render\Font.cpp" />
<ClCompile Include="..\..\src\kiwano\renderer\LayerArea.cpp" /> <ClCompile Include="..\..\src\kiwano\render\Geometry.cpp" />
<ClCompile Include="..\..\src\kiwano\renderer\Renderer.cpp" /> <ClCompile Include="..\..\src\kiwano\render\GeometrySink.cpp" />
<ClCompile Include="..\..\src\kiwano\renderer\RenderTarget.cpp" /> <ClCompile Include="..\..\src\kiwano\render\GifImage.cpp" />
<ClCompile Include="..\..\src\kiwano\renderer\TextLayout.cpp" /> <ClCompile Include="..\..\src\kiwano\render\LayerArea.cpp" />
<ClCompile Include="..\..\src\kiwano\renderer\win32\D2DDeviceResources.cpp" /> <ClCompile Include="..\..\src\kiwano\render\RenderContext.cpp" />
<ClCompile Include="..\..\src\kiwano\renderer\win32\D3D10DeviceResources.cpp" /> <ClCompile Include="..\..\src\kiwano\render\Renderer.cpp" />
<ClCompile Include="..\..\src\kiwano\renderer\win32\D3D11DeviceResources.cpp" /> <ClCompile Include="..\..\src\kiwano\render\StrokeStyle.cpp" />
<ClCompile Include="..\..\src\kiwano\renderer\win32\FontCollectionLoader.cpp" /> <ClCompile Include="..\..\src\kiwano\render\TextLayout.cpp" />
<ClCompile Include="..\..\src\kiwano\renderer\win32\TextRenderer.cpp" /> <ClCompile Include="..\..\src\kiwano\render\Texture.cpp" />
<ClCompile Include="..\..\src\kiwano\ui\Button.cpp" /> <ClCompile Include="..\..\src\kiwano\render\TextureCache.cpp" />
<ClCompile Include="..\..\src\kiwano\ui\Menu.cpp" />
<ClCompile Include="..\..\src\kiwano\utils\LocalStorage.cpp" /> <ClCompile Include="..\..\src\kiwano\utils\LocalStorage.cpp" />
<ClCompile Include="..\..\src\kiwano\utils\ResourceCache.cpp" /> <ClCompile Include="..\..\src\kiwano\utils\ResourceCache.cpp" />
<ClCompile Include="..\..\src\kiwano\utils\UserData.cpp" /> <ClCompile Include="..\..\src\kiwano\utils\UserData.cpp" />
@ -165,11 +166,6 @@
<Platform>Win32</Platform> <Platform>Win32</Platform>
</ProjectConfiguration> </ProjectConfiguration>
</ItemGroup> </ItemGroup>
<ItemGroup>
<ProjectReference Include="..\3rd-party\tinyxml2\libtinyxml2.vcxproj">
<Project>{ab47e875-85e5-4105-a71e-88930eaab910}</Project>
</ProjectReference>
</ItemGroup>
<PropertyGroup Label="Globals"> <PropertyGroup Label="Globals">
<ProjectGuid>{FF7F943D-A89C-4E6C-97CF-84F7D8FF8EDF}</ProjectGuid> <ProjectGuid>{FF7F943D-A89C-4E6C-97CF-84F7D8FF8EDF}</ProjectGuid>
<RootNamespace>kiwano</RootNamespace> <RootNamespace>kiwano</RootNamespace>

View File

@ -7,9 +7,6 @@
<Filter Include="utils"> <Filter Include="utils">
<UniqueIdentifier>{68eac919-ee87-4030-a033-c251731928f5}</UniqueIdentifier> <UniqueIdentifier>{68eac919-ee87-4030-a033-c251731928f5}</UniqueIdentifier>
</Filter> </Filter>
<Filter Include="ui">
<UniqueIdentifier>{07b6d541-4a1b-472a-aae0-daf9d082fe84}</UniqueIdentifier>
</Filter>
<Filter Include="platform"> <Filter Include="platform">
<UniqueIdentifier>{c2654ccc-59f6-4c17-bb6b-99b07fc78702}</UniqueIdentifier> <UniqueIdentifier>{c2654ccc-59f6-4c17-bb6b-99b07fc78702}</UniqueIdentifier>
</Filter> </Filter>
@ -19,29 +16,23 @@
<Filter Include="core"> <Filter Include="core">
<UniqueIdentifier>{2e18d99a-e906-499a-9e29-4e0783202644}</UniqueIdentifier> <UniqueIdentifier>{2e18d99a-e906-499a-9e29-4e0783202644}</UniqueIdentifier>
</Filter> </Filter>
<Filter Include="renderer">
<UniqueIdentifier>{7897afce-24cb-42b4-9443-56508e4ec89c}</UniqueIdentifier>
</Filter>
<Filter Include="2d\action"> <Filter Include="2d\action">
<UniqueIdentifier>{9314f30d-5742-48b6-94e5-e3b4284106f6}</UniqueIdentifier> <UniqueIdentifier>{9314f30d-5742-48b6-94e5-e3b4284106f6}</UniqueIdentifier>
</Filter> </Filter>
<Filter Include="renderer\win32">
<UniqueIdentifier>{30333461-e9bc-4709-84bd-ce6e0e1a3079}</UniqueIdentifier>
</Filter>
<Filter Include="platform\win32"> <Filter Include="platform\win32">
<UniqueIdentifier>{e84dcf9a-e650-473e-8c9c-193804ab9e76}</UniqueIdentifier> <UniqueIdentifier>{e84dcf9a-e650-473e-8c9c-193804ab9e76}</UniqueIdentifier>
</Filter> </Filter>
<Filter Include="core\event"> <Filter Include="core\event">
<UniqueIdentifier>{c629aedd-ffb9-4bc1-82c3-f50e77c82e77}</UniqueIdentifier> <UniqueIdentifier>{c629aedd-ffb9-4bc1-82c3-f50e77c82e77}</UniqueIdentifier>
</Filter> </Filter>
<Filter Include="render">
<UniqueIdentifier>{adb44ca9-674a-4b77-993f-d65193d8ab06}</UniqueIdentifier>
</Filter>
<Filter Include="render\DirectX">
<UniqueIdentifier>{fd281702-0006-46d2-8fd1-28c502464164}</UniqueIdentifier>
</Filter>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\..\src\kiwano\ui\Button.h">
<Filter>ui</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\ui\Menu.h">
<Filter>ui</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\2d\Canvas.h"> <ClInclude Include="..\..\src\kiwano\2d\Canvas.h">
<Filter>2d</Filter> <Filter>2d</Filter>
</ClInclude> </ClInclude>
@ -66,9 +57,6 @@
<ClInclude Include="..\..\src\kiwano\core\Resource.h"> <ClInclude Include="..\..\src\kiwano\core\Resource.h">
<Filter>core</Filter> <Filter>core</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\src\kiwano\core\time.h">
<Filter>core</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\math\Matrix.hpp"> <ClInclude Include="..\..\src\kiwano\math\Matrix.hpp">
<Filter>math</Filter> <Filter>math</Filter>
</ClInclude> </ClInclude>
@ -156,63 +144,9 @@
<ClInclude Include="..\..\src\kiwano\core\ObjectBase.h"> <ClInclude Include="..\..\src\kiwano\core\ObjectBase.h">
<Filter>core</Filter> <Filter>core</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\src\kiwano\renderer\Color.h">
<Filter>renderer</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\renderer\Font.h">
<Filter>renderer</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\renderer\Geometry.h">
<Filter>renderer</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\renderer\GifImage.h">
<Filter>renderer</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\renderer\LayerArea.h">
<Filter>renderer</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\renderer\Renderer.h">
<Filter>renderer</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\renderer\TextLayout.h">
<Filter>renderer</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\renderer\win32\D2DDeviceResources.h">
<Filter>renderer\win32</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\renderer\win32\D3D10DeviceResources.h">
<Filter>renderer\win32</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\renderer\win32\D3D11DeviceResources.h">
<Filter>renderer\win32</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\renderer\win32\D3DDeviceResourcesBase.h">
<Filter>renderer\win32</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\renderer\win32\FontCollectionLoader.h">
<Filter>renderer\win32</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\renderer\win32\TextRenderer.h">
<Filter>renderer\win32</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\renderer\RenderTarget.h">
<Filter>renderer</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\2d\Transform.h"> <ClInclude Include="..\..\src\kiwano\2d\Transform.h">
<Filter>2d</Filter> <Filter>2d</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\src\kiwano\renderer\Texture.h">
<Filter>renderer</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\renderer\TextureCache.h">
<Filter>renderer</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\renderer\StrokeStyle.h">
<Filter>renderer</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\renderer\Brush.h">
<Filter>renderer</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\math\constants.h"> <ClInclude Include="..\..\src\kiwano\math\constants.h">
<Filter>math</Filter> <Filter>math</Filter>
</ClInclude> </ClInclude>
@ -234,36 +168,18 @@
<ClInclude Include="..\..\src\kiwano\platform\FileSystem.h"> <ClInclude Include="..\..\src\kiwano\platform\FileSystem.h">
<Filter>platform</Filter> <Filter>platform</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\src\kiwano\core\keys.h">
<Filter>core</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\platform\Input.h"> <ClInclude Include="..\..\src\kiwano\platform\Input.h">
<Filter>platform</Filter> <Filter>platform</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\src\kiwano\platform\Window.h"> <ClInclude Include="..\..\src\kiwano\platform\Window.h">
<Filter>platform</Filter> <Filter>platform</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\src\kiwano\platform\Director.h">
<Filter>platform</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\2d\TextActor.h"> <ClInclude Include="..\..\src\kiwano\2d\TextActor.h">
<Filter>2d</Filter> <Filter>2d</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\src\kiwano\core\common.h">
<Filter>core</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\core\RefCounter.h"> <ClInclude Include="..\..\src\kiwano\core\RefCounter.h">
<Filter>core</Filter> <Filter>core</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\src\kiwano\renderer\TextStyle.hpp">
<Filter>renderer</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\renderer\win32\helper.h">
<Filter>renderer\win32</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\renderer\GeometrySink.h">
<Filter>renderer</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\platform\win32\ComPtr.hpp"> <ClInclude Include="..\..\src\kiwano\platform\win32\ComPtr.hpp">
<Filter>platform\win32</Filter> <Filter>platform\win32</Filter>
</ClInclude> </ClInclude>
@ -288,14 +204,89 @@
<ClInclude Include="..\..\src\kiwano\core\event\WindowEvent.h"> <ClInclude Include="..\..\src\kiwano\core\event\WindowEvent.h">
<Filter>core\event</Filter> <Filter>core\event</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\src\kiwano\2d\Button.h">
<Filter>2d</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\core\Director.h">
<Filter>core</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\core\Singleton.h">
<Filter>core</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\core\Common.h">
<Filter>core</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\core\Keys.h">
<Filter>core</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\core\Time.h">
<Filter>core</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\render\Brush.h">
<Filter>render</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\render\Color.h">
<Filter>render</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\render\Font.h">
<Filter>render</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\render\Geometry.h">
<Filter>render</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\render\GeometrySink.h">
<Filter>render</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\render\GifImage.h">
<Filter>render</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\render\LayerArea.h">
<Filter>render</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\render\RenderContext.h">
<Filter>render</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\render\Renderer.h">
<Filter>render</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\render\StrokeStyle.h">
<Filter>render</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\render\TextLayout.h">
<Filter>render</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\render\TextStyle.hpp">
<Filter>render</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\render\Texture.h">
<Filter>render</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\render\TextureCache.h">
<Filter>render</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\render\DirectX\D2DDeviceResources.h">
<Filter>render\DirectX</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\render\DirectX\D3D10DeviceResources.h">
<Filter>render\DirectX</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\render\DirectX\D3D11DeviceResources.h">
<Filter>render\DirectX</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\render\DirectX\D3DDeviceResourcesBase.h">
<Filter>render\DirectX</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\render\DirectX\FontCollectionLoader.h">
<Filter>render\DirectX</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\render\DirectX\helper.h">
<Filter>render\DirectX</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\render\DirectX\TextRenderer.h">
<Filter>render\DirectX</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="..\..\src\kiwano\ui\Button.cpp">
<Filter>ui</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\ui\Menu.cpp">
<Filter>ui</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\2d\Canvas.cpp"> <ClCompile Include="..\..\src\kiwano\2d\Canvas.cpp">
<Filter>2d</Filter> <Filter>2d</Filter>
</ClCompile> </ClCompile>
@ -317,9 +308,6 @@
<ClCompile Include="..\..\src\kiwano\core\Resource.cpp"> <ClCompile Include="..\..\src\kiwano\core\Resource.cpp">
<Filter>core</Filter> <Filter>core</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\kiwano\core\time.cpp">
<Filter>core</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\platform\Application.cpp"> <ClCompile Include="..\..\src\kiwano\platform\Application.cpp">
<Filter>platform</Filter> <Filter>platform</Filter>
</ClCompile> </ClCompile>
@ -383,57 +371,9 @@
<ClCompile Include="..\..\src\kiwano\core\ObjectBase.cpp"> <ClCompile Include="..\..\src\kiwano\core\ObjectBase.cpp">
<Filter>core</Filter> <Filter>core</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\kiwano\renderer\Color.cpp">
<Filter>renderer</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\renderer\Font.cpp">
<Filter>renderer</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\renderer\Geometry.cpp">
<Filter>renderer</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\renderer\GifImage.cpp">
<Filter>renderer</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\renderer\LayerArea.cpp">
<Filter>renderer</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\renderer\Renderer.cpp">
<Filter>renderer</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\renderer\TextLayout.cpp">
<Filter>renderer</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\renderer\win32\D2DDeviceResources.cpp">
<Filter>renderer\win32</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\renderer\win32\D3D10DeviceResources.cpp">
<Filter>renderer\win32</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\renderer\win32\D3D11DeviceResources.cpp">
<Filter>renderer\win32</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\renderer\win32\FontCollectionLoader.cpp">
<Filter>renderer\win32</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\renderer\win32\TextRenderer.cpp">
<Filter>renderer\win32</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\renderer\RenderTarget.cpp">
<Filter>renderer</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\2d\Transform.cpp"> <ClCompile Include="..\..\src\kiwano\2d\Transform.cpp">
<Filter>2d</Filter> <Filter>2d</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\kiwano\renderer\Texture.cpp">
<Filter>renderer</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\renderer\TextureCache.cpp">
<Filter>renderer</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\renderer\Brush.cpp">
<Filter>renderer</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\core\Component.cpp"> <ClCompile Include="..\..\src\kiwano\core\Component.cpp">
<Filter>core</Filter> <Filter>core</Filter>
</ClCompile> </ClCompile>
@ -455,18 +395,12 @@
<ClCompile Include="..\..\src\kiwano\platform\Window.cpp"> <ClCompile Include="..\..\src\kiwano\platform\Window.cpp">
<Filter>platform</Filter> <Filter>platform</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\kiwano\platform\Director.cpp">
<Filter>platform</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\2d\TextActor.cpp"> <ClCompile Include="..\..\src\kiwano\2d\TextActor.cpp">
<Filter>2d</Filter> <Filter>2d</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\kiwano\core\RefCounter.cpp"> <ClCompile Include="..\..\src\kiwano\core\RefCounter.cpp">
<Filter>core</Filter> <Filter>core</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\kiwano\renderer\GeometrySink.cpp">
<Filter>renderer</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\platform\win32\libraries.cpp"> <ClCompile Include="..\..\src\kiwano\platform\win32\libraries.cpp">
<Filter>platform\win32</Filter> <Filter>platform\win32</Filter>
</ClCompile> </ClCompile>
@ -485,5 +419,71 @@
<ClCompile Include="..\..\src\kiwano\core\event\WindowEvent.cpp"> <ClCompile Include="..\..\src\kiwano\core\event\WindowEvent.cpp">
<Filter>core\event</Filter> <Filter>core\event</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\kiwano\2d\Button.cpp">
<Filter>2d</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\core\Director.cpp">
<Filter>core</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\platform\win32\WindowImpl.cpp">
<Filter>platform\win32</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\core\Time.cpp">
<Filter>core</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\render\Brush.cpp">
<Filter>render</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\render\Color.cpp">
<Filter>render</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\render\Font.cpp">
<Filter>render</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\render\Geometry.cpp">
<Filter>render</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\render\GeometrySink.cpp">
<Filter>render</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\render\GifImage.cpp">
<Filter>render</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\render\LayerArea.cpp">
<Filter>render</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\render\RenderContext.cpp">
<Filter>render</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\render\Renderer.cpp">
<Filter>render</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\render\StrokeStyle.cpp">
<Filter>render</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\render\TextLayout.cpp">
<Filter>render</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\render\Texture.cpp">
<Filter>render</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\render\TextureCache.cpp">
<Filter>render</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\render\DirectX\D2DDeviceResources.cpp">
<Filter>render\DirectX</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\render\DirectX\D3D10DeviceResources.cpp">
<Filter>render\DirectX</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\render\DirectX\D3D11DeviceResources.cpp">
<Filter>render\DirectX</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\render\DirectX\FontCollectionLoader.cpp">
<Filter>render\DirectX</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\render\DirectX\TextRenderer.cpp">
<Filter>render\DirectX</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
</Project> </Project>

84
scripts/clang-format-all Normal file
View File

@ -0,0 +1,84 @@
#!/bin/bash
#
# clang-format-all: a tool to run clang-format on an entire project
# Copyright (C) 2016 Evan Klitzke <evan@eklitzke.org>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
function usage {
echo "Usage: $0 DIR..."
exit 1
}
if [ $# -eq 0 ]; then
usage
fi
# Variable that will hold the name of the clang-format command
FMT=""
# Some distros just call it clang-format. Others (e.g. Ubuntu) are insistent
# that the version number be part of the command. We prefer clang-format if
# that's present, otherwise we work backwards from highest version to lowest
# version.
for clangfmt in clang-format{,-{4,3}.{9,8,7,6,5,4,3,2,1,0}}; do
if which "$clangfmt" &>/dev/null; then
FMT="$clangfmt"
break
fi
done
# Check if we found a working clang-format
if [ -z "$FMT" ]; then
echo "failed to find clang-format"
exit 1
fi
# Check all of the arguments first to make sure they're all directories
for dir in "$@"; do
if [ ! -d "${dir}" ]; then
echo "${dir} is not a directory"
usage
fi
done
# Find a dominating file, starting from a given directory and going up.
find-dominating-file() {
if [ -r "$1"/"$2" ]; then
return 0
fi
if [ "$1" = "/" ]; then
return 1
fi
find-dominating-file "$(realpath "$1"/..)" "$2"
return $?
}
# Run clang-format -i on all of the things
for dir in "$@"; do
pushd "${dir}" &>/dev/null
if ! find-dominating-file . .clang-format; then
echo "Failed to find dominating .clang-format starting at $PWD"
continue
fi
find . \
\( -name '*.c' \
-o -name '*.cc' \
-o -name '*.cpp' \
-o -name '*.h' \
-o -name '*.hh' \
-o -name '*.hpp' \) \
-exec "${FMT}" -i '{}' \;
popd &>/dev/null
done

View File

@ -115,23 +115,23 @@ public:
virtual _Ret invoke(_Args... args) const override virtual _Ret invoke(_Args... args) const override
{ {
return (static_cast<_Ty*>(ptr_)->*func_)(::std::forward<_Args>(args)...); return (ptr_->*func_)(::std::forward<_Args>(args)...);
} }
static inline callable<_Ret, _Args...>* make(void* ptr, _FuncType func) static inline callable<_Ret, _Args...>* make(_Ty* ptr, _FuncType func)
{ {
return new (::std::nothrow) proxy_mem_callable<_Ty, _Ret, _Args...>(ptr, func); return new (::std::nothrow) proxy_mem_callable<_Ty, _Ret, _Args...>(ptr, func);
} }
protected: protected:
proxy_mem_callable(void* ptr, _FuncType func) proxy_mem_callable(_Ty* ptr, _FuncType func)
: ptr_(ptr) : ptr_(ptr)
, func_(func) , func_(func)
{ {
} }
protected: protected:
void* ptr_; _Ty* ptr_;
_FuncType func_; _FuncType func_;
}; };
@ -144,23 +144,23 @@ public:
virtual _Ret invoke(_Args... args) const override virtual _Ret invoke(_Args... args) const override
{ {
return (static_cast<_Ty*>(ptr_)->*func_)(::std::forward<_Args>(args)...); return (ptr_->*func_)(::std::forward<_Args>(args)...);
} }
static inline callable<_Ret, _Args...>* make(void* ptr, _FuncType func) static inline callable<_Ret, _Args...>* make(_Ty* ptr, _FuncType func)
{ {
return new (::std::nothrow) proxy_const_mem_callable<_Ty, _Ret, _Args...>(ptr, func); return new (::std::nothrow) proxy_const_mem_callable<_Ty, _Ret, _Args...>(ptr, func);
} }
protected: protected:
proxy_const_mem_callable(void* ptr, _FuncType func) proxy_const_mem_callable(_Ty* ptr, _FuncType func)
: ptr_(ptr) : ptr_(ptr)
, func_(func) , func_(func)
{ {
} }
protected: protected:
void* ptr_; _Ty* ptr_;
_FuncType func_; _FuncType func_;
}; };

View File

@ -16,20 +16,19 @@ template <typename _Ty, typename _PTy = typename std::pointer_traits<_Ty>::point
class intrusive_list_item class intrusive_list_item
{ {
public: public:
using pointer_type = _PTy; using pointer = _PTy;
using const_pointer_type = const _PTy;
intrusive_list_item() : prev_(nullptr), next_(nullptr) {} intrusive_list_item() : prev_(nullptr), next_(nullptr) {}
intrusive_list_item(pointer_type rhs) : prev_(nullptr), next_(nullptr) { if (rhs) { prev_ = rhs->prev_; next_ = rhs->next_; } } intrusive_list_item(pointer rhs) : prev_(nullptr), next_(nullptr) { if (rhs) { prev_ = rhs->prev_; next_ = rhs->next_; } }
const_pointer_type prev_item() const { return prev_; } const pointer prev_item() const { return prev_; }
pointer_type prev_item() { return prev_; } pointer prev_item() { return prev_; }
const_pointer_type next_item() const { return next_; } const pointer next_item() const { return next_; }
pointer_type next_item() { return next_; } pointer next_item() { return next_; }
private: private:
pointer_type prev_; pointer prev_;
pointer_type next_; pointer next_;
friend class intrusive_list<_Ty, _PTy>; friend class intrusive_list<_Ty, _PTy>;
}; };
@ -39,23 +38,24 @@ template <typename _Ty, typename _PTy>
class intrusive_list class intrusive_list
{ {
public: public:
using pointer_type = _PTy; using value_type = typename std::pointer_traits<_PTy>::element_type;
using const_pointer_type = const _PTy; using pointer = _PTy;
using reference = value_type&;
intrusive_list() : first_(), last_() {} intrusive_list() : first_(), last_() {}
~intrusive_list() { clear(); } ~intrusive_list() { clear(); }
const_pointer_type first_item() const { return first_; } const pointer first_item() const { return first_; }
pointer_type first_item() { return first_; } pointer first_item() { return first_; }
const_pointer_type last_item() const { return last_; } const pointer last_item() const { return last_; }
pointer_type last_item() { return last_; } pointer last_item() { return last_; }
inline bool empty() const inline bool empty() const
{ {
return first_ == nullptr; return first_ == nullptr;
} }
void push_back(pointer_type child) void push_back(pointer child)
{ {
if (child->prev_) if (child->prev_)
child->prev_->next_ = child->next_; child->prev_->next_ = child->next_;
@ -77,7 +77,7 @@ public:
last_ = child; last_ = child;
} }
void push_front(pointer_type child) void push_front(pointer child)
{ {
if (child->prev_) if (child->prev_)
child->prev_->next_ = child->next_; child->prev_->next_ = child->next_;
@ -99,7 +99,7 @@ public:
first_ = child; first_ = child;
} }
void insert_before(pointer_type child, pointer_type before) void insert_before(pointer child, pointer before)
{ {
if (child->prev_) if (child->prev_)
child->prev_->next_ = child->next_; child->prev_->next_ = child->next_;
@ -116,7 +116,7 @@ public:
before->prev_ = child; before->prev_ = child;
} }
void insert_after(pointer_type child, pointer_type after) void insert_after(pointer child, pointer after)
{ {
if (child->prev_) if (child->prev_)
child->prev_->next_ = child->next_; child->prev_->next_ = child->next_;
@ -133,7 +133,7 @@ public:
after->next_ = child; after->next_ = child;
} }
void remove(pointer_type child) void remove(pointer child)
{ {
if (child->next_) if (child->next_)
{ {
@ -159,10 +159,10 @@ public:
void clear() void clear()
{ {
pointer_type p = first_; pointer p = first_;
while (p) while (p)
{ {
pointer_type tmp = p; pointer tmp = p;
p = p->next_; p = p->next_;
if (tmp) if (tmp)
{ {
@ -180,8 +180,8 @@ public:
return; return;
int pos = 0; int pos = 0;
pointer_type p = first_; pointer p = first_;
pointer_type tmp = p; pointer tmp = p;
do do
{ {
tmp = p; tmp = p;
@ -205,15 +205,19 @@ public:
struct iterator_impl struct iterator_impl
{ {
using iterator_category = std::bidirectional_iterator_tag; using iterator_category = std::bidirectional_iterator_tag;
using pointer_type = _PTy; using value_type = typename std::pointer_traits<_PTy>::element_type;
using const_pointer_type = const _PTy; using difference_type = ptrdiff_t;
using pointer = _PTy;
using reference = value_type&;
inline iterator_impl(pointer_type ptr = nullptr, bool is_end = false) : base_(ptr), is_end_(is_end) {} inline iterator_impl(pointer ptr = nullptr, bool is_end = false) : base_(ptr), is_end_(is_end) {}
inline pointer_type operator*() const { OC_ASSERT(base_ && !is_end_); return base_; } inline pointer base() const { OC_ASSERT(!is_end_); return const_cast<pointer&>(base_); }
inline iterator_impl& operator++() { OC_ASSERT(base_ && !is_end_); pointer_type next = base_->next_item(); if (next) base_ = next; else is_end_ = true; return (*this); } inline reference operator*() const { OC_ASSERT(base_ && !is_end_); return const_cast<reference>(*base_); }
inline pointer operator->() const { OC_ASSERT(base_ && !is_end_); return const_cast<pointer&>(base_); }
inline iterator_impl& operator++() { OC_ASSERT(base_ && !is_end_); pointer next = base_->next_item(); if (next) base_ = next; else is_end_ = true; return (*this); }
inline iterator_impl operator++(int) { iterator_impl old = (*this); ++(*this); return old; } inline iterator_impl operator++(int) { iterator_impl old = (*this); ++(*this); return old; }
inline iterator_impl& operator--() { OC_ASSERT(base_); if (is_end_) is_end_ = false; else base_ = pointer_type(base_->prev_item()); return (*this); } inline iterator_impl& operator--() { OC_ASSERT(base_); if (is_end_) is_end_ = false; else base_ = pointer(base_->prev_item()); return (*this); }
inline iterator_impl operator--(int) { iterator_impl old = (*this); --(*this); return old; } inline iterator_impl operator--(int) { iterator_impl old = (*this); --(*this); return old; }
inline bool operator==(iterator_impl const& other) const { return base_ == other.base_ && is_end_ == other.is_end_; } inline bool operator==(iterator_impl const& other) const { return base_ == other.base_ && is_end_ == other.is_end_; }
inline bool operator!=(iterator_impl const& other) const { return !(*this == other); } inline bool operator!=(iterator_impl const& other) const { return !(*this == other); }
@ -221,11 +225,11 @@ public:
private: private:
bool is_end_; bool is_end_;
pointer_type base_; pointer base_;
}; };
using iterator = iterator_impl<pointer_type>; using iterator = iterator_impl<pointer>;
using const_iterator = iterator_impl<const pointer_type>; using const_iterator = iterator_impl<const pointer>;
using reverse_iterator = std::reverse_iterator<iterator>; using reverse_iterator = std::reverse_iterator<iterator>;
using const_reverse_iterator = std::reverse_iterator<const_iterator>; using const_reverse_iterator = std::reverse_iterator<const_iterator>;
@ -241,14 +245,14 @@ public:
inline reverse_iterator rend() { return reverse_iterator(begin()); } inline reverse_iterator rend() { return reverse_iterator(begin()); }
inline const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } inline const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
inline const_reverse_iterator crend() const { return rend(); } inline const_reverse_iterator crend() const { return rend(); }
inline pointer_type front() { if (empty()) throw std::out_of_range("front() called on empty intrusive_list"); return first_item(); } inline pointer front() { if (empty()) throw std::out_of_range("front() called on empty intrusive_list"); return first_item(); }
inline const_pointer_type front() const { if (empty()) throw std::out_of_range("front() called on empty intrusive_list"); return first_item(); } inline const pointer front() const { if (empty()) throw std::out_of_range("front() called on empty intrusive_list"); return first_item(); }
inline pointer_type back() { if (empty()) throw std::out_of_range("back() called on empty intrusive_list"); return last_item(); } inline pointer back() { if (empty()) throw std::out_of_range("back() called on empty intrusive_list"); return last_item(); }
inline const_pointer_type back() const { if (empty()) throw std::out_of_range("back() called on empty intrusive_list"); return last_item(); } inline const pointer back() const { if (empty()) throw std::out_of_range("back() called on empty intrusive_list"); return last_item(); }
private: private:
pointer_type first_; pointer first_;
pointer_type last_; pointer last_;
}; };
} // namespace oc } // namespace oc

74
src/3rd-party/pugixml/pugiconfig.hpp vendored Normal file
View File

@ -0,0 +1,74 @@
/**
* pugixml parser - version 1.10
* --------------------------------------------------------
* Copyright (C) 2006-2019, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com)
* Report bugs and download new versions at https://pugixml.org/
*
* This library is distributed under the MIT License. See notice at the end
* of this file.
*
* This work is based on the pugxml parser, which is:
* Copyright (C) 2003, by Kristen Wegner (kristen@tima.net)
*/
#ifndef HEADER_PUGICONFIG_HPP
#define HEADER_PUGICONFIG_HPP
// Uncomment this to enable wchar_t mode
#define PUGIXML_WCHAR_MODE
// Uncomment this to enable compact mode
// #define PUGIXML_COMPACT
// Uncomment this to disable XPath
// #define PUGIXML_NO_XPATH
// Uncomment this to disable STL
// #define PUGIXML_NO_STL
// Uncomment this to disable exceptions
#define PUGIXML_NO_EXCEPTIONS
// Set this to control attributes for public classes/functions, i.e.:
// #define PUGIXML_API __declspec(dllexport) // to export all public symbols from DLL
// #define PUGIXML_CLASS __declspec(dllimport) // to import all classes from DLL
// #define PUGIXML_FUNCTION __fastcall // to set calling conventions to all public functions to fastcall
// In absence of PUGIXML_CLASS/PUGIXML_FUNCTION definitions PUGIXML_API is used instead
// Tune these constants to adjust memory-related behavior
// #define PUGIXML_MEMORY_PAGE_SIZE 32768
// #define PUGIXML_MEMORY_OUTPUT_STACK 10240
// #define PUGIXML_MEMORY_XPATH_PAGE_SIZE 4096
// Uncomment this to switch to header-only version
#define PUGIXML_HEADER_ONLY
// Uncomment this to enable long long support
// #define PUGIXML_HAS_LONG_LONG
#endif
/**
* Copyright (c) 2006-2019 Arseny Kapoulkine
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* 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 AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/

12865
src/3rd-party/pugixml/pugixml.cpp vendored Normal file

File diff suppressed because it is too large Load Diff

1477
src/3rd-party/pugixml/pugixml.hpp vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,18 +0,0 @@
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product documentation
would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,15 +1,15 @@
// Copyright (c) 2016-2018 Kiwano - Nomango // Copyright (c) 2016-2018 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -18,108 +18,106 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE. // THE SOFTWARE.
#include <kiwano/platform/win32/helper.h> // win32::ThrowIfFailed
#include <kiwano/core/Logger.h>
#include <kiwano-audio/libraries.h>
#include <kiwano-audio/AudioEngine.h> #include <kiwano-audio/AudioEngine.h>
#include <kiwano-audio/libraries.h>
#include <kiwano/core/Logger.h>
#include <kiwano/platform/win32/helper.h> // win32::ThrowIfFailed
namespace kiwano namespace kiwano
{ {
namespace audio namespace audio
{ {
AudioEngine::AudioEngine() AudioEngine::AudioEngine()
: x_audio2_(nullptr) : x_audio2_(nullptr)
, mastering_voice_(nullptr) , mastering_voice_(nullptr)
{ {
}
AudioEngine::~AudioEngine()
{
}
void AudioEngine::SetupComponent()
{
KGE_SYS_LOG(L"Creating audio resources");
HRESULT hr = dlls::MediaFoundation::Get().MFStartup(MF_VERSION, MFSTARTUP_FULL);
if (SUCCEEDED(hr))
{
hr = dlls::XAudio2::Get().XAudio2Create(&x_audio2_, 0, XAUDIO2_DEFAULT_PROCESSOR);
}
if (SUCCEEDED(hr))
{
hr = x_audio2_->CreateMasteringVoice(&mastering_voice_);
}
win32::ThrowIfFailed(hr);
}
void AudioEngine::DestroyComponent()
{
KGE_SYS_LOG(L"Destroying audio resources");
if (mastering_voice_)
{
mastering_voice_->DestroyVoice();
mastering_voice_ = nullptr;
}
if (x_audio2_)
{
x_audio2_->Release();
x_audio2_ = nullptr;
}
dlls::MediaFoundation::Get().MFShutdown();
}
bool AudioEngine::CreateSound(Sound& sound, const Transcoder::Buffer& buffer)
{
KGE_ASSERT(x_audio2_ && "AudioEngine hasn't been initialized!");
HRESULT hr = S_OK;
if (buffer.format == nullptr)
hr = E_INVALIDARG;
if (SUCCEEDED(hr))
{
IXAudio2SourceVoice* voice = nullptr;
hr = x_audio2_->CreateSourceVoice(&voice, buffer.format, 0, XAUDIO2_DEFAULT_FREQ_RATIO);
if (SUCCEEDED(hr))
{
IXAudio2SourceVoice* old = sound.GetXAudio2Voice();
if (old)
{
old->DestroyVoice();
old = nullptr;
}
sound.SetXAudio2Voice(voice);
}
}
win32::WarnIfFailed(hr);
return SUCCEEDED(hr);
}
void AudioEngine::Open()
{
KGE_ASSERT(x_audio2_ && "AudioEngine hasn't been initialized!");
if (x_audio2_)
x_audio2_->StartEngine();
}
void AudioEngine::Close()
{
KGE_ASSERT(x_audio2_ && "AudioEngine hasn't been initialized!");
if (x_audio2_)
x_audio2_->StopEngine();
}
}
} }
AudioEngine::~AudioEngine() {}
void AudioEngine::SetupComponent()
{
KGE_SYS_LOG(L"Creating audio resources");
HRESULT hr = dlls::MediaFoundation::Get().MFStartup(MF_VERSION, MFSTARTUP_FULL);
if (SUCCEEDED(hr))
{
hr = dlls::XAudio2::Get().XAudio2Create(&x_audio2_, 0, XAUDIO2_DEFAULT_PROCESSOR);
}
if (SUCCEEDED(hr))
{
hr = x_audio2_->CreateMasteringVoice(&mastering_voice_);
}
win32::ThrowIfFailed(hr);
}
void AudioEngine::DestroyComponent()
{
KGE_SYS_LOG(L"Destroying audio resources");
if (mastering_voice_)
{
mastering_voice_->DestroyVoice();
mastering_voice_ = nullptr;
}
if (x_audio2_)
{
x_audio2_->Release();
x_audio2_ = nullptr;
}
dlls::MediaFoundation::Get().MFShutdown();
}
bool AudioEngine::CreateSound(Sound& sound, const Transcoder::Buffer& buffer)
{
KGE_ASSERT(x_audio2_ && "AudioEngine hasn't been initialized!");
HRESULT hr = S_OK;
if (buffer.format == nullptr)
hr = E_INVALIDARG;
if (SUCCEEDED(hr))
{
IXAudio2SourceVoice* voice = nullptr;
hr = x_audio2_->CreateSourceVoice(&voice, buffer.format, 0, XAUDIO2_DEFAULT_FREQ_RATIO);
if (SUCCEEDED(hr))
{
IXAudio2SourceVoice* old = sound.GetXAudio2Voice();
if (old)
{
old->DestroyVoice();
old = nullptr;
}
sound.SetXAudio2Voice(voice);
}
}
win32::WarnIfFailed(hr);
return SUCCEEDED(hr);
}
void AudioEngine::Open()
{
KGE_ASSERT(x_audio2_ && "AudioEngine hasn't been initialized!");
if (x_audio2_)
x_audio2_->StartEngine();
}
void AudioEngine::Close()
{
KGE_ASSERT(x_audio2_ && "AudioEngine hasn't been initialized!");
if (x_audio2_)
x_audio2_->StopEngine();
}
} // namespace audio
} // namespace kiwano

View File

@ -1,15 +1,15 @@
// Copyright (c) 2016-2018 Kiwano - Nomango // Copyright (c) 2016-2018 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -19,64 +19,66 @@
// THE SOFTWARE. // THE SOFTWARE.
#pragma once #pragma once
#include <kiwano/core/common.h>
#include <kiwano/core/Component.h>
#include <kiwano-audio/Transcoder.h>
#include <kiwano-audio/Sound.h> #include <kiwano-audio/Sound.h>
#include <kiwano-audio/Transcoder.h>
#include <kiwano/core/Common.h>
#include <kiwano/core/Component.h>
#include <xaudio2.h> #include <xaudio2.h>
namespace kiwano namespace kiwano
{ {
namespace audio namespace audio
{ {
/**
* \~chinese
* \defgroup Audio
*/
/** /**
* \addtogroup Audio * \~chinese
* @{ * \defgroup Audio
*/ */
/** /**
* \~chinese * \addtogroup Audio
* @brief * @{
*/ */
class KGE_API AudioEngine
: public Singleton<AudioEngine>
, public ComponentBase
{
friend Singleton<AudioEngine>;
public: /**
/// \~chinese * \~chinese
/// @brief 开启音频设备 * @brief
void Open(); */
class KGE_API AudioEngine
: public Singleton<AudioEngine>
, public ComponentBase
{
friend Singleton<AudioEngine>;
/// \~chinese public:
/// @brief 关闭音频设备 /// \~chinese
void Close(); /// @brief 开启音频设备
void Open();
/// \~chinese /// \~chinese
/// @brief 从解码器数据缓冲中创建音频对象 /// @brief 关闭音频设备
bool CreateSound(Sound& sound, const Transcoder::Buffer& buffer); void Close();
public: /// \~chinese
void SetupComponent() override; /// @brief 从解码器数据缓冲中创建音频对象
bool CreateSound(Sound& sound, const Transcoder::Buffer& buffer);
void DestroyComponent() override; public:
void SetupComponent() override;
private: void DestroyComponent() override;
AudioEngine();
~AudioEngine(); private:
AudioEngine();
private: ~AudioEngine();
IXAudio2* x_audio2_;
IXAudio2MasteringVoice* mastering_voice_;
};
/** @} */ private:
} IXAudio2* x_audio2_;
} IXAudio2MasteringVoice* mastering_voice_;
};
/** @} */
} // namespace audio
} // namespace kiwano

View File

@ -1,15 +1,15 @@
// Copyright (c) 2016-2018 Kiwano - Nomango // Copyright (c) 2016-2018 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -18,210 +18,210 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE. // THE SOFTWARE.
#include <kiwano-audio/AudioEngine.h>
#include <kiwano-audio/Sound.h>
#include <kiwano/core/Logger.h> #include <kiwano/core/Logger.h>
#include <kiwano/platform/FileSystem.h> #include <kiwano/platform/FileSystem.h>
#include <kiwano-audio/Sound.h>
#include <kiwano-audio/AudioEngine.h>
namespace kiwano namespace kiwano
{ {
namespace audio namespace audio
{ {
Sound::Sound() Sound::Sound()
: opened_(false) : opened_(false)
, playing_(false) , playing_(false)
, voice_(nullptr) , voice_(nullptr)
{ {
}
Sound::~Sound()
{
Close();
}
bool Sound::Load(String const& file_path)
{
if (!FileSystem::instance().IsFileExists(file_path))
{
KGE_WARN(L"Media file '%s' not found", file_path.c_str());
return false;
}
if (opened_)
{
Close();
}
String full_path = FileSystem::instance().GetFullPathForFile(file_path);
HRESULT hr = transcoder_.LoadMediaFile(full_path);
if (FAILED(hr))
{
KGE_ERROR(L"Load media file failed with HRESULT of %08X", hr);
return false;
}
if (!AudioEngine::instance().CreateSound(*this, transcoder_.GetBuffer()))
{
Close();
return false;
}
opened_ = true;
return true;
}
bool Sound::Load(Resource const& res)
{
if (opened_)
{
Close();
}
HRESULT hr = transcoder_.LoadMediaResource(res);
if (FAILED(hr))
{
KGE_ERROR(L"Load media resource failed with HRESULT of %08X", hr);
return false;
}
if (!AudioEngine::instance().CreateSound(*this, transcoder_.GetBuffer()))
{
Close();
return false;
}
opened_ = true;
return true;
}
bool Sound::IsValid() const
{
return voice_ != nullptr;
}
void Sound::Play(int loop_count)
{
if (!opened_)
{
KGE_ERROR(L"Sound must be opened first!");
return;
}
KGE_ASSERT(voice_ != nullptr && "IXAudio2SourceVoice* is NULL");
// if sound stream is not empty, stop() will clear it
XAUDIO2_VOICE_STATE state;
voice_->GetState(&state);
if (state.BuffersQueued)
Stop();
// clamp loop count
loop_count = (loop_count < 0) ? XAUDIO2_LOOP_INFINITE : std::min(loop_count, XAUDIO2_LOOP_INFINITE - 1);
auto wave_buffer = transcoder_.GetBuffer();
XAUDIO2_BUFFER buffer = { 0 };
buffer.pAudioData = wave_buffer.data;
buffer.Flags = XAUDIO2_END_OF_STREAM;
buffer.AudioBytes = wave_buffer.size;
buffer.LoopCount = static_cast<uint32_t>(loop_count);
HRESULT hr = voice_->SubmitSourceBuffer(&buffer);
if (SUCCEEDED(hr))
{
hr = voice_->Start();
}
if (FAILED(hr))
{
KGE_ERROR(L"Submitting source buffer failed with HRESULT of %08X", hr);
}
playing_ = SUCCEEDED(hr);
}
void Sound::Pause()
{
KGE_ASSERT(voice_ != nullptr && "IXAudio2SourceVoice* is NULL");
if (SUCCEEDED(voice_->Stop()))
playing_ = false;
}
void Sound::Resume()
{
KGE_ASSERT(voice_ != nullptr && "IXAudio2SourceVoice* is NULL");
if (SUCCEEDED(voice_->Start()))
playing_ = true;
}
void Sound::Stop()
{
KGE_ASSERT(voice_ != nullptr && "IXAudio2SourceVoice* is NULL");
HRESULT hr = voice_->Stop();
if (SUCCEEDED(hr))
hr = voice_->ExitLoop();
if (SUCCEEDED(hr))
hr = voice_->FlushSourceBuffers();
if (SUCCEEDED(hr))
playing_ = false;
}
void Sound::Close()
{
if (voice_)
{
voice_->Stop();
voice_->FlushSourceBuffers();
voice_->DestroyVoice();
voice_ = nullptr;
}
transcoder_.ClearBuffer();
opened_ = false;
playing_ = false;
}
bool Sound::IsPlaying() const
{
if (opened_)
{
if (!voice_)
return false;
XAUDIO2_VOICE_STATE state;
voice_->GetState(&state);
uint32_t buffers_queued = state.BuffersQueued;
if (buffers_queued && playing_)
return true;
}
return false;
}
float Sound::GetVolume() const
{
KGE_ASSERT(voice_ != nullptr && "IXAudio2SourceVoice* is NULL");
float volume = 0.0f;
voice_->GetVolume(&volume);
return volume;
}
void Sound::SetVolume(float volume)
{
KGE_ASSERT(voice_ != nullptr && "IXAudio2SourceVoice* is NULL");
volume = std::min(std::max(volume, -224.f), 224.f);
voice_->SetVolume(volume);
}
}
} }
Sound::~Sound()
{
Close();
}
bool Sound::Load(String const& file_path)
{
if (!FileSystem::Instance().IsFileExists(file_path))
{
KGE_WARN(L"Media file '%s' not found", file_path.c_str());
return false;
}
if (opened_)
{
Close();
}
String full_path = FileSystem::Instance().GetFullPathForFile(file_path);
HRESULT hr = transcoder_.LoadMediaFile(full_path);
if (FAILED(hr))
{
KGE_ERROR(L"Load media file failed with HRESULT of %08X", hr);
return false;
}
if (!AudioEngine::Instance().CreateSound(*this, transcoder_.GetBuffer()))
{
Close();
return false;
}
opened_ = true;
return true;
}
bool Sound::Load(Resource const& res)
{
if (opened_)
{
Close();
}
HRESULT hr = transcoder_.LoadMediaResource(res);
if (FAILED(hr))
{
KGE_ERROR(L"Load media resource failed with HRESULT of %08X", hr);
return false;
}
if (!AudioEngine::Instance().CreateSound(*this, transcoder_.GetBuffer()))
{
Close();
return false;
}
opened_ = true;
return true;
}
bool Sound::IsValid() const
{
return voice_ != nullptr;
}
void Sound::Play(int loop_count)
{
if (!opened_)
{
KGE_ERROR(L"Sound must be opened first!");
return;
}
KGE_ASSERT(voice_ != nullptr && "IXAudio2SourceVoice* is NULL");
// if sound stream is not empty, stop() will clear it
XAUDIO2_VOICE_STATE state;
voice_->GetState(&state);
if (state.BuffersQueued)
Stop();
// clamp loop count
loop_count = (loop_count < 0) ? XAUDIO2_LOOP_INFINITE : std::min(loop_count, XAUDIO2_LOOP_INFINITE - 1);
auto wave_buffer = transcoder_.GetBuffer();
XAUDIO2_BUFFER buffer = { 0 };
buffer.pAudioData = wave_buffer.data;
buffer.Flags = XAUDIO2_END_OF_STREAM;
buffer.AudioBytes = wave_buffer.size;
buffer.LoopCount = static_cast<uint32_t>(loop_count);
HRESULT hr = voice_->SubmitSourceBuffer(&buffer);
if (SUCCEEDED(hr))
{
hr = voice_->Start();
}
if (FAILED(hr))
{
KGE_ERROR(L"Submitting source buffer failed with HRESULT of %08X", hr);
}
playing_ = SUCCEEDED(hr);
}
void Sound::Pause()
{
KGE_ASSERT(voice_ != nullptr && "IXAudio2SourceVoice* is NULL");
if (SUCCEEDED(voice_->Stop()))
playing_ = false;
}
void Sound::Resume()
{
KGE_ASSERT(voice_ != nullptr && "IXAudio2SourceVoice* is NULL");
if (SUCCEEDED(voice_->Start()))
playing_ = true;
}
void Sound::Stop()
{
KGE_ASSERT(voice_ != nullptr && "IXAudio2SourceVoice* is NULL");
HRESULT hr = voice_->Stop();
if (SUCCEEDED(hr))
hr = voice_->ExitLoop();
if (SUCCEEDED(hr))
hr = voice_->FlushSourceBuffers();
if (SUCCEEDED(hr))
playing_ = false;
}
void Sound::Close()
{
if (voice_)
{
voice_->Stop();
voice_->FlushSourceBuffers();
voice_->DestroyVoice();
voice_ = nullptr;
}
transcoder_.ClearBuffer();
opened_ = false;
playing_ = false;
}
bool Sound::IsPlaying() const
{
if (opened_)
{
if (!voice_)
return false;
XAUDIO2_VOICE_STATE state;
voice_->GetState(&state);
uint32_t buffers_queued = state.BuffersQueued;
if (buffers_queued && playing_)
return true;
}
return false;
}
float Sound::GetVolume() const
{
KGE_ASSERT(voice_ != nullptr && "IXAudio2SourceVoice* is NULL");
float volume = 0.0f;
voice_->GetVolume(&volume);
return volume;
}
void Sound::SetVolume(float volume)
{
KGE_ASSERT(voice_ != nullptr && "IXAudio2SourceVoice* is NULL");
volume = std::min(std::max(volume, -224.f), 224.f);
voice_->SetVolume(volume);
}
} // namespace audio
} // namespace kiwano

View File

@ -1,15 +1,15 @@
// Copyright (c) 2016-2018 Kiwano - Nomango // Copyright (c) 2016-2018 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -19,110 +19,108 @@
// THE SOFTWARE. // THE SOFTWARE.
#pragma once #pragma once
#include <kiwano-audio/Transcoder.h>
#include <kiwano/core/ObjectBase.h> #include <kiwano/core/ObjectBase.h>
#include <kiwano/core/Resource.h> #include <kiwano/core/Resource.h>
#include <kiwano/platform/win32/ComPtr.hpp> #include <kiwano/platform/win32/ComPtr.hpp>
#include <kiwano-audio/Transcoder.h>
#include <xaudio2.h> #include <xaudio2.h>
namespace kiwano namespace kiwano
{ {
namespace audio namespace audio
{ {
class AudioEngine; class AudioEngine;
KGE_DECLARE_SMART_PTR(Sound); KGE_DECLARE_SMART_PTR(Sound);
/** /**
* \addtogroup Audio * \addtogroup Audio
* @{ * @{
*/ */
/** /**
* \~chinese * \~chinese
* @brief * @brief
*/ */
class KGE_API Sound class KGE_API Sound : public virtual ObjectBase
: public ObjectBase {
{ friend class AudioEngine;
friend class AudioEngine;
public: public:
Sound(); Sound();
virtual ~Sound(); virtual ~Sound();
/// \~chinese /// \~chinese
/// @brief 打开本地音频文件 /// @brief 打开本地音频文件
/// @param res 本地音频文件路径 /// @param res 本地音频文件路径
bool Load(String const& file_path); bool Load(String const& file_path);
/// \~chinese /// \~chinese
/// @brief 打开音频资源 /// @brief 打开音频资源
/// @param res 音频资源 /// @param res 音频资源
bool Load(Resource const& res); bool Load(Resource const& res);
/// \~chinese /// \~chinese
/// @brief 是否有效 /// @brief 是否有效
bool IsValid() const; bool IsValid() const;
/// \~chinese /// \~chinese
/// @brief 播放 /// @brief 播放
/// @param loop_count 播放循环次数,设置 -1 为循环播放 /// @param loop_count 播放循环次数,设置 -1 为循环播放
void Play(int loop_count = 0); void Play(int loop_count = 0);
/// \~chinese /// \~chinese
/// @brief 暂停 /// @brief 暂停
void Pause(); void Pause();
/// \~chinese /// \~chinese
/// @brief 继续 /// @brief 继续
void Resume(); void Resume();
/// \~chinese /// \~chinese
/// @brief 停止 /// @brief 停止
void Stop(); void Stop();
/// \~chinese /// \~chinese
/// @brief 关闭并销毁资源 /// @brief 关闭并销毁资源
void Close(); void Close();
/// \~chinese /// \~chinese
/// @brief 是否正在播放 /// @brief 是否正在播放
bool IsPlaying() const; bool IsPlaying() const;
/// \~chinese /// \~chinese
/// @brief 获取音量 /// @brief 获取音量
float GetVolume() const; float GetVolume() const;
/// \~chinese /// \~chinese
/// @brief 设置音量 /// @brief 设置音量
/// @param volume 音量大小1.0 为原始音量, 大于 1 为放大音量, 0 为最小音量 /// @param volume 音量大小1.0 为原始音量, 大于 1 为放大音量, 0 为最小音量
void SetVolume(float volume); void SetVolume(float volume);
private: private:
IXAudio2SourceVoice* GetXAudio2Voice() const; IXAudio2SourceVoice* GetXAudio2Voice() const;
void SetXAudio2Voice(IXAudio2SourceVoice* voice); void SetXAudio2Voice(IXAudio2SourceVoice* voice);
private: private:
bool opened_; bool opened_;
bool playing_; bool playing_;
Transcoder transcoder_; Transcoder transcoder_;
IXAudio2SourceVoice* voice_; IXAudio2SourceVoice* voice_;
}; };
/** @} */ /** @} */
inline IXAudio2SourceVoice* Sound::GetXAudio2Voice() const
inline IXAudio2SourceVoice* Sound::GetXAudio2Voice() const {
{ return voice_;
return voice_;
}
inline void Sound::SetXAudio2Voice(IXAudio2SourceVoice* voice)
{
voice_ = voice;
}
}
} }
inline void Sound::SetXAudio2Voice(IXAudio2SourceVoice* voice)
{
voice_ = voice;
}
} // namespace audio
} // namespace kiwano

View File

@ -1,15 +1,15 @@
// Copyright (c) 2016-2018 Kiwano - Nomango // Copyright (c) 2016-2018 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -22,135 +22,135 @@
namespace kiwano namespace kiwano
{ {
namespace audio namespace audio
{ {
SoundPlayer::SoundPlayer() SoundPlayer::SoundPlayer()
: volume_(1.f) : volume_(1.f)
{ {
}
SoundPlayer::~SoundPlayer()
{
ClearCache();
}
size_t SoundPlayer::Load(String const& file_path)
{
int hash_code = static_cast<int>(file_path.hash());
if (sound_cache_.end() != sound_cache_.find(hash_code))
return hash_code;
SoundPtr sound = new (std::nothrow) Sound;
if (sound)
{
if (sound->Load(file_path))
{
sound->SetVolume(volume_);
sound_cache_.insert(std::make_pair(hash_code, sound));
return hash_code;
}
}
return 0;
}
size_t SoundPlayer::Load(Resource const& res)
{
size_t hash_code = static_cast<size_t>(res.GetId());
if (sound_cache_.end() != sound_cache_.find(hash_code))
return hash_code;
SoundPtr sound = new (std::nothrow) Sound;
if (sound)
{
if (sound->Load(res))
{
sound->SetVolume(volume_);
sound_cache_.insert(std::make_pair(hash_code, sound));
return hash_code;
}
}
return 0;
}
void SoundPlayer::Play(size_t id, int loop_count)
{
auto iter = sound_cache_.find(id);
if (sound_cache_.end() != iter)
iter->second->Play(loop_count);
}
void SoundPlayer::Pause(size_t id)
{
auto iter = sound_cache_.find(id);
if (sound_cache_.end() != iter)
iter->second->Pause();
}
void SoundPlayer::Resume(size_t id)
{
auto iter = sound_cache_.find(id);
if (sound_cache_.end() != iter)
iter->second->Resume();
}
void SoundPlayer::Stop(size_t id)
{
auto iter = sound_cache_.find(id);
if (sound_cache_.end() != iter)
iter->second->Stop();
}
bool SoundPlayer::IsPlaying(size_t id)
{
auto iter = sound_cache_.find(id);
if (sound_cache_.end() != iter)
return iter->second->IsPlaying();
return false;
}
float SoundPlayer::GetVolume() const
{
return volume_;
}
void SoundPlayer::SetVolume(float volume)
{
volume_ = std::min(std::max(volume, -224.f), 224.f);
for (auto& pair : sound_cache_)
{
pair.second->SetVolume(volume_);
}
}
void SoundPlayer::PauseAll()
{
for (auto& pair : sound_cache_)
{
pair.second->Pause();
}
}
void SoundPlayer::ResumeAll()
{
for (auto& pair : sound_cache_)
{
pair.second->Resume();
}
}
void SoundPlayer::StopAll()
{
for (auto& pair : sound_cache_)
{
pair.second->Stop();
}
}
void SoundPlayer::ClearCache()
{
sound_cache_.clear();
}
}
} }
SoundPlayer::~SoundPlayer()
{
ClearCache();
}
size_t SoundPlayer::Load(String const& file_path)
{
int hash_code = static_cast<int>(file_path.hash());
if (sound_cache_.end() != sound_cache_.find(hash_code))
return hash_code;
SoundPtr sound = new (std::nothrow) Sound;
if (sound)
{
if (sound->Load(file_path))
{
sound->SetVolume(volume_);
sound_cache_.insert(std::make_pair(hash_code, sound));
return hash_code;
}
}
return 0;
}
size_t SoundPlayer::Load(Resource const& res)
{
size_t hash_code = static_cast<size_t>(res.GetId());
if (sound_cache_.end() != sound_cache_.find(hash_code))
return hash_code;
SoundPtr sound = new (std::nothrow) Sound;
if (sound)
{
if (sound->Load(res))
{
sound->SetVolume(volume_);
sound_cache_.insert(std::make_pair(hash_code, sound));
return hash_code;
}
}
return 0;
}
void SoundPlayer::Play(size_t id, int loop_count)
{
auto iter = sound_cache_.find(id);
if (sound_cache_.end() != iter)
iter->second->Play(loop_count);
}
void SoundPlayer::Pause(size_t id)
{
auto iter = sound_cache_.find(id);
if (sound_cache_.end() != iter)
iter->second->Pause();
}
void SoundPlayer::Resume(size_t id)
{
auto iter = sound_cache_.find(id);
if (sound_cache_.end() != iter)
iter->second->Resume();
}
void SoundPlayer::Stop(size_t id)
{
auto iter = sound_cache_.find(id);
if (sound_cache_.end() != iter)
iter->second->Stop();
}
bool SoundPlayer::IsPlaying(size_t id)
{
auto iter = sound_cache_.find(id);
if (sound_cache_.end() != iter)
return iter->second->IsPlaying();
return false;
}
float SoundPlayer::GetVolume() const
{
return volume_;
}
void SoundPlayer::SetVolume(float volume)
{
volume_ = std::min(std::max(volume, -224.f), 224.f);
for (auto& pair : sound_cache_)
{
pair.second->SetVolume(volume_);
}
}
void SoundPlayer::PauseAll()
{
for (auto& pair : sound_cache_)
{
pair.second->Pause();
}
}
void SoundPlayer::ResumeAll()
{
for (auto& pair : sound_cache_)
{
pair.second->Resume();
}
}
void SoundPlayer::StopAll()
{
for (auto& pair : sound_cache_)
{
pair.second->Stop();
}
}
void SoundPlayer::ClearCache()
{
sound_cache_.clear();
}
} // namespace audio
} // namespace kiwano

View File

@ -1,15 +1,15 @@
// Copyright (c) 2016-2018 Kiwano - Nomango // Copyright (c) 2016-2018 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -19,102 +19,101 @@
// THE SOFTWARE. // THE SOFTWARE.
#pragma once #pragma once
#include <kiwano/core/ObjectBase.h>
#include <kiwano-audio/Sound.h> #include <kiwano-audio/Sound.h>
#include <kiwano/core/ObjectBase.h>
namespace kiwano namespace kiwano
{ {
namespace audio namespace audio
{ {
KGE_DECLARE_SMART_PTR(SoundPlayer); KGE_DECLARE_SMART_PTR(SoundPlayer);
/** /**
* \addtogroup Audio * \addtogroup Audio
* @{ * @{
*/ */
/** /**
* \~chinese * \~chinese
* @brief * @brief
*/ */
class KGE_API SoundPlayer class KGE_API SoundPlayer : public virtual ObjectBase
: public ObjectBase {
{ public:
public: SoundPlayer();
SoundPlayer();
~SoundPlayer(); ~SoundPlayer();
/// \~chinese /// \~chinese
/// @brief 加载本地音频文件 /// @brief 加载本地音频文件
/// @param file_path 本地音频文件路径 /// @param file_path 本地音频文件路径
/// @return 音频标识符 /// @return 音频标识符
size_t Load(String const& file_path); size_t Load(String const& file_path);
/// \~chinese /// \~chinese
/// @brief 加载音频资源 /// @brief 加载音频资源
/// @param res 音频资源 /// @param res 音频资源
/// @return 音频标识符 /// @return 音频标识符
size_t Load(Resource const& res); size_t Load(Resource const& res);
/// \~chinese /// \~chinese
/// @brief 播放音频 /// @brief 播放音频
/// @param id 音频标识符 /// @param id 音频标识符
/// @param loop_count 播放循环次数,设置 -1 为循环播放 /// @param loop_count 播放循环次数,设置 -1 为循环播放
void Play(size_t id, int loop_count = 0); void Play(size_t id, int loop_count = 0);
/// \~chinese /// \~chinese
/// @brief 暂停音频 /// @brief 暂停音频
/// @param id 音频标识符 /// @param id 音频标识符
void Pause(size_t id); void Pause(size_t id);
/// \~chinese /// \~chinese
/// @brief 继续播放音频 /// @brief 继续播放音频
/// @param id 音频标识符 /// @param id 音频标识符
void Resume(size_t id); void Resume(size_t id);
/// \~chinese /// \~chinese
/// @brief 停止音频 /// @brief 停止音频
/// @param id 音频标识符 /// @param id 音频标识符
void Stop(size_t id); void Stop(size_t id);
/// \~chinese /// \~chinese
/// @brief 获取音频播放状态 /// @brief 获取音频播放状态
/// @param id 音频标识符 /// @param id 音频标识符
bool IsPlaying(size_t id); bool IsPlaying(size_t id);
/// \~chinese /// \~chinese
/// @brief 获取音量 /// @brief 获取音量
float GetVolume() const; float GetVolume() const;
/// \~chinese /// \~chinese
/// @brief 设置音量 /// @brief 设置音量
/// @param volume 音量大小1.0 为原始音量, 大于 1 为放大音量, 0 为最小音量 /// @param volume 音量大小1.0 为原始音量, 大于 1 为放大音量, 0 为最小音量
void SetVolume(float volume); void SetVolume(float volume);
/// \~chinese /// \~chinese
/// @brief 暂停所有音频 /// @brief 暂停所有音频
void PauseAll(); void PauseAll();
/// \~chinese /// \~chinese
/// @brief 继续播放所有音频 /// @brief 继续播放所有音频
void ResumeAll(); void ResumeAll();
/// \~chinese /// \~chinese
/// @brief 停止所有音频 /// @brief 停止所有音频
void StopAll(); void StopAll();
/// \~chinese /// \~chinese
/// @brief 清除缓存 /// @brief 清除缓存
void ClearCache(); void ClearCache();
private: private:
float volume_; float volume_;
using SoundMap = Map<size_t, SoundPtr>; using SoundMap = Map<size_t, SoundPtr>;
SoundMap sound_cache_; SoundMap sound_cache_;
}; };
/** @} */ /** @} */
} } // namespace audio
} } // namespace kiwano

View File

@ -1,15 +1,15 @@
// Copyright (c) 2016-2018 Kiwano - Nomango // Copyright (c) 2016-2018 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -19,280 +19,252 @@
// THE SOFTWARE. // THE SOFTWARE.
#ifndef INITGUID #ifndef INITGUID
# define INITGUID // MFAudioFormat_PCM, MF_MT_MAJOR_TYPE, MF_MT_SUBTYPE, MFMediaType_Audio #define INITGUID // MFAudioFormat_PCM, MF_MT_MAJOR_TYPE, MF_MT_SUBTYPE, MFMediaType_Audio
#endif #endif
#include <kiwano/macros.h> #include <kiwano-audio/Transcoder.h>
#include <kiwano/core/common.h> #include <kiwano-audio/libraries.h>
#include <kiwano/core/Resource.h> #include <kiwano/core/Common.h>
#include <kiwano/core/Logger.h> #include <kiwano/core/Logger.h>
#include <kiwano/core/Resource.h>
#include <kiwano/macros.h>
#include <kiwano/platform/win32/ComPtr.hpp> #include <kiwano/platform/win32/ComPtr.hpp>
#include <kiwano/platform/win32/libraries.h> #include <kiwano/platform/win32/libraries.h>
#include <kiwano-audio/libraries.h>
#include <kiwano-audio/Transcoder.h>
namespace kiwano namespace kiwano
{ {
namespace audio namespace audio
{ {
Transcoder::Transcoder() Transcoder::Transcoder()
: wave_format_(nullptr) : wave_format_(nullptr)
, wave_data_(nullptr) , wave_data_(nullptr)
, wave_size_(0) , wave_size_(0)
{ {
}
Transcoder::~Transcoder()
{
ClearBuffer();
}
Transcoder::Buffer Transcoder::GetBuffer() const
{
return Buffer{ wave_data_, wave_size_, wave_format_ };
}
void Transcoder::ClearBuffer()
{
if (wave_format_)
{
::CoTaskMemFree(wave_format_);
wave_format_ = nullptr;
}
if (wave_data_)
{
delete[] wave_data_;
wave_data_ = nullptr;
}
wave_size_ = 0;
}
HRESULT Transcoder::LoadMediaFile(String const& file_path)
{
HRESULT hr = S_OK;
ComPtr<IMFSourceReader> reader;
hr = dlls::MediaFoundation::Get().MFCreateSourceReaderFromURL(
file_path.c_str(),
nullptr,
&reader
);
if (SUCCEEDED(hr))
{
hr = ReadSource(reader.get());
}
return hr;
}
HRESULT Transcoder::LoadMediaResource(Resource const& res)
{
HRESULT hr = S_OK;
ComPtr<IStream> stream;
ComPtr<IMFByteStream> byte_stream;
ComPtr<IMFSourceReader> reader;
Resource::Data data = res.GetData();
if (!data) { return E_FAIL; }
stream = win32::dlls::Shlwapi::Get().SHCreateMemStream(
static_cast<const BYTE*>(data.buffer),
static_cast<uint32_t>(data.size)
);
if (stream == nullptr)
{
KGE_ERROR(L"SHCreateMemStream failed");
return E_OUTOFMEMORY;
}
if (SUCCEEDED(hr))
{
hr = dlls::MediaFoundation::Get().MFCreateMFByteStreamOnStream(stream.get(), &byte_stream);
}
if (SUCCEEDED(hr))
{
hr = dlls::MediaFoundation::Get().MFCreateSourceReaderFromByteStream(
byte_stream.get(),
nullptr,
&reader
);
}
if (SUCCEEDED(hr))
{
hr = ReadSource(reader.get());
}
return hr;
}
HRESULT Transcoder::ReadSource(IMFSourceReader* reader)
{
HRESULT hr = S_OK;
DWORD max_stream_size = 0;
ComPtr<IMFMediaType> partial_type;
ComPtr<IMFMediaType> uncompressed_type;
hr = dlls::MediaFoundation::Get().MFCreateMediaType(&partial_type);
if (SUCCEEDED(hr))
{
hr = partial_type->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio);
}
if (SUCCEEDED(hr))
{
hr = partial_type->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_PCM);
}
// 设置 source reader 的媒体类型,它将使用合适的解码器去解码这个音频
if (SUCCEEDED(hr))
{
hr = reader->SetCurrentMediaType(
(DWORD)MF_SOURCE_READER_FIRST_AUDIO_STREAM,
0,
partial_type.get()
);
}
// 从 IMFMediaType 中获取 WAVEFORMAT 结构
if (SUCCEEDED(hr))
{
hr = reader->GetCurrentMediaType(
(DWORD)MF_SOURCE_READER_FIRST_AUDIO_STREAM,
&uncompressed_type
);
}
// 指定音频流
if (SUCCEEDED(hr))
{
hr = reader->SetStreamSelection(
(DWORD)MF_SOURCE_READER_FIRST_AUDIO_STREAM,
true
);
}
// 获取 WAVEFORMAT 数据
if (SUCCEEDED(hr))
{
uint32_t size = 0;
hr = dlls::MediaFoundation::Get().MFCreateWaveFormatExFromMFMediaType(
uncompressed_type.get(),
&wave_format_,
&size,
(DWORD)MFWaveFormatExConvertFlag_Normal
);
}
// 估算音频流大小
if (SUCCEEDED(hr))
{
PROPVARIANT prop;
PropVariantInit(&prop);
hr = reader->GetPresentationAttribute(
(DWORD)MF_SOURCE_READER_MEDIASOURCE,
MF_PD_DURATION,
&prop
);
LONGLONG duration = prop.uhVal.QuadPart;
max_stream_size = static_cast<DWORD>(
(duration * wave_format_->nAvgBytesPerSec) / 10000000 + 1
);
PropVariantClear(&prop);
}
// 读取音频数据
if (SUCCEEDED(hr))
{
DWORD flags = 0;
DWORD position = 0;
BYTE* data = new (std::nothrow) BYTE[max_stream_size];
ComPtr<IMFSample> sample;
ComPtr<IMFMediaBuffer> buffer;
if (data == nullptr)
{
KGE_ERROR(L"Low memory");
hr = E_OUTOFMEMORY;
}
else
{
while (true)
{
hr = reader->ReadSample(
(DWORD)MF_SOURCE_READER_FIRST_AUDIO_STREAM,
0,
nullptr,
&flags,
nullptr,
&sample
);
if (flags & MF_SOURCE_READERF_ENDOFSTREAM) { break; }
if (sample == nullptr) { continue; }
if (SUCCEEDED(hr))
{
hr = sample->ConvertToContiguousBuffer(&buffer);
if (SUCCEEDED(hr))
{
BYTE* audio_data = nullptr;
DWORD sample_buffer_length = 0;
hr = buffer->Lock(
&audio_data,
nullptr,
&sample_buffer_length
);
if (position + sample_buffer_length >= max_stream_size)
{
hr = E_FAIL;
}
if (SUCCEEDED(hr))
{
::memcpy(data + position, audio_data, sample_buffer_length);
position += sample_buffer_length;
hr = buffer->Unlock();
}
}
buffer = nullptr;
}
sample = nullptr;
if (FAILED(hr)) { break; }
}
if (SUCCEEDED(hr))
{
wave_data_ = data;
wave_size_ = position;
}
else
{
delete[] data;
data = nullptr;
}
}
}
return hr;
}
}
} }
Transcoder::~Transcoder()
{
ClearBuffer();
}
Transcoder::Buffer Transcoder::GetBuffer() const
{
return Buffer{ wave_data_, wave_size_, wave_format_ };
}
void Transcoder::ClearBuffer()
{
if (wave_format_)
{
::CoTaskMemFree(wave_format_);
wave_format_ = nullptr;
}
if (wave_data_)
{
delete[] wave_data_;
wave_data_ = nullptr;
}
wave_size_ = 0;
}
HRESULT Transcoder::LoadMediaFile(String const& file_path)
{
HRESULT hr = S_OK;
ComPtr<IMFSourceReader> reader;
hr = dlls::MediaFoundation::Get().MFCreateSourceReaderFromURL(file_path.c_str(), nullptr, &reader);
if (SUCCEEDED(hr))
{
hr = ReadSource(reader.get());
}
return hr;
}
HRESULT Transcoder::LoadMediaResource(Resource const& res)
{
HRESULT hr = S_OK;
ComPtr<IStream> stream;
ComPtr<IMFByteStream> byte_stream;
ComPtr<IMFSourceReader> reader;
Resource::Data data = res.GetData();
if (!data)
{
return E_FAIL;
}
stream = win32::dlls::Shlwapi::Get().SHCreateMemStream(static_cast<const BYTE*>(data.buffer),
static_cast<uint32_t>(data.size));
if (stream == nullptr)
{
KGE_ERROR(L"SHCreateMemStream failed");
return E_OUTOFMEMORY;
}
if (SUCCEEDED(hr))
{
hr = dlls::MediaFoundation::Get().MFCreateMFByteStreamOnStream(stream.get(), &byte_stream);
}
if (SUCCEEDED(hr))
{
hr = dlls::MediaFoundation::Get().MFCreateSourceReaderFromByteStream(byte_stream.get(), nullptr, &reader);
}
if (SUCCEEDED(hr))
{
hr = ReadSource(reader.get());
}
return hr;
}
HRESULT Transcoder::ReadSource(IMFSourceReader* reader)
{
HRESULT hr = S_OK;
DWORD max_stream_size = 0;
ComPtr<IMFMediaType> partial_type;
ComPtr<IMFMediaType> uncompressed_type;
hr = dlls::MediaFoundation::Get().MFCreateMediaType(&partial_type);
if (SUCCEEDED(hr))
{
hr = partial_type->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio);
}
if (SUCCEEDED(hr))
{
hr = partial_type->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_PCM);
}
// 设置 source reader 的媒体类型,它将使用合适的解码器去解码这个音频
if (SUCCEEDED(hr))
{
hr = reader->SetCurrentMediaType((DWORD)MF_SOURCE_READER_FIRST_AUDIO_STREAM, 0, partial_type.get());
}
// 从 IMFMediaType 中获取 WAVEFORMAT 结构
if (SUCCEEDED(hr))
{
hr = reader->GetCurrentMediaType((DWORD)MF_SOURCE_READER_FIRST_AUDIO_STREAM, &uncompressed_type);
}
// 指定音频流
if (SUCCEEDED(hr))
{
hr = reader->SetStreamSelection((DWORD)MF_SOURCE_READER_FIRST_AUDIO_STREAM, true);
}
// 获取 WAVEFORMAT 数据
if (SUCCEEDED(hr))
{
uint32_t size = 0;
hr = dlls::MediaFoundation::Get().MFCreateWaveFormatExFromMFMediaType(
uncompressed_type.get(), &wave_format_, &size, (DWORD)MFWaveFormatExConvertFlag_Normal);
}
// 估算音频流大小
if (SUCCEEDED(hr))
{
PROPVARIANT prop;
PropVariantInit(&prop);
hr = reader->GetPresentationAttribute((DWORD)MF_SOURCE_READER_MEDIASOURCE, MF_PD_DURATION, &prop);
LONGLONG duration = prop.uhVal.QuadPart;
max_stream_size = static_cast<DWORD>((duration * wave_format_->nAvgBytesPerSec) / 10000000 + 1);
PropVariantClear(&prop);
}
// 读取音频数据
if (SUCCEEDED(hr))
{
DWORD flags = 0;
DWORD position = 0;
BYTE* data = new (std::nothrow) BYTE[max_stream_size];
ComPtr<IMFSample> sample;
ComPtr<IMFMediaBuffer> buffer;
if (data == nullptr)
{
KGE_ERROR(L"Low memory");
hr = E_OUTOFMEMORY;
}
else
{
while (true)
{
hr = reader->ReadSample((DWORD)MF_SOURCE_READER_FIRST_AUDIO_STREAM, 0, nullptr, &flags, nullptr,
&sample);
if (flags & MF_SOURCE_READERF_ENDOFSTREAM)
{
break;
}
if (sample == nullptr)
{
continue;
}
if (SUCCEEDED(hr))
{
hr = sample->ConvertToContiguousBuffer(&buffer);
if (SUCCEEDED(hr))
{
BYTE* audio_data = nullptr;
DWORD sample_buffer_length = 0;
hr = buffer->Lock(&audio_data, nullptr, &sample_buffer_length);
if (position + sample_buffer_length >= max_stream_size)
{
hr = E_FAIL;
}
if (SUCCEEDED(hr))
{
::memcpy(data + position, audio_data, sample_buffer_length);
position += sample_buffer_length;
hr = buffer->Unlock();
}
}
buffer = nullptr;
}
sample = nullptr;
if (FAILED(hr))
{
break;
}
}
if (SUCCEEDED(hr))
{
wave_data_ = data;
wave_size_ = position;
}
else
{
delete[] data;
data = nullptr;
}
}
}
return hr;
}
} // namespace audio
} // namespace kiwano

View File

@ -1,15 +1,15 @@
// Copyright (c) 2016-2018 Kiwano - Nomango // Copyright (c) 2016-2018 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -26,66 +26,66 @@
namespace kiwano namespace kiwano
{ {
namespace audio namespace audio
{ {
class Sound; class Sound;
/** /**
* \addtogroup Audio * \addtogroup Audio
* @{ * @{
*/ */
/** /**
* \~chinese * \~chinese
* @brief * @brief
*/ */
class KGE_API Transcoder class KGE_API Transcoder
{ {
friend class Sound; friend class Sound;
public: public:
/** /**
* \~chinese * \~chinese
* @brief * @brief
*/ */
struct Buffer struct Buffer
{ {
BYTE* data; ///< 音频数据 BYTE* data; ///< 音频数据
uint32_t size; ///< 音频数据大小 uint32_t size; ///< 音频数据大小
const WAVEFORMATEX* format; ///< 音频数据格式 const WAVEFORMATEX* format; ///< 音频数据格式
}; };
Transcoder(); Transcoder();
~Transcoder(); ~Transcoder();
/// \~chinese /// \~chinese
/// @brief 获取数据缓冲 /// @brief 获取数据缓冲
Buffer GetBuffer() const; Buffer GetBuffer() const;
/// \~chinese /// \~chinese
/// @brief 清空数据缓冲 /// @brief 清空数据缓冲
void ClearBuffer(); void ClearBuffer();
private: private:
/// \~chinese /// \~chinese
/// @brief 解码本地音频文件 /// @brief 解码本地音频文件
HRESULT LoadMediaFile(String const& file_path); HRESULT LoadMediaFile(String const& file_path);
/// \~chinese /// \~chinese
/// @brief 解码音频资源 /// @brief 解码音频资源
HRESULT LoadMediaResource(Resource const& res); HRESULT LoadMediaResource(Resource const& res);
/// \~chinese /// \~chinese
/// @brief 读取音频源数据 /// @brief 读取音频源数据
HRESULT ReadSource(IMFSourceReader* reader); HRESULT ReadSource(IMFSourceReader* reader);
private: private:
BYTE* wave_data_; BYTE* wave_data_;
uint32_t wave_size_; uint32_t wave_size_;
WAVEFORMATEX* wave_format_; WAVEFORMATEX* wave_format_;
}; };
/** @} */ /** @} */
} } // namespace audio
} } // namespace kiwano

View File

@ -1,15 +1,15 @@
// Copyright (c) 2016-2018 Kiwano - Nomango // Copyright (c) 2016-2018 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE

View File

@ -1,15 +1,15 @@
// Copyright (c) 2016-2018 Kiwano - Nomango // Copyright (c) 2016-2018 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -18,81 +18,84 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE. // THE SOFTWARE.
#include <kiwano/core/Logger.h>
#include <kiwano-audio/libraries.h> #include <kiwano-audio/libraries.h>
#include <kiwano/core/Logger.h>
namespace kiwano namespace kiwano
{ {
namespace audio namespace audio
{ {
namespace dlls namespace dlls
{ {
XAudio2::XAudio2() XAudio2::XAudio2()
: xaudio2() : xaudio2()
, XAudio2Create(nullptr) , XAudio2Create(nullptr)
{ {
const auto xaudio2_dll_names = const auto xaudio2_dll_names = {
{ "xaudio2_9.dll", // for Windows 10
"xaudio2_9.dll", // for Windows 10 "xaudio2_8.dll", // for Windows 8
"xaudio2_8.dll", // for Windows 8 "xaudio2_7.dll" // for DirectX SDK
"xaudio2_7.dll" // for DirectX SDK };
};
for (const auto& name : xaudio2_dll_names) for (const auto& name : xaudio2_dll_names)
{ {
if (xaudio2.Load(name)) if (xaudio2.Load(name))
{ {
break; break;
} }
} }
if (xaudio2.IsValid()) if (xaudio2.IsValid())
{ {
XAudio2Create = xaudio2.GetProcess<PFN_XAudio2Create>("XAudio2Create"); XAudio2Create = xaudio2.GetProcess<PFN_XAudio2Create>("XAudio2Create");
} }
else else
{ {
KGE_ERROR(L"Load xaudio2.dll failed"); KGE_ERROR(L"Load xaudio2.dll failed");
throw std::runtime_error("Load xaudio2.dll failed"); throw std::runtime_error("Load xaudio2.dll failed");
} }
}
MediaFoundation::MediaFoundation()
: mfplat()
, mfreadwrite()
, MFStartup(nullptr)
, MFShutdown(nullptr)
, MFCreateMediaType(nullptr)
, MFCreateWaveFormatExFromMFMediaType(nullptr)
, MFCreateSourceReaderFromURL(nullptr)
, MFCreateSourceReaderFromByteStream(nullptr)
, MFCreateMFByteStreamOnStream(nullptr)
{
if (mfplat.Load("Mfplat.dll"))
{
MFStartup = mfplat.GetProcess<PFN_MFStartup>("MFStartup");
MFShutdown = mfplat.GetProcess<PFN_MFShutdown>("MFShutdown");
MFCreateMediaType = mfplat.GetProcess<PFN_MFCreateMediaType>("MFCreateMediaType");
MFCreateWaveFormatExFromMFMediaType = mfplat.GetProcess<PFN_MFCreateWaveFormatExFromMFMediaType>("MFCreateWaveFormatExFromMFMediaType");
MFCreateMFByteStreamOnStream = mfplat.GetProcess<PFN_MFCreateMFByteStreamOnStream>("MFCreateMFByteStreamOnStream");
}
else
{
KGE_ERROR(L"Load Mfplat.dll failed");
throw std::runtime_error("Load Mfplat.dll failed");
}
if (mfreadwrite.Load("Mfreadwrite.dll"))
{
MFCreateSourceReaderFromURL = mfreadwrite.GetProcess<PFN_MFCreateSourceReaderFromURL>("MFCreateSourceReaderFromURL");
MFCreateSourceReaderFromByteStream = mfreadwrite.GetProcess<PFN_MFCreateSourceReaderFromByteStream>("MFCreateSourceReaderFromByteStream");
}
else
{
KGE_ERROR(L"Load Mfreadwrite.dll failed");
throw std::runtime_error("Load Mfreadwrite.dll failed");
}
}
}
}
} }
MediaFoundation::MediaFoundation()
: mfplat()
, mfreadwrite()
, MFStartup(nullptr)
, MFShutdown(nullptr)
, MFCreateMediaType(nullptr)
, MFCreateWaveFormatExFromMFMediaType(nullptr)
, MFCreateSourceReaderFromURL(nullptr)
, MFCreateSourceReaderFromByteStream(nullptr)
, MFCreateMFByteStreamOnStream(nullptr)
{
if (mfplat.Load("Mfplat.dll"))
{
MFStartup = mfplat.GetProcess<PFN_MFStartup>("MFStartup");
MFShutdown = mfplat.GetProcess<PFN_MFShutdown>("MFShutdown");
MFCreateMediaType = mfplat.GetProcess<PFN_MFCreateMediaType>("MFCreateMediaType");
MFCreateWaveFormatExFromMFMediaType =
mfplat.GetProcess<PFN_MFCreateWaveFormatExFromMFMediaType>("MFCreateWaveFormatExFromMFMediaType");
MFCreateMFByteStreamOnStream =
mfplat.GetProcess<PFN_MFCreateMFByteStreamOnStream>("MFCreateMFByteStreamOnStream");
}
else
{
KGE_ERROR(L"Load Mfplat.dll failed");
throw std::runtime_error("Load Mfplat.dll failed");
}
if (mfreadwrite.Load("Mfreadwrite.dll"))
{
MFCreateSourceReaderFromURL =
mfreadwrite.GetProcess<PFN_MFCreateSourceReaderFromURL>("MFCreateSourceReaderFromURL");
MFCreateSourceReaderFromByteStream =
mfreadwrite.GetProcess<PFN_MFCreateSourceReaderFromByteStream>("MFCreateSourceReaderFromByteStream");
}
else
{
KGE_ERROR(L"Load Mfreadwrite.dll failed");
throw std::runtime_error("Load Mfreadwrite.dll failed");
}
}
} // namespace dlls
} // namespace audio
} // namespace kiwano

View File

@ -1,15 +1,15 @@
// Copyright (c) 2016-2018 Kiwano - Nomango // Copyright (c) 2016-2018 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -20,80 +20,79 @@
#pragma once #pragma once
#include <kiwano/core/Library.h> #include <kiwano/core/Library.h>
#include <xaudio2.h>
#include <mfapi.h> #include <mfapi.h>
#include <mfidl.h> #include <mfidl.h>
#include <mfreadwrite.h> #include <mfreadwrite.h>
#include <xaudio2.h>
#ifndef KGE_DOXYGEN_DO_NOT_INCLUDE #ifndef KGE_DOXYGEN_DO_NOT_INCLUDE
namespace kiwano namespace kiwano
{ {
namespace audio namespace audio
{ {
namespace dlls namespace dlls
{ {
class KGE_API XAudio2 class KGE_API XAudio2
{ {
public: public:
static inline XAudio2& Get() static inline XAudio2& Get()
{ {
static XAudio2 instance; static XAudio2 instance;
return instance; return instance;
} }
// XAudio2 functions // XAudio2 functions
typedef HRESULT(WINAPI* PFN_XAudio2Create)(IXAudio2**, UINT32, XAUDIO2_PROCESSOR); typedef HRESULT(WINAPI* PFN_XAudio2Create)(IXAudio2**, UINT32, XAUDIO2_PROCESSOR);
PFN_XAudio2Create XAudio2Create; PFN_XAudio2Create XAudio2Create;
private: private:
XAudio2(); XAudio2();
XAudio2(const XAudio2&) = delete; XAudio2(const XAudio2&) = delete;
XAudio2& operator=(const XAudio2&) = delete; XAudio2& operator=(const XAudio2&) = delete;
Library xaudio2; Library xaudio2;
}; };
class KGE_API MediaFoundation
{
public:
static inline MediaFoundation& Get()
{
static MediaFoundation instance;
return instance;
}
class KGE_API MediaFoundation // MediaFoundation functions
{ typedef HRESULT(WINAPI* PFN_MFStartup)(ULONG, DWORD);
public: typedef HRESULT(WINAPI* PFN_MFShutdown)();
static inline MediaFoundation& Get() typedef HRESULT(WINAPI* PFN_MFCreateMediaType)(IMFMediaType**);
{ typedef HRESULT(WINAPI* PFN_MFCreateWaveFormatExFromMFMediaType)(IMFMediaType*, WAVEFORMATEX**, UINT32*, UINT32);
static MediaFoundation instance; typedef HRESULT(WINAPI* PFN_MFCreateSourceReaderFromURL)(LPCWSTR, IMFAttributes*, IMFSourceReader**);
return instance; typedef HRESULT(WINAPI* PFN_MFCreateSourceReaderFromByteStream)(IMFByteStream*, IMFAttributes*, IMFSourceReader**);
} typedef HRESULT(WINAPI* PFN_MFCreateMFByteStreamOnStream)(IStream*, IMFByteStream**);
// MediaFoundation functions PFN_MFStartup MFStartup;
typedef HRESULT(WINAPI* PFN_MFStartup)(ULONG, DWORD); PFN_MFShutdown MFShutdown;
typedef HRESULT(WINAPI* PFN_MFShutdown)(); PFN_MFCreateMediaType MFCreateMediaType;
typedef HRESULT(WINAPI* PFN_MFCreateMediaType)(IMFMediaType**); PFN_MFCreateWaveFormatExFromMFMediaType MFCreateWaveFormatExFromMFMediaType;
typedef HRESULT(WINAPI* PFN_MFCreateWaveFormatExFromMFMediaType)(IMFMediaType*, WAVEFORMATEX**, UINT32*, UINT32); PFN_MFCreateSourceReaderFromURL MFCreateSourceReaderFromURL;
typedef HRESULT(WINAPI* PFN_MFCreateSourceReaderFromURL)(LPCWSTR, IMFAttributes*, IMFSourceReader**); PFN_MFCreateSourceReaderFromByteStream MFCreateSourceReaderFromByteStream;
typedef HRESULT(WINAPI* PFN_MFCreateSourceReaderFromByteStream)(IMFByteStream*, IMFAttributes*, IMFSourceReader**); PFN_MFCreateMFByteStreamOnStream MFCreateMFByteStreamOnStream;
typedef HRESULT(WINAPI* PFN_MFCreateMFByteStreamOnStream)(IStream*, IMFByteStream**);
PFN_MFStartup MFStartup; private:
PFN_MFShutdown MFShutdown; MediaFoundation();
PFN_MFCreateMediaType MFCreateMediaType;
PFN_MFCreateWaveFormatExFromMFMediaType MFCreateWaveFormatExFromMFMediaType;
PFN_MFCreateSourceReaderFromURL MFCreateSourceReaderFromURL;
PFN_MFCreateSourceReaderFromByteStream MFCreateSourceReaderFromByteStream;
PFN_MFCreateMFByteStreamOnStream MFCreateMFByteStreamOnStream;
private: MediaFoundation(const MediaFoundation&) = delete;
MediaFoundation(); MediaFoundation& operator=(const MediaFoundation&) = delete;
MediaFoundation(const MediaFoundation&) = delete; Library mfplat;
MediaFoundation& operator=(const MediaFoundation&) = delete; Library mfreadwrite;
};
Library mfplat; } // namespace dlls
Library mfreadwrite; } // namespace audio
}; } // namespace kiwano
}
}
}
#endif #endif

View File

@ -1,15 +1,15 @@
// Copyright (c) 2016-2018 Kiwano - Nomango // Copyright (c) 2016-2018 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -22,43 +22,45 @@
namespace kiwano namespace kiwano
{ {
namespace imgui namespace imgui
{ {
ImGuiLayer::ImGuiLayer() ImGuiLayer::ImGuiLayer()
{ {
SetSwallowEvents(true); SetSwallowEvents(true);
}
ImGuiLayer::~ImGuiLayer()
{
}
void ImGuiLayer::OnRender(RenderTarget* rt)
{
PrepareToRender(rt);
for (const auto& pipeline : pipelines_)
{
pipeline.second();
}
}
void ImGuiLayer::AddItem(ImGuiPipeline const& item, String const& name)
{
pipelines_.insert(std::make_pair(name, item));
}
void ImGuiLayer::RemoveItem(String const& name)
{
auto iter = pipelines_.find(name);
if (iter != pipelines_.end())
{
pipelines_.erase(iter);
}
}
void ImGuiLayer::RemoveAllItems()
{
pipelines_.clear();
}
}
} }
ImGuiLayer::~ImGuiLayer() {}
void ImGuiLayer::OnRender(RenderContext& ctx)
{
for (const auto& pipeline : pipelines_)
{
pipeline.second();
}
}
bool ImGuiLayer::CheckVisibility(RenderContext& ctx) const
{
return true;
}
void ImGuiLayer::AddItem(String const& name, ImGuiPipeline const& item)
{
pipelines_.insert(std::make_pair(name, item));
}
void ImGuiLayer::RemoveItem(String const& name)
{
auto iter = pipelines_.find(name);
if (iter != pipelines_.end())
{
pipelines_.erase(iter);
}
}
void ImGuiLayer::RemoveAllItems()
{
pipelines_.clear();
}
} // namespace imgui
} // namespace kiwano

View File

@ -1,15 +1,15 @@
// Copyright (c) 2016-2018 Kiwano - Nomango // Copyright (c) 2016-2018 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -23,47 +23,48 @@
namespace kiwano namespace kiwano
{ {
namespace imgui namespace imgui
{ {
KGE_DECLARE_SMART_PTR(ImGuiLayer); KGE_DECLARE_SMART_PTR(ImGuiLayer);
/// \~chinese /// \~chinese
/// @brief ImGui管道 /// @brief ImGui管道
using ImGuiPipeline = Function<void()>; using ImGuiPipeline = Function<void()>;
/** /**
* \~chinese * \~chinese
* @brief ImGui图层 * @brief ImGui图层
*/ */
class ImGuiLayer class ImGuiLayer : public Layer
: public Layer {
{ public:
public: ImGuiLayer();
ImGuiLayer();
virtual ~ImGuiLayer(); virtual ~ImGuiLayer();
/// \~chinese /// \~chinese
/// @brief 添加 ImGui 元素 /// @brief 添加 ImGui 元素
/// @param item 管道 /// @param name 元素名称
/// @param name 元素名称 /// @param item 管道
void AddItem(ImGuiPipeline const& item, String const& name); void AddItem(String const& name, ImGuiPipeline const& item);
/// \~chinese /// \~chinese
/// @brief 移除 ImGui 元素 /// @brief 移除 ImGui 元素
/// @param name 元素名称 /// @param name 元素名称
void RemoveItem(String const& name); void RemoveItem(String const& name);
// 移除所有元素 // 移除所有元素
/// \~chinese /// \~chinese
/// @brief 移除所有元素 /// @brief 移除所有元素
void RemoveAllItems(); void RemoveAllItems();
public: public:
void OnRender(RenderTarget* rt) override; void OnRender(RenderContext& ctx) override;
private: bool CheckVisibility(RenderContext& ctx) const override;
Map<String, ImGuiPipeline> pipelines_;
}; private:
} Map<String, ImGuiPipeline> pipelines_;
} };
} // namespace imgui
} // namespace kiwano

View File

@ -1,309 +1,236 @@
// Copyright (C) 2019 Nomango // Copyright (C) 2019 Nomango
#include <kiwano/core/common.h>
#include <kiwano/platform/Window.h> #include <kiwano/core/Common.h>
#include <kiwano/core/event/KeyEvent.h>
#include <kiwano/core/event/MouseEvent.h>
#include <kiwano/platform/Input.h> #include <kiwano/platform/Input.h>
#include <kiwano/renderer/Renderer.h> #include <kiwano/platform/Window.h>
#include <kiwano/render/Renderer.h>
#include <kiwano-imgui/ImGuiModule.h> #include <kiwano-imgui/ImGuiModule.h>
#include <kiwano-imgui/imgui_impl.h> #include <kiwano-imgui/imgui_impl.h>
#include <XInput.h>
#pragma comment(lib, "xinput")
// Allow compilation with old Windows SDK. MinGW doesn't have default _WIN32_WINNT/WINVER versions.
#ifndef WM_MOUSEHWHEEL
# define WM_MOUSEHWHEEL 0x020E
#endif
#ifndef DBT_DEVNODES_CHANGED
# define DBT_DEVNODES_CHANGED 0x0007
#endif
namespace kiwano namespace kiwano
{ {
namespace imgui namespace imgui
{ {
ImGuiModule::ImGuiModule() ImGuiModule::ImGuiModule()
: has_gamepad_(false) : target_window_(nullptr)
, want_update_has_gamepad_(false) {
, target_window_(nullptr)
{
}
void ImGuiModule::SetupComponent()
{
// Setup Dear ImGui context
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
// Setup Dear ImGui style
ImGui::StyleColorsDark();
//ImGui::StyleColorsClassic();
// Setup Platform/Renderer bindings
Init(Window::instance().GetHandle());
target_window_ = Renderer::instance().GetTargetWindow();
}
void ImGuiModule::DestroyComponent()
{
ImGui_Impl_Shutdown();
ImGui::DestroyContext();
}
void ImGuiModule::OnUpdate(Duration dt)
{
ImGuiIO& io = ImGui::GetIO();
// Setup time step
io.DeltaTime = dt.Seconds();
// Read keyboard modifiers inputs
io.KeyCtrl = Input::instance().IsDown(KeyCode::Ctrl);
io.KeyShift = Input::instance().IsDown(KeyCode::Shift);
io.KeyAlt = Input::instance().IsDown(KeyCode::Alt);
io.KeySuper = false;
// io.KeysDown[], io.MousePos, io.MouseDown[], io.MouseWheel: filled by the WndProc handler below.
// Update OS mouse position
UpdateMousePos();
// Update OS mouse cursor with the cursor requested by imgui
UpdateMouseCursor();
// Update game controllers (if enabled and available)
UpdateGamepads();
}
void ImGuiModule::Init(HWND hwnd)
{
ImGuiIO& io = ImGui::GetIO();
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used)
io.BackendPlatformName = "imgui_impl_win32";
io.ImeWindowHandle = hwnd;
// Keyboard mapping. ImGui will use those indices to peek into the io.KeysDown[] array that we will update during the application lifetime.
io.KeyMap[ImGuiKey_Tab] = KeyCode::Tab;
io.KeyMap[ImGuiKey_LeftArrow] = KeyCode::Left;
io.KeyMap[ImGuiKey_RightArrow] = KeyCode::Right;
io.KeyMap[ImGuiKey_UpArrow] = KeyCode::Up;
io.KeyMap[ImGuiKey_DownArrow] = KeyCode::Down;
io.KeyMap[ImGuiKey_Delete] = KeyCode::Delete;
io.KeyMap[ImGuiKey_Backspace] = KeyCode::Back;
io.KeyMap[ImGuiKey_Space] = KeyCode::Space;
io.KeyMap[ImGuiKey_Enter] = KeyCode::Enter;
io.KeyMap[ImGuiKey_Escape] = KeyCode::Esc;
io.KeyMap[ImGuiKey_A] = KeyCode::A;
io.KeyMap[ImGuiKey_C] = KeyCode::C;
io.KeyMap[ImGuiKey_V] = KeyCode::V;
io.KeyMap[ImGuiKey_X] = KeyCode::X;
io.KeyMap[ImGuiKey_Y] = KeyCode::Y;
io.KeyMap[ImGuiKey_Z] = KeyCode::Z;
ImGui_Impl_Init(&Renderer::instance());
}
void ImGuiModule::BeforeRender()
{
NewFrame();
}
void ImGuiModule::AfterRender()
{
Render();
}
void ImGuiModule::HandleMessage(HWND hwnd, UINT32 msg, WPARAM wparam, LPARAM lparam)
{
if (ImGui::GetCurrentContext() == NULL)
return;
ImGuiIO& io = ImGui::GetIO();
switch (msg)
{
case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK:
case WM_RBUTTONDOWN: case WM_RBUTTONDBLCLK:
case WM_MBUTTONDOWN: case WM_MBUTTONDBLCLK:
case WM_XBUTTONDOWN: case WM_XBUTTONDBLCLK:
{
int button = 0;
if (msg == WM_LBUTTONDOWN || msg == WM_LBUTTONDBLCLK) { button = 0; }
if (msg == WM_RBUTTONDOWN || msg == WM_RBUTTONDBLCLK) { button = 1; }
if (msg == WM_MBUTTONDOWN || msg == WM_MBUTTONDBLCLK) { button = 2; }
if (msg == WM_XBUTTONDOWN || msg == WM_XBUTTONDBLCLK) { button = (GET_XBUTTON_WPARAM(wparam) == XBUTTON1) ? 3 : 4; }
if (!ImGui::IsAnyMouseDown() && ::GetCapture() == NULL)
::SetCapture(hwnd);
io.MouseDown[button] = true;
break;
}
case WM_LBUTTONUP:
case WM_RBUTTONUP:
case WM_MBUTTONUP:
case WM_XBUTTONUP:
{
int button = 0;
if (msg == WM_LBUTTONUP) { button = 0; }
if (msg == WM_RBUTTONUP) { button = 1; }
if (msg == WM_MBUTTONUP) { button = 2; }
if (msg == WM_XBUTTONUP) { button = (GET_XBUTTON_WPARAM(wparam) == XBUTTON1) ? 3 : 4; }
io.MouseDown[button] = false;
if (!ImGui::IsAnyMouseDown() && ::GetCapture() == hwnd)
::ReleaseCapture();
break;
}
case WM_MOUSEWHEEL:
{
io.MouseWheel += (float)GET_WHEEL_DELTA_WPARAM(wparam) / (float)WHEEL_DELTA;
break;
}
case WM_MOUSEHWHEEL:
{
io.MouseWheelH += (float)GET_WHEEL_DELTA_WPARAM(wparam) / (float)WHEEL_DELTA;
break;
}
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
{
if (wparam < 256)
io.KeysDown[wparam] = 1;
break;
}
case WM_KEYUP:
case WM_SYSKEYUP:
{
if (wparam < 256)
io.KeysDown[wparam] = 0;
break;
}
case WM_CHAR:
{
// You can also use ToAscii()+GetKeyboardState() to retrieve characters.
io.AddInputCharacter((uint32_t)wparam);
break;
}
case WM_SETCURSOR:
{
if (LOWORD(lparam) == HTCLIENT)
{
UpdateMouseCursor();
}
break;
}
case WM_DEVICECHANGE:
{
if ((uint32_t)wparam == DBT_DEVNODES_CHANGED)
want_update_has_gamepad_ = true;
break;
}
}
}
void ImGuiModule::NewFrame()
{
ImGui_Impl_NewFrame();
ImGuiIO& io = ImGui::GetIO();
KGE_ASSERT(io.Fonts->IsBuilt() && "Font atlas not built!");
// Setup display size (every frame to accommodate for window resizing)
Size display_size = Renderer::instance().GetOutputSize();
io.DisplaySize = ImVec2(display_size.x, display_size.y);
ImGui::NewFrame();
}
void ImGuiModule::Render()
{
ImGui::Render();
ImGui_Impl_RenderDrawData(ImGui::GetDrawData());
}
void ImGuiModule::UpdateMousePos()
{
ImGuiIO& io = ImGui::GetIO();
// Set OS mouse position if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user)
if (io.WantSetMousePos)
{
POINT pos = { (int)io.MousePos.x, (int)io.MousePos.y };
::ClientToScreen(target_window_, &pos);
::SetCursorPos(pos.x, pos.y);
}
Point pos = Input::instance().GetMousePos();
io.MousePos = ImVec2(pos.x, pos.y);
}
void ImGuiModule::UpdateMouseCursor()
{
if (ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange)
return;
CursorType cursor = CursorType::Arrow;
switch (ImGui::GetMouseCursor())
{
case ImGuiMouseCursor_Arrow: cursor = CursorType::Arrow; break;
case ImGuiMouseCursor_TextInput: cursor = CursorType::TextInput; break;
case ImGuiMouseCursor_ResizeAll: cursor = CursorType::SizeAll; break;
case ImGuiMouseCursor_ResizeEW: cursor = CursorType::SizeWE; break;
case ImGuiMouseCursor_ResizeNS: cursor = CursorType::SizeNS; break;
case ImGuiMouseCursor_ResizeNESW: cursor = CursorType::SizeNESW; break;
case ImGuiMouseCursor_ResizeNWSE: cursor = CursorType::SizeNWSE; break;
case ImGuiMouseCursor_Hand: cursor = CursorType::Hand; break;
}
Window::instance().SetCursor(cursor);
}
void ImGuiModule::UpdateGamepads()
{
ImGuiIO& io = ImGui::GetIO();
memset(io.NavInputs, 0, sizeof(io.NavInputs));
if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0)
return;
// Calling XInputGetState() every frame on disconnected gamepads is unfortunately too slow.
// Instead we refresh gamepad availability by calling XInputGetCapabilities() _only_ after receiving WM_DEVICECHANGE.
if (want_update_has_gamepad_)
{
XINPUT_CAPABILITIES caps;
has_gamepad_ = (XInputGetCapabilities(0, XINPUT_FLAG_GAMEPAD, &caps) == ERROR_SUCCESS);
want_update_has_gamepad_ = false;
}
XINPUT_STATE xinput_state;
io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad;
if (has_gamepad_ && XInputGetState(0, &xinput_state) == ERROR_SUCCESS)
{
const XINPUT_GAMEPAD& gamepad = xinput_state.Gamepad;
io.BackendFlags |= ImGuiBackendFlags_HasGamepad;
#define MAP_BUTTON(NAV_NO, BUTTON_ENUM) { io.NavInputs[NAV_NO] = (gamepad.wButtons & BUTTON_ENUM) ? 1.0f : 0.0f; }
#define MAP_ANALOG(NAV_NO, VALUE, V0, V1) { float vn = (float)(VALUE - V0) / (float)(V1 - V0); if (vn > 1.0f) vn = 1.0f; if (vn > 0.0f && io.NavInputs[NAV_NO] < vn) io.NavInputs[NAV_NO] = vn; }
MAP_BUTTON(ImGuiNavInput_Activate, XINPUT_GAMEPAD_A); // Cross / A
MAP_BUTTON(ImGuiNavInput_Cancel, XINPUT_GAMEPAD_B); // Circle / B
MAP_BUTTON(ImGuiNavInput_Menu, XINPUT_GAMEPAD_X); // Square / X
MAP_BUTTON(ImGuiNavInput_Input, XINPUT_GAMEPAD_Y); // Triangle / Y
MAP_BUTTON(ImGuiNavInput_DpadLeft, XINPUT_GAMEPAD_DPAD_LEFT); // D-Pad Left
MAP_BUTTON(ImGuiNavInput_DpadRight, XINPUT_GAMEPAD_DPAD_RIGHT); // D-Pad Right
MAP_BUTTON(ImGuiNavInput_DpadUp, XINPUT_GAMEPAD_DPAD_UP); // D-Pad Up
MAP_BUTTON(ImGuiNavInput_DpadDown, XINPUT_GAMEPAD_DPAD_DOWN); // D-Pad Down
MAP_BUTTON(ImGuiNavInput_FocusPrev, XINPUT_GAMEPAD_LEFT_SHOULDER); // L1 / LB
MAP_BUTTON(ImGuiNavInput_FocusNext, XINPUT_GAMEPAD_RIGHT_SHOULDER); // R1 / RB
MAP_BUTTON(ImGuiNavInput_TweakSlow, XINPUT_GAMEPAD_LEFT_SHOULDER); // L1 / LB
MAP_BUTTON(ImGuiNavInput_TweakFast, XINPUT_GAMEPAD_RIGHT_SHOULDER); // R1 / RB
MAP_ANALOG(ImGuiNavInput_LStickLeft, gamepad.sThumbLX, -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, -32768);
MAP_ANALOG(ImGuiNavInput_LStickRight, gamepad.sThumbLX, +XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, +32767);
MAP_ANALOG(ImGuiNavInput_LStickUp, gamepad.sThumbLY, +XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, +32767);
MAP_ANALOG(ImGuiNavInput_LStickDown, gamepad.sThumbLY, -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, -32767);
#undef MAP_BUTTON
#undef MAP_ANALOG
}
}
}
} }
void ImGuiModule::SetupComponent()
{
// Setup Dear ImGui context
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO();
(void)io;
// Setup Dear ImGui style
ImGui::StyleColorsDark();
// Setup Platform/Renderer bindings
target_window_ = Renderer::Instance().GetTargetWindow();
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
io.BackendFlags |=
ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used)
io.BackendPlatformName = "imgui_impl_win32";
io.ImeWindowHandle = target_window_;
// Keyboard mapping. ImGui will use those indices to peek into the io.KeysDown[] array that we will update during
// the application lifetime.
io.KeyMap[ImGuiKey_Tab] = (int)KeyCode::Tab;
io.KeyMap[ImGuiKey_LeftArrow] = (int)KeyCode::Left;
io.KeyMap[ImGuiKey_RightArrow] = (int)KeyCode::Right;
io.KeyMap[ImGuiKey_UpArrow] = (int)KeyCode::Up;
io.KeyMap[ImGuiKey_DownArrow] = (int)KeyCode::Down;
io.KeyMap[ImGuiKey_Delete] = (int)KeyCode::Delete;
io.KeyMap[ImGuiKey_Backspace] = (int)KeyCode::Back;
io.KeyMap[ImGuiKey_Space] = (int)KeyCode::Space;
io.KeyMap[ImGuiKey_Enter] = (int)KeyCode::Enter;
io.KeyMap[ImGuiKey_Escape] = (int)KeyCode::Esc;
io.KeyMap[ImGuiKey_A] = (int)KeyCode::A;
io.KeyMap[ImGuiKey_C] = (int)KeyCode::C;
io.KeyMap[ImGuiKey_V] = (int)KeyCode::V;
io.KeyMap[ImGuiKey_X] = (int)KeyCode::X;
io.KeyMap[ImGuiKey_Y] = (int)KeyCode::Y;
io.KeyMap[ImGuiKey_Z] = (int)KeyCode::Z;
ImGui_Impl_Init(Renderer::Instance());
}
void ImGuiModule::DestroyComponent()
{
ImGui_Impl_Shutdown();
ImGui::DestroyContext();
}
void ImGuiModule::OnUpdate(Duration dt)
{
ImGuiIO& io = ImGui::GetIO();
// Setup time step
io.DeltaTime = dt.Seconds();
// Read keyboard modifiers inputs
io.KeyCtrl = Input::Instance().IsDown(KeyCode::Ctrl);
io.KeyShift = Input::Instance().IsDown(KeyCode::Shift);
io.KeyAlt = Input::Instance().IsDown(KeyCode::Alt);
io.KeySuper = Input::Instance().IsDown(KeyCode::Super);
// io.KeysDown[], io.MousePos, io.MouseDown[], io.MouseWheel: filled by the HandleEvent function below.
// Update OS mouse position
UpdateMousePos();
// Update OS mouse cursor with the cursor requested by imgui
UpdateMouseCursor();
}
void ImGuiModule::BeforeRender()
{
NewFrame();
}
void ImGuiModule::AfterRender()
{
Render();
}
void ImGuiModule::HandleEvent(Event* evt)
{
if (ImGui::GetCurrentContext() == NULL)
return;
ImGuiIO& io = ImGui::GetIO();
if (evt->IsType<MouseEvent>())
{
if (evt->IsType<MouseDownEvent>())
{
MouseButton button = dynamic_cast<MouseDownEvent*>(evt)->button;
int index = 0;
if (button == MouseButton::Left)
index = 0;
else if (button == MouseButton::Right)
index = 1;
else if (button == MouseButton::Middle)
index = 2;
io.MouseDown[index] = true;
}
else if (evt->IsType<MouseUpEvent>())
{
MouseButton button = dynamic_cast<MouseUpEvent*>(evt)->button;
int index = 0;
if (button == MouseButton::Left)
index = 0;
else if (button == MouseButton::Right)
index = 1;
else if (button == MouseButton::Middle)
index = 2;
io.MouseDown[index] = false;
}
else if (evt->IsType<MouseWheelEvent>())
{
float wheel = dynamic_cast<MouseWheelEvent*>(evt)->wheel;
io.MouseWheel += wheel;
}
}
else if (evt->IsType<KeyEvent>())
{
if (evt->IsType<KeyDownEvent>())
{
KeyCode key = dynamic_cast<KeyDownEvent*>(evt)->code;
io.KeysDown[(int)key] = true;
}
else if (evt->IsType<KeyUpEvent>())
{
KeyCode key = dynamic_cast<KeyUpEvent*>(evt)->code;
io.KeysDown[(int)key] = false;
}
else if (evt->IsType<KeyCharEvent>())
{
// You can also use ToAscii()+GetKeyboardState() to retrieve characters.
char ch = dynamic_cast<KeyCharEvent*>(evt)->value;
io.AddInputCharacter(static_cast<ImWchar>(ch));
}
}
}
void ImGuiModule::NewFrame()
{
ImGui_Impl_NewFrame();
ImGuiIO& io = ImGui::GetIO();
KGE_ASSERT(io.Fonts->IsBuilt() && "Font atlas not built!");
// Setup display size (every frame to accommodate for window resizing)
Size display_size = Renderer::Instance().GetOutputSize();
io.DisplaySize = ImVec2(display_size.x, display_size.y);
ImGui::NewFrame();
}
void ImGuiModule::Render()
{
ImGui::Render();
ImGui_Impl_RenderDrawData(ImGui::GetDrawData());
}
void ImGuiModule::UpdateMousePos()
{
ImGuiIO& io = ImGui::GetIO();
// Set OS mouse position if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by
// user)
if (io.WantSetMousePos)
{
POINT pos = { (int)io.MousePos.x, (int)io.MousePos.y };
::ClientToScreen(target_window_, &pos);
::SetCursorPos(pos.x, pos.y);
}
Point pos = Input::Instance().GetMousePos();
io.MousePos = ImVec2(pos.x, pos.y);
}
void ImGuiModule::UpdateMouseCursor()
{
if (ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange)
return;
CursorType cursor = CursorType::Arrow;
switch (ImGui::GetMouseCursor())
{
case ImGuiMouseCursor_Arrow:
cursor = CursorType::Arrow;
break;
case ImGuiMouseCursor_TextInput:
cursor = CursorType::TextInput;
break;
case ImGuiMouseCursor_ResizeAll:
cursor = CursorType::SizeAll;
break;
case ImGuiMouseCursor_ResizeEW:
cursor = CursorType::SizeWE;
break;
case ImGuiMouseCursor_ResizeNS:
cursor = CursorType::SizeNS;
break;
case ImGuiMouseCursor_ResizeNESW:
cursor = CursorType::SizeNESW;
break;
case ImGuiMouseCursor_ResizeNWSE:
cursor = CursorType::SizeNWSE;
break;
case ImGuiMouseCursor_Hand:
cursor = CursorType::Hand;
break;
}
Window::Instance().SetCursor(cursor);
}
} // namespace imgui
} // namespace kiwano

View File

@ -1,15 +1,15 @@
// Copyright (c) 2016-2018 Kiwano - Nomango // Copyright (c) 2016-2018 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -19,57 +19,51 @@
// THE SOFTWARE. // THE SOFTWARE.
#pragma once #pragma once
#include <kiwano/core/common.h> #include <kiwano/core/Common.h>
#include <kiwano/core/Component.h> #include <kiwano/core/Component.h>
namespace kiwano namespace kiwano
{ {
namespace imgui namespace imgui
{ {
/** /**
* \~chinese * \~chinese
* @brief ImGuiÄ£¿é * @brief ImGuiÄ£¿é
*/ */
class ImGuiModule class ImGuiModule
: public Singleton<ImGuiModule> : public Singleton<ImGuiModule>
, public RenderComponent , public RenderComponent
, public UpdateComponent , public UpdateComponent
, public EventComponent , public EventComponent
{ {
friend Singleton<ImGuiModule>; friend Singleton<ImGuiModule>;
public: public:
ImGuiModule(); ImGuiModule();
void SetupComponent() override; void SetupComponent() override;
void DestroyComponent() override; void DestroyComponent() override;
void BeforeRender() override; void BeforeRender() override;
void AfterRender() override; void AfterRender() override;
void HandleMessage(HWND hwnd, UINT32 msg, WPARAM wparam, LPARAM lparam) override; void HandleEvent(Event* evt) override;
void OnUpdate(Duration dt) override; void OnUpdate(Duration dt) override;
private: private:
void Init(HWND hwnd); void NewFrame();
void NewFrame(); void Render();
void Render(); void UpdateMousePos();
void UpdateMousePos(); void UpdateMouseCursor();
void UpdateMouseCursor(); private:
WindowHandle target_window_;
void UpdateGamepads(); };
} // namespace imgui
private: } // namespace kiwano
bool has_gamepad_;
bool want_update_has_gamepad_;
HWND target_window_;
};
}
}

View File

@ -8,25 +8,62 @@
#include <kiwano-imgui/imgui_impl_dx11.h> #include <kiwano-imgui/imgui_impl_dx11.h>
inline bool ImGui_Impl_Init(::kiwano::Renderer* renderer) { return ImGui_ImplDX11_Init(renderer->GetD3DDeviceResources()->GetDevice(), renderer->GetD3DDeviceResources()->GetDeviceContext()); } inline bool ImGui_Impl_Init(::kiwano::Renderer& renderer)
inline void ImGui_Impl_Shutdown() { ImGui_ImplDX11_Shutdown(); } {
inline void ImGui_Impl_NewFrame() { ImGui_ImplDX11_NewFrame(); } return ImGui_ImplDX11_Init(renderer.GetD3DDeviceResources()->GetDevice(),
inline void ImGui_Impl_RenderDrawData(ImDrawData* draw_data) { ImGui_ImplDX11_RenderDrawData(draw_data); } renderer.GetD3DDeviceResources()->GetDeviceContext());
}
inline void ImGui_Impl_Shutdown()
{
ImGui_ImplDX11_Shutdown();
}
inline void ImGui_Impl_NewFrame()
{
ImGui_ImplDX11_NewFrame();
}
inline void ImGui_Impl_RenderDrawData(ImDrawData* draw_data)
{
ImGui_ImplDX11_RenderDrawData(draw_data);
}
inline void ImGui_Impl_InvalidateDeviceObjects() { ImGui_ImplDX11_InvalidateDeviceObjects(); } inline void ImGui_Impl_InvalidateDeviceObjects()
inline bool ImGui_Impl_CreateDeviceObjects() { return ImGui_ImplDX11_CreateDeviceObjects(); } {
ImGui_ImplDX11_InvalidateDeviceObjects();
}
inline bool ImGui_Impl_CreateDeviceObjects()
{
return ImGui_ImplDX11_CreateDeviceObjects();
}
#else #else
#include <kiwano-imgui/imgui_impl_dx10.h> #include <kiwano-imgui/imgui_impl_dx10.h>
inline bool ImGui_Impl_Init(::kiwano::Renderer* renderer) { return ImGui_ImplDX10_Init(renderer->GetD3DDeviceResources()->GetDevice()); } inline bool ImGui_Impl_Init(::kiwano::Renderer& renderer)
inline void ImGui_Impl_Shutdown() { ImGui_ImplDX10_Shutdown(); } {
inline void ImGui_Impl_NewFrame() { ImGui_ImplDX10_NewFrame(); } return ImGui_ImplDX10_Init(renderer.GetD3DDeviceResources()->GetDevice());
inline void ImGui_Impl_RenderDrawData(ImDrawData* draw_data) { ImGui_ImplDX10_RenderDrawData(draw_data); } }
inline void ImGui_Impl_Shutdown()
{
ImGui_ImplDX10_Shutdown();
}
inline void ImGui_Impl_NewFrame()
{
ImGui_ImplDX10_NewFrame();
}
inline void ImGui_Impl_RenderDrawData(ImDrawData* draw_data)
{
ImGui_ImplDX10_RenderDrawData(draw_data);
}
inline void ImGui_Impl_InvalidateDeviceObjects() { ImGui_ImplDX10_InvalidateDeviceObjects(); } inline void ImGui_Impl_InvalidateDeviceObjects()
inline bool ImGui_Impl_CreateDeviceObjects() { return ImGui_ImplDX10_CreateDeviceObjects(); } {
ImGui_ImplDX10_InvalidateDeviceObjects();
}
inline bool ImGui_Impl_CreateDeviceObjects()
{
return ImGui_ImplDX10_CreateDeviceObjects();
}
#endif #endif

View File

@ -3,40 +3,41 @@
#include <kiwano-imgui/imgui_impl_dx10.h> #include <kiwano-imgui/imgui_impl_dx10.h>
// DirectX // DirectX
#include <stdio.h>
#include <d3d10_1.h> #include <d3d10_1.h>
#include <d3d10.h> #include <d3d10.h>
#include <d3dcompiler.h> #include <d3dcompiler.h>
#include <stdio.h>
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma comment(lib, "d3dcompiler") // Automatically link with d3dcompiler.lib as we are using D3DCompile() below. #pragma comment(lib, "d3dcompiler") // Automatically link with d3dcompiler.lib as we are using D3DCompile() below.
#endif #endif
// DirectX data // DirectX data
static ID3D10Device* g_pd3dDevice = NULL; static ID3D10Device* g_pd3dDevice = NULL;
static IDXGIFactory* g_pFactory = NULL; static IDXGIFactory* g_pFactory = NULL;
static ID3D10Buffer* g_pVB = NULL; static ID3D10Buffer* g_pVB = NULL;
static ID3D10Buffer* g_pIB = NULL; static ID3D10Buffer* g_pIB = NULL;
static ID3D10Blob* g_pVertexShaderBlob = NULL; static ID3D10Blob* g_pVertexShaderBlob = NULL;
static ID3D10VertexShader* g_pVertexShader = NULL; static ID3D10VertexShader* g_pVertexShader = NULL;
static ID3D10InputLayout* g_pInputLayout = NULL; static ID3D10InputLayout* g_pInputLayout = NULL;
static ID3D10Buffer* g_pVertexConstantBuffer = NULL; static ID3D10Buffer* g_pVertexConstantBuffer = NULL;
static ID3D10Blob* g_pPixelShaderBlob = NULL; static ID3D10Blob* g_pPixelShaderBlob = NULL;
static ID3D10PixelShader* g_pPixelShader = NULL; static ID3D10PixelShader* g_pPixelShader = NULL;
static ID3D10SamplerState* g_pFontSampler = NULL; static ID3D10SamplerState* g_pFontSampler = NULL;
static ID3D10ShaderResourceView*g_pFontTextureView = NULL; static ID3D10ShaderResourceView* g_pFontTextureView = NULL;
static ID3D10RasterizerState* g_pRasterizerState = NULL; static ID3D10RasterizerState* g_pRasterizerState = NULL;
static ID3D10BlendState* g_pBlendState = NULL; static ID3D10BlendState* g_pBlendState = NULL;
static ID3D10DepthStencilState* g_pDepthStencilState = NULL; static ID3D10DepthStencilState* g_pDepthStencilState = NULL;
static int g_VertexBufferSize = 5000, g_IndexBufferSize = 10000; static int g_VertexBufferSize = 5000, g_IndexBufferSize = 10000;
struct VERTEX_CONSTANT_BUFFER struct VERTEX_CONSTANT_BUFFER
{ {
float mvp[4][4]; float mvp[4][4];
}; };
// Render Function // Render Function
// (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop) // (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from
// your main loop)
void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data) void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
{ {
ID3D10Device* ctx = g_pd3dDevice; ID3D10Device* ctx = g_pd3dDevice;
@ -44,28 +45,36 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
// Create and grow vertex/index buffers if needed // Create and grow vertex/index buffers if needed
if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount)
{ {
if (g_pVB) { g_pVB->Release(); g_pVB = NULL; } if (g_pVB)
{
g_pVB->Release();
g_pVB = NULL;
}
g_VertexBufferSize = draw_data->TotalVtxCount + 5000; g_VertexBufferSize = draw_data->TotalVtxCount + 5000;
D3D10_BUFFER_DESC desc; D3D10_BUFFER_DESC desc;
memset(&desc, 0, sizeof(D3D10_BUFFER_DESC)); memset(&desc, 0, sizeof(D3D10_BUFFER_DESC));
desc.Usage = D3D10_USAGE_DYNAMIC; desc.Usage = D3D10_USAGE_DYNAMIC;
desc.ByteWidth = g_VertexBufferSize * sizeof(ImDrawVert); desc.ByteWidth = g_VertexBufferSize * sizeof(ImDrawVert);
desc.BindFlags = D3D10_BIND_VERTEX_BUFFER; desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
desc.MiscFlags = 0; desc.MiscFlags = 0;
if (ctx->CreateBuffer(&desc, NULL, &g_pVB) < 0) if (ctx->CreateBuffer(&desc, NULL, &g_pVB) < 0)
return; return;
} }
if (!g_pIB || g_IndexBufferSize < draw_data->TotalIdxCount) if (!g_pIB || g_IndexBufferSize < draw_data->TotalIdxCount)
{ {
if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } if (g_pIB)
{
g_pIB->Release();
g_pIB = NULL;
}
g_IndexBufferSize = draw_data->TotalIdxCount + 10000; g_IndexBufferSize = draw_data->TotalIdxCount + 10000;
D3D10_BUFFER_DESC desc; D3D10_BUFFER_DESC desc;
memset(&desc, 0, sizeof(D3D10_BUFFER_DESC)); memset(&desc, 0, sizeof(D3D10_BUFFER_DESC));
desc.Usage = D3D10_USAGE_DYNAMIC; desc.Usage = D3D10_USAGE_DYNAMIC;
desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx);
desc.BindFlags = D3D10_BIND_INDEX_BUFFER; desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
if (ctx->CreateBuffer(&desc, NULL, &g_pIB) < 0) if (ctx->CreateBuffer(&desc, NULL, &g_pIB) < 0)
return; return;
@ -73,7 +82,7 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
// Copy and convert all vertices into a single contiguous buffer // Copy and convert all vertices into a single contiguous buffer
ImDrawVert* vtx_dst = NULL; ImDrawVert* vtx_dst = NULL;
ImDrawIdx* idx_dst = NULL; ImDrawIdx* idx_dst = NULL;
g_pVB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&vtx_dst); g_pVB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&vtx_dst);
g_pIB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&idx_dst); g_pIB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&idx_dst);
for (int n = 0; n < draw_data->CmdListsCount; n++) for (int n = 0; n < draw_data->CmdListsCount; n++)
@ -88,48 +97,49 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
g_pIB->Unmap(); g_pIB->Unmap();
// Setup orthographic projection matrix into our constant buffer // Setup orthographic projection matrix into our constant buffer
// Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). // Our visible imgui space lies from draw_data->DisplayPos (top left) to
// draw_data->DisplayPos+data_data->DisplaySize (bottom right).
{ {
void* mapped_resource; void* mapped_resource;
if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK)
return; return;
VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource; VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource;
float L = draw_data->DisplayPos.x; float L = draw_data->DisplayPos.x;
float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x; float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x;
float T = draw_data->DisplayPos.y; float T = draw_data->DisplayPos.y;
float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y; float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y;
float mvp[4][4] = float mvp[4][4] = {
{ { 2.0f / (R - L), 0.0f, 0.0f, 0.0f },
{ 2.0f/(R-L), 0.0f, 0.0f, 0.0f }, { 0.0f, 2.0f / (T - B), 0.0f, 0.0f },
{ 0.0f, 2.0f/(T-B), 0.0f, 0.0f }, { 0.0f, 0.0f, 0.5f, 0.0f },
{ 0.0f, 0.0f, 0.5f, 0.0f }, { (R + L) / (L - R), (T + B) / (B - T), 0.5f, 1.0f },
{ (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f },
}; };
memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); memcpy(&constant_buffer->mvp, mvp, sizeof(mvp));
g_pVertexConstantBuffer->Unmap(); g_pVertexConstantBuffer->Unmap();
} }
// Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and
// verbose. Close your eyes!)
struct BACKUP_DX10_STATE struct BACKUP_DX10_STATE
{ {
UINT ScissorRectsCount, ViewportsCount; UINT ScissorRectsCount, ViewportsCount;
D3D10_RECT ScissorRects[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; D3D10_RECT ScissorRects[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE];
D3D10_VIEWPORT Viewports[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; D3D10_VIEWPORT Viewports[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE];
ID3D10RasterizerState* RS; ID3D10RasterizerState* RS;
ID3D10BlendState* BlendState; ID3D10BlendState* BlendState;
FLOAT BlendFactor[4]; FLOAT BlendFactor[4];
UINT SampleMask; UINT SampleMask;
UINT StencilRef; UINT StencilRef;
ID3D10DepthStencilState* DepthStencilState; ID3D10DepthStencilState* DepthStencilState;
ID3D10ShaderResourceView* PSShaderResource; ID3D10ShaderResourceView* PSShaderResource;
ID3D10SamplerState* PSSampler; ID3D10SamplerState* PSSampler;
ID3D10PixelShader* PS; ID3D10PixelShader* PS;
ID3D10VertexShader* VS; ID3D10VertexShader* VS;
D3D10_PRIMITIVE_TOPOLOGY PrimitiveTopology; D3D10_PRIMITIVE_TOPOLOGY PrimitiveTopology;
ID3D10Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; ID3D10Buffer * IndexBuffer, *VertexBuffer, *VSConstantBuffer;
UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset;
DXGI_FORMAT IndexBufferFormat; DXGI_FORMAT IndexBufferFormat;
ID3D10InputLayout* InputLayout; ID3D10InputLayout* InputLayout;
}; };
BACKUP_DX10_STATE old; BACKUP_DX10_STATE old;
old.ScissorRectsCount = old.ViewportsCount = D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; old.ScissorRectsCount = old.ViewportsCount = D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE;
@ -151,8 +161,8 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
// Setup viewport // Setup viewport
D3D10_VIEWPORT vp; D3D10_VIEWPORT vp;
memset(&vp, 0, sizeof(D3D10_VIEWPORT)); memset(&vp, 0, sizeof(D3D10_VIEWPORT));
vp.Width = (UINT)draw_data->DisplaySize.x; vp.Width = (UINT)draw_data->DisplaySize.x;
vp.Height = (UINT)draw_data->DisplaySize.y; vp.Height = (UINT)draw_data->DisplaySize.y;
vp.MinDepth = 0.0f; vp.MinDepth = 0.0f;
vp.MaxDepth = 1.0f; vp.MaxDepth = 1.0f;
vp.TopLeftX = vp.TopLeftY = 0; vp.TopLeftX = vp.TopLeftY = 0;
@ -177,9 +187,9 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
ctx->RSSetState(g_pRasterizerState); ctx->RSSetState(g_pRasterizerState);
// Render command lists // Render command lists
int vtx_offset = 0; int vtx_offset = 0;
int idx_offset = 0; int idx_offset = 0;
ImVec2 pos = draw_data->DisplayPos; ImVec2 pos = draw_data->DisplayPos;
for (int n = 0; n < draw_data->CmdListsCount; n++) for (int n = 0; n < draw_data->CmdListsCount; n++)
{ {
const ImDrawList* cmd_list = draw_data->CmdLists[n]; const ImDrawList* cmd_list = draw_data->CmdLists[n];
@ -194,7 +204,8 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
else else
{ {
// Apply scissor/clipping rectangle // Apply scissor/clipping rectangle
const D3D10_RECT r = { (LONG)(pcmd->ClipRect.x - pos.x), (LONG)(pcmd->ClipRect.y - pos.y), (LONG)(pcmd->ClipRect.z - pos.x), (LONG)(pcmd->ClipRect.w - pos.y)}; const D3D10_RECT r = { (LONG)(pcmd->ClipRect.x - pos.x), (LONG)(pcmd->ClipRect.y - pos.y),
(LONG)(pcmd->ClipRect.z - pos.x), (LONG)(pcmd->ClipRect.w - pos.y) };
ctx->RSSetScissorRects(1, &r); ctx->RSSetScissorRects(1, &r);
// Bind texture, Draw // Bind texture, Draw
@ -210,55 +221,77 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
// Restore modified DX state // Restore modified DX state
ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects);
ctx->RSSetViewports(old.ViewportsCount, old.Viewports); ctx->RSSetViewports(old.ViewportsCount, old.Viewports);
ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); ctx->RSSetState(old.RS);
ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); if (old.RS)
ctx->OMSetDepthStencilState(old.DepthStencilState, old.StencilRef); if (old.DepthStencilState) old.DepthStencilState->Release(); old.RS->Release();
ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask);
ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); if (old.BlendState)
ctx->PSSetShader(old.PS); if (old.PS) old.PS->Release(); old.BlendState->Release();
ctx->VSSetShader(old.VS); if (old.VS) old.VS->Release(); ctx->OMSetDepthStencilState(old.DepthStencilState, old.StencilRef);
ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); if (old.DepthStencilState)
old.DepthStencilState->Release();
ctx->PSSetShaderResources(0, 1, &old.PSShaderResource);
if (old.PSShaderResource)
old.PSShaderResource->Release();
ctx->PSSetSamplers(0, 1, &old.PSSampler);
if (old.PSSampler)
old.PSSampler->Release();
ctx->PSSetShader(old.PS);
if (old.PS)
old.PS->Release();
ctx->VSSetShader(old.VS);
if (old.VS)
old.VS->Release();
ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer);
if (old.VSConstantBuffer)
old.VSConstantBuffer->Release();
ctx->IASetPrimitiveTopology(old.PrimitiveTopology); ctx->IASetPrimitiveTopology(old.PrimitiveTopology);
ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset);
ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); if (old.IndexBuffer)
ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); old.IndexBuffer->Release();
ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset);
if (old.VertexBuffer)
old.VertexBuffer->Release();
ctx->IASetInputLayout(old.InputLayout);
if (old.InputLayout)
old.InputLayout->Release();
} }
static void ImGui_ImplDX10_CreateFontsTexture() static void ImGui_ImplDX10_CreateFontsTexture()
{ {
// Build texture atlas // Build texture atlas
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
unsigned char* pixels; unsigned char* pixels;
int width, height; int width, height;
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
// Upload texture to graphics system // Upload texture to graphics system
{ {
D3D10_TEXTURE2D_DESC desc; D3D10_TEXTURE2D_DESC desc;
ZeroMemory(&desc, sizeof(desc)); ZeroMemory(&desc, sizeof(desc));
desc.Width = width; desc.Width = width;
desc.Height = height; desc.Height = height;
desc.MipLevels = 1; desc.MipLevels = 1;
desc.ArraySize = 1; desc.ArraySize = 1;
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
desc.SampleDesc.Count = 1; desc.SampleDesc.Count = 1;
desc.Usage = D3D10_USAGE_DEFAULT; desc.Usage = D3D10_USAGE_DEFAULT;
desc.BindFlags = D3D10_BIND_SHADER_RESOURCE; desc.BindFlags = D3D10_BIND_SHADER_RESOURCE;
desc.CPUAccessFlags = 0; desc.CPUAccessFlags = 0;
ID3D10Texture2D *pTexture = NULL; ID3D10Texture2D* pTexture = NULL;
D3D10_SUBRESOURCE_DATA subResource; D3D10_SUBRESOURCE_DATA subResource;
subResource.pSysMem = pixels; subResource.pSysMem = pixels;
subResource.SysMemPitch = desc.Width * 4; subResource.SysMemPitch = desc.Width * 4;
subResource.SysMemSlicePitch = 0; subResource.SysMemSlicePitch = 0;
g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture);
// Create texture view // Create texture view
D3D10_SHADER_RESOURCE_VIEW_DESC srv_desc; D3D10_SHADER_RESOURCE_VIEW_DESC srv_desc;
ZeroMemory(&srv_desc, sizeof(srv_desc)); ZeroMemory(&srv_desc, sizeof(srv_desc));
srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
srv_desc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; srv_desc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D;
srv_desc.Texture2D.MipLevels = desc.MipLevels; srv_desc.Texture2D.MipLevels = desc.MipLevels;
srv_desc.Texture2D.MostDetailedMip = 0; srv_desc.Texture2D.MostDetailedMip = 0;
g_pd3dDevice->CreateShaderResourceView(pTexture, &srv_desc, &g_pFontTextureView); g_pd3dDevice->CreateShaderResourceView(pTexture, &srv_desc, &g_pFontTextureView);
pTexture->Release(); pTexture->Release();
@ -271,35 +304,36 @@ static void ImGui_ImplDX10_CreateFontsTexture()
{ {
D3D10_SAMPLER_DESC desc; D3D10_SAMPLER_DESC desc;
ZeroMemory(&desc, sizeof(desc)); ZeroMemory(&desc, sizeof(desc));
desc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; desc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR;
desc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; desc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP;
desc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; desc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP;
desc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; desc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP;
desc.MipLODBias = 0.f; desc.MipLODBias = 0.f;
desc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; desc.ComparisonFunc = D3D10_COMPARISON_ALWAYS;
desc.MinLOD = 0.f; desc.MinLOD = 0.f;
desc.MaxLOD = 0.f; desc.MaxLOD = 0.f;
g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler);
} }
} }
bool ImGui_ImplDX10_CreateDeviceObjects() bool ImGui_ImplDX10_CreateDeviceObjects()
{ {
if (!g_pd3dDevice) if (!g_pd3dDevice)
return false; return false;
if (g_pFontSampler) if (g_pFontSampler)
ImGui_ImplDX10_InvalidateDeviceObjects(); ImGui_ImplDX10_InvalidateDeviceObjects();
// By using D3DCompile() from <d3dcompiler.h> / d3dcompiler.lib, we introduce a dependency to a given version of d3dcompiler_XX.dll (see D3DCOMPILER_DLL_A) // By using D3DCompile() from <d3dcompiler.h> / d3dcompiler.lib, we introduce a dependency to a given version of
// If you would like to use this DX10 sample code but remove this dependency you can: // d3dcompiler_XX.dll (see D3DCOMPILER_DLL_A) If you would like to use this DX10 sample code but remove this
// 1) compile once, save the compiled shader blobs into a file or source code and pass them to CreateVertexShader()/CreatePixelShader() [preferred solution] // dependency you can:
// 2) use code to detect any version of the DLL and grab a pointer to D3DCompile from the DLL. // 1) compile once, save the compiled shader blobs into a file or source code and pass them to
// CreateVertexShader()/CreatePixelShader() [preferred solution] 2) use code to detect any version of the DLL and
// grab a pointer to D3DCompile from the DLL.
// See https://github.com/ocornut/imgui/pull/638 for sources and details. // See https://github.com/ocornut/imgui/pull/638 for sources and details.
// Create the vertex shader // Create the vertex shader
{ {
static const char* vertexShader = static const char* vertexShader = "cbuffer vertexBuffer : register(b0) \
"cbuffer vertexBuffer : register(b0) \
{\ {\
float4x4 ProjectionMatrix; \ float4x4 ProjectionMatrix; \
};\ };\
@ -326,38 +360,46 @@ bool ImGui_ImplDX10_CreateDeviceObjects()
return output;\ return output;\
}"; }";
D3DCompile(vertexShader, strlen(vertexShader), NULL, NULL, NULL, "main", "vs_4_0", 0, 0, &g_pVertexShaderBlob, NULL); D3DCompile(vertexShader, strlen(vertexShader), NULL, NULL, NULL, "main", "vs_4_0", 0, 0, &g_pVertexShaderBlob,
if (g_pVertexShaderBlob == NULL) // NB: Pass ID3D10Blob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob! NULL);
if (g_pVertexShaderBlob
== NULL) // NB: Pass ID3D10Blob* pErrorBlob to D3DCompile() to get error showing in (const
// char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!
return false; return false;
if (g_pd3dDevice->CreateVertexShader((DWORD*)g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pVertexShader) != S_OK) if (g_pd3dDevice->CreateVertexShader((DWORD*)g_pVertexShaderBlob->GetBufferPointer(),
g_pVertexShaderBlob->GetBufferSize(), &g_pVertexShader)
!= S_OK)
return false; return false;
// Create the input layout // Create the input layout
D3D10_INPUT_ELEMENT_DESC local_layout[] = D3D10_INPUT_ELEMENT_DESC local_layout[] = {
{ { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D10_INPUT_PER_VERTEX_DATA,
{ "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D10_INPUT_PER_VERTEX_DATA, 0 }, 0 },
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D10_INPUT_PER_VERTEX_DATA,
{ "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D10_INPUT_PER_VERTEX_DATA, 0 }, 0 },
{ "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D10_INPUT_PER_VERTEX_DATA,
0 },
}; };
if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(),
g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout)
!= S_OK)
return false; return false;
// Create the constant buffer // Create the constant buffer
{ {
D3D10_BUFFER_DESC desc; D3D10_BUFFER_DESC desc;
desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER);
desc.Usage = D3D10_USAGE_DYNAMIC; desc.Usage = D3D10_USAGE_DYNAMIC;
desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
desc.MiscFlags = 0; desc.MiscFlags = 0;
g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer);
} }
} }
// Create the pixel shader // Create the pixel shader
{ {
static const char* pixelShader = static const char* pixelShader = "struct PS_INPUT\
"struct PS_INPUT\
{\ {\
float4 pos : SV_POSITION;\ float4 pos : SV_POSITION;\
float4 col : COLOR0;\ float4 col : COLOR0;\
@ -372,10 +414,15 @@ bool ImGui_ImplDX10_CreateDeviceObjects()
return out_col; \ return out_col; \
}"; }";
D3DCompile(pixelShader, strlen(pixelShader), NULL, NULL, NULL, "main", "ps_4_0", 0, 0, &g_pPixelShaderBlob, NULL); D3DCompile(pixelShader, strlen(pixelShader), NULL, NULL, NULL, "main", "ps_4_0", 0, 0, &g_pPixelShaderBlob,
if (g_pPixelShaderBlob == NULL) // NB: Pass ID3D10Blob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob! NULL);
if (g_pPixelShaderBlob
== NULL) // NB: Pass ID3D10Blob* pErrorBlob to D3DCompile() to get error showing in (const
// char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!
return false; return false;
if (g_pd3dDevice->CreatePixelShader((DWORD*)g_pPixelShaderBlob->GetBufferPointer(), g_pPixelShaderBlob->GetBufferSize(), &g_pPixelShader) != S_OK) if (g_pd3dDevice->CreatePixelShader((DWORD*)g_pPixelShaderBlob->GetBufferPointer(),
g_pPixelShaderBlob->GetBufferSize(), &g_pPixelShader)
!= S_OK)
return false; return false;
} }
@ -383,14 +430,14 @@ bool ImGui_ImplDX10_CreateDeviceObjects()
{ {
D3D10_BLEND_DESC desc; D3D10_BLEND_DESC desc;
ZeroMemory(&desc, sizeof(desc)); ZeroMemory(&desc, sizeof(desc));
desc.AlphaToCoverageEnable = false; desc.AlphaToCoverageEnable = false;
desc.BlendEnable[0] = true; desc.BlendEnable[0] = true;
desc.SrcBlend = D3D10_BLEND_SRC_ALPHA; desc.SrcBlend = D3D10_BLEND_SRC_ALPHA;
desc.DestBlend = D3D10_BLEND_INV_SRC_ALPHA; desc.DestBlend = D3D10_BLEND_INV_SRC_ALPHA;
desc.BlendOp = D3D10_BLEND_OP_ADD; desc.BlendOp = D3D10_BLEND_OP_ADD;
desc.SrcBlendAlpha = D3D10_BLEND_INV_SRC_ALPHA; desc.SrcBlendAlpha = D3D10_BLEND_INV_SRC_ALPHA;
desc.DestBlendAlpha = D3D10_BLEND_ZERO; desc.DestBlendAlpha = D3D10_BLEND_ZERO;
desc.BlendOpAlpha = D3D10_BLEND_OP_ADD; desc.BlendOpAlpha = D3D10_BLEND_OP_ADD;
desc.RenderTargetWriteMask[0] = D3D10_COLOR_WRITE_ENABLE_ALL; desc.RenderTargetWriteMask[0] = D3D10_COLOR_WRITE_ENABLE_ALL;
g_pd3dDevice->CreateBlendState(&desc, &g_pBlendState); g_pd3dDevice->CreateBlendState(&desc, &g_pBlendState);
} }
@ -399,9 +446,9 @@ bool ImGui_ImplDX10_CreateDeviceObjects()
{ {
D3D10_RASTERIZER_DESC desc; D3D10_RASTERIZER_DESC desc;
ZeroMemory(&desc, sizeof(desc)); ZeroMemory(&desc, sizeof(desc));
desc.FillMode = D3D10_FILL_SOLID; desc.FillMode = D3D10_FILL_SOLID;
desc.CullMode = D3D10_CULL_NONE; desc.CullMode = D3D10_CULL_NONE;
desc.ScissorEnable = true; desc.ScissorEnable = true;
desc.DepthClipEnable = true; desc.DepthClipEnable = true;
g_pd3dDevice->CreateRasterizerState(&desc, &g_pRasterizerState); g_pd3dDevice->CreateRasterizerState(&desc, &g_pRasterizerState);
} }
@ -410,13 +457,14 @@ bool ImGui_ImplDX10_CreateDeviceObjects()
{ {
D3D10_DEPTH_STENCIL_DESC desc; D3D10_DEPTH_STENCIL_DESC desc;
ZeroMemory(&desc, sizeof(desc)); ZeroMemory(&desc, sizeof(desc));
desc.DepthEnable = false; desc.DepthEnable = false;
desc.DepthWriteMask = D3D10_DEPTH_WRITE_MASK_ALL; desc.DepthWriteMask = D3D10_DEPTH_WRITE_MASK_ALL;
desc.DepthFunc = D3D10_COMPARISON_ALWAYS; desc.DepthFunc = D3D10_COMPARISON_ALWAYS;
desc.StencilEnable = false; desc.StencilEnable = false;
desc.FrontFace.StencilFailOp = desc.FrontFace.StencilDepthFailOp = desc.FrontFace.StencilPassOp = D3D10_STENCIL_OP_KEEP; desc.FrontFace.StencilFailOp = desc.FrontFace.StencilDepthFailOp = desc.FrontFace.StencilPassOp =
D3D10_STENCIL_OP_KEEP;
desc.FrontFace.StencilFunc = D3D10_COMPARISON_ALWAYS; desc.FrontFace.StencilFunc = D3D10_COMPARISON_ALWAYS;
desc.BackFace = desc.FrontFace; desc.BackFace = desc.FrontFace;
g_pd3dDevice->CreateDepthStencilState(&desc, &g_pDepthStencilState); g_pd3dDevice->CreateDepthStencilState(&desc, &g_pDepthStencilState);
} }
@ -425,46 +473,101 @@ bool ImGui_ImplDX10_CreateDeviceObjects()
return true; return true;
} }
void ImGui_ImplDX10_InvalidateDeviceObjects() void ImGui_ImplDX10_InvalidateDeviceObjects()
{ {
if (!g_pd3dDevice) if (!g_pd3dDevice)
return; return;
if (g_pFontSampler) { g_pFontSampler->Release(); g_pFontSampler = NULL; } if (g_pFontSampler)
if (g_pFontTextureView) { g_pFontTextureView->Release(); g_pFontTextureView = NULL; ImGui::GetIO().Fonts->TexID = NULL; } // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well. {
if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_pFontSampler->Release();
if (g_pVB) { g_pVB->Release(); g_pVB = NULL; } g_pFontSampler = NULL;
}
if (g_pFontTextureView)
{
g_pFontTextureView->Release();
g_pFontTextureView = NULL;
ImGui::GetIO().Fonts->TexID = NULL;
} // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well.
if (g_pIB)
{
g_pIB->Release();
g_pIB = NULL;
}
if (g_pVB)
{
g_pVB->Release();
g_pVB = NULL;
}
if (g_pBlendState) { g_pBlendState->Release(); g_pBlendState = NULL; } if (g_pBlendState)
if (g_pDepthStencilState) { g_pDepthStencilState->Release(); g_pDepthStencilState = NULL; } {
if (g_pRasterizerState) { g_pRasterizerState->Release(); g_pRasterizerState = NULL; } g_pBlendState->Release();
if (g_pPixelShader) { g_pPixelShader->Release(); g_pPixelShader = NULL; } g_pBlendState = NULL;
if (g_pPixelShaderBlob) { g_pPixelShaderBlob->Release(); g_pPixelShaderBlob = NULL; } }
if (g_pVertexConstantBuffer) { g_pVertexConstantBuffer->Release(); g_pVertexConstantBuffer = NULL; } if (g_pDepthStencilState)
if (g_pInputLayout) { g_pInputLayout->Release(); g_pInputLayout = NULL; } {
if (g_pVertexShader) { g_pVertexShader->Release(); g_pVertexShader = NULL; } g_pDepthStencilState->Release();
if (g_pVertexShaderBlob) { g_pVertexShaderBlob->Release(); g_pVertexShaderBlob = NULL; } g_pDepthStencilState = NULL;
}
if (g_pRasterizerState)
{
g_pRasterizerState->Release();
g_pRasterizerState = NULL;
}
if (g_pPixelShader)
{
g_pPixelShader->Release();
g_pPixelShader = NULL;
}
if (g_pPixelShaderBlob)
{
g_pPixelShaderBlob->Release();
g_pPixelShaderBlob = NULL;
}
if (g_pVertexConstantBuffer)
{
g_pVertexConstantBuffer->Release();
g_pVertexConstantBuffer = NULL;
}
if (g_pInputLayout)
{
g_pInputLayout->Release();
g_pInputLayout = NULL;
}
if (g_pVertexShader)
{
g_pVertexShader->Release();
g_pVertexShader = NULL;
}
if (g_pVertexShaderBlob)
{
g_pVertexShaderBlob->Release();
g_pVertexShaderBlob = NULL;
}
} }
bool ImGui_ImplDX10_Init(ID3D10Device* device) bool ImGui_ImplDX10_Init(ID3D10Device* device)
{ {
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
io.BackendRendererName = "imgui_impl_dx10"; io.BackendRendererName = "imgui_impl_dx10";
// Get factory from device // Get factory from device
IDXGIDevice* pDXGIDevice = NULL; IDXGIDevice* pDXGIDevice = NULL;
IDXGIAdapter* pDXGIAdapter = NULL; IDXGIAdapter* pDXGIAdapter = NULL;
IDXGIFactory* pFactory = NULL; IDXGIFactory* pFactory = NULL;
if (device->QueryInterface(IID_PPV_ARGS(&pDXGIDevice)) == S_OK) if (device->QueryInterface(IID_PPV_ARGS(&pDXGIDevice)) == S_OK)
if (pDXGIDevice->GetParent(IID_PPV_ARGS(&pDXGIAdapter)) == S_OK) if (pDXGIDevice->GetParent(IID_PPV_ARGS(&pDXGIAdapter)) == S_OK)
if (pDXGIAdapter->GetParent(IID_PPV_ARGS(&pFactory)) == S_OK) if (pDXGIAdapter->GetParent(IID_PPV_ARGS(&pFactory)) == S_OK)
{ {
g_pd3dDevice = device; g_pd3dDevice = device;
g_pFactory = pFactory; g_pFactory = pFactory;
} }
if (pDXGIDevice) pDXGIDevice->Release(); if (pDXGIDevice)
if (pDXGIAdapter) pDXGIAdapter->Release(); pDXGIDevice->Release();
if (pDXGIAdapter)
pDXGIAdapter->Release();
return true; return true;
} }
@ -472,7 +575,11 @@ bool ImGui_ImplDX10_Init(ID3D10Device* device)
void ImGui_ImplDX10_Shutdown() void ImGui_ImplDX10_Shutdown()
{ {
ImGui_ImplDX10_InvalidateDeviceObjects(); ImGui_ImplDX10_InvalidateDeviceObjects();
if (g_pFactory) { g_pFactory->Release(); g_pFactory = NULL; } if (g_pFactory)
{
g_pFactory->Release();
g_pFactory = NULL;
}
g_pd3dDevice = NULL; g_pd3dDevice = NULL;
} }

View File

@ -7,13 +7,13 @@
struct ID3D10Device; struct ID3D10Device;
IMGUI_IMPL_API bool ImGui_ImplDX10_Init(ID3D10Device* device); IMGUI_IMPL_API bool ImGui_ImplDX10_Init(ID3D10Device* device);
IMGUI_IMPL_API void ImGui_ImplDX10_Shutdown(); IMGUI_IMPL_API void ImGui_ImplDX10_Shutdown();
IMGUI_IMPL_API void ImGui_ImplDX10_NewFrame(); IMGUI_IMPL_API void ImGui_ImplDX10_NewFrame();
IMGUI_IMPL_API void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data); IMGUI_IMPL_API void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data);
// Use if you want to reset your rendering device without losing ImGui state. // Use if you want to reset your rendering device without losing ImGui state.
IMGUI_IMPL_API void ImGui_ImplDX10_InvalidateDeviceObjects(); IMGUI_IMPL_API void ImGui_ImplDX10_InvalidateDeviceObjects();
IMGUI_IMPL_API bool ImGui_ImplDX10_CreateDeviceObjects(); IMGUI_IMPL_API bool ImGui_ImplDX10_CreateDeviceObjects();
#endif #endif

View File

@ -3,40 +3,41 @@
#include <kiwano-imgui/imgui_impl_dx11.h> #include <kiwano-imgui/imgui_impl_dx11.h>
// DirectX // DirectX
#include <stdio.h>
#include <d3d11.h> #include <d3d11.h>
#include <d3dcompiler.h> #include <d3dcompiler.h>
#include <stdio.h>
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma comment(lib, "d3dcompiler") // Automatically link with d3dcompiler.lib as we are using D3DCompile() below. #pragma comment(lib, "d3dcompiler") // Automatically link with d3dcompiler.lib as we are using D3DCompile() below.
#endif #endif
// DirectX data // DirectX data
static ID3D11Device* g_pd3dDevice = NULL; static ID3D11Device* g_pd3dDevice = NULL;
static ID3D11DeviceContext* g_pd3dDeviceContext = NULL; static ID3D11DeviceContext* g_pd3dDeviceContext = NULL;
static IDXGIFactory* g_pFactory = NULL; static IDXGIFactory* g_pFactory = NULL;
static ID3D11Buffer* g_pVB = NULL; static ID3D11Buffer* g_pVB = NULL;
static ID3D11Buffer* g_pIB = NULL; static ID3D11Buffer* g_pIB = NULL;
static ID3D10Blob* g_pVertexShaderBlob = NULL; static ID3D10Blob* g_pVertexShaderBlob = NULL;
static ID3D11VertexShader* g_pVertexShader = NULL; static ID3D11VertexShader* g_pVertexShader = NULL;
static ID3D11InputLayout* g_pInputLayout = NULL; static ID3D11InputLayout* g_pInputLayout = NULL;
static ID3D11Buffer* g_pVertexConstantBuffer = NULL; static ID3D11Buffer* g_pVertexConstantBuffer = NULL;
static ID3D10Blob* g_pPixelShaderBlob = NULL; static ID3D10Blob* g_pPixelShaderBlob = NULL;
static ID3D11PixelShader* g_pPixelShader = NULL; static ID3D11PixelShader* g_pPixelShader = NULL;
static ID3D11SamplerState* g_pFontSampler = NULL; static ID3D11SamplerState* g_pFontSampler = NULL;
static ID3D11ShaderResourceView*g_pFontTextureView = NULL; static ID3D11ShaderResourceView* g_pFontTextureView = NULL;
static ID3D11RasterizerState* g_pRasterizerState = NULL; static ID3D11RasterizerState* g_pRasterizerState = NULL;
static ID3D11BlendState* g_pBlendState = NULL; static ID3D11BlendState* g_pBlendState = NULL;
static ID3D11DepthStencilState* g_pDepthStencilState = NULL; static ID3D11DepthStencilState* g_pDepthStencilState = NULL;
static int g_VertexBufferSize = 5000, g_IndexBufferSize = 10000; static int g_VertexBufferSize = 5000, g_IndexBufferSize = 10000;
struct VERTEX_CONSTANT_BUFFER struct VERTEX_CONSTANT_BUFFER
{ {
float mvp[4][4]; float mvp[4][4];
}; };
// Render Function // Render Function
// (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop) // (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from
// your main loop)
void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data) void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
{ {
ID3D11DeviceContext* ctx = g_pd3dDeviceContext; ID3D11DeviceContext* ctx = g_pd3dDeviceContext;
@ -44,27 +45,35 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
// Create and grow vertex/index buffers if needed // Create and grow vertex/index buffers if needed
if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount)
{ {
if (g_pVB) { g_pVB->Release(); g_pVB = NULL; } if (g_pVB)
{
g_pVB->Release();
g_pVB = NULL;
}
g_VertexBufferSize = draw_data->TotalVtxCount + 5000; g_VertexBufferSize = draw_data->TotalVtxCount + 5000;
D3D11_BUFFER_DESC desc; D3D11_BUFFER_DESC desc;
memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); memset(&desc, 0, sizeof(D3D11_BUFFER_DESC));
desc.Usage = D3D11_USAGE_DYNAMIC; desc.Usage = D3D11_USAGE_DYNAMIC;
desc.ByteWidth = g_VertexBufferSize * sizeof(ImDrawVert); desc.ByteWidth = g_VertexBufferSize * sizeof(ImDrawVert);
desc.BindFlags = D3D11_BIND_VERTEX_BUFFER; desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
desc.MiscFlags = 0; desc.MiscFlags = 0;
if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0) if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0)
return; return;
} }
if (!g_pIB || g_IndexBufferSize < draw_data->TotalIdxCount) if (!g_pIB || g_IndexBufferSize < draw_data->TotalIdxCount)
{ {
if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } if (g_pIB)
{
g_pIB->Release();
g_pIB = NULL;
}
g_IndexBufferSize = draw_data->TotalIdxCount + 10000; g_IndexBufferSize = draw_data->TotalIdxCount + 10000;
D3D11_BUFFER_DESC desc; D3D11_BUFFER_DESC desc;
memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); memset(&desc, 0, sizeof(D3D11_BUFFER_DESC));
desc.Usage = D3D11_USAGE_DYNAMIC; desc.Usage = D3D11_USAGE_DYNAMIC;
desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx);
desc.BindFlags = D3D11_BIND_INDEX_BUFFER; desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0) if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0)
return; return;
@ -77,7 +86,7 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK)
return; return;
ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData; ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData;
ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData; ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData;
for (int n = 0; n < draw_data->CmdListsCount; n++) for (int n = 0; n < draw_data->CmdListsCount; n++)
{ {
const ImDrawList* cmd_list = draw_data->CmdLists[n]; const ImDrawList* cmd_list = draw_data->CmdLists[n];
@ -90,50 +99,51 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
ctx->Unmap(g_pIB, 0); ctx->Unmap(g_pIB, 0);
// Setup orthographic projection matrix into our constant buffer // Setup orthographic projection matrix into our constant buffer
// Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). // Our visible imgui space lies from draw_data->DisplayPos (top left) to
// draw_data->DisplayPos+data_data->DisplaySize (bottom right).
{ {
D3D11_MAPPED_SUBRESOURCE mapped_resource; D3D11_MAPPED_SUBRESOURCE mapped_resource;
if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK)
return; return;
VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData; VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData;
float L = draw_data->DisplayPos.x; float L = draw_data->DisplayPos.x;
float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x; float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x;
float T = draw_data->DisplayPos.y; float T = draw_data->DisplayPos.y;
float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y; float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y;
float mvp[4][4] = float mvp[4][4] = {
{ { 2.0f / (R - L), 0.0f, 0.0f, 0.0f },
{ 2.0f/(R-L), 0.0f, 0.0f, 0.0f }, { 0.0f, 2.0f / (T - B), 0.0f, 0.0f },
{ 0.0f, 2.0f/(T-B), 0.0f, 0.0f }, { 0.0f, 0.0f, 0.5f, 0.0f },
{ 0.0f, 0.0f, 0.5f, 0.0f }, { (R + L) / (L - R), (T + B) / (B - T), 0.5f, 1.0f },
{ (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f },
}; };
memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); memcpy(&constant_buffer->mvp, mvp, sizeof(mvp));
ctx->Unmap(g_pVertexConstantBuffer, 0); ctx->Unmap(g_pVertexConstantBuffer, 0);
} }
// Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and
// verbose. Close your eyes!)
struct BACKUP_DX11_STATE struct BACKUP_DX11_STATE
{ {
UINT ScissorRectsCount, ViewportsCount; UINT ScissorRectsCount, ViewportsCount;
D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE];
D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE];
ID3D11RasterizerState* RS; ID3D11RasterizerState* RS;
ID3D11BlendState* BlendState; ID3D11BlendState* BlendState;
FLOAT BlendFactor[4]; FLOAT BlendFactor[4];
UINT SampleMask; UINT SampleMask;
UINT StencilRef; UINT StencilRef;
ID3D11DepthStencilState* DepthStencilState; ID3D11DepthStencilState* DepthStencilState;
ID3D11ShaderResourceView* PSShaderResource; ID3D11ShaderResourceView* PSShaderResource;
ID3D11SamplerState* PSSampler; ID3D11SamplerState* PSSampler;
ID3D11PixelShader* PS; ID3D11PixelShader* PS;
ID3D11VertexShader* VS; ID3D11VertexShader* VS;
UINT PSInstancesCount, VSInstancesCount; UINT PSInstancesCount, VSInstancesCount;
ID3D11ClassInstance* PSInstances[256], *VSInstances[256]; // 256 is max according to PSSetShader documentation ID3D11ClassInstance *PSInstances[256], *VSInstances[256]; // 256 is max according to PSSetShader documentation
D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology; D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology;
ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; ID3D11Buffer * IndexBuffer, *VertexBuffer, *VSConstantBuffer;
UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset;
DXGI_FORMAT IndexBufferFormat; DXGI_FORMAT IndexBufferFormat;
ID3D11InputLayout* InputLayout; ID3D11InputLayout* InputLayout;
}; };
BACKUP_DX11_STATE old; BACKUP_DX11_STATE old;
old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE;
@ -156,8 +166,8 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
// Setup viewport // Setup viewport
D3D11_VIEWPORT vp; D3D11_VIEWPORT vp;
memset(&vp, 0, sizeof(D3D11_VIEWPORT)); memset(&vp, 0, sizeof(D3D11_VIEWPORT));
vp.Width = draw_data->DisplaySize.x; vp.Width = draw_data->DisplaySize.x;
vp.Height = draw_data->DisplaySize.y; vp.Height = draw_data->DisplaySize.y;
vp.MinDepth = 0.0f; vp.MinDepth = 0.0f;
vp.MaxDepth = 1.0f; vp.MaxDepth = 1.0f;
vp.TopLeftX = vp.TopLeftY = 0; vp.TopLeftX = vp.TopLeftY = 0;
@ -182,9 +192,9 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
ctx->RSSetState(g_pRasterizerState); ctx->RSSetState(g_pRasterizerState);
// Render command lists // Render command lists
int vtx_offset = 0; int vtx_offset = 0;
int idx_offset = 0; int idx_offset = 0;
ImVec2 pos = draw_data->DisplayPos; ImVec2 pos = draw_data->DisplayPos;
for (int n = 0; n < draw_data->CmdListsCount; n++) for (int n = 0; n < draw_data->CmdListsCount; n++)
{ {
const ImDrawList* cmd_list = draw_data->CmdLists[n]; const ImDrawList* cmd_list = draw_data->CmdLists[n];
@ -199,7 +209,8 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
else else
{ {
// Apply scissor/clipping rectangle // Apply scissor/clipping rectangle
const D3D11_RECT r = { (LONG)(pcmd->ClipRect.x - pos.x), (LONG)(pcmd->ClipRect.y - pos.y), (LONG)(pcmd->ClipRect.z - pos.x), (LONG)(pcmd->ClipRect.w - pos.y) }; const D3D11_RECT r = { (LONG)(pcmd->ClipRect.x - pos.x), (LONG)(pcmd->ClipRect.y - pos.y),
(LONG)(pcmd->ClipRect.z - pos.x), (LONG)(pcmd->ClipRect.w - pos.y) };
ctx->RSSetScissorRects(1, &r); ctx->RSSetScissorRects(1, &r);
// Bind texture, Draw // Bind texture, Draw
@ -215,61 +226,87 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
// Restore modified DX state // Restore modified DX state
ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects);
ctx->RSSetViewports(old.ViewportsCount, old.Viewports); ctx->RSSetViewports(old.ViewportsCount, old.Viewports);
ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); ctx->RSSetState(old.RS);
ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); if (old.RS)
ctx->OMSetDepthStencilState(old.DepthStencilState, old.StencilRef); if (old.DepthStencilState) old.DepthStencilState->Release(); old.RS->Release();
ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask);
ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); if (old.BlendState)
ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release(); old.BlendState->Release();
for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release(); ctx->OMSetDepthStencilState(old.DepthStencilState, old.StencilRef);
ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release(); if (old.DepthStencilState)
ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); old.DepthStencilState->Release();
for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release(); ctx->PSSetShaderResources(0, 1, &old.PSShaderResource);
if (old.PSShaderResource)
old.PSShaderResource->Release();
ctx->PSSetSamplers(0, 1, &old.PSSampler);
if (old.PSSampler)
old.PSSampler->Release();
ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount);
if (old.PS)
old.PS->Release();
for (UINT i = 0; i < old.PSInstancesCount; i++)
if (old.PSInstances[i])
old.PSInstances[i]->Release();
ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount);
if (old.VS)
old.VS->Release();
ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer);
if (old.VSConstantBuffer)
old.VSConstantBuffer->Release();
for (UINT i = 0; i < old.VSInstancesCount; i++)
if (old.VSInstances[i])
old.VSInstances[i]->Release();
ctx->IASetPrimitiveTopology(old.PrimitiveTopology); ctx->IASetPrimitiveTopology(old.PrimitiveTopology);
ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset);
ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); if (old.IndexBuffer)
ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); old.IndexBuffer->Release();
ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset);
if (old.VertexBuffer)
old.VertexBuffer->Release();
ctx->IASetInputLayout(old.InputLayout);
if (old.InputLayout)
old.InputLayout->Release();
} }
static void ImGui_ImplDX11_CreateFontsTexture() static void ImGui_ImplDX11_CreateFontsTexture()
{ {
// Build texture atlas // Build texture atlas
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
unsigned char* pixels; unsigned char* pixels;
int width, height; int width, height;
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
// Upload texture to graphics system // Upload texture to graphics system
{ {
D3D11_TEXTURE2D_DESC desc; D3D11_TEXTURE2D_DESC desc;
ZeroMemory(&desc, sizeof(desc)); ZeroMemory(&desc, sizeof(desc));
desc.Width = width; desc.Width = width;
desc.Height = height; desc.Height = height;
desc.MipLevels = 1; desc.MipLevels = 1;
desc.ArraySize = 1; desc.ArraySize = 1;
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
desc.SampleDesc.Count = 1; desc.SampleDesc.Count = 1;
desc.Usage = D3D11_USAGE_DEFAULT; desc.Usage = D3D11_USAGE_DEFAULT;
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
desc.CPUAccessFlags = 0; desc.CPUAccessFlags = 0;
ID3D11Texture2D *pTexture = NULL; ID3D11Texture2D* pTexture = NULL;
D3D11_SUBRESOURCE_DATA subResource; D3D11_SUBRESOURCE_DATA subResource;
subResource.pSysMem = pixels; subResource.pSysMem = pixels;
subResource.SysMemPitch = desc.Width * 4; subResource.SysMemPitch = desc.Width * 4;
subResource.SysMemSlicePitch = 0; subResource.SysMemSlicePitch = 0;
g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture);
if (pTexture) if (pTexture)
{ {
// Create texture view // Create texture view
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
ZeroMemory(&srvDesc, sizeof(srvDesc)); ZeroMemory(&srvDesc, sizeof(srvDesc));
srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
srvDesc.Texture2D.MipLevels = desc.MipLevels; srvDesc.Texture2D.MipLevels = desc.MipLevels;
srvDesc.Texture2D.MostDetailedMip = 0; srvDesc.Texture2D.MostDetailedMip = 0;
g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView);
pTexture->Release(); pTexture->Release();
} }
@ -282,35 +319,36 @@ static void ImGui_ImplDX11_CreateFontsTexture()
{ {
D3D11_SAMPLER_DESC desc; D3D11_SAMPLER_DESC desc;
ZeroMemory(&desc, sizeof(desc)); ZeroMemory(&desc, sizeof(desc));
desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
desc.MipLODBias = 0.f; desc.MipLODBias = 0.f;
desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
desc.MinLOD = 0.f; desc.MinLOD = 0.f;
desc.MaxLOD = 0.f; desc.MaxLOD = 0.f;
g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler);
} }
} }
bool ImGui_ImplDX11_CreateDeviceObjects() bool ImGui_ImplDX11_CreateDeviceObjects()
{ {
if (!g_pd3dDevice) if (!g_pd3dDevice)
return false; return false;
if (g_pFontSampler) if (g_pFontSampler)
ImGui_ImplDX11_InvalidateDeviceObjects(); ImGui_ImplDX11_InvalidateDeviceObjects();
// By using D3DCompile() from <d3dcompiler.h> / d3dcompiler.lib, we introduce a dependency to a given version of d3dcompiler_XX.dll (see D3DCOMPILER_DLL_A) // By using D3DCompile() from <d3dcompiler.h> / d3dcompiler.lib, we introduce a dependency to a given version of
// If you would like to use this DX11 sample code but remove this dependency you can: // d3dcompiler_XX.dll (see D3DCOMPILER_DLL_A) If you would like to use this DX11 sample code but remove this
// 1) compile once, save the compiled shader blobs into a file or source code and pass them to CreateVertexShader()/CreatePixelShader() [preferred solution] // dependency you can:
// 2) use code to detect any version of the DLL and grab a pointer to D3DCompile from the DLL. // 1) compile once, save the compiled shader blobs into a file or source code and pass them to
// CreateVertexShader()/CreatePixelShader() [preferred solution] 2) use code to detect any version of the DLL and
// grab a pointer to D3DCompile from the DLL.
// See https://github.com/ocornut/imgui/pull/638 for sources and details. // See https://github.com/ocornut/imgui/pull/638 for sources and details.
// Create the vertex shader // Create the vertex shader
{ {
static const char* vertexShader = static const char* vertexShader = "cbuffer vertexBuffer : register(b0) \
"cbuffer vertexBuffer : register(b0) \
{\ {\
float4x4 ProjectionMatrix; \ float4x4 ProjectionMatrix; \
};\ };\
@ -337,38 +375,46 @@ bool ImGui_ImplDX11_CreateDeviceObjects()
return output;\ return output;\
}"; }";
D3DCompile(vertexShader, strlen(vertexShader), NULL, NULL, NULL, "main", "vs_4_0", 0, 0, &g_pVertexShaderBlob, NULL); D3DCompile(vertexShader, strlen(vertexShader), NULL, NULL, NULL, "main", "vs_4_0", 0, 0, &g_pVertexShaderBlob,
if (g_pVertexShaderBlob == NULL) // NB: Pass ID3D10Blob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob! NULL);
if (g_pVertexShaderBlob
== NULL) // NB: Pass ID3D10Blob* pErrorBlob to D3DCompile() to get error showing in (const
// char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!
return false; return false;
if (g_pd3dDevice->CreateVertexShader((DWORD*)g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), NULL, &g_pVertexShader) != S_OK) if (g_pd3dDevice->CreateVertexShader((DWORD*)g_pVertexShaderBlob->GetBufferPointer(),
g_pVertexShaderBlob->GetBufferSize(), NULL, &g_pVertexShader)
!= S_OK)
return false; return false;
// Create the input layout // Create the input layout
D3D11_INPUT_ELEMENT_DESC local_layout[] = D3D11_INPUT_ELEMENT_DESC local_layout[] = {
{ { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D11_INPUT_PER_VERTEX_DATA,
{ "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D11_INPUT_PER_VERTEX_DATA, 0 }, 0 },
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D11_INPUT_PER_VERTEX_DATA,
{ "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D11_INPUT_PER_VERTEX_DATA, 0 }, 0 },
{ "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D11_INPUT_PER_VERTEX_DATA,
0 },
}; };
if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(),
g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout)
!= S_OK)
return false; return false;
// Create the constant buffer // Create the constant buffer
{ {
D3D11_BUFFER_DESC desc; D3D11_BUFFER_DESC desc;
desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER);
desc.Usage = D3D11_USAGE_DYNAMIC; desc.Usage = D3D11_USAGE_DYNAMIC;
desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
desc.MiscFlags = 0; desc.MiscFlags = 0;
g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer);
} }
} }
// Create the pixel shader // Create the pixel shader
{ {
static const char* pixelShader = static const char* pixelShader = "struct PS_INPUT\
"struct PS_INPUT\
{\ {\
float4 pos : SV_POSITION;\ float4 pos : SV_POSITION;\
float4 col : COLOR0;\ float4 col : COLOR0;\
@ -383,10 +429,15 @@ bool ImGui_ImplDX11_CreateDeviceObjects()
return out_col; \ return out_col; \
}"; }";
D3DCompile(pixelShader, strlen(pixelShader), NULL, NULL, NULL, "main", "ps_4_0", 0, 0, &g_pPixelShaderBlob, NULL); D3DCompile(pixelShader, strlen(pixelShader), NULL, NULL, NULL, "main", "ps_4_0", 0, 0, &g_pPixelShaderBlob,
if (g_pPixelShaderBlob == NULL) // NB: Pass ID3D10Blob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob! NULL);
if (g_pPixelShaderBlob
== NULL) // NB: Pass ID3D10Blob* pErrorBlob to D3DCompile() to get error showing in (const
// char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!
return false; return false;
if (g_pd3dDevice->CreatePixelShader((DWORD*)g_pPixelShaderBlob->GetBufferPointer(), g_pPixelShaderBlob->GetBufferSize(), NULL, &g_pPixelShader) != S_OK) if (g_pd3dDevice->CreatePixelShader((DWORD*)g_pPixelShaderBlob->GetBufferPointer(),
g_pPixelShaderBlob->GetBufferSize(), NULL, &g_pPixelShader)
!= S_OK)
return false; return false;
} }
@ -394,14 +445,14 @@ bool ImGui_ImplDX11_CreateDeviceObjects()
{ {
D3D11_BLEND_DESC desc; D3D11_BLEND_DESC desc;
ZeroMemory(&desc, sizeof(desc)); ZeroMemory(&desc, sizeof(desc));
desc.AlphaToCoverageEnable = false; desc.AlphaToCoverageEnable = false;
desc.RenderTarget[0].BlendEnable = true; desc.RenderTarget[0].BlendEnable = true;
desc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA; desc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
desc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA; desc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA; desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA;
desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO; desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
g_pd3dDevice->CreateBlendState(&desc, &g_pBlendState); g_pd3dDevice->CreateBlendState(&desc, &g_pBlendState);
} }
@ -410,9 +461,9 @@ bool ImGui_ImplDX11_CreateDeviceObjects()
{ {
D3D11_RASTERIZER_DESC desc; D3D11_RASTERIZER_DESC desc;
ZeroMemory(&desc, sizeof(desc)); ZeroMemory(&desc, sizeof(desc));
desc.FillMode = D3D11_FILL_SOLID; desc.FillMode = D3D11_FILL_SOLID;
desc.CullMode = D3D11_CULL_NONE; desc.CullMode = D3D11_CULL_NONE;
desc.ScissorEnable = true; desc.ScissorEnable = true;
desc.DepthClipEnable = true; desc.DepthClipEnable = true;
g_pd3dDevice->CreateRasterizerState(&desc, &g_pRasterizerState); g_pd3dDevice->CreateRasterizerState(&desc, &g_pRasterizerState);
} }
@ -421,13 +472,14 @@ bool ImGui_ImplDX11_CreateDeviceObjects()
{ {
D3D11_DEPTH_STENCIL_DESC desc; D3D11_DEPTH_STENCIL_DESC desc;
ZeroMemory(&desc, sizeof(desc)); ZeroMemory(&desc, sizeof(desc));
desc.DepthEnable = false; desc.DepthEnable = false;
desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
desc.DepthFunc = D3D11_COMPARISON_ALWAYS; desc.DepthFunc = D3D11_COMPARISON_ALWAYS;
desc.StencilEnable = false; desc.StencilEnable = false;
desc.FrontFace.StencilFailOp = desc.FrontFace.StencilDepthFailOp = desc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; desc.FrontFace.StencilFailOp = desc.FrontFace.StencilDepthFailOp = desc.FrontFace.StencilPassOp =
D3D11_STENCIL_OP_KEEP;
desc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; desc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
desc.BackFace = desc.FrontFace; desc.BackFace = desc.FrontFace;
g_pd3dDevice->CreateDepthStencilState(&desc, &g_pDepthStencilState); g_pd3dDevice->CreateDepthStencilState(&desc, &g_pDepthStencilState);
} }
@ -436,47 +488,102 @@ bool ImGui_ImplDX11_CreateDeviceObjects()
return true; return true;
} }
void ImGui_ImplDX11_InvalidateDeviceObjects() void ImGui_ImplDX11_InvalidateDeviceObjects()
{ {
if (!g_pd3dDevice) if (!g_pd3dDevice)
return; return;
if (g_pFontSampler) { g_pFontSampler->Release(); g_pFontSampler = NULL; } if (g_pFontSampler)
if (g_pFontTextureView) { g_pFontTextureView->Release(); g_pFontTextureView = NULL; ImGui::GetIO().Fonts->TexID = NULL; } // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well. {
if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_pFontSampler->Release();
if (g_pVB) { g_pVB->Release(); g_pVB = NULL; } g_pFontSampler = NULL;
}
if (g_pFontTextureView)
{
g_pFontTextureView->Release();
g_pFontTextureView = NULL;
ImGui::GetIO().Fonts->TexID = NULL;
} // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well.
if (g_pIB)
{
g_pIB->Release();
g_pIB = NULL;
}
if (g_pVB)
{
g_pVB->Release();
g_pVB = NULL;
}
if (g_pBlendState) { g_pBlendState->Release(); g_pBlendState = NULL; } if (g_pBlendState)
if (g_pDepthStencilState) { g_pDepthStencilState->Release(); g_pDepthStencilState = NULL; } {
if (g_pRasterizerState) { g_pRasterizerState->Release(); g_pRasterizerState = NULL; } g_pBlendState->Release();
if (g_pPixelShader) { g_pPixelShader->Release(); g_pPixelShader = NULL; } g_pBlendState = NULL;
if (g_pPixelShaderBlob) { g_pPixelShaderBlob->Release(); g_pPixelShaderBlob = NULL; } }
if (g_pVertexConstantBuffer) { g_pVertexConstantBuffer->Release(); g_pVertexConstantBuffer = NULL; } if (g_pDepthStencilState)
if (g_pInputLayout) { g_pInputLayout->Release(); g_pInputLayout = NULL; } {
if (g_pVertexShader) { g_pVertexShader->Release(); g_pVertexShader = NULL; } g_pDepthStencilState->Release();
if (g_pVertexShaderBlob) { g_pVertexShaderBlob->Release(); g_pVertexShaderBlob = NULL; } g_pDepthStencilState = NULL;
}
if (g_pRasterizerState)
{
g_pRasterizerState->Release();
g_pRasterizerState = NULL;
}
if (g_pPixelShader)
{
g_pPixelShader->Release();
g_pPixelShader = NULL;
}
if (g_pPixelShaderBlob)
{
g_pPixelShaderBlob->Release();
g_pPixelShaderBlob = NULL;
}
if (g_pVertexConstantBuffer)
{
g_pVertexConstantBuffer->Release();
g_pVertexConstantBuffer = NULL;
}
if (g_pInputLayout)
{
g_pInputLayout->Release();
g_pInputLayout = NULL;
}
if (g_pVertexShader)
{
g_pVertexShader->Release();
g_pVertexShader = NULL;
}
if (g_pVertexShaderBlob)
{
g_pVertexShaderBlob->Release();
g_pVertexShaderBlob = NULL;
}
} }
bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_context) bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_context)
{ {
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
io.BackendRendererName = "imgui_impl_dx11"; io.BackendRendererName = "imgui_impl_dx11";
// Get factory from device // Get factory from device
IDXGIDevice* pDXGIDevice = NULL; IDXGIDevice* pDXGIDevice = NULL;
IDXGIAdapter* pDXGIAdapter = NULL; IDXGIAdapter* pDXGIAdapter = NULL;
IDXGIFactory* pFactory = NULL; IDXGIFactory* pFactory = NULL;
if (device->QueryInterface(IID_PPV_ARGS(&pDXGIDevice)) == S_OK) if (device->QueryInterface(IID_PPV_ARGS(&pDXGIDevice)) == S_OK)
if (pDXGIDevice->GetParent(IID_PPV_ARGS(&pDXGIAdapter)) == S_OK) if (pDXGIDevice->GetParent(IID_PPV_ARGS(&pDXGIAdapter)) == S_OK)
if (pDXGIAdapter->GetParent(IID_PPV_ARGS(&pFactory)) == S_OK) if (pDXGIAdapter->GetParent(IID_PPV_ARGS(&pFactory)) == S_OK)
{ {
g_pd3dDevice = device; g_pd3dDevice = device;
g_pd3dDeviceContext = device_context; g_pd3dDeviceContext = device_context;
g_pFactory = pFactory; g_pFactory = pFactory;
} }
if (pDXGIDevice) pDXGIDevice->Release(); if (pDXGIDevice)
if (pDXGIAdapter) pDXGIAdapter->Release(); pDXGIDevice->Release();
if (pDXGIAdapter)
pDXGIAdapter->Release();
return true; return true;
} }
@ -484,8 +591,12 @@ bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_co
void ImGui_ImplDX11_Shutdown() void ImGui_ImplDX11_Shutdown()
{ {
ImGui_ImplDX11_InvalidateDeviceObjects(); ImGui_ImplDX11_InvalidateDeviceObjects();
if (g_pFactory) { g_pFactory->Release(); g_pFactory = NULL; } if (g_pFactory)
g_pd3dDevice = NULL; {
g_pFactory->Release();
g_pFactory = NULL;
}
g_pd3dDevice = NULL;
g_pd3dDeviceContext = NULL; g_pd3dDeviceContext = NULL;
} }

View File

@ -8,13 +8,13 @@
struct ID3D11Device; struct ID3D11Device;
struct ID3D11DeviceContext; struct ID3D11DeviceContext;
IMGUI_IMPL_API bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_context); IMGUI_IMPL_API bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_context);
IMGUI_IMPL_API void ImGui_ImplDX11_Shutdown(); IMGUI_IMPL_API void ImGui_ImplDX11_Shutdown();
IMGUI_IMPL_API void ImGui_ImplDX11_NewFrame(); IMGUI_IMPL_API void ImGui_ImplDX11_NewFrame();
IMGUI_IMPL_API void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data); IMGUI_IMPL_API void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data);
// Use if you want to reset your rendering device without losing ImGui state. // Use if you want to reset your rendering device without losing ImGui state.
IMGUI_IMPL_API void ImGui_ImplDX11_InvalidateDeviceObjects(); IMGUI_IMPL_API void ImGui_ImplDX11_InvalidateDeviceObjects();
IMGUI_IMPL_API bool ImGui_ImplDX11_CreateDeviceObjects(); IMGUI_IMPL_API bool ImGui_ImplDX11_CreateDeviceObjects();
#endif #endif

View File

@ -1,15 +1,15 @@
// Copyright (c) 2016-2018 Kiwano - Nomango // Copyright (c) 2016-2018 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE

View File

@ -1,15 +1,15 @@
// Copyright (c) 2016-2018 Kiwano - Nomango // Copyright (c) 2016-2018 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -18,364 +18,338 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE. // THE SOFTWARE.
#include <thread>
#include <codecvt> #include <codecvt>
#include <thread>
#include <kiwano/core/Logger.h>
#include <kiwano/platform/Application.h>
#include <kiwano-network/HttpRequest.h> #include <kiwano-network/HttpRequest.h>
#include <kiwano-network/HttpResponse.hpp> #include <kiwano-network/HttpResponse.hpp>
#include <kiwano-network/HttpClient.h> #include <kiwano-network/HttpClient.h>
#include <kiwano/core/Logger.h>
#include <kiwano/platform/Application.h>
#include <3rd-party/curl/curl.h> // CURL #include <3rd-party/curl/curl.h> // CURL
namespace namespace
{ {
using namespace kiwano; using namespace kiwano;
using namespace kiwano::network; using namespace kiwano::network;
uint32_t write_data(void* buffer, uint32_t size, uint32_t nmemb, void* userp) uint32_t write_data(void* buffer, uint32_t size, uint32_t nmemb, void* userp)
{ {
ByteString* recv_buffer = (ByteString*)userp; ByteString* recv_buffer = (ByteString*)userp;
uint32_t total = size * nmemb; uint32_t total = size * nmemb;
// add data to the end of recv_buffer // add data to the end of recv_buffer
// write data maybe called more than once in a single request // write data maybe called more than once in a single request
recv_buffer->append((char*)buffer, total); recv_buffer->append((char*)buffer, total);
return total; return total;
}
ByteString convert_to_utf8(String const& str)
{
std::wstring_convert<std::codecvt_utf8<wchar_t>> utf8_conv;
ByteString result;
try
{
result = utf8_conv.to_bytes(str.c_str());
}
catch (std::range_error&)
{
// bad conversion
result = WideToMultiByte(str);
}
return result;
}
String convert_from_utf8(ByteString const& str)
{
oc::string_convert<std::codecvt_utf8<wchar_t>> utf8_conv;
String result;
try
{
result = utf8_conv.from_bytes(str);
}
catch (std::range_error&)
{
// bad conversion
result = MultiByteToWide(str);
}
return result;
}
class Curl
{
public:
Curl()
: curl_(curl_easy_init())
, curl_headers_(nullptr)
{
}
~Curl()
{
if (curl_)
{
curl_easy_cleanup(curl_);
curl_ = nullptr;
}
if (curl_headers_)
{
curl_slist_free_all(curl_headers_);
curl_headers_ = nullptr;
}
}
bool Init(HttpClient* client, Vector<ByteString> const& headers, ByteString const& url, ByteString* response_data, ByteString* response_header, char* error_buffer)
{
if (!SetOption(CURLOPT_ERRORBUFFER, error_buffer))
return false;
if (!SetOption(CURLOPT_TIMEOUT, client->GetTimeoutForRead()))
return false;
if (!SetOption(CURLOPT_CONNECTTIMEOUT, client->GetTimeoutForConnect()))
return false;
const auto ssl_ca_file = wide_to_string(client->GetSSLVerification());
if (ssl_ca_file.empty()) {
if (!SetOption(CURLOPT_SSL_VERIFYPEER, 0L))
return false;
if (!SetOption(CURLOPT_SSL_VERIFYHOST, 0L))
return false;
}
else {
if (!SetOption(CURLOPT_SSL_VERIFYPEER, 1L))
return false;
if (!SetOption(CURLOPT_SSL_VERIFYHOST, 2L))
return false;
if (!SetOption(CURLOPT_CAINFO, ssl_ca_file.c_str()))
return false;
}
if (!SetOption(CURLOPT_NOSIGNAL, 1L))
return false;
if (!SetOption(CURLOPT_ACCEPT_ENCODING, ""))
return false;
// set request headers
if (!headers.empty())
{
for (const auto& header : headers)
{
curl_headers_ = curl_slist_append(curl_headers_, header.c_str());
}
if (!SetOption(CURLOPT_HTTPHEADER, curl_headers_))
return false;
}
return SetOption(CURLOPT_URL, url.c_str())
&& SetOption(CURLOPT_WRITEFUNCTION, write_data)
&& SetOption(CURLOPT_WRITEDATA, response_data)
&& SetOption(CURLOPT_HEADERFUNCTION, write_data)
&& SetOption(CURLOPT_HEADERDATA, response_header);
}
bool Perform(long* response_code)
{
if (CURLE_OK != curl_easy_perform(curl_))
return false;
CURLcode code = curl_easy_getinfo(curl_, CURLINFO_RESPONSE_CODE, response_code);
return code == CURLE_OK && (*response_code >= 200 && *response_code < 300);
}
template <typename ..._Args>
bool SetOption(CURLoption option, _Args&&... args)
{
return CURLE_OK == curl_easy_setopt(curl_, option, std::forward<_Args>(args)...);
}
public:
static inline bool GetRequest(
HttpClient* client,
Vector<ByteString> const& headers,
ByteString const& url,
long* response_code,
ByteString* response_data,
ByteString* response_header,
char* error_buffer)
{
Curl curl;
return curl.Init(client, headers, url, response_data, response_header, error_buffer)
&& curl.SetOption(CURLOPT_FOLLOWLOCATION, true)
&& curl.Perform(response_code);
}
static inline bool PostRequest(
HttpClient* client,
Vector<ByteString> const& headers,
ByteString const& url,
ByteString const& request_data,
long* response_code,
ByteString* response_data,
ByteString* response_header,
char* error_buffer)
{
Curl curl;
return curl.Init(client, headers, url, response_data, response_header, error_buffer)
&& curl.SetOption(CURLOPT_POST, 1)
&& curl.SetOption(CURLOPT_POSTFIELDS, request_data.c_str())
&& curl.SetOption(CURLOPT_POSTFIELDSIZE, request_data.size())
&& curl.Perform(response_code);
}
static inline bool PutRequest(
HttpClient* client,
Vector<ByteString> const& headers,
ByteString const& url,
ByteString const& request_data,
long* response_code,
ByteString* response_data,
ByteString* response_header,
char* error_buffer)
{
Curl curl;
return curl.Init(client, headers, url, response_data, response_header, error_buffer)
&& curl.SetOption(CURLOPT_CUSTOMREQUEST, "PUT")
&& curl.SetOption(CURLOPT_POSTFIELDS, request_data.c_str())
&& curl.SetOption(CURLOPT_POSTFIELDSIZE, request_data.size())
&& curl.Perform(response_code);
}
static inline bool DeleteRequest(
HttpClient* client,
Vector<ByteString> const& headers,
ByteString const& url,
long* response_code,
ByteString* response_data,
ByteString* response_header,
char* error_buffer)
{
Curl curl;
return curl.Init(client, headers, url, response_data, response_header, error_buffer)
&& curl.SetOption(CURLOPT_CUSTOMREQUEST, "DELETE")
&& curl.SetOption(CURLOPT_FOLLOWLOCATION, true)
&& curl.Perform(response_code);
}
private:
CURL* curl_;
curl_slist* curl_headers_;
};
} }
ByteString convert_to_utf8(String const& str)
{
std::wstring_convert<std::codecvt_utf8<wchar_t>> utf8_conv;
ByteString result;
try
{
result = utf8_conv.to_bytes(str.c_str());
}
catch (std::range_error&)
{
// bad conversion
result = WideToMultiByte(str);
}
return result;
}
String convert_from_utf8(ByteString const& str)
{
oc::string_convert<std::codecvt_utf8<wchar_t>> utf8_conv;
String result;
try
{
result = utf8_conv.from_bytes(str);
}
catch (std::range_error&)
{
// bad conversion
result = MultiByteToWide(str);
}
return result;
}
class Curl
{
public:
Curl()
: curl_(curl_easy_init())
, curl_headers_(nullptr)
{
}
~Curl()
{
if (curl_)
{
curl_easy_cleanup(curl_);
curl_ = nullptr;
}
if (curl_headers_)
{
curl_slist_free_all(curl_headers_);
curl_headers_ = nullptr;
}
}
bool Init(HttpClient* client, Vector<ByteString> const& headers, ByteString const& url, ByteString* response_data,
ByteString* response_header, char* error_buffer)
{
if (!SetOption(CURLOPT_ERRORBUFFER, error_buffer))
return false;
if (!SetOption(CURLOPT_TIMEOUT, client->GetTimeoutForRead()))
return false;
if (!SetOption(CURLOPT_CONNECTTIMEOUT, client->GetTimeoutForConnect()))
return false;
const auto ssl_ca_file = wide_to_string(client->GetSSLVerification());
if (ssl_ca_file.empty())
{
if (!SetOption(CURLOPT_SSL_VERIFYPEER, 0L))
return false;
if (!SetOption(CURLOPT_SSL_VERIFYHOST, 0L))
return false;
}
else
{
if (!SetOption(CURLOPT_SSL_VERIFYPEER, 1L))
return false;
if (!SetOption(CURLOPT_SSL_VERIFYHOST, 2L))
return false;
if (!SetOption(CURLOPT_CAINFO, ssl_ca_file.c_str()))
return false;
}
if (!SetOption(CURLOPT_NOSIGNAL, 1L))
return false;
if (!SetOption(CURLOPT_ACCEPT_ENCODING, ""))
return false;
// set request headers
if (!headers.empty())
{
for (const auto& header : headers)
{
curl_headers_ = curl_slist_append(curl_headers_, header.c_str());
}
if (!SetOption(CURLOPT_HTTPHEADER, curl_headers_))
return false;
}
return SetOption(CURLOPT_URL, url.c_str()) && SetOption(CURLOPT_WRITEFUNCTION, write_data)
&& SetOption(CURLOPT_WRITEDATA, response_data) && SetOption(CURLOPT_HEADERFUNCTION, write_data)
&& SetOption(CURLOPT_HEADERDATA, response_header);
}
bool Perform(long* response_code)
{
if (CURLE_OK != curl_easy_perform(curl_))
return false;
CURLcode code = curl_easy_getinfo(curl_, CURLINFO_RESPONSE_CODE, response_code);
return code == CURLE_OK && (*response_code >= 200 && *response_code < 300);
}
template <typename... _Args>
bool SetOption(CURLoption option, _Args&&... args)
{
return CURLE_OK == curl_easy_setopt(curl_, option, std::forward<_Args>(args)...);
}
public:
static inline bool GetRequest(HttpClient* client, Vector<ByteString> const& headers, ByteString const& url,
long* response_code, ByteString* response_data, ByteString* response_header,
char* error_buffer)
{
Curl curl;
return curl.Init(client, headers, url, response_data, response_header, error_buffer)
&& curl.SetOption(CURLOPT_FOLLOWLOCATION, true) && curl.Perform(response_code);
}
static inline bool PostRequest(HttpClient* client, Vector<ByteString> const& headers, ByteString const& url,
ByteString const& request_data, long* response_code, ByteString* response_data,
ByteString* response_header, char* error_buffer)
{
Curl curl;
return curl.Init(client, headers, url, response_data, response_header, error_buffer)
&& curl.SetOption(CURLOPT_POST, 1) && curl.SetOption(CURLOPT_POSTFIELDS, request_data.c_str())
&& curl.SetOption(CURLOPT_POSTFIELDSIZE, request_data.size()) && curl.Perform(response_code);
}
static inline bool PutRequest(HttpClient* client, Vector<ByteString> const& headers, ByteString const& url,
ByteString const& request_data, long* response_code, ByteString* response_data,
ByteString* response_header, char* error_buffer)
{
Curl curl;
return curl.Init(client, headers, url, response_data, response_header, error_buffer)
&& curl.SetOption(CURLOPT_CUSTOMREQUEST, "PUT")
&& curl.SetOption(CURLOPT_POSTFIELDS, request_data.c_str())
&& curl.SetOption(CURLOPT_POSTFIELDSIZE, request_data.size()) && curl.Perform(response_code);
}
static inline bool DeleteRequest(HttpClient* client, Vector<ByteString> const& headers, ByteString const& url,
long* response_code, ByteString* response_data, ByteString* response_header,
char* error_buffer)
{
Curl curl;
return curl.Init(client, headers, url, response_data, response_header, error_buffer)
&& curl.SetOption(CURLOPT_CUSTOMREQUEST, "DELETE") && curl.SetOption(CURLOPT_FOLLOWLOCATION, true)
&& curl.Perform(response_code);
}
private:
CURL* curl_;
curl_slist* curl_headers_;
};
} // namespace
namespace kiwano namespace kiwano
{ {
namespace network namespace network
{ {
HttpClient::HttpClient() HttpClient::HttpClient()
: timeout_for_connect_(30000 /* 30 seconds */) : timeout_for_connect_(30000 /* 30 seconds */)
, timeout_for_read_(60000 /* 60 seconds */) , timeout_for_read_(60000 /* 60 seconds */)
{ {
}
void HttpClient::SetupComponent()
{
::curl_global_init(CURL_GLOBAL_ALL);
std::thread thread(Closure(this, &HttpClient::NetworkThread));
thread.detach();
}
void HttpClient::DestroyComponent()
{
::curl_global_cleanup();
}
void HttpClient::Send(HttpRequestPtr request)
{
if (!request)
return;
request_mutex_.lock();
request_queue_.push(request);
request_mutex_.unlock();
sleep_condition_.notify_one();
}
void HttpClient::NetworkThread()
{
while (true)
{
HttpRequestPtr request;
{
std::lock_guard<std::mutex> lock(request_mutex_);
while (request_queue_.empty())
{
sleep_condition_.wait(request_mutex_);
}
request = request_queue_.front();
request_queue_.pop();
}
HttpResponsePtr response = new (std::nothrow) HttpResponse(request);
Perform(request, response);
response_mutex_.lock();
response_queue_.push(response);
response_mutex_.unlock();
Application::PreformInMainThread(Closure(this, &HttpClient::DispatchResponseCallback));
}
}
void HttpClient::Perform(HttpRequestPtr request, HttpResponsePtr response)
{
bool ok = false;
long response_code = 0;
char error_message[256] = { 0 };
ByteString response_header;
ByteString response_data;
ByteString url = convert_to_utf8(request->GetUrl());
ByteString data = convert_to_utf8(request->GetData());
Vector<ByteString> headers;
headers.reserve(request->GetHeaders().size());
for (const auto& pair : request->GetHeaders())
{
headers.push_back(wide_to_string(pair.first) + ":" + wide_to_string(pair.second));
}
switch (request->GetType())
{
case HttpRequest::Type::Get:
ok = Curl::GetRequest(this, headers, url, &response_code, &response_data, &response_header, error_message);
break;
case HttpRequest::Type::Post:
ok = Curl::PostRequest(this, headers, url, data, &response_code, &response_data, &response_header, error_message);
break;
case HttpRequest::Type::Put:
ok = Curl::PutRequest(this, headers, url, data, &response_code, &response_data, &response_header, error_message);
break;
case HttpRequest::Type::Delete:
ok = Curl::DeleteRequest(this, headers, url, &response_code, &response_data, &response_header, error_message);
break;
default:
KGE_ERROR(L"HttpClient: unknown request type, only GET, POST, PUT or DELETE is supported");
return;
}
response->SetResponseCode(response_code);
response->SetHeader(MultiByteToWide(response_header));
response->SetData(convert_from_utf8(response_data));
if (!ok)
{
response->SetSucceed(false);
response->SetError(MultiByteToWide(error_message));
}
else
{
response->SetSucceed(true);
}
}
void HttpClient::DispatchResponseCallback()
{
HttpResponsePtr response;
response_mutex_.lock();
if (!response_queue_.empty())
{
response = response_queue_.front();
response_queue_.pop();
}
response_mutex_.unlock();
if (response)
{
HttpRequestPtr request = response->GetRequest();
const auto& callback = request->GetResponseCallback();
if (callback)
{
callback(request.get(), response.get());
}
}
}
}
} }
void HttpClient::SetupComponent()
{
::curl_global_init(CURL_GLOBAL_ALL);
std::thread thread(Closure(this, &HttpClient::NetworkThread));
thread.detach();
}
void HttpClient::DestroyComponent()
{
::curl_global_cleanup();
}
void HttpClient::Send(HttpRequestPtr request)
{
if (!request)
return;
request_mutex_.lock();
request_queue_.push(request);
request_mutex_.unlock();
sleep_condition_.notify_one();
}
void HttpClient::NetworkThread()
{
while (true)
{
HttpRequestPtr request;
{
std::lock_guard<std::mutex> lock(request_mutex_);
while (request_queue_.empty())
{
sleep_condition_.wait(request_mutex_);
}
request = request_queue_.front();
request_queue_.pop();
}
HttpResponsePtr response = new (std::nothrow) HttpResponse(request);
Perform(request, response);
response_mutex_.lock();
response_queue_.push(response);
response_mutex_.unlock();
Application::PreformInMainThread(Closure(this, &HttpClient::DispatchResponseCallback));
}
}
void HttpClient::Perform(HttpRequestPtr request, HttpResponsePtr response)
{
bool ok = false;
long response_code = 0;
char error_message[256] = { 0 };
ByteString response_header;
ByteString response_data;
ByteString url = convert_to_utf8(request->GetUrl());
ByteString data = convert_to_utf8(request->GetData());
Vector<ByteString> headers;
headers.reserve(request->GetHeaders().size());
for (const auto& pair : request->GetHeaders())
{
headers.push_back(wide_to_string(pair.first) + ":" + wide_to_string(pair.second));
}
switch (request->GetType())
{
case HttpRequest::Type::Get:
ok = Curl::GetRequest(this, headers, url, &response_code, &response_data, &response_header, error_message);
break;
case HttpRequest::Type::Post:
ok = Curl::PostRequest(this, headers, url, data, &response_code, &response_data, &response_header,
error_message);
break;
case HttpRequest::Type::Put:
ok =
Curl::PutRequest(this, headers, url, data, &response_code, &response_data, &response_header, error_message);
break;
case HttpRequest::Type::Delete:
ok = Curl::DeleteRequest(this, headers, url, &response_code, &response_data, &response_header, error_message);
break;
default:
KGE_ERROR(L"HttpClient: unknown request type, only GET, POST, PUT or DELETE is supported");
return;
}
response->SetResponseCode(response_code);
response->SetHeader(MultiByteToWide(response_header));
response->SetData(convert_from_utf8(response_data));
if (!ok)
{
response->SetSucceed(false);
response->SetError(MultiByteToWide(error_message));
}
else
{
response->SetSucceed(true);
}
}
void HttpClient::DispatchResponseCallback()
{
HttpResponsePtr response;
response_mutex_.lock();
if (!response_queue_.empty())
{
response = response_queue_.front();
response_queue_.pop();
}
response_mutex_.unlock();
if (response)
{
HttpRequestPtr request = response->GetRequest();
const auto& callback = request->GetResponseCallback();
if (callback)
{
callback(request.get(), response.get());
}
}
}
} // namespace network
} // namespace kiwano

View File

@ -1,15 +1,15 @@
// Copyright (c) 2016-2018 Kiwano - Nomango // Copyright (c) 2016-2018 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -19,127 +19,126 @@
// THE SOFTWARE. // THE SOFTWARE.
#pragma once #pragma once
#include <kiwano/core/common.h> #include <condition_variable>
#include <kiwano/core/Common.h>
#include <kiwano/core/Component.h> #include <kiwano/core/Component.h>
#include <mutex> #include <mutex>
#include <condition_variable>
namespace kiwano namespace kiwano
{ {
namespace network namespace network
{ {
/** /**
* \~chinese * \~chinese
* \defgroup Network * \defgroup Network
*/ */
/** /**
* \addtogroup Network * \addtogroup Network
* @{ * @{
*/ */
/** /**
* \~chinese * \~chinese
* @brief HTTP客户端 * @brief HTTP客户端
*/ */
class KGE_API HttpClient class KGE_API HttpClient
: public Singleton<HttpClient> : public Singleton<HttpClient>
, public ComponentBase , public ComponentBase
{ {
friend Singleton<HttpClient>; friend Singleton<HttpClient>;
public: public:
/// \~chinese /// \~chinese
/// @brief 发送HTTP请求 /// @brief 发送HTTP请求
/// @param[in] request HTTP请求 /// @param[in] request HTTP请求
/// @details 发送请求后,无论结束或失败都将调用请求的响应回调函数 /// @details 发送请求后,无论结束或失败都将调用请求的响应回调函数
void Send(HttpRequestPtr request); void Send(HttpRequestPtr request);
/// \~chinese /// \~chinese
/// @brief 设置连接超时时长 /// @brief 设置连接超时时长
void SetTimeoutForConnect(Duration timeout); void SetTimeoutForConnect(Duration timeout);
/// \~chinese /// \~chinese
/// @brief 获取连接超时时长 /// @brief 获取连接超时时长
Duration GetTimeoutForConnect() const; Duration GetTimeoutForConnect() const;
/// \~chinese /// \~chinese
/// @brief 设置读取超时时长 /// @brief 设置读取超时时长
void SetTimeoutForRead(Duration timeout); void SetTimeoutForRead(Duration timeout);
/// \~chinese /// \~chinese
/// @brief 获取读取超时时长 /// @brief 获取读取超时时长
Duration GetTimeoutForRead() const; Duration GetTimeoutForRead() const;
/// \~chinese /// \~chinese
/// @brief 设置SSL证书地址 /// @brief 设置SSL证书地址
void SetSSLVerification(String const& root_certificate_path); void SetSSLVerification(String const& root_certificate_path);
/// \~chinese /// \~chinese
/// @brief 获取SSL证书地址 /// @brief 获取SSL证书地址
String const& GetSSLVerification() const; String const& GetSSLVerification() const;
public: public:
virtual void SetupComponent() override; virtual void SetupComponent() override;
virtual void DestroyComponent() override; virtual void DestroyComponent() override;
private: private:
HttpClient(); HttpClient();
void NetworkThread(); void NetworkThread();
void Perform(HttpRequestPtr request, HttpResponsePtr response); void Perform(HttpRequestPtr request, HttpResponsePtr response);
void DispatchResponseCallback(); void DispatchResponseCallback();
private: private:
Duration timeout_for_connect_; Duration timeout_for_connect_;
Duration timeout_for_read_; Duration timeout_for_read_;
String ssl_verification_; String ssl_verification_;
std::mutex request_mutex_; std::mutex request_mutex_;
Queue<HttpRequestPtr> request_queue_; Queue<HttpRequestPtr> request_queue_;
std::mutex response_mutex_; std::mutex response_mutex_;
Queue<HttpResponsePtr> response_queue_; Queue<HttpResponsePtr> response_queue_;
std::condition_variable_any sleep_condition_; std::condition_variable_any sleep_condition_;
}; };
/** @} */ /** @} */
inline void HttpClient::SetTimeoutForConnect(Duration timeout)
inline void HttpClient::SetTimeoutForConnect(Duration timeout) {
{ timeout_for_connect_ = timeout;
timeout_for_connect_ = timeout;
}
inline Duration HttpClient::GetTimeoutForConnect() const
{
return timeout_for_connect_;
}
inline void HttpClient::SetTimeoutForRead(Duration timeout)
{
timeout_for_read_ = timeout;
}
inline Duration HttpClient::GetTimeoutForRead() const
{
return timeout_for_read_;
}
inline void HttpClient::SetSSLVerification(String const& root_certificate_path)
{
ssl_verification_ = root_certificate_path;
}
inline String const& HttpClient::GetSSLVerification() const
{
return ssl_verification_;
}
}
} }
inline Duration HttpClient::GetTimeoutForConnect() const
{
return timeout_for_connect_;
}
inline void HttpClient::SetTimeoutForRead(Duration timeout)
{
timeout_for_read_ = timeout;
}
inline Duration HttpClient::GetTimeoutForRead() const
{
return timeout_for_read_;
}
inline void HttpClient::SetSSLVerification(String const& root_certificate_path)
{
ssl_verification_ = root_certificate_path;
}
inline String const& HttpClient::GetSSLVerification() const
{
return ssl_verification_;
}
} // namespace network
} // namespace kiwano

View File

@ -1,15 +1,15 @@
// Copyright (c) 2016-2018 Kiwano - Nomango // Copyright (c) 2016-2018 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -23,12 +23,12 @@
namespace kiwano namespace kiwano
{ {
namespace network namespace network
{ {
void HttpRequest::SetJsonData(Json const& json) void HttpRequest::SetJsonData(Json const& json)
{ {
SetHeader(L"Content-Type", L"application/json;charset=UTF-8"); SetHeader(L"Content-Type", L"application/json;charset=UTF-8");
data_ = json.dump(); data_ = json.dump();
}
}
} }
} // namespace network
} // namespace kiwano

View File

@ -1,15 +1,15 @@
// Copyright (c) 2016-2018 Kiwano - Nomango // Copyright (c) 2016-2018 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -19,138 +19,179 @@
// THE SOFTWARE. // THE SOFTWARE.
#pragma once #pragma once
#include <kiwano/core/common.h> #include <kiwano/core/Common.h>
#include <kiwano/core/ObjectBase.h> #include <kiwano/core/ObjectBase.h>
#include <kiwano/core/SmartPtr.hpp> #include <kiwano/core/SmartPtr.hpp>
namespace kiwano namespace kiwano
{ {
namespace network namespace network
{ {
class HttpResponse; class HttpResponse;
KGE_DECLARE_SMART_PTR(HttpRequest); KGE_DECLARE_SMART_PTR(HttpRequest);
/** /**
* \addtogroup Network * \addtogroup Network
* @{ * @{
*/ */
/** /**
* \~chinese * \~chinese
* @brief HTTP请求 * @brief HTTP请求
*/ */
class KGE_API HttpRequest class KGE_API HttpRequest : public virtual ObjectBase
: public ObjectBase {
{ public:
public: /// \~chinese
/// \~chinese /// @brief 响应回调函数
/// @brief 响应回调函数 using ResponseCallback = Function<void(HttpRequest* /* request */, HttpResponse* /* response */)>;
using ResponseCallback = Function<void(HttpRequest* /* request */, HttpResponse* /* response */)>;
/// \~chinese /// \~chinese
/// @brief 请求类型 /// @brief 请求类型
enum class Type enum class Type
{ {
Unknown, ///< 未知 Unknown, ///< 未知
Get, ///< HTTP GET请求 Get, ///< HTTP GET请求
Post, ///< HTTP POST请求 Post, ///< HTTP POST请求
Put, ///< HTTP PUT请求 Put, ///< HTTP PUT请求
Delete ///< HTTP DELETE请求 Delete ///< HTTP DELETE请求
}; };
HttpRequest(); HttpRequest();
HttpRequest(Type type); HttpRequest(Type type);
/// \~chinese /// \~chinese
/// @brief 设置请求地址 /// @brief 设置请求地址
void SetUrl(String const& url); void SetUrl(String const& url);
/// \~chinese /// \~chinese
/// @brief 设置请求类型 /// @brief 设置请求类型
void SetType(Type type); void SetType(Type type);
/// \~chinese /// \~chinese
/// @brief 设置请求携带的数据 /// @brief 设置请求携带的数据
void SetData(String const& data); void SetData(String const& data);
/// \~chinese /// \~chinese
/// @brief 设置请求携带的JSON数据 /// @brief 设置请求携带的JSON数据
void SetJsonData(Json const& json); void SetJsonData(Json const& json);
/// \~chinese /// \~chinese
/// @brief 设置HTTP头 /// @brief 设置HTTP头
void SetHeaders(Map<String, String> const& headers); void SetHeaders(Map<String, String> const& headers);
/// \~chinese /// \~chinese
/// @brief 设置HTTP头 /// @brief 设置HTTP头
void SetHeader(String const& field, String const& content); void SetHeader(String const& field, String const& content);
/// \~chinese /// \~chinese
/// @brief 设置响应回调函数 /// @brief 设置响应回调函数
void SetResponseCallback(ResponseCallback const& callback); void SetResponseCallback(ResponseCallback const& callback);
/// \~chinese /// \~chinese
/// @brief 获取请求地址 /// @brief 获取请求地址
String const& GetUrl() const; String const& GetUrl() const;
/// \~chinese /// \~chinese
/// @brief 获取请求类型 /// @brief 获取请求类型
Type GetType() const; Type GetType() const;
/// \~chinese /// \~chinese
/// @brief 获取请求数据 /// @brief 获取请求数据
String const& GetData() const; String const& GetData() const;
/// \~chinese /// \~chinese
/// @brief 获取HTTP头 /// @brief 获取HTTP头
Map<String, String>& GetHeaders(); Map<String, String>& GetHeaders();
/// \~chinese /// \~chinese
/// @brief 获取HTTP头 /// @brief 获取HTTP头
String const& GetHeader(String const& header) const; String const& GetHeader(String const& header) const;
/// \~chinese /// \~chinese
/// @brief 获取响应回调函数 /// @brief 获取响应回调函数
ResponseCallback const& GetResponseCallback() const; ResponseCallback const& GetResponseCallback() const;
private: private:
Type type_; Type type_;
String url_; String url_;
String data_; String data_;
Map<String, String> headers_; Map<String, String> headers_;
ResponseCallback response_cb_; ResponseCallback response_cb_;
}; };
/** @} */ /** @} */
inline HttpRequest::HttpRequest() : type_(Type::Unknown) {} inline HttpRequest::HttpRequest()
: type_(Type::Unknown)
inline HttpRequest::HttpRequest(Type type) : type_(type) {} {
inline void HttpRequest::SetUrl(String const& url) { url_ = url; }
inline String const& HttpRequest::GetUrl() const { return url_; }
inline void HttpRequest::SetType(Type type) { type_ = type; }
inline HttpRequest::Type HttpRequest::GetType() const { return type_; }
inline void HttpRequest::SetData(String const& data) { data_ = data; }
inline String const& HttpRequest::GetData() const { return data_; }
inline void HttpRequest::SetHeaders(Map<String, String> const& headers) { headers_ = headers; }
inline void HttpRequest::SetHeader(String const& field, String const& content) { headers_[field] = content; }
inline Map<String, String>& HttpRequest::GetHeaders() { return headers_; }
inline String const& HttpRequest::GetHeader(String const& header) const { return headers_.at(header); }
inline void HttpRequest::SetResponseCallback(ResponseCallback const& callback) { response_cb_ = callback; }
inline HttpRequest::ResponseCallback const& HttpRequest::GetResponseCallback() const { return response_cb_; }
}
} }
inline HttpRequest::HttpRequest(Type type)
: type_(type)
{
}
inline void HttpRequest::SetUrl(String const& url)
{
url_ = url;
}
inline String const& HttpRequest::GetUrl() const
{
return url_;
}
inline void HttpRequest::SetType(Type type)
{
type_ = type;
}
inline HttpRequest::Type HttpRequest::GetType() const
{
return type_;
}
inline void HttpRequest::SetData(String const& data)
{
data_ = data;
}
inline String const& HttpRequest::GetData() const
{
return data_;
}
inline void HttpRequest::SetHeaders(Map<String, String> const& headers)
{
headers_ = headers;
}
inline void HttpRequest::SetHeader(String const& field, String const& content)
{
headers_[field] = content;
}
inline Map<String, String>& HttpRequest::GetHeaders()
{
return headers_;
}
inline String const& HttpRequest::GetHeader(String const& header) const
{
return headers_.at(header);
}
inline void HttpRequest::SetResponseCallback(ResponseCallback const& callback)
{
response_cb_ = callback;
}
inline HttpRequest::ResponseCallback const& HttpRequest::GetResponseCallback() const
{
return response_cb_;
}
} // namespace network
} // namespace kiwano

View File

@ -1,15 +1,15 @@
// Copyright (c) 2016-2018 Kiwano - Nomango // Copyright (c) 2016-2018 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -23,103 +23,140 @@
namespace kiwano namespace kiwano
{ {
namespace network namespace network
{ {
KGE_DECLARE_SMART_PTR(HttpResponse); KGE_DECLARE_SMART_PTR(HttpResponse);
/** /**
* \addtogroup Network * \addtogroup Network
* @{ * @{
*/ */
/** /**
* \~chinese * \~chinese
* @brief HTTP响应 * @brief HTTP响应
*/ */
class KGE_API HttpResponse class KGE_API HttpResponse : public virtual ObjectBase
: public ObjectBase {
{ public:
public: HttpResponse(HttpRequestPtr request);
HttpResponse(HttpRequestPtr request);
/// \~chinese /// \~chinese
/// @brief 获取对应的HTTP请求 /// @brief 获取对应的HTTP请求
HttpRequestPtr GetRequest() const; HttpRequestPtr GetRequest() const;
/// \~chinese /// \~chinese
/// @brief 获取响应状态 /// @brief 获取响应状态
bool IsSucceed() const; bool IsSucceed() const;
/// \~chinese /// \~chinese
/// @brief 获取HTTP状态码 /// @brief 获取HTTP状态码
long GetResponseCode() const; long GetResponseCode() const;
/// \~chinese /// \~chinese
/// @brief 获取响应头 /// @brief 获取响应头
String GetHeader() const; String GetHeader() const;
/// \~chinese /// \~chinese
/// @brief 获取响应数据 /// @brief 获取响应数据
String const& GetData() const; String const& GetData() const;
/// \~chinese /// \~chinese
/// @brief 获取错误信息 /// @brief 获取错误信息
String const& GetError() const; String const& GetError() const;
/// \~chinese /// \~chinese
/// @brief 设置响应状态 /// @brief 设置响应状态
void SetSucceed(bool succeed); void SetSucceed(bool succeed);
/// \~chinese /// \~chinese
/// @brief 设置HTTP状态码 /// @brief 设置HTTP状态码
void SetResponseCode(long response_code); void SetResponseCode(long response_code);
/// \~chinese /// \~chinese
/// @brief 设置响应头 /// @brief 设置响应头
void SetHeader(String const& response_header); void SetHeader(String const& response_header);
/// \~chinese /// \~chinese
/// @brief 设置响应数据 /// @brief 设置响应数据
void SetData(String const& response_data); void SetData(String const& response_data);
/// \~chinese /// \~chinese
/// @brief 设置错误信息 /// @brief 设置错误信息
void SetError(String const& error_buffer); void SetError(String const& error_buffer);
private: private:
bool succeed_; bool succeed_;
long response_code_; long response_code_;
HttpRequestPtr request_; HttpRequestPtr request_;
String response_header_; String response_header_;
String response_data_; String response_data_;
String error_buffer_; String error_buffer_;
}; };
/** @} */ /** @} */
inline HttpResponse::HttpResponse(HttpRequestPtr request) : request_(request), succeed_(false), response_code_(0) {} inline HttpResponse::HttpResponse(HttpRequestPtr request)
: request_(request)
inline HttpRequestPtr HttpResponse::GetRequest() const { return request_; } , succeed_(false)
, response_code_(0)
inline void HttpResponse::SetSucceed(bool succeed) { succeed_ = succeed; } {
inline bool HttpResponse::IsSucceed() const { return succeed_; }
inline void HttpResponse::SetResponseCode(long response_code) { response_code_ = response_code; }
inline long HttpResponse::GetResponseCode() const { return response_code_; }
inline void HttpResponse::SetHeader(String const& response_header) { response_header_ = response_header; }
inline String HttpResponse::GetHeader() const { return response_header_; }
inline void HttpResponse::SetData(String const& response_data) { response_data_ = response_data; }
inline String const& HttpResponse::GetData() const { return response_data_; }
inline void HttpResponse::SetError(String const& error_buffer) { error_buffer_ = error_buffer; }
inline String const& HttpResponse::GetError() const { return error_buffer_; }
}
} }
inline HttpRequestPtr HttpResponse::GetRequest() const
{
return request_;
}
inline void HttpResponse::SetSucceed(bool succeed)
{
succeed_ = succeed;
}
inline bool HttpResponse::IsSucceed() const
{
return succeed_;
}
inline void HttpResponse::SetResponseCode(long response_code)
{
response_code_ = response_code;
}
inline long HttpResponse::GetResponseCode() const
{
return response_code_;
}
inline void HttpResponse::SetHeader(String const& response_header)
{
response_header_ = response_header;
}
inline String HttpResponse::GetHeader() const
{
return response_header_;
}
inline void HttpResponse::SetData(String const& response_data)
{
response_data_ = response_data;
}
inline String const& HttpResponse::GetData() const
{
return response_data_;
}
inline void HttpResponse::SetError(String const& error_buffer)
{
error_buffer_ = error_buffer;
}
inline String const& HttpResponse::GetError() const
{
return error_buffer_;
}
} // namespace network
} // namespace kiwano

View File

@ -1,15 +1,15 @@
// Copyright (c) 2016-2018 Kiwano - Nomango // Copyright (c) 2016-2018 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -20,6 +20,6 @@
#pragma once #pragma once
#include <kiwano-network/HttpClient.h>
#include <kiwano-network/HttpRequest.h> #include <kiwano-network/HttpRequest.h>
#include <kiwano-network/HttpResponse.hpp> #include <kiwano-network/HttpResponse.hpp>
#include <kiwano-network/HttpClient.h>

View File

@ -1,15 +1,15 @@
// Copyright (c) 2018-2019 Kiwano - Nomango // Copyright (c) 2018-2019 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -23,291 +23,280 @@
namespace kiwano namespace kiwano
{ {
namespace physics namespace physics
{ {
Body::Body()
: body_(nullptr)
, actor_(nullptr)
, world_(nullptr)
, category_bits_(0x0001)
, mask_bits_(0xFFFF)
, group_index_(0)
{
}
Body::Body(b2Body* body, Actor* actor)
: Body()
{
SetB2Body(body);
SetActor(actor);
}
Body::Body(World* world, Actor* actor)
: Body()
{
Init(world, actor);
}
Body::~Body()
{
Destroy();
}
void Body::Init(World* world, Actor* actor)
{
KGE_ASSERT(world);
Destroy();
world_ = world;
b2BodyDef def;
b2Body* b2body = world->GetB2World()->CreateBody(&def);
SetB2Body(b2body);
SetActor(actor);
UpdateFromActor();
}
Fixture Body::AddFixture(Shape* shape, const Fixture::Param& param)
{
KGE_ASSERT(body_ && world_);
return Fixture(this, shape, param);
}
Fixture Body::AddCircleShape(float radius, float density)
{
return AddFixture(&CircleShape(radius), Fixture::Param(density));
}
Fixture Body::AddBoxShape(Vec2 const& size, float density)
{
return AddFixture(&BoxShape(size), Fixture::Param(density));
}
Fixture Body::AddPolygonShape(Vector<Point> const& vertexs, float density)
{
return AddFixture(&PolygonShape(vertexs), Fixture::Param(density));
}
Fixture Body::AddEdgeShape(Point const& p1, Point const& p2, float density)
{
return AddFixture(&EdgeShape(p1, p2), Fixture::Param(density));
}
Fixture Body::AddChainShape(Vector<Point> const& vertexs, bool loop, float density)
{
return AddFixture(&ChainShape(vertexs, loop), Fixture::Param(density));
}
void Body::RemoveFixture(Fixture const& fixture)
{
if (fixture.GetB2Fixture())
{
body_->DestroyFixture(fixture.GetB2Fixture());
}
}
void Body::SetCategoryBits(uint16_t category_bits)
{
KGE_ASSERT(body_);
if (category_bits != category_bits_)
{
category_bits_ = category_bits;
b2Fixture* fixture = body_->GetFixtureList();
while (fixture)
{
UpdateFixtureFilter(fixture);
fixture = fixture->GetNext();
}
}
}
void Body::SetMaskBits(uint16_t mask_bits)
{
KGE_ASSERT(body_);
if (mask_bits != mask_bits_)
{
mask_bits_ = mask_bits;
b2Fixture* fixture = body_->GetFixtureList();
while (fixture)
{
UpdateFixtureFilter(fixture);
fixture = fixture->GetNext();
}
}
}
void Body::SetGroupIndex(int16_t index)
{
KGE_ASSERT(body_);
if (index != group_index_)
{
group_index_ = index;
b2Fixture* fixture = body_->GetFixtureList();
while (fixture)
{
UpdateFixtureFilter(fixture);
fixture = fixture->GetNext();
}
}
}
void Body::GetMassData(float* mass, Point* center, float* inertia) const
{
KGE_ASSERT(body_ && world_);
b2MassData data;
body_->GetMassData(&data);
if (mass) *mass = data.mass;
if (center) *center = world_->World2Stage(data.center);
if (inertia) *inertia = data.I;
}
void Body::SetMassData(float mass, Point const& center, float inertia)
{
KGE_ASSERT(body_ && world_);
b2MassData data;
data.mass = mass;
data.center = world_->Stage2World(center);
data.I = inertia;
body_->SetMassData(&data);
}
void Body::ResetMassData()
{
KGE_ASSERT(body_);
body_->ResetMassData();
}
Point Body::GetBodyPosition() const
{
KGE_ASSERT(body_ && world_);
return world_->World2Stage(body_->GetPosition());
}
void Body::SetBodyTransform(Point const& pos, float angle)
{
KGE_ASSERT(body_ && world_);
body_->SetTransform(world_->Stage2World(pos), math::Degree2Radian(angle));
}
Point Body::GetLocalPoint(Point const& world) const
{
KGE_ASSERT(body_ && world_);
return world_->World2Stage(body_->GetLocalPoint(world_->Stage2World(world)));
}
Point Body::GetWorldPoint(Point const& local) const
{
KGE_ASSERT(body_ && world_);
return world_->World2Stage(body_->GetWorldPoint(world_->Stage2World(local)));
}
Point Body::GetLocalCenter() const
{
KGE_ASSERT(body_ && world_);
return world_->World2Stage(body_->GetLocalCenter());
}
Point Body::GetWorldCenter() const
{
KGE_ASSERT(body_ && world_);
return world_->World2Stage(body_->GetWorldCenter());
}
void Body::ApplyForce(Vec2 const& force, Point const& point, bool wake)
{
KGE_ASSERT(body_ && world_);
body_->ApplyForce(b2Vec2(force.x, force.y), world_->Stage2World(point), wake);
}
void Body::ApplyForceToCenter(Vec2 const& force, bool wake)
{
KGE_ASSERT(body_ && world_);
body_->ApplyForceToCenter(b2Vec2(force.x, force.y), wake);
}
void Body::ApplyTorque(float torque, bool wake)
{
KGE_ASSERT(body_ && world_);
body_->ApplyTorque(torque, wake);
}
void Body::SetB2Body(b2Body* body)
{
body_ = body;
if (body_)
{
body_->SetUserData(this);
}
}
void Body::Destroy()
{
if (world_ && body_)
{
world_->RemoveBody(this);
}
body_ = nullptr;
world_ = nullptr;
actor_ = nullptr;
}
void Body::UpdateActor()
{
if (actor_ && body_)
{
if (world_)
{
actor_->SetPosition(world_->World2Stage(body_->GetPosition()));
}
else
{
actor_->SetPosition(World2Stage(body_->GetPosition()));
}
actor_->SetRotation(math::Radian2Degree(body_->GetAngle()));
}
}
void Body::UpdateFromActor()
{
if (actor_ && body_)
{
if (world_)
{
body_->SetTransform(
world_->Stage2World(actor_->GetPosition()),
math::Degree2Radian(actor_->GetRotation())
);
}
else
{
body_->SetTransform(
Stage2World(actor_->GetPosition()),
math::Degree2Radian(actor_->GetRotation())
);
}
}
}
void Body::UpdateFixtureFilter(b2Fixture* fixture)
{
b2Filter filter;
filter.categoryBits = category_bits_;
filter.maskBits = mask_bits_;
filter.groupIndex = group_index_;
fixture->SetFilterData(filter);
}
Body::Body()
: body_(nullptr)
, actor_(nullptr)
, world_(nullptr)
, category_bits_(0x0001)
, mask_bits_(0xFFFF)
, group_index_(0)
{
} }
Body::~Body()
{
Destroy();
} }
bool Body::InitBody(World* world, Actor* actor)
{
KGE_ASSERT(world);
Destroy();
world_ = world;
b2BodyDef def;
b2Body* b2body = world->GetB2World()->CreateBody(&def);
if (b2body)
{
SetB2Body(b2body);
SetActor(actor);
UpdateFromActor();
return true;
}
return false;
}
Fixture Body::AddFixture(Shape* shape, const Fixture::Param& param)
{
KGE_ASSERT(body_ && world_);
return Fixture(this, shape, param);
}
Fixture Body::AddCircleShape(float radius, float density)
{
return AddFixture(&CircleShape(radius), Fixture::Param(density));
}
Fixture Body::AddBoxShape(Vec2 const& size, float density)
{
return AddFixture(&BoxShape(size), Fixture::Param(density));
}
Fixture Body::AddPolygonShape(Vector<Point> const& vertexs, float density)
{
return AddFixture(&PolygonShape(vertexs), Fixture::Param(density));
}
Fixture Body::AddEdgeShape(Point const& p1, Point const& p2, float density)
{
return AddFixture(&EdgeShape(p1, p2), Fixture::Param(density));
}
Fixture Body::AddChainShape(Vector<Point> const& vertexs, bool loop, float density)
{
return AddFixture(&ChainShape(vertexs, loop), Fixture::Param(density));
}
void Body::RemoveFixture(Fixture const& fixture)
{
if (fixture.GetB2Fixture())
{
body_->DestroyFixture(fixture.GetB2Fixture());
}
}
void Body::SetCategoryBits(uint16_t category_bits)
{
KGE_ASSERT(body_);
if (category_bits != category_bits_)
{
category_bits_ = category_bits;
b2Fixture* fixture = body_->GetFixtureList();
while (fixture)
{
UpdateFixtureFilter(fixture);
fixture = fixture->GetNext();
}
}
}
void Body::SetMaskBits(uint16_t mask_bits)
{
KGE_ASSERT(body_);
if (mask_bits != mask_bits_)
{
mask_bits_ = mask_bits;
b2Fixture* fixture = body_->GetFixtureList();
while (fixture)
{
UpdateFixtureFilter(fixture);
fixture = fixture->GetNext();
}
}
}
void Body::SetGroupIndex(int16_t index)
{
KGE_ASSERT(body_);
if (index != group_index_)
{
group_index_ = index;
b2Fixture* fixture = body_->GetFixtureList();
while (fixture)
{
UpdateFixtureFilter(fixture);
fixture = fixture->GetNext();
}
}
}
void Body::GetMassData(float* mass, Point* center, float* inertia) const
{
KGE_ASSERT(body_ && world_);
b2MassData data;
body_->GetMassData(&data);
if (mass)
*mass = data.mass;
if (center)
*center = world_->World2Stage(data.center);
if (inertia)
*inertia = data.I;
}
void Body::SetMassData(float mass, Point const& center, float inertia)
{
KGE_ASSERT(body_ && world_);
b2MassData data;
data.mass = mass;
data.center = world_->Stage2World(center);
data.I = inertia;
body_->SetMassData(&data);
}
void Body::ResetMassData()
{
KGE_ASSERT(body_);
body_->ResetMassData();
}
Point Body::GetBodyPosition() const
{
KGE_ASSERT(body_ && world_);
return world_->World2Stage(body_->GetPosition());
}
void Body::SetBodyTransform(Point const& pos, float angle)
{
KGE_ASSERT(body_ && world_);
body_->SetTransform(world_->Stage2World(pos), math::Degree2Radian(angle));
}
Point Body::GetLocalPoint(Point const& world) const
{
KGE_ASSERT(body_ && world_);
return world_->World2Stage(body_->GetLocalPoint(world_->Stage2World(world)));
}
Point Body::GetWorldPoint(Point const& local) const
{
KGE_ASSERT(body_ && world_);
return world_->World2Stage(body_->GetWorldPoint(world_->Stage2World(local)));
}
Point Body::GetLocalCenter() const
{
KGE_ASSERT(body_ && world_);
return world_->World2Stage(body_->GetLocalCenter());
}
Point Body::GetWorldCenter() const
{
KGE_ASSERT(body_ && world_);
return world_->World2Stage(body_->GetWorldCenter());
}
void Body::ApplyForce(Vec2 const& force, Point const& point, bool wake)
{
KGE_ASSERT(body_ && world_);
body_->ApplyForce(b2Vec2(force.x, force.y), world_->Stage2World(point), wake);
}
void Body::ApplyForceToCenter(Vec2 const& force, bool wake)
{
KGE_ASSERT(body_ && world_);
body_->ApplyForceToCenter(b2Vec2(force.x, force.y), wake);
}
void Body::ApplyTorque(float torque, bool wake)
{
KGE_ASSERT(body_ && world_);
body_->ApplyTorque(torque, wake);
}
void Body::SetB2Body(b2Body* body)
{
body_ = body;
if (body_)
{
body_->SetUserData(this);
}
}
void Body::Destroy()
{
if (world_)
{
world_->RemoveBody(this);
}
body_ = nullptr;
world_ = nullptr;
actor_ = nullptr;
}
void Body::UpdateActor()
{
if (actor_ && body_)
{
if (world_)
{
actor_->SetPosition(world_->World2Stage(body_->GetPosition()));
}
else
{
actor_->SetPosition(World2Stage(body_->GetPosition()));
}
actor_->SetRotation(math::Radian2Degree(body_->GetAngle()));
}
}
void Body::UpdateFromActor()
{
if (actor_ && body_)
{
if (world_)
{
body_->SetTransform(world_->Stage2World(actor_->GetPosition()), math::Degree2Radian(actor_->GetRotation()));
}
else
{
body_->SetTransform(Stage2World(actor_->GetPosition()), math::Degree2Radian(actor_->GetRotation()));
}
}
}
void Body::UpdateFixtureFilter(b2Fixture* fixture)
{
b2Filter filter;
filter.categoryBits = category_bits_;
filter.maskBits = mask_bits_;
filter.groupIndex = group_index_;
fixture->SetFilterData(filter);
}
} // namespace physics
} // namespace kiwano

View File

@ -1,15 +1,15 @@
// Copyright (c) 2018-2019 Kiwano - Nomango // Copyright (c) 2018-2019 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -19,362 +19,471 @@
// THE SOFTWARE. // THE SOFTWARE.
#pragma once #pragma once
#include <kiwano-physics/helper.h>
#include <kiwano-physics/Shape.h>
#include <kiwano-physics/Fixture.h>
#include <kiwano-physics/ContactEdge.h> #include <kiwano-physics/ContactEdge.h>
#include <kiwano-physics/Fixture.h>
#include <kiwano-physics/Shape.h>
#include <kiwano-physics/helper.h>
namespace kiwano namespace kiwano
{ {
namespace physics namespace physics
{ {
class World; class World;
KGE_DECLARE_SMART_PTR(Body); KGE_DECLARE_SMART_PTR(Body);
/** /**
* \addtogroup Physics * \addtogroup Physics
* @{ * @{
*/ */
/// \~chinese /// \~chinese
/// @brief 物体 /// @brief 物体
class KGE_API Body class KGE_API Body : public virtual ObjectBase
: public virtual RefCounter {
{ public:
public: /// \~chinese
/// \~chinese /// @brief 物体类型
/// @brief 物体类型 enum class Type
enum class Type {
{ Static = 0, ///< 静态物体
Static = 0, ///< 静态物体 Kinematic, ///< 动力学物体
Kinematic, ///< 动力学物体 Dynamic, ///< 动态物体
Dynamic, ///< 动态物体 };
};
Body();
Body();
Body(b2Body* body, Actor* actor); virtual ~Body();
Body(World* world, Actor* actor);
Body(World* world, ActorPtr actor); /// \~chinese
virtual ~Body(); /// @brief 初始化
/// @param[in] world 物理世界
/// \~chinese /// @param[in] actor 绑定的角色
/// @brief 初始化 bool InitBody(World* world, ActorPtr actor);
/// @param[in] world 物理世界
/// @param[in] actor 绑定的角色 /// \~chinese
void Init(World* world, Actor* actor); /// @brief 初始化
/// @param[in] world 物理世界
/// \~chinese /// @param[in] actor 绑定的角色
/// @brief 添加夹具 bool InitBody(World* world, Actor* actor);
/// @param shape 物体形状
/// @param density 物体密度 /// \~chinese
Fixture AddFixture(Shape* shape, const Fixture::Param& param); /// @brief 添加夹具
/// @param shape 物体形状
/// \~chinese /// @param density 物体密度
/// @brief 添加圆形夹具 Fixture AddFixture(Shape* shape, const Fixture::Param& param);
/// @param radius 圆形半径
/// @param density 物体密度 /// \~chinese
Fixture AddCircleShape(float radius, float density = 0.f); /// @brief 添加圆形夹具
/// @param radius 圆形半径
/// \~chinese /// @param density 物体密度
/// @brief 添加盒形夹具 Fixture AddCircleShape(float radius, float density = 0.f);
/// @param size 盒大小
/// @param density 物体密度 /// \~chinese
Fixture AddBoxShape(Vec2 const& size, float density = 0.f); /// @brief 添加盒形夹具
/// @param size 盒大小
/// \~chinese /// @param density 物体密度
/// @brief 添加多边形夹具 Fixture AddBoxShape(Vec2 const& size, float density = 0.f);
/// @param vertexs 多边形端点
/// @param density 物体密度 /// \~chinese
Fixture AddPolygonShape(Vector<Point> const& vertexs, float density = 0.f); /// @brief 添加多边形夹具
/// @param vertexs 多边形端点
/// \~chinese /// @param density 物体密度
/// @brief 添加线段形夹具 Fixture AddPolygonShape(Vector<Point> const& vertexs, float density = 0.f);
/// @param p1 线段起点
/// @param p2 线段终点 /// \~chinese
/// @param density 物体密度 /// @brief 添加线段形夹具
Fixture AddEdgeShape(Point const& p1, Point const& p2, float density = 0.f); /// @param p1 线段起点
/// @param p2 线段终点
/// \~chinese /// @param density 物体密度
/// @brief 添加链条形夹具 Fixture AddEdgeShape(Point const& p1, Point const& p2, float density = 0.f);
/// @param vertexs 链条端点
/// @param loop 是否闭合 /// \~chinese
/// @param density 物体密度 /// @brief 添加链条形夹具
Fixture AddChainShape(Vector<Point> const& vertexs, bool loop, float density = 0.f); /// @param vertexs 链条端点
/// @param loop 是否闭合
/// \~chinese /// @param density 物体密度
/// @brief 获取夹具列表 Fixture AddChainShape(Vector<Point> const& vertexs, bool loop, float density = 0.f);
FixtureList GetFixtureList() const;
/// \~chinese
/// \~chinese /// @brief 获取夹具列表
/// @brief 移除夹具 FixtureList GetFixtureList() const;
void RemoveFixture(Fixture const& fixture);
/// \~chinese
/// \~chinese /// @brief 移除夹具
/// @brief 获取接触边列表 void RemoveFixture(Fixture const& fixture);
ContactEdgeList GetContactList() const;
/// \~chinese
/// \~chinese /// @brief 获取接触边列表
/// @brief 获取类别码 ContactEdgeList GetContactList() const;
uint16_t GetCategoryBits() const;
/// \~chinese
/// \~chinese /// @brief 获取类别码
/// @brief 设置类别码 uint16_t GetCategoryBits() const;
void SetCategoryBits(uint16_t category_bits);
/// \~chinese
/// \~chinese /// @brief 设置类别码
/// @brief 获取碰撞掩码 void SetCategoryBits(uint16_t category_bits);
uint16_t GetMaskBits() const;
/// \~chinese
/// \~chinese /// @brief 获取碰撞掩码
/// @brief 设置碰撞掩码 uint16_t GetMaskBits() const;
void SetMaskBits(uint16_t mask_bits);
/// \~chinese
/// \~chinese /// @brief 设置碰撞掩码
/// @brief 获取组索引 void SetMaskBits(uint16_t mask_bits);
int16_t GetGroupIndex() const;
/// \~chinese
/// \~chinese /// @brief 获取组索引
/// @brief 设置组索引 int16_t GetGroupIndex() const;
void SetGroupIndex(int16_t index);
/// \~chinese
/// \~chinese /// @brief 设置组索引
/// @brief 获取旋转角度 void SetGroupIndex(int16_t index);
float GetBodyRotation() const;
/// \~chinese
/// \~chinese /// @brief 获取旋转角度
/// @brief 设置旋转角度 float GetBodyRotation() const;
void SetBodyRotation(float angle);
/// \~chinese
/// \~chinese /// @brief 设置旋转角度
/// @brief 获取物体位置 void SetBodyRotation(float angle);
Point GetBodyPosition() const;
/// \~chinese
/// \~chinese /// @brief 获取物体位置
/// @brief 设置物体位置 Point GetBodyPosition() const;
void SetBodyPosition(Point const& pos);
/// \~chinese
/// \~chinese /// @brief 设置物体位置
/// @brief 位置和旋转变换 void SetBodyPosition(Point const& pos);
void SetBodyTransform(Point const& pos, float angle);
/// \~chinese
/// \~chinese /// @brief 位置和旋转变换
/// @brief 获取质量 [kg] void SetBodyTransform(Point const& pos, float angle);
float GetMass() const;
/// \~chinese
/// \~chinese /// @brief 获取质量 [kg]
/// @brief 获取惯性 float GetMass() const;
float GetInertia() const;
/// \~chinese
/// \~chinese /// @brief 获取惯性
/// @brief 获取质量数据 float GetInertia() const;
/// @param[out] mass 物体质量 [kg]
/// @param[out] center 质心位置 /// \~chinese
/// @param[out] inertia 惯性 /// @brief 获取质量数据
void GetMassData(float* mass, Point* center, float* inertia) const; /// @param[out] mass 物体质量 [kg]
/// @param[out] center 质心位置
/// \~chinese /// @param[out] inertia 惯性
/// @brief 设置质量数据 void GetMassData(float* mass, Point* center, float* inertia) const;
/// @param mass 物体质量 [kg]
/// @param center 质心位置 /// \~chinese
/// @param inertia 惯性 /// @brief 设置质量数据
void SetMassData(float mass, Point const& center, float inertia); /// @param mass 物体质量 [kg]
/// @param center 质心位置
/// \~chinese /// @param inertia 惯性
/// @brief 重置质量数据 void SetMassData(float mass, Point const& center, float inertia);
void ResetMassData();
/// \~chinese
/// \~chinese /// @brief 重置质量数据
/// @brief 获取世界坐标系上的点在物体上的位置 void ResetMassData();
Point GetLocalPoint(Point const& world) const;
/// \~chinese
/// \~chinese /// @brief 获取世界坐标系上的点在物体上的位置
/// @brief 获取物体上的点在世界坐标系的位置 Point GetLocalPoint(Point const& world) const;
Point GetWorldPoint(Point const& local) const;
/// \~chinese
/// \~chinese /// @brief 获取物体上的点在世界坐标系的位置
/// @brief 获取物体质心相对于物体的位置 Point GetWorldPoint(Point const& local) const;
Point GetLocalCenter() const;
/// \~chinese
/// \~chinese /// @brief 获取物体质心相对于物体的位置
/// @brief 获取物体质心位置 Point GetLocalCenter() const;
Point GetWorldCenter() const;
/// \~chinese
/// \~chinese /// @brief 获取物体质心位置
/// @brief 获取物体类型 Point GetWorldCenter() const;
Type GetType() const;
/// \~chinese
/// \~chinese /// @brief 获取物体类型
/// @brief 设置物体类型 Type GetType() const;
void SetType(Type type);
/// \~chinese
/// \~chinese /// @brief 设置物体类型
/// @brief 获取物体受重力的比例 void SetType(Type type);
float GetGravityScale() const;
/// \~chinese
/// \~chinese /// @brief 获取物体受重力的比例
/// @brief 设置物体受重力的比例 float GetGravityScale() const;
void SetGravityScale(float scale);
/// \~chinese
/// \~chinese /// @brief 设置物体受重力的比例
/// @brief 施力 void SetGravityScale(float scale);
/// @param force 力的大小和方向
/// @param point 施力点 /// \~chinese
/// @param wake 是否唤醒物体 /// @brief 施力
void ApplyForce(Vec2 const& force, Point const& point, bool wake = true); /// @param force 力的大小和方向
/// @param point 施力点
/// \~chinese /// @param wake 是否唤醒物体
/// @brief 给物体中心施力 void ApplyForce(Vec2 const& force, Point const& point, bool wake = true);
/// @param force 力的大小和方向
/// @param wake 是否唤醒物体 /// \~chinese
void ApplyForceToCenter(Vec2 const& force, bool wake = true); /// @brief 给物体中心施力
/// @param force 力的大小和方向
/// \~chinese /// @param wake 是否唤醒物体
/// @brief 施加扭矩 void ApplyForceToCenter(Vec2 const& force, bool wake = true);
/// @param torque 扭矩
/// @param wake 是否唤醒物体 /// \~chinese
void ApplyTorque(float torque, bool wake = false); /// @brief 施加扭矩
/// @param torque 扭矩
/// \~chinese /// @param wake 是否唤醒物体
/// @brief 旋转角度是否固定 void ApplyTorque(float torque, bool wake = false);
bool IsIgnoreRotation() const;
/// \~chinese
/// \~chinese /// @brief 旋转角度是否固定
/// @brief 设置是否固定旋转角度 bool IsIgnoreRotation() const;
void SetIgnoreRotation(bool flag);
/// \~chinese
/// \~chinese /// @brief 设置是否固定旋转角度
/// @brief 是否是子弹物体 void SetIgnoreRotation(bool flag);
bool IsBullet() const;
/// \~chinese
/// \~chinese /// @brief 是否是子弹物体
/// @brief 设置物体是否是子弹物体 bool IsBullet() const;
void SetBullet(bool flag);
/// \~chinese
/// \~chinese /// @brief 设置物体是否是子弹物体
/// @brief 是否处于唤醒状态 void SetBullet(bool flag);
bool IsAwake() const;
/// \~chinese
/// \~chinese /// @brief 是否处于唤醒状态
/// @brief 设置唤醒状态 bool IsAwake() const;
void SetAwake(bool flag);
/// \~chinese
/// \~chinese /// @brief 设置唤醒状态
/// @brief 是否启用休眠 void SetAwake(bool flag);
bool IsSleepingAllowed() const;
/// \~chinese
/// \~chinese /// @brief 是否启用休眠
/// @brief 设置是否允许休眠 bool IsSleepingAllowed() const;
void SetSleepingAllowed(bool flag);
/// \~chinese
/// \~chinese /// @brief 设置是否允许休眠
/// @brief 是否启用 void SetSleepingAllowed(bool flag);
bool IsActive() const;
/// \~chinese
/// \~chinese /// @brief 是否启用
/// @brief 设置启用状态 bool IsActive() const;
void SetActive(bool flag);
/// \~chinese
/// \~chinese /// @brief 设置启用状态
/// @brief 获取物体所在物理世界 void SetActive(bool flag);
World* GetWorld() const;
/// \~chinese
/// \~chinese /// @brief 获取物体所在物理世界
/// @brief 获取物体绑定的角色 World* GetWorld() const;
Actor* GetActor() const;
/// \~chinese
/// \~chinese /// @brief 获取物体绑定的角色
/// @brief 设置物体绑定的角色 Actor* GetActor() const;
void SetActor(Actor* actor);
/// \~chinese
/// \~chinese /// @brief 设置物体绑定的角色
/// @brief 将物体信息更新到角色 void SetActor(Actor* actor);
void UpdateActor();
/// \~chinese
/// \~chinese /// @brief 将物体信息更新到角色
/// @brief 将角色信息更新到物体 void UpdateActor();
void UpdateFromActor();
/// \~chinese
b2Body* GetB2Body() const; /// @brief 将角色信息更新到物体
void SetB2Body(b2Body* body); void UpdateFromActor();
private: b2Body* GetB2Body() const;
/// \~chinese void SetB2Body(b2Body* body);
/// @brief 销毁物体
void UpdateFixtureFilter(b2Fixture* fixture); private:
/// \~chinese
/// \~chinese /// @brief 销毁物体
/// @brief 销毁物体 void UpdateFixtureFilter(b2Fixture* fixture);
void Destroy();
/// \~chinese
private: /// @brief 销毁物体
Actor* actor_; void Destroy();
World* world_;
b2Body* body_; private:
Actor* actor_;
uint16_t category_bits_; World* world_;
uint16_t mask_bits_; b2Body* body_;
int16_t group_index_;
}; uint16_t category_bits_;
uint16_t mask_bits_;
/** @} */ int16_t group_index_;
};
inline Body::Body(World* world, ActorPtr actor) : Body(world, actor.get()) {}
/** @} */
inline FixtureList Body::GetFixtureList() const { KGE_ASSERT(body_); return FixtureList(Fixture(body_->GetFixtureList())); }
inline bool Body::InitBody(World* world, ActorPtr actor)
inline ContactEdgeList Body::GetContactList() const { KGE_ASSERT(body_); return ContactEdgeList(ContactEdge(body_->GetContactList())); } {
return InitBody(world, actor.get());
inline uint16_t Body::GetCategoryBits() const { return category_bits_; }
inline uint16_t Body::GetMaskBits() const { return mask_bits_; }
inline int16_t Body::GetGroupIndex() const { return group_index_; }
inline float Body::GetBodyRotation() const { KGE_ASSERT(body_); return math::Radian2Degree(body_->GetAngle()); }
inline void Body::SetBodyRotation(float angle) { SetBodyTransform(GetBodyPosition(), angle); }
inline void Body::SetBodyPosition(Point const& pos) { SetBodyTransform(pos, GetBodyRotation()); }
inline float Body::GetMass() const { KGE_ASSERT(body_); return body_->GetMass(); }
inline float Body::GetInertia() const { KGE_ASSERT(body_); return body_->GetInertia(); }
inline Body::Type Body::GetType() const { KGE_ASSERT(body_); return Type(body_->GetType()); }
inline void Body::SetType(Type type) { KGE_ASSERT(body_); body_->SetType(static_cast<b2BodyType>(type)); }
inline float Body::GetGravityScale() const { KGE_ASSERT(body_); return body_->GetGravityScale(); }
inline void Body::SetGravityScale(float scale) { KGE_ASSERT(body_); body_->SetGravityScale(scale); }
inline bool Body::IsIgnoreRotation() const { KGE_ASSERT(body_); return body_->IsFixedRotation(); }
inline void Body::SetIgnoreRotation(bool flag) { KGE_ASSERT(body_); body_->SetFixedRotation(flag); }
inline bool Body::IsBullet() const { KGE_ASSERT(body_); return body_->IsBullet(); }
inline void Body::SetBullet(bool flag) { KGE_ASSERT(body_); body_->SetBullet(flag); }
inline bool Body::IsAwake() const { KGE_ASSERT(body_); return body_->IsAwake(); }
inline void Body::SetAwake(bool flag) { KGE_ASSERT(body_); body_->SetAwake(flag); }
inline bool Body::IsSleepingAllowed() const { KGE_ASSERT(body_); return body_->IsSleepingAllowed(); }
inline void Body::SetSleepingAllowed(bool flag) { KGE_ASSERT(body_); body_->SetSleepingAllowed(flag); }
inline bool Body::IsActive() const { KGE_ASSERT(body_); return body_->IsActive(); }
inline void Body::SetActive(bool flag) { KGE_ASSERT(body_); body_->SetActive(flag); }
inline Actor* Body::GetActor() const { return actor_; }
inline void Body::SetActor(Actor* actor) { actor_ = actor; }
inline b2Body* Body::GetB2Body() const { return body_; }
inline World* Body::GetWorld() const { return world_; }
}
} }
inline FixtureList Body::GetFixtureList() const
{
KGE_ASSERT(body_);
return FixtureList(Fixture(body_->GetFixtureList()));
}
inline ContactEdgeList Body::GetContactList() const
{
KGE_ASSERT(body_);
return ContactEdgeList(ContactEdge(body_->GetContactList()));
}
inline uint16_t Body::GetCategoryBits() const
{
return category_bits_;
}
inline uint16_t Body::GetMaskBits() const
{
return mask_bits_;
}
inline int16_t Body::GetGroupIndex() const
{
return group_index_;
}
inline float Body::GetBodyRotation() const
{
KGE_ASSERT(body_);
return math::Radian2Degree(body_->GetAngle());
}
inline void Body::SetBodyRotation(float angle)
{
SetBodyTransform(GetBodyPosition(), angle);
}
inline void Body::SetBodyPosition(Point const& pos)
{
SetBodyTransform(pos, GetBodyRotation());
}
inline float Body::GetMass() const
{
KGE_ASSERT(body_);
return body_->GetMass();
}
inline float Body::GetInertia() const
{
KGE_ASSERT(body_);
return body_->GetInertia();
}
inline Body::Type Body::GetType() const
{
KGE_ASSERT(body_);
return Type(body_->GetType());
}
inline void Body::SetType(Type type)
{
KGE_ASSERT(body_);
body_->SetType(static_cast<b2BodyType>(type));
}
inline float Body::GetGravityScale() const
{
KGE_ASSERT(body_);
return body_->GetGravityScale();
}
inline void Body::SetGravityScale(float scale)
{
KGE_ASSERT(body_);
body_->SetGravityScale(scale);
}
inline bool Body::IsIgnoreRotation() const
{
KGE_ASSERT(body_);
return body_->IsFixedRotation();
}
inline void Body::SetIgnoreRotation(bool flag)
{
KGE_ASSERT(body_);
body_->SetFixedRotation(flag);
}
inline bool Body::IsBullet() const
{
KGE_ASSERT(body_);
return body_->IsBullet();
}
inline void Body::SetBullet(bool flag)
{
KGE_ASSERT(body_);
body_->SetBullet(flag);
}
inline bool Body::IsAwake() const
{
KGE_ASSERT(body_);
return body_->IsAwake();
}
inline void Body::SetAwake(bool flag)
{
KGE_ASSERT(body_);
body_->SetAwake(flag);
}
inline bool Body::IsSleepingAllowed() const
{
KGE_ASSERT(body_);
return body_->IsSleepingAllowed();
}
inline void Body::SetSleepingAllowed(bool flag)
{
KGE_ASSERT(body_);
body_->SetSleepingAllowed(flag);
}
inline bool Body::IsActive() const
{
KGE_ASSERT(body_);
return body_->IsActive();
}
inline void Body::SetActive(bool flag)
{
KGE_ASSERT(body_);
body_->SetActive(flag);
}
inline Actor* Body::GetActor() const
{
return actor_;
}
inline void Body::SetActor(Actor* actor)
{
actor_ = actor;
}
inline b2Body* Body::GetB2Body() const
{
return body_;
}
inline World* Body::GetWorld() const
{
return world_;
}
} // namespace physics
} // namespace kiwano

View File

@ -1,15 +1,15 @@
// Copyright (c) 2018-2019 Kiwano - Nomango // Copyright (c) 2018-2019 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -18,73 +18,73 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE. // THE SOFTWARE.
#include <kiwano-physics/Contact.h>
#include <kiwano-physics/Body.h> #include <kiwano-physics/Body.h>
#include <kiwano-physics/Contact.h>
#include <kiwano-physics/World.h> #include <kiwano-physics/World.h>
namespace kiwano namespace kiwano
{ {
namespace physics namespace physics
{ {
Contact::Contact() Contact::Contact()
: contact_(nullptr) : contact_(nullptr)
{ {
}
Contact::Contact(b2Contact* contact)
: Contact()
{
SetB2Contact(contact);
}
Fixture Contact::GetFixtureA() const
{
KGE_ASSERT(contact_);
return Fixture(contact_->GetFixtureA());
}
Fixture Contact::GetFixtureB() const
{
KGE_ASSERT(contact_);
return Fixture(contact_->GetFixtureB());
}
Body* Contact::GetBodyA() const
{
return GetFixtureA().GetBody();
}
Body* Contact::GetBodyB() const
{
return GetFixtureB().GetBody();
}
void Contact::SetTangentSpeed(float speed)
{
KGE_ASSERT(contact_);
Body* body = GetFixtureA().GetBody();
KGE_ASSERT(body);
World* world = body->GetWorld();
KGE_ASSERT(world);
contact_->SetTangentSpeed(world->Stage2World(speed));
}
float Contact::GetTangentSpeed() const
{
KGE_ASSERT(contact_);
const Body* body = GetFixtureA().GetBody();
KGE_ASSERT(body);
const World* world = body->GetWorld();
KGE_ASSERT(world);
return world->World2Stage(contact_->GetTangentSpeed());
}
}
} }
Contact::Contact(b2Contact* contact)
: Contact()
{
SetB2Contact(contact);
}
Fixture Contact::GetFixtureA() const
{
KGE_ASSERT(contact_);
return Fixture(contact_->GetFixtureA());
}
Fixture Contact::GetFixtureB() const
{
KGE_ASSERT(contact_);
return Fixture(contact_->GetFixtureB());
}
Body* Contact::GetBodyA() const
{
return GetFixtureA().GetBody();
}
Body* Contact::GetBodyB() const
{
return GetFixtureB().GetBody();
}
void Contact::SetTangentSpeed(float speed)
{
KGE_ASSERT(contact_);
Body* body = GetFixtureA().GetBody();
KGE_ASSERT(body);
World* world = body->GetWorld();
KGE_ASSERT(world);
contact_->SetTangentSpeed(world->Stage2World(speed));
}
float Contact::GetTangentSpeed() const
{
KGE_ASSERT(contact_);
const Body* body = GetFixtureA().GetBody();
KGE_ASSERT(body);
const World* world = body->GetWorld();
KGE_ASSERT(world);
return world->World2Stage(contact_->GetTangentSpeed());
}
} // namespace physics
} // namespace kiwano

View File

@ -1,15 +1,15 @@
// Copyright (c) 2018-2019 Kiwano - Nomango // Copyright (c) 2018-2019 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -19,232 +19,277 @@
// THE SOFTWARE. // THE SOFTWARE.
#pragma once #pragma once
#include <kiwano-physics/helper.h>
#include <kiwano-physics/Fixture.h> #include <kiwano-physics/Fixture.h>
#include <kiwano-physics/helper.h>
namespace kiwano namespace kiwano
{ {
namespace physics namespace physics
{ {
class Body; class Body;
/** /**
* \addtogroup Physics * \addtogroup Physics
* @{ * @{
*/ */
/// \~chinese /// \~chinese
/// @brief 物理接触 /// @brief 物理接触
class KGE_API Contact class KGE_API Contact
{ {
public: public:
Contact(); Contact();
Contact(b2Contact* contact); Contact(b2Contact* contact);
/// \~chinese /// \~chinese
/// @brief 是否有效 /// @brief 是否有效
bool IsValid() const; bool IsValid() const;
/// \~chinese /// \~chinese
/// @brief 是否是接触 /// @brief 是否是接触
bool IsTouching() const; bool IsTouching() const;
/// \~chinese /// \~chinese
/// @brief 启用或禁用 (仅作用于一个时间步) /// @brief 启用或禁用 (仅作用于一个时间步)
void SetEnabled(bool flag); void SetEnabled(bool flag);
/// \~chinese /// \~chinese
/// @brief 是否启用 /// @brief 是否启用
bool IsEnabled() const; bool IsEnabled() const;
/// \~chinese /// \~chinese
/// @brief 获取物体A的夹具 /// @brief 获取物体A的夹具
Fixture GetFixtureA() const; Fixture GetFixtureA() const;
/// \~chinese /// \~chinese
/// @brief 获取物体B的夹具 /// @brief 获取物体B的夹具
Fixture GetFixtureB() const; Fixture GetFixtureB() const;
/// \~chinese /// \~chinese
/// @brief 获取物体A /// @brief 获取物体A
Body* GetBodyA() const; Body* GetBodyA() const;
/// \~chinese /// \~chinese
/// @brief 获取物体B /// @brief 获取物体B
Body* GetBodyB() const; Body* GetBodyB() const;
/// \~chinese /// \~chinese
/// @brief 设置摩擦力 /// @brief 设置摩擦力
void SetFriction(float friction); void SetFriction(float friction);
/// \~chinese /// \~chinese
/// @brief 获取摩擦力 /// @brief 获取摩擦力
float GetFriction() const; float GetFriction() const;
/// \~chinese /// \~chinese
/// @brief 重置摩擦力 /// @brief 重置摩擦力
void ResetFriction(); void ResetFriction();
/// \~chinese /// \~chinese
/// @brief 设置弹性恢复 /// @brief 设置弹性恢复
void SetRestitution(float restitution); void SetRestitution(float restitution);
/// \~chinese /// \~chinese
/// @brief 获取弹性恢复 /// @brief 获取弹性恢复
float GetRestitution() const; float GetRestitution() const;
/// \~chinese /// \~chinese
/// @brief 重置弹性恢复 /// @brief 重置弹性恢复
void ResetRestitution(); void ResetRestitution();
/// \~chinese /// \~chinese
/// @brief 设置切线速度 /// @brief 设置切线速度
void SetTangentSpeed(float speed); void SetTangentSpeed(float speed);
/// \~chinese /// \~chinese
/// @brief 获取切线速度 /// @brief 获取切线速度
float GetTangentSpeed() const; float GetTangentSpeed() const;
b2Contact* GetB2Contact() const; b2Contact* GetB2Contact() const;
void SetB2Contact(b2Contact* contact); void SetB2Contact(b2Contact* contact);
bool operator== (const Contact& rhs) const; bool operator==(const Contact& rhs) const;
bool operator!= (const Contact& rhs) const; bool operator!=(const Contact& rhs) const;
private: private:
b2Contact* contact_; b2Contact* contact_;
}; };
/// \~chinese
/// @brief 物理接触列表
class ContactList : public List<Contact>
{
template <typename _Ty>
class IteratorImpl : public std::iterator<std::forward_iterator_tag, _Ty>
{
using herit = std::iterator<std::forward_iterator_tag, _Ty>;
/// \~chinese public:
/// @brief 物理接触列表 IteratorImpl(const _Ty& elem)
class ContactList : elem_(elem)
: public List<Contact> {
{ }
template <typename _Ty>
class IteratorImpl
: public std::iterator<std::forward_iterator_tag, _Ty>
{
using herit = std::iterator<std::forward_iterator_tag, _Ty>;
public: inline typename herit::reference operator*() const
IteratorImpl(const _Ty& elem) {
: elem_(elem) return const_cast<typename herit::reference>(elem_);
{ }
}
inline typename herit::reference operator*() const inline typename herit::pointer operator->() const
{ {
return const_cast<typename herit::reference>(elem_); return std::pointer_traits<typename herit::pointer>::pointer_to(**this);
} }
inline typename herit::pointer operator->() const inline IteratorImpl& operator++()
{ {
return std::pointer_traits<typename herit::pointer>::pointer_to(**this); elem_ = elem_.GetB2Contact()->GetNext();
} return *this;
}
inline IteratorImpl& operator++() inline IteratorImpl operator++(int)
{ {
elem_ = elem_.GetB2Contact()->GetNext(); IteratorImpl old = *this;
return *this; operator++();
} return old;
}
inline IteratorImpl operator++(int) inline bool operator==(const IteratorImpl& rhs) const
{ {
IteratorImpl old = *this; return elem_ == rhs.elem_;
operator++(); }
return old;
}
inline bool operator== (const IteratorImpl& rhs) const inline bool operator!=(const IteratorImpl& rhs) const
{ {
return elem_ == rhs.elem_; return !operator==(rhs);
} }
inline bool operator!= (const IteratorImpl& rhs) const private:
{ _Ty elem_;
return !operator==(rhs); };
}
private: public:
_Ty elem_; using value_type = Contact;
}; using iterator = IteratorImpl<value_type>;
using const_iterator = IteratorImpl<const value_type>;
public: inline ContactList() {}
using value_type = Contact;
using iterator = IteratorImpl<value_type>;
using const_iterator = IteratorImpl<const value_type>;
inline ContactList() inline ContactList(const value_type& first)
{ : first_(first)
} {
}
inline ContactList(const value_type& first) inline const value_type& front() const
: first_(first) {
{ return first_;
} }
inline const value_type& front() const inline value_type& front()
{ {
return first_; return first_;
} }
inline value_type& front() inline iterator begin()
{ {
return first_; return iterator(first_);
} }
inline iterator begin() inline const_iterator begin() const
{ {
return iterator(first_); return cbegin();
} }
inline const_iterator begin() const inline const_iterator cbegin() const
{ {
return cbegin(); return const_iterator(first_);
} }
inline const_iterator cbegin() const inline iterator end()
{ {
return const_iterator(first_); return iterator(nullptr);
} }
inline iterator end() inline const_iterator end() const
{ {
return iterator(nullptr); return cend();
} }
inline const_iterator end() const inline const_iterator cend() const
{ {
return cend(); return const_iterator(nullptr);
} }
inline const_iterator cend() const private:
{ value_type first_;
return const_iterator(nullptr); };
}
private: /** @} */
value_type first_;
};
/** @} */ inline bool Contact::IsValid() const
{
return contact_ != nullptr;
inline bool Contact::IsValid() const { return contact_ != nullptr;}
inline bool Contact::IsTouching() const { KGE_ASSERT(contact_); return contact_->IsTouching(); }
inline void Contact::SetEnabled(bool flag) { KGE_ASSERT(contact_); contact_->SetEnabled(flag); }
inline bool Contact::IsEnabled() const { KGE_ASSERT(contact_); return contact_->IsEnabled(); }
inline void Contact::SetFriction(float friction) { KGE_ASSERT(contact_); contact_->SetFriction(friction); }
inline float Contact::GetFriction() const { KGE_ASSERT(contact_); return contact_->GetFriction(); }
inline void Contact::ResetFriction() { KGE_ASSERT(contact_); contact_->ResetFriction(); }
inline void Contact::SetRestitution(float restitution) { KGE_ASSERT(contact_); contact_->SetRestitution(restitution); }
inline float Contact::GetRestitution() const { KGE_ASSERT(contact_); return contact_->GetRestitution(); }
inline void Contact::ResetRestitution() { KGE_ASSERT(contact_); contact_->ResetRestitution(); }
inline b2Contact* Contact::GetB2Contact() const { return contact_; }
inline void Contact::SetB2Contact(b2Contact* contact) { contact_ = contact; }
inline bool Contact::operator==(const Contact& rhs) const { return contact_ == rhs.contact_; }
inline bool Contact::operator!=(const Contact& rhs) const { return contact_ != rhs.contact_; }
}
} }
inline bool Contact::IsTouching() const
{
KGE_ASSERT(contact_);
return contact_->IsTouching();
}
inline void Contact::SetEnabled(bool flag)
{
KGE_ASSERT(contact_);
contact_->SetEnabled(flag);
}
inline bool Contact::IsEnabled() const
{
KGE_ASSERT(contact_);
return contact_->IsEnabled();
}
inline void Contact::SetFriction(float friction)
{
KGE_ASSERT(contact_);
contact_->SetFriction(friction);
}
inline float Contact::GetFriction() const
{
KGE_ASSERT(contact_);
return contact_->GetFriction();
}
inline void Contact::ResetFriction()
{
KGE_ASSERT(contact_);
contact_->ResetFriction();
}
inline void Contact::SetRestitution(float restitution)
{
KGE_ASSERT(contact_);
contact_->SetRestitution(restitution);
}
inline float Contact::GetRestitution() const
{
KGE_ASSERT(contact_);
return contact_->GetRestitution();
}
inline void Contact::ResetRestitution()
{
KGE_ASSERT(contact_);
contact_->ResetRestitution();
}
inline b2Contact* Contact::GetB2Contact() const
{
return contact_;
}
inline void Contact::SetB2Contact(b2Contact* contact)
{
contact_ = contact;
}
inline bool Contact::operator==(const Contact& rhs) const
{
return contact_ == rhs.contact_;
}
inline bool Contact::operator!=(const Contact& rhs) const
{
return contact_ != rhs.contact_;
}
} // namespace physics
} // namespace kiwano

View File

@ -1,15 +1,15 @@
// Copyright (c) 2018-2019 Kiwano - Nomango // Copyright (c) 2018-2019 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -22,19 +22,19 @@
namespace kiwano namespace kiwano
{ {
namespace physics namespace physics
{ {
ContactEdge::ContactEdge() ContactEdge::ContactEdge()
: edge_(nullptr) : edge_(nullptr)
{ {
}
ContactEdge::ContactEdge(b2ContactEdge* edge)
: ContactEdge()
{
SetB2ContactEdge(edge);
}
}
} }
ContactEdge::ContactEdge(b2ContactEdge* edge)
: ContactEdge()
{
SetB2ContactEdge(edge);
}
} // namespace physics
} // namespace kiwano

View File

@ -1,15 +1,15 @@
// Copyright (c) 2018-2019 Kiwano - Nomango // Copyright (c) 2018-2019 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -23,164 +23,183 @@
namespace kiwano namespace kiwano
{ {
namespace physics namespace physics
{ {
/** /**
* \addtogroup Physics * \addtogroup Physics
* @{ * @{
*/ */
/// \~chinese /// \~chinese
/// @brief 接触边 /// @brief 接触边
class KGE_API ContactEdge class KGE_API ContactEdge
{ {
public: public:
ContactEdge(); ContactEdge();
ContactEdge(b2ContactEdge* edge); ContactEdge(b2ContactEdge* edge);
/// \~chinese /// \~chinese
/// @brief 是否有效 /// @brief 是否有效
bool IsValid() const; bool IsValid() const;
/// \~chinese /// \~chinese
/// @brief 获取接触物体 /// @brief 获取接触物体
Body* GetOtherBody() const; Body* GetOtherBody() const;
/// \~chinese /// \~chinese
/// @brief 获取接触 /// @brief 获取接触
Contact GetContact() const; Contact GetContact() const;
b2ContactEdge* GetB2ContactEdge() const; b2ContactEdge* GetB2ContactEdge() const;
void SetB2ContactEdge(b2ContactEdge* edge); void SetB2ContactEdge(b2ContactEdge* edge);
bool operator== (const ContactEdge& rhs) const; bool operator==(const ContactEdge& rhs) const;
bool operator!= (const ContactEdge& rhs) const; bool operator!=(const ContactEdge& rhs) const;
private: private:
b2ContactEdge* edge_; b2ContactEdge* edge_;
}; };
/// \~chinese
/// @brief 物理接触边列表
class ContactEdgeList
{
template <typename _Ty>
class IteratorImpl : public std::iterator<std::forward_iterator_tag, _Ty>
{
using herit = std::iterator<std::forward_iterator_tag, _Ty>;
/// \~chinese public:
/// @brief 物理接触边列表 inline IteratorImpl(const _Ty& elem)
class ContactEdgeList : elem_(elem)
{ {
template <typename _Ty> }
class IteratorImpl
: public std::iterator<std::forward_iterator_tag, _Ty>
{
using herit = std::iterator<std::forward_iterator_tag, _Ty>;
public: inline typename herit::reference operator*() const
inline IteratorImpl(const _Ty& elem) {
: elem_(elem) return const_cast<typename herit::reference>(elem_);
{ }
}
inline typename herit::reference operator*() const inline typename herit::pointer operator->() const
{ {
return const_cast<typename herit::reference>(elem_); return std::pointer_traits<typename herit::pointer>::pointer_to(**this);
} }
inline typename herit::pointer operator->() const inline IteratorImpl& operator++()
{ {
return std::pointer_traits<typename herit::pointer>::pointer_to(**this); elem_ = elem_.GetB2ContactEdge()->next;
} return *this;
}
inline IteratorImpl& operator++() inline IteratorImpl operator++(int)
{ {
elem_ = elem_.GetB2ContactEdge()->next; IteratorImpl old = *this;
return *this; operator++();
} return old;
}
inline IteratorImpl operator++(int) inline bool operator==(const IteratorImpl& rhs) const
{ {
IteratorImpl old = *this; return elem_ == rhs.elem_;
operator++(); }
return old;
}
inline bool operator== (const IteratorImpl& rhs) const inline bool operator!=(const IteratorImpl& rhs) const
{ {
return elem_ == rhs.elem_; return !operator==(rhs);
} }
inline bool operator!= (const IteratorImpl& rhs) const private:
{ _Ty elem_;
return !operator==(rhs); };
}
private: public:
_Ty elem_; using value_type = ContactEdge;
}; using iterator = IteratorImpl<value_type>;
using const_iterator = IteratorImpl<const value_type>;
public: inline ContactEdgeList() {}
using value_type = ContactEdge;
using iterator = IteratorImpl<value_type>;
using const_iterator = IteratorImpl<const value_type>;
inline ContactEdgeList() inline ContactEdgeList(const value_type& first)
{ : first_(first)
} {
}
inline ContactEdgeList(const value_type& first) inline const value_type& front() const
: first_(first) {
{ return first_;
} }
inline const value_type& front() const inline value_type& front()
{ {
return first_; return first_;
} }
inline value_type& front() inline iterator begin()
{ {
return first_; return iterator(first_);
} }
inline iterator begin() inline const_iterator begin() const
{ {
return iterator(first_); return cbegin();
} }
inline const_iterator begin() const inline const_iterator cbegin() const
{ {
return cbegin(); return const_iterator(first_);
} }
inline const_iterator cbegin() const inline iterator end()
{ {
return const_iterator(first_); return iterator(nullptr);
} }
inline iterator end() inline const_iterator end() const
{ {
return iterator(nullptr); return cend();
} }
inline const_iterator end() const inline const_iterator cend() const
{ {
return cend(); return const_iterator(nullptr);
} }
inline const_iterator cend() const private:
{ value_type first_;
return const_iterator(nullptr); };
}
private: /** @} */
value_type first_;
};
/** @} */ inline bool ContactEdge::IsValid() const
{
inline bool ContactEdge::IsValid() const { return edge_ != nullptr; } return edge_ != nullptr;
inline Body* ContactEdge::GetOtherBody() const { KGE_ASSERT(edge_); return static_cast<Body*>(edge_->other->GetUserData()); }
inline Contact ContactEdge::GetContact() const { KGE_ASSERT(edge_); return Contact(edge_->contact); }
inline b2ContactEdge* ContactEdge::GetB2ContactEdge() const { return edge_; }
inline void ContactEdge::SetB2ContactEdge(b2ContactEdge* edge) { edge_ = edge; }
inline bool ContactEdge::operator==(const ContactEdge& rhs) const { return edge_ == rhs.edge_; }
inline bool ContactEdge::operator!=(const ContactEdge& rhs) const { return edge_ != rhs.edge_; }
}
} }
inline Body* ContactEdge::GetOtherBody() const
{
KGE_ASSERT(edge_);
return static_cast<Body*>(edge_->other->GetUserData());
}
inline Contact ContactEdge::GetContact() const
{
KGE_ASSERT(edge_);
return Contact(edge_->contact);
}
inline b2ContactEdge* ContactEdge::GetB2ContactEdge() const
{
return edge_;
}
inline void ContactEdge::SetB2ContactEdge(b2ContactEdge* edge)
{
edge_ = edge;
}
inline bool ContactEdge::operator==(const ContactEdge& rhs) const
{
return edge_ == rhs.edge_;
}
inline bool ContactEdge::operator!=(const ContactEdge& rhs) const
{
return edge_ != rhs.edge_;
}
} // namespace physics
} // namespace kiwano

View File

@ -1,15 +1,15 @@
// Copyright (c) 2018-2019 Kiwano - Nomango // Copyright (c) 2018-2019 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -22,29 +22,29 @@
namespace kiwano namespace kiwano
{ {
namespace physics namespace physics
{ {
ContactBeginEvent::ContactBeginEvent() ContactBeginEvent::ContactBeginEvent()
: Event(KGE_EVENT(ContactBeginEvent)) : Event(KGE_EVENT(ContactBeginEvent))
{ {
}
ContactBeginEvent::ContactBeginEvent(Contact const& contact)
: ContactBeginEvent()
{
this->contact = contact;
}
ContactEndEvent::ContactEndEvent()
: Event(KGE_EVENT(ContactEndEvent))
{
}
ContactEndEvent::ContactEndEvent(Contact const& contact)
: ContactEndEvent()
{
this->contact = contact;
}
} }
ContactBeginEvent::ContactBeginEvent(Contact const& contact)
: ContactBeginEvent()
{
this->contact = contact;
} }
ContactEndEvent::ContactEndEvent()
: Event(KGE_EVENT(ContactEndEvent))
{
}
ContactEndEvent::ContactEndEvent(Contact const& contact)
: ContactEndEvent()
{
this->contact = contact;
}
} // namespace physics
} // namespace kiwano

View File

@ -1,15 +1,15 @@
// Copyright (c) 2018-2019 Kiwano - Nomango // Copyright (c) 2018-2019 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -19,44 +19,45 @@
// THE SOFTWARE. // THE SOFTWARE.
#pragma once #pragma once
#include <kiwano-physics/Contact.h>
#include <kiwano-physics/Body.h> #include <kiwano-physics/Body.h>
#include <kiwano-physics/Contact.h>
namespace kiwano namespace kiwano
{ {
namespace physics namespace physics
{ {
/** KGE_DECLARE_SMART_PTR(ContactBeginEvent);
* \addtogroup Events KGE_DECLARE_SMART_PTR(ContactEndEvent);
* @{
*/
/// \~chinese /**
/// @brief 物理接触开始事件 * \addtogroup Events
class KGE_API ContactBeginEvent * @{
: public Event */
{
public:
Contact contact; ///< 产生的接触
ContactBeginEvent(); /// \~chinese
/// @brief 物理接触开始事件
class KGE_API ContactBeginEvent : public Event
{
public:
Contact contact; ///< 产生的接触
ContactBeginEvent(Contact const& contact); ContactBeginEvent();
};
/// \~chinese ContactBeginEvent(Contact const& contact);
/// @brief 物理接触结束事件 };
class KGE_API ContactEndEvent
: public Event
{
public:
Contact contact; ///< 产生的接触
ContactEndEvent(); /// \~chinese
/// @brief 物理接触结束事件
class KGE_API ContactEndEvent : public Event
{
public:
Contact contact; ///< 产生的接触
ContactEndEvent(Contact const& contact); ContactEndEvent();
};
/** @} */ ContactEndEvent(Contact const& contact);
} };
}
/** @} */
} // namespace physics
} // namespace kiwano

View File

@ -1,15 +1,15 @@
// Copyright (c) 2018-2019 Kiwano - Nomango // Copyright (c) 2018-2019 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -18,88 +18,91 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE. // THE SOFTWARE.
#include <kiwano-physics/Fixture.h>
#include <kiwano-physics/Body.h> #include <kiwano-physics/Body.h>
#include <kiwano-physics/Fixture.h>
#include <kiwano-physics/World.h> #include <kiwano-physics/World.h>
namespace kiwano namespace kiwano
{ {
namespace physics namespace physics
{ {
Fixture::Fixture() Fixture::Fixture()
: fixture_(nullptr) : fixture_(nullptr)
{ {
}
Fixture::Fixture(b2Fixture* fixture)
: Fixture()
{
SetB2Fixture(fixture);
}
Fixture::Fixture(Body* body, Shape* shape, const Param& param)
: Fixture()
{
KGE_ASSERT(body);
if (shape)
{
shape->FitWorld(body->GetWorld());
b2Body* b2body = body->GetB2Body();
b2FixtureDef fd;
fd.density = param.density;
fd.friction = param.friction;
fd.restitution = param.restitution;
fd.shape = shape->GetB2Shape();
auto fixture = b2body->CreateFixture(&fd);
SetB2Fixture(fixture);
}
}
Body* Fixture::GetBody() const
{
KGE_ASSERT(fixture_);
return static_cast<Body*>(fixture_->GetBody()->GetUserData());
}
Shape Fixture::GetShape() const
{
KGE_ASSERT(fixture_);
return Shape(fixture_->GetShape());
}
void Fixture::GetMassData(float* mass, Point* center, float* inertia) const
{
KGE_ASSERT(fixture_);
const Body* body = GetBody();
KGE_ASSERT(body);
const World* world = body->GetWorld();
KGE_ASSERT(world);
b2MassData data;
fixture_->GetMassData(&data);
if (mass) *mass = data.mass;
if (center) *center = world->World2Stage(data.center);
if (inertia) *inertia = data.I;
}
bool Fixture::TestPoint(const Point& p) const
{
KGE_ASSERT(fixture_);
const Body* body = GetBody();
KGE_ASSERT(body);
const World* world = body->GetWorld();
KGE_ASSERT(world);
return fixture_->TestPoint(world->Stage2World(p));
}
}
} }
Fixture::Fixture(b2Fixture* fixture)
: Fixture()
{
SetB2Fixture(fixture);
}
Fixture::Fixture(Body* body, Shape* shape, const Param& param)
: Fixture()
{
KGE_ASSERT(body);
if (shape)
{
shape->FitWorld(body->GetWorld());
b2Body* b2body = body->GetB2Body();
b2FixtureDef fd;
fd.density = param.density;
fd.friction = param.friction;
fd.restitution = param.restitution;
fd.shape = shape->GetB2Shape();
auto fixture = b2body->CreateFixture(&fd);
SetB2Fixture(fixture);
}
}
Body* Fixture::GetBody() const
{
KGE_ASSERT(fixture_);
return static_cast<Body*>(fixture_->GetBody()->GetUserData());
}
Shape Fixture::GetShape() const
{
KGE_ASSERT(fixture_);
return Shape(fixture_->GetShape());
}
void Fixture::GetMassData(float* mass, Point* center, float* inertia) const
{
KGE_ASSERT(fixture_);
const Body* body = GetBody();
KGE_ASSERT(body);
const World* world = body->GetWorld();
KGE_ASSERT(world);
b2MassData data;
fixture_->GetMassData(&data);
if (mass)
*mass = data.mass;
if (center)
*center = world->World2Stage(data.center);
if (inertia)
*inertia = data.I;
}
bool Fixture::TestPoint(const Point& p) const
{
KGE_ASSERT(fixture_);
const Body* body = GetBody();
KGE_ASSERT(body);
const World* world = body->GetWorld();
KGE_ASSERT(world);
return fixture_->TestPoint(world->Stage2World(p));
}
} // namespace physics
} // namespace kiwano

View File

@ -1,15 +1,15 @@
// Copyright (c) 2018-2019 Kiwano - Nomango // Copyright (c) 2018-2019 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -19,237 +19,281 @@
// THE SOFTWARE. // THE SOFTWARE.
#pragma once #pragma once
#include <kiwano-physics/helper.h>
#include <kiwano-physics/Shape.h> #include <kiwano-physics/Shape.h>
#include <kiwano-physics/helper.h>
namespace kiwano namespace kiwano
{ {
namespace physics namespace physics
{ {
class Body; class Body;
/** /**
* \addtogroup Physics * \addtogroup Physics
* @{ * @{
*/ */
/// \~chinese /// \~chinese
/// @brief 物理夹具 /// @brief 物理夹具
class Fixture class Fixture
{ {
public: public:
/// \~chinese /// \~chinese
/// @brief 夹具参数 /// @brief 夹具参数
struct Param struct Param
{ {
float density = 0.f; ///< 密度 float density = 0.f; ///< 密度
float friction = 0.2f; ///< 摩擦力 float friction = 0.2f; ///< 摩擦力
float restitution = 0.f; ///< 弹性恢复 float restitution = 0.f; ///< 弹性恢复
bool is_sensor = false; ///< 是否是接触传感器 bool is_sensor = false; ///< 是否是接触传感器
Param() {} Param() {}
Param(float density, float friction = 0.2f, float restitution = 0.f, bool is_sensor = false) Param(float density, float friction = 0.2f, float restitution = 0.f, bool is_sensor = false)
: density(density) : density(density)
, friction(friction) , friction(friction)
, restitution(restitution) , restitution(restitution)
, is_sensor(is_sensor) , is_sensor(is_sensor)
{} {
}; }
};
Fixture(); Fixture();
Fixture(b2Fixture* fixture); Fixture(b2Fixture* fixture);
Fixture(Body* body, Shape* shape, const Param& param); Fixture(Body* body, Shape* shape, const Param& param);
/// \~chinese /// \~chinese
/// @brief 是否有效 /// @brief 是否有效
bool IsValid() const; bool IsValid() const;
/// \~chinese /// \~chinese
/// @brief 获取夹具所在的物体 /// @brief 获取夹具所在的物体
Body* GetBody() const; Body* GetBody() const;
/// \~chinese /// \~chinese
/// @brief 形状 /// @brief 形状
Shape GetShape() const; Shape GetShape() const;
/// \~chinese /// \~chinese
/// @brief 是否是接触传感器 /// @brief 是否是接触传感器
bool IsSensor() const; bool IsSensor() const;
/// \~chinese /// \~chinese
/// @brief 设置夹具是否是接触传感器 /// @brief 设置夹具是否是接触传感器
/// @details 接触传感器只会产生物理接触,而不会影响物体运动 /// @details 接触传感器只会产生物理接触,而不会影响物体运动
void SetSensor(bool sensor); void SetSensor(bool sensor);
/// \~chinese /// \~chinese
/// @brief 获取夹具的质量数据 /// @brief 获取夹具的质量数据
void GetMassData(float* mass, Point* center, float* inertia) const; void GetMassData(float* mass, Point* center, float* inertia) const;
/// \~chinese /// \~chinese
/// @brief 获取密度 /// @brief 获取密度
float GetDensity() const; float GetDensity() const;
/// \~chinese /// \~chinese
/// @brief 设置密度 /// @brief 设置密度
void SetDensity(float density); void SetDensity(float density);
/// \~chinese /// \~chinese
/// @brief 获取摩擦力 [N] /// @brief 获取摩擦力 [N]
float GetFriction() const; float GetFriction() const;
/// \~chinese /// \~chinese
/// @brief 设置摩擦力 [N] /// @brief 设置摩擦力 [N]
void SetFriction(float friction); void SetFriction(float friction);
/// \~chinese /// \~chinese
/// @brief 获取弹性恢复 /// @brief 获取弹性恢复
float GetRestitution() const; float GetRestitution() const;
/// \~chinese /// \~chinese
/// @brief 设置弹性恢复 /// @brief 设置弹性恢复
void SetRestitution(float restitution); void SetRestitution(float restitution);
/// \~chinese /// \~chinese
/// @brief 点测试 /// @brief 点测试
bool TestPoint(const Point& p) const; bool TestPoint(const Point& p) const;
b2Fixture* GetB2Fixture() const; b2Fixture* GetB2Fixture() const;
void SetB2Fixture(b2Fixture* fixture); void SetB2Fixture(b2Fixture* fixture);
bool operator== (const Fixture& rhs) const; bool operator==(const Fixture& rhs) const;
bool operator!= (const Fixture& rhs) const; bool operator!=(const Fixture& rhs) const;
private: private:
b2Fixture* fixture_; b2Fixture* fixture_;
}; };
/// \~chinese /// \~chinese
/// @brief 物理夹具列表 /// @brief 物理夹具列表
class FixtureList class FixtureList : public List<Fixture>
: public List<Fixture> {
{ template <typename _Ty>
template <typename _Ty> class IteratorImpl : public std::iterator<std::forward_iterator_tag, _Ty>
class IteratorImpl {
: public std::iterator<std::forward_iterator_tag, _Ty> using herit = std::iterator<std::forward_iterator_tag, _Ty>;
{
using herit = std::iterator<std::forward_iterator_tag, _Ty>;
public: public:
IteratorImpl(const _Ty& elem) IteratorImpl(const _Ty& elem)
: elem_(elem) : elem_(elem)
{ {
} }
inline typename herit::reference operator*() const inline typename herit::reference operator*() const
{ {
return const_cast<typename herit::reference>(elem_); return const_cast<typename herit::reference>(elem_);
} }
inline typename herit::pointer operator->() const inline typename herit::pointer operator->() const
{ {
return std::pointer_traits<typename herit::pointer>::pointer_to(**this); return std::pointer_traits<typename herit::pointer>::pointer_to(**this);
} }
inline IteratorImpl& operator++() inline IteratorImpl& operator++()
{ {
elem_ = elem_.GetB2Fixture()->GetNext(); elem_ = elem_.GetB2Fixture()->GetNext();
return *this; return *this;
} }
inline IteratorImpl operator++(int) inline IteratorImpl operator++(int)
{ {
IteratorImpl old = *this; IteratorImpl old = *this;
operator++(); operator++();
return old; return old;
} }
inline bool operator== (const IteratorImpl& rhs) const inline bool operator==(const IteratorImpl& rhs) const
{ {
return elem_ == rhs.elem_; return elem_ == rhs.elem_;
} }
inline bool operator!= (const IteratorImpl& rhs) const inline bool operator!=(const IteratorImpl& rhs) const
{ {
return !operator==(rhs); return !operator==(rhs);
} }
private: private:
_Ty elem_; _Ty elem_;
}; };
public: public:
using value_type = Fixture; using value_type = Fixture;
using iterator = IteratorImpl<value_type>; using iterator = IteratorImpl<value_type>;
using const_iterator = IteratorImpl<const value_type>; using const_iterator = IteratorImpl<const value_type>;
inline FixtureList() inline FixtureList() {}
{
}
inline FixtureList(const value_type& first) inline FixtureList(const value_type& first)
: first_(first) : first_(first)
{ {
} }
inline const value_type& front() const inline const value_type& front() const
{ {
return first_; return first_;
} }
inline value_type& front() inline value_type& front()
{ {
return first_; return first_;
} }
inline iterator begin() inline iterator begin()
{ {
return iterator(first_); return iterator(first_);
} }
inline const_iterator begin() const inline const_iterator begin() const
{ {
return cbegin(); return cbegin();
} }
inline const_iterator cbegin() const inline const_iterator cbegin() const
{ {
return const_iterator(first_); return const_iterator(first_);
} }
inline iterator end() inline iterator end()
{ {
return iterator(nullptr); return iterator(nullptr);
} }
inline const_iterator end() const inline const_iterator end() const
{ {
return cend(); return cend();
} }
inline const_iterator cend() const inline const_iterator cend() const
{ {
return const_iterator(nullptr); return const_iterator(nullptr);
} }
private: private:
value_type first_; value_type first_;
}; };
/** @} */ /** @} */
inline bool Fixture::IsSensor() const { KGE_ASSERT(fixture_); return fixture_->IsSensor(); } inline bool Fixture::IsSensor() const
inline void Fixture::SetSensor(bool sensor) { KGE_ASSERT(fixture_); fixture_->SetSensor(sensor); } {
inline float Fixture::GetDensity() const { KGE_ASSERT(fixture_); return fixture_->GetDensity(); } KGE_ASSERT(fixture_);
inline void Fixture::SetDensity(float density) { KGE_ASSERT(fixture_); fixture_->SetDensity(density); } return fixture_->IsSensor();
inline float Fixture::GetFriction() const { KGE_ASSERT(fixture_); return fixture_->GetFriction(); }
inline void Fixture::SetFriction(float friction) { KGE_ASSERT(fixture_); fixture_->SetFriction(friction); }
inline float Fixture::GetRestitution() const { KGE_ASSERT(fixture_); return fixture_->GetRestitution(); }
inline void Fixture::SetRestitution(float restitution) { KGE_ASSERT(fixture_); fixture_->SetRestitution(restitution); }
inline bool Fixture::IsValid() const { return fixture_ != nullptr; }
inline b2Fixture* Fixture::GetB2Fixture() const { return fixture_; }
inline void Fixture::SetB2Fixture(b2Fixture* fixture) { fixture_ = fixture; }
inline bool Fixture::operator==(const Fixture& rhs) const { return fixture_ == rhs.fixture_; }
inline bool Fixture::operator!=(const Fixture& rhs) const { return fixture_ != rhs.fixture_; }
}
} }
inline void Fixture::SetSensor(bool sensor)
{
KGE_ASSERT(fixture_);
fixture_->SetSensor(sensor);
}
inline float Fixture::GetDensity() const
{
KGE_ASSERT(fixture_);
return fixture_->GetDensity();
}
inline void Fixture::SetDensity(float density)
{
KGE_ASSERT(fixture_);
fixture_->SetDensity(density);
}
inline float Fixture::GetFriction() const
{
KGE_ASSERT(fixture_);
return fixture_->GetFriction();
}
inline void Fixture::SetFriction(float friction)
{
KGE_ASSERT(fixture_);
fixture_->SetFriction(friction);
}
inline float Fixture::GetRestitution() const
{
KGE_ASSERT(fixture_);
return fixture_->GetRestitution();
}
inline void Fixture::SetRestitution(float restitution)
{
KGE_ASSERT(fixture_);
fixture_->SetRestitution(restitution);
}
inline bool Fixture::IsValid() const
{
return fixture_ != nullptr;
}
inline b2Fixture* Fixture::GetB2Fixture() const
{
return fixture_;
}
inline void Fixture::SetB2Fixture(b2Fixture* fixture)
{
fixture_ = fixture;
}
inline bool Fixture::operator==(const Fixture& rhs) const
{
return fixture_ == rhs.fixture_;
}
inline bool Fixture::operator!=(const Fixture& rhs) const
{
return fixture_ != rhs.fixture_;
}
} // namespace physics
} // namespace kiwano

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,15 +1,15 @@
// Copyright (c) 2018-2019 Kiwano - Nomango // Copyright (c) 2018-2019 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -23,200 +23,200 @@
namespace kiwano namespace kiwano
{ {
namespace physics namespace physics
{ {
Shape::Shape() Shape::Shape()
: shape_(nullptr) : shape_(nullptr)
{ {
}
Shape::Shape(b2Shape* shape)
: shape_(shape)
{
}
b2Shape* Shape::GetB2Shape() const
{
return shape_;
}
void Shape::SetB2Shape(b2Shape* shape)
{
shape_ = shape;
}
//
// CircleShape
//
CircleShape::CircleShape()
: Shape(&circle_)
, circle_()
, radius_(0.f)
{
}
CircleShape::CircleShape(float radius, Point const& offset)
: CircleShape()
{
Set(radius, offset);
}
void CircleShape::Set(float radius, Point const& offset)
{
radius_ = radius;
offset_ = offset;
}
void CircleShape::FitWorld(World* world)
{
KGE_ASSERT(world);
circle_.m_radius = world->Stage2World(radius_);
circle_.m_p = world->Stage2World(offset_);
}
//
// BoxShape
//
BoxShape::BoxShape()
: Shape(&polygon_)
, polygon_()
, rotation_(0.f)
{
}
BoxShape::BoxShape(Vec2 const& size, Point const& offset, float rotation)
: BoxShape()
{
Set(size, offset, rotation);
}
void BoxShape::Set(Vec2 const& size, Point const& offset, float rotation)
{
box_size_ = size;
offset_ = offset;
rotation_ = rotation;
}
void BoxShape::FitWorld(World* world)
{
KGE_ASSERT(world);
b2Vec2 box = world->Stage2World(box_size_);
b2Vec2 offset = world->Stage2World(offset_);
polygon_.SetAsBox(box.x / 2, box.y / 2, offset, rotation_);
}
//
// PolygonShape
//
PolygonShape::PolygonShape()
: Shape(&polygon_)
, polygon_()
{
}
PolygonShape::PolygonShape(Vector<Point> const& vertexs)
: PolygonShape()
{
Set(vertexs);
}
void PolygonShape::Set(Vector<Point> const& vertexs)
{
vertexs_ = vertexs;
}
void PolygonShape::FitWorld(World* world)
{
KGE_ASSERT(world);
Vector<b2Vec2> b2vertexs;
b2vertexs.reserve(vertexs_.size());
for (const auto& v : vertexs_)
{
b2vertexs.push_back(world->Stage2World(v));
}
polygon_.Set(&b2vertexs[0], static_cast<int32>(b2vertexs.size()));
}
//
// EdgeShape
//
EdgeShape::EdgeShape()
: Shape(&edge_)
, edge_()
{
}
EdgeShape::EdgeShape(Point const& p1, Point const& p2)
: EdgeShape()
{
Set(p1, p2);
}
void EdgeShape::Set(Point const& p1, Point const& p2)
{
p_[0] = p1;
p_[1] = p2;
}
void EdgeShape::FitWorld(World* world)
{
KGE_ASSERT(world);
b2Vec2 p1 = world->Stage2World(p_[0]);
b2Vec2 p2 = world->Stage2World(p_[1]);
edge_.Set(p1, p2);
}
//
// ChainShape
//
ChainShape::ChainShape()
: Shape(&chain_)
, chain_()
, loop_(false)
{
}
ChainShape::ChainShape(Vector<Point> const& vertexs, bool loop)
: ChainShape()
{
Set(vertexs, loop);
}
void ChainShape::Set(Vector<Point> const& vertexs, bool loop)
{
vertexs_ = vertexs;
loop_ = loop;
}
void ChainShape::FitWorld(World* world)
{
KGE_ASSERT(world);
Vector<b2Vec2> b2vertexs;
b2vertexs.reserve(vertexs_.size());
for (const auto& v : vertexs_)
{
b2vertexs.push_back(world->Stage2World(v));
}
if (loop_)
{
chain_.CreateLoop(&b2vertexs[0], static_cast<int32>(b2vertexs.size()));
}
else
{
chain_.CreateChain(&b2vertexs[0], static_cast<int32>(b2vertexs.size()));
}
}
} }
Shape::Shape(b2Shape* shape)
: shape_(shape)
{
} }
b2Shape* Shape::GetB2Shape() const
{
return shape_;
}
void Shape::SetB2Shape(b2Shape* shape)
{
shape_ = shape;
}
//
// CircleShape
//
CircleShape::CircleShape()
: Shape(&circle_)
, circle_()
, radius_(0.f)
{
}
CircleShape::CircleShape(float radius, Point const& offset)
: CircleShape()
{
Set(radius, offset);
}
void CircleShape::Set(float radius, Point const& offset)
{
radius_ = radius;
offset_ = offset;
}
void CircleShape::FitWorld(World* world)
{
KGE_ASSERT(world);
circle_.m_radius = world->Stage2World(radius_);
circle_.m_p = world->Stage2World(offset_);
}
//
// BoxShape
//
BoxShape::BoxShape()
: Shape(&polygon_)
, polygon_()
, rotation_(0.f)
{
}
BoxShape::BoxShape(Vec2 const& size, Point const& offset, float rotation)
: BoxShape()
{
Set(size, offset, rotation);
}
void BoxShape::Set(Vec2 const& size, Point const& offset, float rotation)
{
box_size_ = size;
offset_ = offset;
rotation_ = rotation;
}
void BoxShape::FitWorld(World* world)
{
KGE_ASSERT(world);
b2Vec2 box = world->Stage2World(box_size_);
b2Vec2 offset = world->Stage2World(offset_);
polygon_.SetAsBox(box.x / 2, box.y / 2, offset, rotation_);
}
//
// PolygonShape
//
PolygonShape::PolygonShape()
: Shape(&polygon_)
, polygon_()
{
}
PolygonShape::PolygonShape(Vector<Point> const& vertexs)
: PolygonShape()
{
Set(vertexs);
}
void PolygonShape::Set(Vector<Point> const& vertexs)
{
vertexs_ = vertexs;
}
void PolygonShape::FitWorld(World* world)
{
KGE_ASSERT(world);
Vector<b2Vec2> b2vertexs;
b2vertexs.reserve(vertexs_.size());
for (const auto& v : vertexs_)
{
b2vertexs.push_back(world->Stage2World(v));
}
polygon_.Set(&b2vertexs[0], static_cast<int32>(b2vertexs.size()));
}
//
// EdgeShape
//
EdgeShape::EdgeShape()
: Shape(&edge_)
, edge_()
{
}
EdgeShape::EdgeShape(Point const& p1, Point const& p2)
: EdgeShape()
{
Set(p1, p2);
}
void EdgeShape::Set(Point const& p1, Point const& p2)
{
p_[0] = p1;
p_[1] = p2;
}
void EdgeShape::FitWorld(World* world)
{
KGE_ASSERT(world);
b2Vec2 p1 = world->Stage2World(p_[0]);
b2Vec2 p2 = world->Stage2World(p_[1]);
edge_.Set(p1, p2);
}
//
// ChainShape
//
ChainShape::ChainShape()
: Shape(&chain_)
, chain_()
, loop_(false)
{
}
ChainShape::ChainShape(Vector<Point> const& vertexs, bool loop)
: ChainShape()
{
Set(vertexs, loop);
}
void ChainShape::Set(Vector<Point> const& vertexs, bool loop)
{
vertexs_ = vertexs;
loop_ = loop;
}
void ChainShape::FitWorld(World* world)
{
KGE_ASSERT(world);
Vector<b2Vec2> b2vertexs;
b2vertexs.reserve(vertexs_.size());
for (const auto& v : vertexs_)
{
b2vertexs.push_back(world->Stage2World(v));
}
if (loop_)
{
chain_.CreateLoop(&b2vertexs[0], static_cast<int32>(b2vertexs.size()));
}
else
{
chain_.CreateChain(&b2vertexs[0], static_cast<int32>(b2vertexs.size()));
}
}
} // namespace physics
} // namespace kiwano

View File

@ -1,15 +1,15 @@
// Copyright (c) 2018-2019 Kiwano - Nomango // Copyright (c) 2018-2019 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -23,140 +23,135 @@
namespace kiwano namespace kiwano
{ {
namespace physics namespace physics
{ {
class World; class World;
class Fixture; class Fixture;
/** /**
* \addtogroup Physics * \addtogroup Physics
* @{ * @{
*/ */
/// \~chinese /// \~chinese
/// @brief 形状基类 /// @brief 形状基类
class KGE_API Shape class KGE_API Shape
{ {
friend class Fixture; friend class Fixture;
public: public:
Shape(); Shape();
Shape(b2Shape* shape); Shape(b2Shape* shape);
b2Shape* GetB2Shape() const; b2Shape* GetB2Shape() const;
void SetB2Shape(b2Shape* shape); void SetB2Shape(b2Shape* shape);
private: private:
virtual void FitWorld(World* world) {} virtual void FitWorld(World* world) {}
private: private:
b2Shape* shape_; b2Shape* shape_;
}; };
/// \~chinese /// \~chinese
/// @brief 圆形形状 /// @brief 圆形形状
class KGE_API CircleShape class KGE_API CircleShape : public Shape
: public Shape {
{ public:
public: CircleShape();
CircleShape();
CircleShape(float radius, Point const& offset = Point()); CircleShape(float radius, Point const& offset = Point());
void Set(float radius, Point const& offset = Point()); void Set(float radius, Point const& offset = Point());
private: private:
void FitWorld(World* world) override; void FitWorld(World* world) override;
private: private:
float radius_; float radius_;
Point offset_; Point offset_;
b2CircleShape circle_; b2CircleShape circle_;
}; };
/// \~chinese /// \~chinese
/// @brief 盒子形状 /// @brief 盒子形状
class KGE_API BoxShape class KGE_API BoxShape : public Shape
: public Shape {
{ public:
public: BoxShape();
BoxShape();
BoxShape(Vec2 const& size, Point const& offset = Point(), float rotation = 0.f); BoxShape(Vec2 const& size, Point const& offset = Point(), float rotation = 0.f);
void Set(Vec2 const& size, Point const& offset = Point(), float rotation = 0.f); void Set(Vec2 const& size, Point const& offset = Point(), float rotation = 0.f);
private: private:
void FitWorld(World* world) override; void FitWorld(World* world) override;
private: private:
float rotation_; float rotation_;
Vec2 box_size_; Vec2 box_size_;
Point offset_; Point offset_;
b2PolygonShape polygon_; b2PolygonShape polygon_;
}; };
/// \~chinese /// \~chinese
/// @brief 多边形形状 /// @brief 多边形形状
class KGE_API PolygonShape class KGE_API PolygonShape : public Shape
: public Shape {
{ public:
public: PolygonShape();
PolygonShape();
PolygonShape(Vector<Point> const& vertexs); PolygonShape(Vector<Point> const& vertexs);
void Set(Vector<Point> const& vertexs); void Set(Vector<Point> const& vertexs);
private: private:
void FitWorld(World* world) override; void FitWorld(World* world) override;
private: private:
Vector<Point> vertexs_; Vector<Point> vertexs_;
b2PolygonShape polygon_; b2PolygonShape polygon_;
}; };
/// \~chinese /// \~chinese
/// @brief 线段形状, 用于表示一条边 /// @brief 线段形状, 用于表示一条边
class KGE_API EdgeShape class KGE_API EdgeShape : public Shape
: public Shape {
{ public:
public: EdgeShape();
EdgeShape();
EdgeShape(Point const& p1, Point const& p2); EdgeShape(Point const& p1, Point const& p2);
void Set(Point const& p1, Point const& p2); void Set(Point const& p1, Point const& p2);
private: private:
void FitWorld(World* world) override; void FitWorld(World* world) override;
private: private:
Point p_[2]; Point p_[2];
b2EdgeShape edge_; b2EdgeShape edge_;
}; };
/// \~chinese /// \~chinese
/// @brief 链式形状 /// @brief 链式形状
class KGE_API ChainShape class KGE_API ChainShape : public Shape
: public Shape {
{ public:
public: ChainShape();
ChainShape();
ChainShape(Vector<Point> const& vertexs, bool loop = false); ChainShape(Vector<Point> const& vertexs, bool loop = false);
void Set(Vector<Point> const& vertexs, bool loop = false); void Set(Vector<Point> const& vertexs, bool loop = false);
private: private:
void FitWorld(World* world) override; void FitWorld(World* world) override;
private: private:
bool loop_; bool loop_;
Vector<Point> vertexs_; Vector<Point> vertexs_;
b2ChainShape chain_; b2ChainShape chain_;
}; };
/** @} */ /** @} */
} } // namespace physics
} } // namespace kiwano

View File

@ -1,15 +1,15 @@
// Copyright (c) 2018-2019 Kiwano - Nomango // Copyright (c) 2018-2019 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -19,235 +19,237 @@
// THE SOFTWARE. // THE SOFTWARE.
#include "World.h" #include "World.h"
#include <kiwano-physics/ContactEvent.h> #include <kiwano-physics/ContactEvent.h>
namespace kiwano namespace kiwano
{ {
namespace physics namespace physics
{ {
namespace namespace
{ {
const float default_global_scale = 100.f; // 100 pixels per meters const float default_global_scale = 100.f; // 100 pixels per meters
}
class World::DestructionListener : public b2DestructionListener
{
World* world_;
public:
DestructionListener(World* world)
: world_(world)
{
}
void SayGoodbye(b2Joint* joint) override
{
if (world_)
{
world_->JointRemoved(joint);
}
}
void SayGoodbye(b2Fixture* fixture) override
{
}
};
class World::ContactListener
: public b2ContactListener
{
World* world_;
public:
ContactListener(World* world)
: world_(world)
{
}
void BeginContact(b2Contact* contact) override
{
ContactBeginEvent evt(contact);
world_->Dispatch(evt);
}
void EndContact(b2Contact* contact) override
{
ContactEndEvent evt(contact);
world_->Dispatch(evt);
}
void PreSolve(b2Contact* contact, const b2Manifold* oldManifold) override { KGE_NOT_USED(contact); KGE_NOT_USED(oldManifold); }
void PostSolve(b2Contact* contact, const b2ContactImpulse* impulse) override { KGE_NOT_USED(contact); KGE_NOT_USED(impulse); }
};
World::World()
: world_(b2Vec2(0, 10.0f))
, vel_iter_(6)
, pos_iter_(2)
, global_scale_(default_global_scale)
, destruction_listener_(nullptr)
, contact_listener_(nullptr)
, removing_joint_(false)
{
destruction_listener_ = new DestructionListener(this);
world_.SetDestructionListener(destruction_listener_);
contact_listener_ = new ContactListener(this);
world_.SetContactListener(contact_listener_);
}
World::~World()
{
world_.SetDestructionListener(nullptr);
if (destruction_listener_)
{
delete destruction_listener_;
destruction_listener_ = nullptr;
}
world_.SetContactListener(nullptr);
if (contact_listener_)
{
delete contact_listener_;
contact_listener_ = nullptr;
}
// Make sure b2World was destroyed after b2Body
RemoveAllChildren();
RemoveAllBodies();
RemoveAllJoints();
}
void World::RemoveBody(Body* body)
{
if (body && body->GetB2Body())
{
world_.DestroyBody(body->GetB2Body());
}
}
void World::RemoveAllBodies()
{
if (world_.GetBodyCount())
{
b2Body* body = world_.GetBodyList();
while (body)
{
b2Body* next = body->GetNext();
world_.DestroyBody(body);
body = next;
}
}
}
void World::AddJoint(Joint* joint)
{
if (joint)
{
joints_.push_back(joint);
}
}
void World::RemoveJoint(Joint* joint)
{
if (joint)
{
auto iter = std::find(joints_.begin(), joints_.end(), joint);
if (iter != joints_.end())
{
joints_.erase(iter);
if (joint->GetB2Joint())
{
removing_joint_ = true;
world_.DestroyJoint(joint->GetB2Joint());
removing_joint_ = false;
}
}
}
}
void World::RemoveAllJoints()
{
if (world_.GetJointCount())
{
removing_joint_ = true;
{
b2Joint* joint = world_.GetJointList();
while (joint)
{
b2Joint* next = joint->GetNext();
world_.DestroyJoint(joint);
joint = next;
}
}
removing_joint_ = false;
}
joints_.clear();
}
void World::JointRemoved(b2Joint* joint)
{
if (!removing_joint_ && joint)
{
auto iter = std::find_if(
joints_.begin(),
joints_.end(),
[joint](Joint* j) -> bool { return j->GetB2Joint() == joint; }
);
if (iter != joints_.end())
{
joints_.erase(iter);
}
}
}
b2World* World::GetB2World()
{
return &world_;
}
const b2World* World::GetB2World() const
{
return &world_;
}
Vec2 World::GetGravity() const
{
b2Vec2 g = world_.GetGravity();
return Vec2(g.x, g.y);
}
void World::SetGravity(Vec2 gravity)
{
world_.SetGravity(b2Vec2(gravity.x, gravity.y));
}
ContactList World::GetContactList()
{
return ContactList(Contact(world_.GetContactList()));
}
void World::Update(Duration dt)
{
world_.Step(dt.Seconds(), vel_iter_, pos_iter_);
b2Body* b2body = world_.GetBodyList();
while (b2body)
{
Body* body = static_cast<Body*>(b2body->GetUserData());
if (body && body->GetType() != Body::Type::Static)
{
body->UpdateActor();
}
b2body = b2body->GetNext();
}
Stage::Update(dt);
}
}
} }
class World::DestructionListener : public b2DestructionListener
{
World* world_;
public:
DestructionListener(World* world)
: world_(world)
{
}
void SayGoodbye(b2Joint* joint) override
{
if (world_)
{
world_->JointRemoved(joint);
}
}
void SayGoodbye(b2Fixture* fixture) override {}
};
class World::ContactListener : public b2ContactListener
{
World* world_;
public:
ContactListener(World* world)
: world_(world)
{
}
void BeginContact(b2Contact* contact) override
{
ContactBeginEventPtr evt = new ContactBeginEvent(contact);
world_->DispatchEvent(evt.get());
}
void EndContact(b2Contact* contact) override
{
ContactEndEventPtr evt = new ContactEndEvent(contact);
world_->DispatchEvent(evt.get());
}
void PreSolve(b2Contact* contact, const b2Manifold* oldManifold) override
{
KGE_NOT_USED(contact);
KGE_NOT_USED(oldManifold);
}
void PostSolve(b2Contact* contact, const b2ContactImpulse* impulse) override
{
KGE_NOT_USED(contact);
KGE_NOT_USED(impulse);
}
};
World::World()
: world_(b2Vec2(0, 10.0f))
, vel_iter_(6)
, pos_iter_(2)
, global_scale_(default_global_scale)
, destruction_listener_(nullptr)
, contact_listener_(nullptr)
, removing_joint_(false)
{
destruction_listener_ = new DestructionListener(this);
world_.SetDestructionListener(destruction_listener_);
contact_listener_ = new ContactListener(this);
world_.SetContactListener(contact_listener_);
}
World::~World()
{
world_.SetDestructionListener(nullptr);
if (destruction_listener_)
{
delete destruction_listener_;
destruction_listener_ = nullptr;
}
world_.SetContactListener(nullptr);
if (contact_listener_)
{
delete contact_listener_;
contact_listener_ = nullptr;
}
// Make sure b2World was destroyed after b2Body
RemoveAllChildren();
RemoveAllBodies();
RemoveAllJoints();
}
void World::RemoveBody(Body* body)
{
if (body && body->GetB2Body())
{
world_.DestroyBody(body->GetB2Body());
}
}
void World::RemoveAllBodies()
{
if (world_.GetBodyCount())
{
b2Body* body = world_.GetBodyList();
while (body)
{
b2Body* next = body->GetNext();
world_.DestroyBody(body);
body = next;
}
}
}
void World::AddJoint(Joint* joint)
{
if (joint)
{
joints_.push_back(joint);
}
}
void World::RemoveJoint(Joint* joint)
{
if (joint)
{
auto iter = std::find(joints_.begin(), joints_.end(), joint);
if (iter != joints_.end())
{
joints_.erase(iter);
if (joint->GetB2Joint())
{
removing_joint_ = true;
world_.DestroyJoint(joint->GetB2Joint());
removing_joint_ = false;
}
}
}
}
void World::RemoveAllJoints()
{
if (world_.GetJointCount())
{
removing_joint_ = true;
{
b2Joint* joint = world_.GetJointList();
while (joint)
{
b2Joint* next = joint->GetNext();
world_.DestroyJoint(joint);
joint = next;
}
}
removing_joint_ = false;
}
joints_.clear();
}
void World::JointRemoved(b2Joint* joint)
{
if (!removing_joint_ && joint)
{
auto iter = std::find_if(joints_.begin(), joints_.end(),
[joint](Joint* j) -> bool { return j->GetB2Joint() == joint; });
if (iter != joints_.end())
{
joints_.erase(iter);
}
}
}
b2World* World::GetB2World()
{
return &world_;
}
const b2World* World::GetB2World() const
{
return &world_;
}
Vec2 World::GetGravity() const
{
b2Vec2 g = world_.GetGravity();
return Vec2(g.x, g.y);
}
void World::SetGravity(Vec2 gravity)
{
world_.SetGravity(b2Vec2(gravity.x, gravity.y));
}
ContactList World::GetContactList()
{
return ContactList(Contact(world_.GetContactList()));
}
void World::Update(Duration dt)
{
world_.Step(dt.Seconds(), vel_iter_, pos_iter_);
b2Body* b2body = world_.GetBodyList();
while (b2body)
{
Body* body = static_cast<Body*>(b2body->GetUserData());
if (body && body->GetType() != Body::Type::Static)
{
body->UpdateActor();
}
b2body = b2body->GetNext();
}
Stage::Update(dt);
}
} // namespace physics
} // namespace kiwano

View File

@ -1,15 +1,15 @@
// Copyright (c) 2018-2019 Kiwano - Nomango // Copyright (c) 2018-2019 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -24,176 +24,174 @@
namespace kiwano namespace kiwano
{ {
namespace physics namespace physics
{ {
KGE_DECLARE_SMART_PTR(World); KGE_DECLARE_SMART_PTR(World);
/** /**
* \~chinese * \~chinese
* \defgroup Physics * \defgroup Physics
*/ */
/** /**
* \addtogroup Physics * \addtogroup Physics
* @{ * @{
*/ */
/** /**
* \~chinese * \~chinese
* @brief * @brief
*/ */
class KGE_API World class KGE_API World : public Stage
: public Stage {
{ friend class Body;
friend class Body; friend class Joint;
friend class Joint;
public: public:
World(); World();
virtual ~World(); virtual ~World();
/// \~chinese /// \~chinese
/// @brief 获取重力 [N] /// @brief 获取重力 [N]
Vec2 GetGravity() const; Vec2 GetGravity() const;
/// \~chinese /// \~chinese
/// @brief 设置重力 [N] /// @brief 设置重力 [N]
void SetGravity(Vec2 gravity); void SetGravity(Vec2 gravity);
/// \~chinese /// \~chinese
/// @brief 获取物理接触列表 /// @brief 获取物理接触列表
ContactList GetContactList(); ContactList GetContactList();
/// \~chinese /// \~chinese
/// @brief 获取全局缩放比例 /// @brief 获取全局缩放比例
/// @details 缩放比例是指由物理世界的单位米转换到屏幕像素的比例默认比例为1:100 /// @details 缩放比例是指由物理世界的单位米转换到屏幕像素的比例默认比例为1:100
float GetGlobalScale() const; float GetGlobalScale() const;
/// \~chinese /// \~chinese
/// @brief 设置全局缩放比例 /// @brief 设置全局缩放比例
/// @details 缩放比例是指由物理世界的单位米转换到屏幕像素的比例默认比例为1:100 /// @details 缩放比例是指由物理世界的单位米转换到屏幕像素的比例默认比例为1:100
void SetGlobalScale(float scale); void SetGlobalScale(float scale);
/// \~chinese /// \~chinese
/// @brief 游戏世界单位转换为物理世界单位 /// @brief 游戏世界单位转换为物理世界单位
/// @details 根据全局缩放比例将物理世界的单位米转换为像素单位 /// @details 根据全局缩放比例将物理世界的单位米转换为像素单位
float World2Stage(float value) const; float World2Stage(float value) const;
/// \~chinese /// \~chinese
/// @brief 游戏世界单位转换为物理世界单位 /// @brief 游戏世界单位转换为物理世界单位
/// @details 根据全局缩放比例将物理世界的单位米转换为像素单位 /// @details 根据全局缩放比例将物理世界的单位米转换为像素单位
Vec2 World2Stage(const b2Vec2& pos) const; Vec2 World2Stage(const b2Vec2& pos) const;
/// \~chinese /// \~chinese
/// @brief 物理世界单位转换为游戏世界单位 /// @brief 物理世界单位转换为游戏世界单位
/// @details 根据全局缩放比例将像素单位转换为物理世界的单位米 /// @details 根据全局缩放比例将像素单位转换为物理世界的单位米
float Stage2World(float value) const; float Stage2World(float value) const;
/// \~chinese /// \~chinese
/// @brief 物理世界单位转换为游戏世界单位 /// @brief 物理世界单位转换为游戏世界单位
/// @details 根据全局缩放比例将像素单位转换为物理世界的单位米 /// @details 根据全局缩放比例将像素单位转换为物理世界的单位米
b2Vec2 Stage2World(const Vec2& pos) const; b2Vec2 Stage2World(const Vec2& pos) const;
/// \~chinese /// \~chinese
/// @brief 设置速度迭代次数, 默认为 6 /// @brief 设置速度迭代次数, 默认为 6
void SetVelocityIterations(int vel_iter); void SetVelocityIterations(int vel_iter);
/// \~chinese /// \~chinese
/// @brief 设置位置迭代次数, 默认为 2 /// @brief 设置位置迭代次数, 默认为 2
void SetPositionIterations(int pos_iter); void SetPositionIterations(int pos_iter);
b2World* GetB2World(); b2World* GetB2World();
const b2World* GetB2World() const; const b2World* GetB2World() const;
private: private:
/// \~chinese /// \~chinese
/// @brief 移除物体 /// @brief 移除物体
void RemoveBody(Body* body); void RemoveBody(Body* body);
/// \~chinese /// \~chinese
/// @brief 移除所有物体 /// @brief 移除所有物体
void RemoveAllBodies(); void RemoveAllBodies();
/// \~chinese /// \~chinese
/// @brief 添加关节 /// @brief 添加关节
void AddJoint(Joint* joint); void AddJoint(Joint* joint);
/// \~chinese /// \~chinese
/// @brief 移除关节 /// @brief 移除关节
void RemoveJoint(Joint* joint); void RemoveJoint(Joint* joint);
/// \~chinese /// \~chinese
/// @brief 移除所有关节 /// @brief 移除所有关节
void RemoveAllJoints(); void RemoveAllJoints();
/// \~chinese /// \~chinese
/// @brief 关节被移除 /// @brief 关节被移除
void JointRemoved(b2Joint* joint); void JointRemoved(b2Joint* joint);
protected: protected:
void Update(Duration dt) override; void Update(Duration dt) override;
private: private:
b2World world_; b2World world_;
int vel_iter_; int vel_iter_;
int pos_iter_; int pos_iter_;
float global_scale_; float global_scale_;
class DestructionListener; class DestructionListener;
friend DestructionListener; friend DestructionListener;
DestructionListener* destruction_listener_; DestructionListener* destruction_listener_;
class ContactListener; class ContactListener;
friend ContactListener; friend ContactListener;
ContactListener* contact_listener_; ContactListener* contact_listener_;
bool removing_joint_; bool removing_joint_;
Vector<Joint*> joints_; Vector<Joint*> joints_;
}; };
/** @} */
/** @} */ inline float World::GetGlobalScale() const
{
inline float World::GetGlobalScale() const return global_scale_;
{
return global_scale_;
}
inline void World::SetGlobalScale(float scale)
{
global_scale_ = scale;
}
inline float World::World2Stage(float value) const
{
return value * GetGlobalScale();
}
inline Vec2 World::World2Stage(const b2Vec2& pos) const
{
return Point(World2Stage(pos.x), World2Stage(pos.y));
}
inline float World::Stage2World(float value) const
{
return value / GetGlobalScale();
}
inline b2Vec2 World::Stage2World(const Vec2& pos) const
{
return b2Vec2(Stage2World(pos.x), Stage2World(pos.y));
}
inline void World::SetVelocityIterations(int vel_iter)
{
vel_iter_ = vel_iter;
}
inline void World::SetPositionIterations(int pos_iter)
{
pos_iter_ = pos_iter;
}
}
} }
inline void World::SetGlobalScale(float scale)
{
global_scale_ = scale;
}
inline float World::World2Stage(float value) const
{
return value * GetGlobalScale();
}
inline Vec2 World::World2Stage(const b2Vec2& pos) const
{
return Point(World2Stage(pos.x), World2Stage(pos.y));
}
inline float World::Stage2World(float value) const
{
return value / GetGlobalScale();
}
inline b2Vec2 World::Stage2World(const Vec2& pos) const
{
return b2Vec2(Stage2World(pos.x), Stage2World(pos.y));
}
inline void World::SetVelocityIterations(int vel_iter)
{
vel_iter_ = vel_iter;
}
inline void World::SetPositionIterations(int pos_iter)
{
pos_iter_ = pos_iter;
}
} // namespace physics
} // namespace kiwano

View File

@ -1,15 +1,15 @@
// Copyright (c) 2018-2019 Kiwano - Nomango // Copyright (c) 2018-2019 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -26,9 +26,15 @@
namespace kiwano namespace kiwano
{ {
namespace physics namespace physics
{ {
inline b2Vec2 Stage2World(const Vec2& pos) { return b2Vec2(pos.x, pos.y); } inline b2Vec2 Stage2World(const Vec2& pos)
inline Vec2 World2Stage(const b2Vec2& pos) { return Vec2(pos.x, pos.y); } {
} return b2Vec2(pos.x, pos.y);
} }
inline Vec2 World2Stage(const b2Vec2& pos)
{
return Vec2(pos.x, pos.y);
}
} // namespace physics
} // namespace kiwano

View File

@ -1,15 +1,15 @@
// Copyright (c) 2018-2019 Kiwano - Nomango // Copyright (c) 2018-2019 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -20,10 +20,10 @@
#pragma once #pragma once
#include <kiwano-physics/Shape.h> #include <kiwano-physics/Body.h>
#include <kiwano-physics/Fixture.h>
#include <kiwano-physics/Contact.h> #include <kiwano-physics/Contact.h>
#include <kiwano-physics/ContactEvent.h> #include <kiwano-physics/ContactEvent.h>
#include <kiwano-physics/Body.h> #include <kiwano-physics/Fixture.h>
#include <kiwano-physics/Joint.h> #include <kiwano-physics/Joint.h>
#include <kiwano-physics/Shape.h>
#include <kiwano-physics/World.h> #include <kiwano-physics/World.h>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

207
src/kiwano/2d/Button.cpp Normal file
View File

@ -0,0 +1,207 @@
// Copyright (c) 2016-2018 Kiwano - Nomango
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// 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 AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include <kiwano/2d/Button.h>
#include <kiwano/2d/Stage.h>
#include <kiwano/platform/Window.h>
namespace kiwano
{
Button::Button()
: enabled_(true)
, status_(Status::Normal)
{
}
Button::Button(const Callback& click)
: Button()
{
this->SetClickCallback(click);
}
Button::Button(Callback const& click, Callback const& pressed, Callback const& mouse_over, Callback const& mouse_out)
: Button()
{
this->SetClickCallback(click);
this->SetPressedCallback(pressed);
this->SetMouseOverCallback(mouse_over);
this->SetMouseOutCallback(mouse_out);
}
Button::~Button() {}
bool Button::IsEnable() const
{
return enabled_;
}
void Button::SetEnabled(bool enabled)
{
if (enabled_ != enabled)
{
enabled_ = enabled;
}
}
void Button::SetClickCallback(const Callback& func)
{
click_callback_ = func;
}
void Button::SetPressedCallback(const Callback& func)
{
pressed_callback_ = func;
}
void Button::SetReleasedCallback(const Callback& func)
{
released_callback_ = func;
}
void Button::SetMouseOverCallback(const Callback& func)
{
mouse_over_callback_ = func;
}
void Button::SetMouseOutCallback(const Callback& func)
{
mouse_out_callback_ = func;
}
void Button::SetStatus(Status status)
{
if (status_ != status)
{
Status old_status = status_;
if (status == Status::Normal)
{
Window::Instance().SetCursor(CursorType::Arrow);
if (mouse_out_callback_)
mouse_out_callback_(this);
}
else if (status == Status::Hover)
{
Window::Instance().SetCursor(CursorType::Hand);
if (old_status == Status::Pressed)
{
if (released_callback_)
released_callback_(this);
}
else
{
if (mouse_over_callback_)
mouse_over_callback_(this);
}
}
else if (status == Status::Pressed)
{
if (pressed_callback_)
pressed_callback_(this);
}
status_ = status;
}
}
Button::Status Button::GetStatus() const
{
return status_;
}
void Button::UpdateStatus(Event* evt)
{
if (!enabled_)
return;
if (evt->IsType<MouseHoverEvent>())
{
SetStatus(Status::Hover);
}
else if (evt->IsType<MouseOutEvent>())
{
SetStatus(Status::Normal);
}
else if (evt->IsType<MouseDownEvent>() && status_ == Status::Hover)
{
SetStatus(Status::Pressed);
}
else if (evt->IsType<MouseUpEvent>() && status_ == Status::Pressed)
{
SetStatus(Status::Hover);
}
else if (evt->IsType<MouseClickEvent>())
{
if (click_callback_)
click_callback_(this);
}
}
SpriteButton::SpriteButton()
: SpriteButton(nullptr, nullptr, nullptr, nullptr)
{
}
SpriteButton::SpriteButton(Callback const& click)
: SpriteButton(click, nullptr, nullptr, nullptr)
{
}
SpriteButton::SpriteButton(Callback const& click, Callback const& pressed, Callback const& mouse_over,
Callback const& mouse_out)
: Button(click, pressed, mouse_over, mouse_out)
{
SetResponsible(true);
EventListener::Callback handler = Closure(this, &SpriteButton::UpdateStatus);
AddListener<MouseHoverEvent>(handler);
AddListener<MouseOutEvent>(handler);
AddListener<MouseDownEvent>(handler);
AddListener<MouseUpEvent>(handler);
AddListener<MouseClickEvent>(handler);
}
TextButton::TextButton()
: TextButton(nullptr, nullptr, nullptr, nullptr)
{
}
TextButton::TextButton(Callback const& click)
: TextButton(click, nullptr, nullptr, nullptr)
{
}
TextButton::TextButton(Callback const& click, Callback const& pressed, Callback const& mouse_over,
Callback const& mouse_out)
: Button(click, pressed, mouse_over, mouse_out)
{
SetResponsible(true);
EventListener::Callback handler = Closure(this, &TextButton::UpdateStatus);
AddListener<MouseHoverEvent>(handler);
AddListener<MouseOutEvent>(handler);
AddListener<MouseDownEvent>(handler);
AddListener<MouseUpEvent>(handler);
AddListener<MouseClickEvent>(handler);
}
} // namespace kiwano

164
src/kiwano/2d/Button.h Normal file
View File

@ -0,0 +1,164 @@
// Copyright (c) 2016-2018 Kiwano - Nomango
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// 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 AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF 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
#include <kiwano/2d/Sprite.h>
#include <kiwano/2d/TextActor.h>
namespace kiwano
{
KGE_DECLARE_SMART_PTR(Button);
KGE_DECLARE_SMART_PTR(SpriteButton);
KGE_DECLARE_SMART_PTR(TextButton);
/**
* \~chinese
* @brief
*/
class KGE_API Button : public virtual ObjectBase
{
public:
/// \~chinese
/// @brief 按钮回调函数
using Callback = Function<void(Button* /* self */)>;
Button();
/// \~chinese
/// @brief 构造按钮
/// @param click 按钮点击回调函数
explicit Button(Callback const& click);
/// \~chinese
/// @brief 构造按钮
/// @param click 按钮点击回调函数
/// @param pressed 按钮按下回调函数
/// @param mouse_over 按钮移入回调函数
/// @param mouse_out 按钮移出回调函数
Button(Callback const& click, Callback const& pressed, Callback const& mouse_over, Callback const& mouse_out);
virtual ~Button();
/// \~chinese
/// @brief 获取按钮状态是启用还是禁用
bool IsEnable() const;
/// \~chinese
/// @brief 设置按钮启用或禁用
void SetEnabled(bool enabled);
/// \~chinese
/// @brief 设置按钮点击后的回调函数
void SetClickCallback(const Callback& func);
/// \~chinese
/// @brief 设置按钮被按下时的回调函数
void SetPressedCallback(const Callback& func);
/// \~chinese
/// @brief 设置按钮被抬起时的回调函数
void SetReleasedCallback(const Callback& func);
/// \~chinese
/// @brief 设置鼠标移入按钮时的回调函数
void SetMouseOverCallback(const Callback& func);
/// \~chinese
/// @brief 设置鼠标移出按钮时的回调函数
void SetMouseOutCallback(const Callback& func);
/// \~chinese
/// @brief 按钮状态
enum class Status
{
Normal, ///< 普通
Hover, ///< 鼠标在按钮内
Pressed ///< 被按下
};
/// \~chinese
/// @brief 设置按钮状态
void SetStatus(Status status);
/// \~chinese
/// @brief 获取按钮状态
Status GetStatus() const;
protected:
/// \~chinese
/// @brief 更新按钮状态
void UpdateStatus(Event* evt);
private:
bool enabled_;
Status status_;
Callback click_callback_;
Callback pressed_callback_;
Callback released_callback_;
Callback mouse_over_callback_;
Callback mouse_out_callback_;
};
/// \~chinese
/// @brief 精灵按钮
class SpriteButton
: public Sprite
, public Button
{
public:
SpriteButton();
/// \~chinese
/// @brief 构造精灵按钮
/// @param click 按钮点击回调函数
explicit SpriteButton(Callback const& click);
/// \~chinese
/// @brief 构造精灵按钮
/// @param click 按钮点击回调函数
/// @param pressed 按钮按下回调函数
/// @param mouse_over 按钮移入回调函数
/// @param mouse_out 按钮移出回调函数
SpriteButton(Callback const& click, Callback const& pressed, Callback const& mouse_over, Callback const& mouse_out);
};
/// \~chinese
/// @brief 文字按钮
class TextButton
: public TextActor
, public Button
{
public:
TextButton();
/// \~chinese
/// @brief 构造文字按钮
/// @param click 按钮点击回调函数
explicit TextButton(Callback const& click);
/// \~chinese
/// @brief 构造文字按钮
/// @param click 按钮点击回调函数
/// @param pressed 按钮按下回调函数
/// @param mouse_over 按钮移入回调函数
/// @param mouse_out 按钮移出回调函数
TextButton(Callback const& click, Callback const& pressed, Callback const& mouse_over, Callback const& mouse_out);
};
} // namespace kiwano

View File

@ -1,15 +1,15 @@
// Copyright (c) 2016-2018 Kiwano - Nomango // Copyright (c) 2016-2018 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -20,334 +20,291 @@
#include <kiwano/2d/Canvas.h> #include <kiwano/2d/Canvas.h>
#include <kiwano/core/Logger.h> #include <kiwano/core/Logger.h>
#include <kiwano/renderer/Renderer.h> #include <kiwano/render/Renderer.h>
namespace kiwano namespace kiwano
{ {
Canvas::Canvas() Canvas::Canvas()
: cache_expired_(false) : cache_expired_(false)
, stroke_width_(1.0f) , stroke_width_(1.0f)
, stroke_style_(StrokeStyle::Miter) , stroke_style_()
{ {
}
Canvas::~Canvas()
{
}
void Canvas::BeginDraw()
{
InitRenderTargetAndBrushs();
rt_->BeginDraw();
}
void Canvas::EndDraw()
{
InitRenderTargetAndBrushs();
rt_->EndDraw();
cache_expired_ = true;
}
void Canvas::OnRender(RenderTarget* rt)
{
UpdateCache();
if (texture_cached_ && texture_cached_->IsValid())
{
PrepareToRender(rt);
Rect bitmap_rect(0.f, 0.f, texture_cached_->GetWidth(), texture_cached_->GetHeight());
rt->DrawTexture(*texture_cached_, bitmap_rect, bitmap_rect);
}
}
void Canvas::SetBrush(BrushPtr brush)
{
InitRenderTargetAndBrushs();
rt_->SetCurrentBrush(brush);
}
float Canvas::GetStrokeWidth() const
{
return stroke_width_;
}
void Canvas::SetBrushTransform(Transform const& transform)
{
InitRenderTargetAndBrushs();
rt_->SetTransform(transform.ToMatrix());
}
void Canvas::SetBrushTransform(Matrix3x2 const & transform)
{
InitRenderTargetAndBrushs();
rt_->SetTransform(transform);
}
void Canvas::PushLayerArea(LayerArea& area)
{
InitRenderTargetAndBrushs();
rt_->PushLayer(area);
}
void Canvas::PopLayerArea()
{
InitRenderTargetAndBrushs();
rt_->PopLayer();
}
void Canvas::PushClipRect(Rect const& clip_rect)
{
InitRenderTargetAndBrushs();
rt_->PushClipRect(clip_rect);
}
void Canvas::PopClipRect()
{
InitRenderTargetAndBrushs();
rt_->PopClipRect();
}
void Canvas::DrawLine(Point const& begin, Point const& end)
{
InitRenderTargetAndBrushs();
rt_->SetCurrentBrush(stroke_brush_);
rt_->DrawLine(
begin,
end,
stroke_width_,
stroke_style_
);
cache_expired_ = true;
}
void Canvas::DrawCircle(Point const& center, float radius)
{
InitRenderTargetAndBrushs();
rt_->SetCurrentBrush(stroke_brush_);
rt_->DrawEllipse(
center,
Vec2(radius, radius),
stroke_width_,
stroke_style_
);
cache_expired_ = true;
}
void Canvas::DrawEllipse(Point const& center, Vec2 const& radius)
{
InitRenderTargetAndBrushs();
rt_->SetCurrentBrush(stroke_brush_);
rt_->DrawEllipse(
center,
radius,
stroke_width_,
stroke_style_
);
cache_expired_ = true;
}
void Canvas::DrawRect(Rect const& rect)
{
InitRenderTargetAndBrushs();
rt_->SetCurrentBrush(stroke_brush_);
rt_->DrawRectangle(
rect,
stroke_width_,
stroke_style_
);
cache_expired_ = true;
}
void Canvas::DrawRoundedRect(Rect const& rect, Vec2 const& radius)
{
InitRenderTargetAndBrushs();
rt_->SetCurrentBrush(stroke_brush_);
rt_->DrawRoundedRectangle(
rect,
radius,
stroke_width_,
stroke_style_
);
cache_expired_ = true;
}
void Canvas::FillCircle(Point const& center, float radius)
{
InitRenderTargetAndBrushs();
rt_->SetCurrentBrush(fill_brush_);
rt_->FillEllipse(
center,
Vec2(radius, radius)
);
cache_expired_ = true;
}
void Canvas::FillEllipse(Point const& center, Vec2 const& radius)
{
InitRenderTargetAndBrushs();
rt_->SetCurrentBrush(fill_brush_);
rt_->FillEllipse(
center,
radius
);
cache_expired_ = true;
}
void Canvas::FillRect(Rect const& rect)
{
InitRenderTargetAndBrushs();
rt_->SetCurrentBrush(fill_brush_);
rt_->FillRectangle(
rect
);
cache_expired_ = true;
}
void Canvas::FillRoundedRect(Rect const& rect, Vec2 const& radius)
{
InitRenderTargetAndBrushs();
rt_->SetCurrentBrush(fill_brush_);
rt_->FillRoundedRectangle(
rect,
radius
);
cache_expired_ = true;
}
void Canvas::DrawTexture(TexturePtr texture, const Rect* src_rect, const Rect* dest_rect)
{
if (texture)
{
InitRenderTargetAndBrushs();
rt_->DrawTexture(*texture, src_rect, dest_rect);
cache_expired_ = true;
}
}
void Canvas::DrawTextLayout(String const& text, Point const& point)
{
if (text.empty())
return;
TextLayout layout;
layout.SetStyle(text_style_);
layout.SetText(text);
DrawTextLayout(layout, point);
}
void Canvas::DrawTextLayout(TextLayout const& layout, Point const& point)
{
InitRenderTargetAndBrushs();
rt_->DrawTextLayout(layout, point);
}
void Canvas::BeginPath(Point const& begin_pos)
{
geo_sink_.BeginPath(begin_pos);
}
void Canvas::EndPath(bool closed)
{
geo_sink_.EndPath(closed);
}
void Canvas::AddLine(Point const & point)
{
geo_sink_.AddLine(point);
}
void Canvas::AddLines(Vector<Point> const& points)
{
geo_sink_.AddLines(points);
}
void Canvas::AddBezier(Point const & point1, Point const & point2, Point const & point3)
{
geo_sink_.AddBezier(point1, point2, point3);
}
void Canvas::AddArc(Point const & point, Size const & radius, float rotation, bool clockwise, bool is_small)
{
geo_sink_.AddArc(point, radius, rotation, clockwise, is_small);
}
void Canvas::StrokePath()
{
InitRenderTargetAndBrushs();
rt_->SetCurrentBrush(stroke_brush_);
rt_->DrawGeometry(
geo_sink_.GetGeometry(),
stroke_width_,
stroke_style_
);
cache_expired_ = true;
}
void Canvas::FillPath()
{
InitRenderTargetAndBrushs();
rt_->SetCurrentBrush(fill_brush_);
rt_->FillGeometry(
geo_sink_.GetGeometry()
);
cache_expired_ = true;
}
void Canvas::Clear()
{
InitRenderTargetAndBrushs();
rt_->Clear();
cache_expired_ = true;
}
void Canvas::Clear(Color const& clear_color)
{
InitRenderTargetAndBrushs();
rt_->Clear(clear_color);
cache_expired_ = true;
}
TexturePtr Canvas::ExportToTexture() const
{
UpdateCache();
return texture_cached_;
}
void Canvas::InitRenderTargetAndBrushs()
{
if (!rt_)
{
Renderer::instance().CreateTextureRenderTarget(rt_);
}
if (!stroke_brush_)
{
stroke_brush_ = new Brush;
stroke_brush_->SetColor(Color::White);
}
if (!fill_brush_)
{
fill_brush_ = new Brush;
fill_brush_->SetColor(Color::White);
}
}
void Canvas::UpdateCache() const
{
if (cache_expired_ && rt_)
{
if (!texture_cached_)
{
texture_cached_ = new Texture;
}
if (rt_->GetOutput(*texture_cached_))
{
cache_expired_ = false;
}
}
}
} }
Canvas::~Canvas() {}
void Canvas::BeginDraw()
{
InitRenderTargetAndBrushs();
ctx_->BeginDraw();
}
void Canvas::EndDraw()
{
InitRenderTargetAndBrushs();
ctx_->EndDraw();
cache_expired_ = true;
}
void Canvas::OnRender(RenderContext& ctx)
{
UpdateCache();
if (texture_cached_ && texture_cached_->IsValid())
{
PrepareToRender(ctx);
Rect bitmap_rect(0.f, 0.f, texture_cached_->GetWidth(), texture_cached_->GetHeight());
ctx.DrawTexture(*texture_cached_, bitmap_rect, bitmap_rect);
}
}
void Canvas::SetBrush(BrushPtr brush)
{
InitRenderTargetAndBrushs();
ctx_->SetCurrentBrush(brush);
}
float Canvas::GetStrokeWidth() const
{
return stroke_width_;
}
void Canvas::SetBrushTransform(Transform const& transform)
{
InitRenderTargetAndBrushs();
ctx_->SetTransform(transform.ToMatrix());
}
void Canvas::SetBrushTransform(Matrix3x2 const& transform)
{
InitRenderTargetAndBrushs();
ctx_->SetTransform(transform);
}
void Canvas::PushLayerArea(LayerArea& area)
{
InitRenderTargetAndBrushs();
ctx_->PushLayer(area);
}
void Canvas::PopLayerArea()
{
InitRenderTargetAndBrushs();
ctx_->PopLayer();
}
void Canvas::PushClipRect(Rect const& clip_rect)
{
InitRenderTargetAndBrushs();
ctx_->PushClipRect(clip_rect);
}
void Canvas::PopClipRect()
{
InitRenderTargetAndBrushs();
ctx_->PopClipRect();
}
void Canvas::DrawLine(Point const& begin, Point const& end)
{
InitRenderTargetAndBrushs();
ctx_->SetCurrentBrush(stroke_brush_);
ctx_->DrawLine(begin, end, stroke_width_, stroke_style_);
cache_expired_ = true;
}
void Canvas::DrawCircle(Point const& center, float radius)
{
InitRenderTargetAndBrushs();
ctx_->SetCurrentBrush(stroke_brush_);
ctx_->DrawEllipse(center, Vec2(radius, radius), stroke_width_, stroke_style_);
cache_expired_ = true;
}
void Canvas::DrawEllipse(Point const& center, Vec2 const& radius)
{
InitRenderTargetAndBrushs();
ctx_->SetCurrentBrush(stroke_brush_);
ctx_->DrawEllipse(center, radius, stroke_width_, stroke_style_);
cache_expired_ = true;
}
void Canvas::DrawRect(Rect const& rect)
{
InitRenderTargetAndBrushs();
ctx_->SetCurrentBrush(stroke_brush_);
ctx_->DrawRectangle(rect, stroke_width_, stroke_style_);
cache_expired_ = true;
}
void Canvas::DrawRoundedRect(Rect const& rect, Vec2 const& radius)
{
InitRenderTargetAndBrushs();
ctx_->SetCurrentBrush(stroke_brush_);
ctx_->DrawRoundedRectangle(rect, radius, stroke_width_, stroke_style_);
cache_expired_ = true;
}
void Canvas::FillCircle(Point const& center, float radius)
{
InitRenderTargetAndBrushs();
ctx_->SetCurrentBrush(fill_brush_);
ctx_->FillEllipse(center, Vec2(radius, radius));
cache_expired_ = true;
}
void Canvas::FillEllipse(Point const& center, Vec2 const& radius)
{
InitRenderTargetAndBrushs();
ctx_->SetCurrentBrush(fill_brush_);
ctx_->FillEllipse(center, radius);
cache_expired_ = true;
}
void Canvas::FillRect(Rect const& rect)
{
InitRenderTargetAndBrushs();
ctx_->SetCurrentBrush(fill_brush_);
ctx_->FillRectangle(rect);
cache_expired_ = true;
}
void Canvas::FillRoundedRect(Rect const& rect, Vec2 const& radius)
{
InitRenderTargetAndBrushs();
ctx_->SetCurrentBrush(fill_brush_);
ctx_->FillRoundedRectangle(rect, radius);
cache_expired_ = true;
}
void Canvas::DrawTexture(TexturePtr texture, const Rect* src_rect, const Rect* dest_rect)
{
if (texture)
{
InitRenderTargetAndBrushs();
ctx_->DrawTexture(*texture, src_rect, dest_rect);
cache_expired_ = true;
}
}
void Canvas::DrawTextLayout(String const& text, Point const& point)
{
if (text.empty())
return;
TextLayout layout;
layout.SetStyle(text_style_);
layout.SetText(text);
DrawTextLayout(layout, point);
}
void Canvas::DrawTextLayout(TextLayout const& layout, Point const& point)
{
InitRenderTargetAndBrushs();
ctx_->DrawTextLayout(layout, point);
}
void Canvas::BeginPath(Point const& begin_pos)
{
geo_sink_.BeginPath(begin_pos);
}
void Canvas::EndPath(bool closed)
{
geo_sink_.EndPath(closed);
}
void Canvas::AddLine(Point const& point)
{
geo_sink_.AddLine(point);
}
void Canvas::AddLines(Vector<Point> const& points)
{
geo_sink_.AddLines(points);
}
void Canvas::AddBezier(Point const& point1, Point const& point2, Point const& point3)
{
geo_sink_.AddBezier(point1, point2, point3);
}
void Canvas::AddArc(Point const& point, Size const& radius, float rotation, bool clockwise, bool is_small)
{
geo_sink_.AddArc(point, radius, rotation, clockwise, is_small);
}
void Canvas::StrokePath()
{
InitRenderTargetAndBrushs();
ctx_->SetCurrentBrush(stroke_brush_);
ctx_->DrawGeometry(geo_sink_.GetGeometry(), stroke_width_, stroke_style_);
cache_expired_ = true;
}
void Canvas::FillPath()
{
InitRenderTargetAndBrushs();
ctx_->SetCurrentBrush(fill_brush_);
ctx_->FillGeometry(geo_sink_.GetGeometry());
cache_expired_ = true;
}
void Canvas::Clear()
{
InitRenderTargetAndBrushs();
ctx_->Clear();
cache_expired_ = true;
}
void Canvas::Clear(Color const& clear_color)
{
InitRenderTargetAndBrushs();
ctx_->Clear(clear_color);
cache_expired_ = true;
}
TexturePtr Canvas::ExportToTexture() const
{
UpdateCache();
return texture_cached_;
}
void Canvas::InitRenderTargetAndBrushs()
{
if (!ctx_)
{
Renderer::Instance().CreateTextureRenderTarget(ctx_);
}
if (!stroke_brush_)
{
stroke_brush_ = new Brush;
stroke_brush_->SetColor(Color::White);
}
if (!fill_brush_)
{
fill_brush_ = new Brush;
fill_brush_->SetColor(Color::White);
}
}
void Canvas::UpdateCache() const
{
if (cache_expired_ && ctx_)
{
if (!texture_cached_)
{
texture_cached_ = new Texture;
}
if (ctx_->GetOutput(*texture_cached_))
{
cache_expired_ = false;
}
}
}
} // namespace kiwano

View File

@ -1,15 +1,15 @@
// Copyright (c) 2016-2018 Kiwano - Nomango // Copyright (c) 2016-2018 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -20,315 +20,313 @@
#pragma once #pragma once
#include <kiwano/2d/Actor.h> #include <kiwano/2d/Actor.h>
#include <kiwano/renderer/RenderTarget.h> #include <kiwano/render/GeometrySink.h>
#include <kiwano/renderer/GeometrySink.h> #include <kiwano/render/RenderContext.h>
namespace kiwano namespace kiwano
{ {
KGE_DECLARE_SMART_PTR(Canvas); KGE_DECLARE_SMART_PTR(Canvas);
/** /**
* \addtogroup Actors * \addtogroup Actors
* @{ * @{
*/ */
/** /**
* \~chinese * \~chinese
* @brief * @brief
*/ */
class KGE_API Canvas class KGE_API Canvas : public Actor
: public Actor {
{ public:
public: /// \~chinese
/// \~chinese /// @brief 构建空画布
/// @brief 构建空画布 Canvas();
Canvas();
virtual ~Canvas(); virtual ~Canvas();
/// \~chinese /// \~chinese
/// @brief 开始绘图 /// @brief 开始绘图
void BeginDraw(); void BeginDraw();
/// \~chinese /// \~chinese
/// @brief 结束绘图 /// @brief 结束绘图
void EndDraw(); void EndDraw();
/// \~chinese /// \~chinese
/// @brief 画线段 /// @brief 画线段
/// @param begin 线段起点 /// @param begin 线段起点
/// @param end 线段终点 /// @param end 线段终点
void DrawLine(Point const& begin, Point const& end); void DrawLine(Point const& begin, Point const& end);
/// \~chinese /// \~chinese
/// @brief 画圆形边框 /// @brief 画圆形边框
/// @param center 圆形原点 /// @param center 圆形原点
/// @param radius 圆形半径 /// @param radius 圆形半径
void DrawCircle(Point const& center, float radius); void DrawCircle(Point const& center, float radius);
/// \~chinese /// \~chinese
/// @brief 画椭圆形边框 /// @brief 画椭圆形边框
/// @param center 椭圆原点 /// @param center 椭圆原点
/// @param radius 椭圆半径 /// @param radius 椭圆半径
void DrawEllipse(Point const& center, Vec2 const& radius); void DrawEllipse(Point const& center, Vec2 const& radius);
/// \~chinese /// \~chinese
/// @brief 画矩形边框 /// @brief 画矩形边框
/// @param rect 矩形 /// @param rect 矩形
void DrawRect(Rect const& rect); void DrawRect(Rect const& rect);
/// \~chinese /// \~chinese
/// @brief 画圆角矩形边框 /// @brief 画圆角矩形边框
/// @param rect 矩形 /// @param rect 矩形
/// @param radius 矩形圆角半径 /// @param radius 矩形圆角半径
void DrawRoundedRect(Rect const& rect, Vec2 const& radius); void DrawRoundedRect(Rect const& rect, Vec2 const& radius);
/// \~chinese /// \~chinese
/// @brief 填充圆形 /// @brief 填充圆形
/// @param center 圆形原点 /// @param center 圆形原点
/// @param radius 圆形半径 /// @param radius 圆形半径
void FillCircle(Point const& center, float radius); void FillCircle(Point const& center, float radius);
/// \~chinese /// \~chinese
/// @brief 填充椭圆形 /// @brief 填充椭圆形
/// @param center 椭圆原点 /// @param center 椭圆原点
/// @param radius 椭圆半径 /// @param radius 椭圆半径
void FillEllipse(Point const& center, Vec2 const& radius); void FillEllipse(Point const& center, Vec2 const& radius);
/// \~chinese /// \~chinese
/// @brief 填充矩形 /// @brief 填充矩形
/// @param rect 矩形 /// @param rect 矩形
void FillRect(Rect const& rect); void FillRect(Rect const& rect);
/// \~chinese /// \~chinese
/// @brief 填充圆角矩形 /// @brief 填充圆角矩形
/// @param rect 矩形 /// @param rect 矩形
/// @param radius 矩形圆角半径 /// @param radius 矩形圆角半径
void FillRoundedRect(Rect const& rect, Vec2 const& radius); void FillRoundedRect(Rect const& rect, Vec2 const& radius);
/// \~chinese /// \~chinese
/// @brief 绘制纹理 /// @brief 绘制纹理
/// @param texture 纹理 /// @param texture 纹理
/// @param src_rect 纹理裁剪区域 /// @param src_rect 纹理裁剪区域
/// @param dest_rect 绘制目标区域 /// @param dest_rect 绘制目标区域
void DrawTexture(TexturePtr texture, const Rect* src_rect = nullptr, const Rect* dest_rect = nullptr); void DrawTexture(TexturePtr texture, const Rect* src_rect = nullptr, const Rect* dest_rect = nullptr);
/// \~chinese /// \~chinese
/// @brief 绘制文字布局 /// @brief 绘制文字布局
/// @param text 文字 /// @param text 文字
/// @param point 绘制文字的位置 /// @param point 绘制文字的位置
void DrawTextLayout(String const& text, Point const& point); void DrawTextLayout(String const& text, Point const& point);
/// \~chinese /// \~chinese
/// @brief 绘制文字布局 /// @brief 绘制文字布局
/// @param layout 文字布局 /// @param layout 文字布局
/// @param point 绘制布局的位置 /// @param point 绘制布局的位置
void DrawTextLayout(TextLayout const& layout, Point const& point); void DrawTextLayout(TextLayout const& layout, Point const& point);
/// \~chinese /// \~chinese
/// @brief 开始绘制路径 /// @brief 开始绘制路径
/// @param begin_pos 路径起始点 /// @param begin_pos 路径起始点
void BeginPath(Point const& begin_pos); void BeginPath(Point const& begin_pos);
/// \~chinese /// \~chinese
/// @brief 结束路径 /// @brief 结束路径
/// @param closed 路径是否闭合 /// @param closed 路径是否闭合
void EndPath(bool closed = false); void EndPath(bool closed = false);
/// \~chinese /// \~chinese
/// @brief 添加一条线段 /// @brief 添加一条线段
/// @param point 端点 /// @param point 端点
void AddLine(Point const& point); void AddLine(Point const& point);
/// \~chinese /// \~chinese
/// @brief 添加多条线段 /// @brief 添加多条线段
/// @param points 端点集合 /// @param points 端点集合
void AddLines(Vector<Point> const& points); void AddLines(Vector<Point> const& points);
/// \~chinese /// \~chinese
/// @brief 添加一条三次方贝塞尔曲线 /// @brief 添加一条三次方贝塞尔曲线
/// @param point1 贝塞尔曲线的第一个控制点 /// @param point1 贝塞尔曲线的第一个控制点
/// @param point2 贝塞尔曲线的第二个控制点 /// @param point2 贝塞尔曲线的第二个控制点
/// @param point3 贝塞尔曲线的终点 /// @param point3 贝塞尔曲线的终点
void AddBezier(Point const& point1, Point const& point2, Point const& point3); void AddBezier(Point const& point1, Point const& point2, Point const& point3);
/// \~chinese /// \~chinese
/// @brief 添加弧线 /// @brief 添加弧线
/// @param point 终点 /// @param point 终点
/// @param radius 椭圆半径 /// @param radius 椭圆半径
/// @param rotation 椭圆旋转角度 /// @param rotation 椭圆旋转角度
/// @param clockwise 顺时针 or 逆时针 /// @param clockwise 顺时针 or 逆时针
/// @param is_small 是否取小于 180° 的弧 /// @param is_small 是否取小于 180° 的弧
void AddArc(Point const& point, Size const& radius, float rotation, bool clockwise = true, bool is_small = true); void AddArc(Point const& point, Size const& radius, float rotation, bool clockwise = true, bool is_small = true);
/// \~chinese /// \~chinese
/// @brief 以描边的方式绘制路径 /// @brief 以描边的方式绘制路径
void StrokePath(); void StrokePath();
/// \~chinese /// \~chinese
/// @brief 以填充的方式绘制路径 /// @brief 以填充的方式绘制路径
void FillPath(); void FillPath();
/// \~chinese /// \~chinese
/// @brief 清空画布 /// @brief 清空画布
void Clear(); void Clear();
/// \~chinese /// \~chinese
/// @brief 清空画布 /// @brief 清空画布
/// @param clear_color 清空颜色 /// @param clear_color 清空颜色
void Clear(Color const& clear_color); void Clear(Color const& clear_color);
/// \~chinese /// \~chinese
/// @brief 设置填充颜色 /// @brief 设置填充颜色
/// @param color 填充颜色 /// @param color 填充颜色
void SetFillColor(Color const& color); void SetFillColor(Color const& color);
/// \~chinese /// \~chinese
/// @brief 设置填充画刷 /// @brief 设置填充画刷
/// @param[in] brush 填充画刷 /// @param[in] brush 填充画刷
void SetFillBrush(BrushPtr brush); void SetFillBrush(BrushPtr brush);
/// \~chinese /// \~chinese
/// @brief 设置轮廓颜色 /// @brief 设置轮廓颜色
/// @param color 轮廓颜色 /// @param color 轮廓颜色
void SetStrokeColor(Color const& color); void SetStrokeColor(Color const& color);
/// \~chinese /// \~chinese
/// @brief 设置轮廓画刷 /// @brief 设置轮廓画刷
/// @param[in] brush 轮廓画刷 /// @param[in] brush 轮廓画刷
void SetStrokeBrush(BrushPtr brush); void SetStrokeBrush(BrushPtr brush);
/// \~chinese /// \~chinese
/// @brief 设置轮廓宽度 /// @brief 设置轮廓宽度
/// @param width 轮廓宽度 /// @param width 轮廓宽度
void SetStrokeWidth(float width); void SetStrokeWidth(float width);
/// \~chinese /// \~chinese
/// @brief 设置轮廓样式 /// @brief 设置轮廓样式
/// @param stroke_style 轮廓样式 /// @param stroke_style 轮廓样式
void SetStrokeStyle(StrokeStyle stroke_style); void SetStrokeStyle(const StrokeStyle& stroke_style);
/// \~chinese /// \~chinese
/// @brief 设置文字画刷样式 /// @brief 设置文字画刷样式
/// @param text_style 文字画刷样式 /// @param text_style 文字画刷样式
void SetTextStyle(TextStyle const& text_style); void SetTextStyle(TextStyle const& text_style);
/// \~chinese /// \~chinese
/// @brief 设置画刷 /// @brief 设置画刷
/// @param[in] brush 画刷 /// @param[in] brush 画刷
void SetBrush(BrushPtr brush); void SetBrush(BrushPtr brush);
/// \~chinese /// \~chinese
/// @brief 设置画刷二维变换 /// @brief 设置画刷二维变换
/// @param transform 二维变换 /// @param transform 二维变换
void SetBrushTransform(Transform const& transform); void SetBrushTransform(Transform const& transform);
/// \~chinese /// \~chinese
/// @brief 设置画刷二维变换矩阵 /// @brief 设置画刷二维变换矩阵
/// @param transform 二维变换矩阵 /// @param transform 二维变换矩阵
void SetBrushTransform(Matrix3x2 const& transform); void SetBrushTransform(Matrix3x2 const& transform);
/// \~chinese /// \~chinese
/// @brief 添加一个图层 /// @brief 添加一个图层
/// @param area 图层区域 /// @param area 图层区域
void PushLayerArea(LayerArea& area); void PushLayerArea(LayerArea& area);
/// \~chinese /// \~chinese
/// @brief 删除最近添加的图层 /// @brief 删除最近添加的图层
void PopLayerArea(); void PopLayerArea();
/// \~chinese /// \~chinese
/// @brief 添加一个裁剪区域 /// @brief 添加一个裁剪区域
/// @param clip_rect 裁剪矩形 /// @param clip_rect 裁剪矩形
void PushClipRect(Rect const& clip_rect); void PushClipRect(Rect const& clip_rect);
/// \~chinese /// \~chinese
/// @brief 删除最近添加的裁剪区域 /// @brief 删除最近添加的裁剪区域
void PopClipRect(); void PopClipRect();
/// \~chinese /// \~chinese
/// @brief 获取轮廓宽度 /// @brief 获取轮廓宽度
float GetStrokeWidth() const; float GetStrokeWidth() const;
/// \~chinese /// \~chinese
/// @brief 获取填充画刷 /// @brief 获取填充画刷
BrushPtr GetFillBrush() const; BrushPtr GetFillBrush() const;
/// \~chinese /// \~chinese
/// @brief 获取轮廓画刷 /// @brief 获取轮廓画刷
BrushPtr GetStrokeBrush() const; BrushPtr GetStrokeBrush() const;
/// \~chinese /// \~chinese
/// @brief 导出纹理 /// @brief 导出纹理
TexturePtr ExportToTexture() const; TexturePtr ExportToTexture() const;
void OnRender(RenderTarget* rt) override; void OnRender(RenderContext& ctx) override;
private: private:
void InitRenderTargetAndBrushs(); void InitRenderTargetAndBrushs();
void UpdateCache() const; void UpdateCache() const;
private: private:
float stroke_width_; float stroke_width_;
TextStyle text_style_; TextStyle text_style_;
StrokeStyle stroke_style_; StrokeStyle stroke_style_;
GeometrySink geo_sink_; GeometrySink geo_sink_;
BrushPtr fill_brush_; BrushPtr fill_brush_;
BrushPtr stroke_brush_; BrushPtr stroke_brush_;
mutable bool cache_expired_; mutable bool cache_expired_;
mutable TexturePtr texture_cached_; mutable TexturePtr texture_cached_;
mutable TextureRenderTargetPtr rt_; mutable TextureRenderContextPtr ctx_;
}; };
/** @} */ /** @} */
inline void Canvas::SetStrokeWidth(float width)
{
stroke_width_ = std::max(width, 0.f);
}
inline void Canvas::SetStrokeStyle(StrokeStyle stroke_style)
{
stroke_style_ = stroke_style;
}
inline void Canvas::SetTextStyle(TextStyle const& text_style)
{
text_style_ = text_style;
}
inline void Canvas::SetStrokeColor(Color const& color)
{
InitRenderTargetAndBrushs();
stroke_brush_->SetColor(color);
}
inline void Canvas::SetFillColor(Color const& color)
{
InitRenderTargetAndBrushs();
fill_brush_->SetColor(color);
}
inline void Canvas::SetFillBrush(BrushPtr brush)
{
fill_brush_ = brush;
}
inline void Canvas::SetStrokeBrush(BrushPtr brush)
{
stroke_brush_ = brush;
}
inline BrushPtr Canvas::GetFillBrush() const
{
return fill_brush_;
}
inline BrushPtr Canvas::GetStrokeBrush() const
{
return stroke_brush_;
}
inline void Canvas::SetStrokeWidth(float width)
{
stroke_width_ = std::max(width, 0.f);
} }
inline void Canvas::SetStrokeStyle(const StrokeStyle& stroke_style)
{
stroke_style_ = stroke_style;
}
inline void Canvas::SetTextStyle(TextStyle const& text_style)
{
text_style_ = text_style;
}
inline void Canvas::SetStrokeColor(Color const& color)
{
InitRenderTargetAndBrushs();
stroke_brush_->SetColor(color);
}
inline void Canvas::SetFillColor(Color const& color)
{
InitRenderTargetAndBrushs();
fill_brush_->SetColor(color);
}
inline void Canvas::SetFillBrush(BrushPtr brush)
{
fill_brush_ = brush;
}
inline void Canvas::SetStrokeBrush(BrushPtr brush)
{
stroke_brush_ = brush;
}
inline BrushPtr Canvas::GetFillBrush() const
{
return fill_brush_;
}
inline BrushPtr Canvas::GetStrokeBrush() const
{
return stroke_brush_;
}
} // namespace kiwano

View File

@ -1,15 +1,15 @@
// Copyright (c) 2016-2018 Kiwano - Nomango // Copyright (c) 2016-2018 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -19,127 +19,128 @@
// THE SOFTWARE. // THE SOFTWARE.
#include <kiwano/2d/DebugActor.h> #include <kiwano/2d/DebugActor.h>
#include <kiwano/renderer/Renderer.h>
#include <kiwano/core/Logger.h> #include <kiwano/core/Logger.h>
#include <kiwano/render/Renderer.h>
#include <psapi.h> #include <psapi.h>
#pragma comment(lib, "psapi.lib") #pragma comment(lib, "psapi.lib")
namespace kiwano namespace kiwano
{ {
namespace namespace
{ {
class comma_numpunct : public std::numpunct<wchar_t> class comma_numpunct : public std::numpunct<wchar_t>
{ {
private: private:
virtual wchar_t do_thousands_sep() const override virtual wchar_t do_thousands_sep() const override
{ {
return L','; return L',';
} }
virtual std::string do_grouping() const override virtual std::string do_grouping() const override
{ {
return "\03"; return "\03";
} }
}; };
} // namespace
std::locale comma_locale(std::locale(), new comma_numpunct); DebugActor::DebugActor()
} {
SetName(L"kiwano-debug-actor");
SetPosition(Point{ 10, 10 });
SetResponsible(true);
SetCascadeOpacityEnabled(true);
DebugActor::DebugActor() comma_locale_ = std::locale(std::locale(), new comma_numpunct);
{
SetName(L"kiwano-debug-actor");
SetPosition(Point{ 10, 10 });
SetResponsible(true);
SetCascadeOpacityEnabled(true);
background_brush_ = new Brush; background_brush_ = new Brush;
background_brush_->SetColor(Color(0.0f, 0.0f, 0.0f, 0.7f)); background_brush_->SetColor(Color(0.0f, 0.0f, 0.0f, 0.7f));
debug_text_ = new TextActor; BrushPtr fill_brush = new Brush;
debug_text_->SetPosition(Point{ 10, 10 }); fill_brush->SetColor(Color::White);
this->AddChild(debug_text_);
TextStyle style; TextStyle style;
style.font_family = L"Arial"; style.font_family = L"Arial";
style.font_size = 16.f; style.font_size = 16.f;
style.font_weight = FontWeight::Normal; style.font_weight = FontWeight::Normal;
style.line_spacing = 20.f; style.line_spacing = 20.f;
debug_text_->SetStyle(style); style.fill_brush = fill_brush;
debug_text_->SetFillColor(Color::White); debug_text_.SetStyle(style);
AddListener<MouseHoverEvent>([=](Event&) { SetOpacity(0.4f); }); AddListener<MouseHoverEvent>([=](Event*) { SetOpacity(0.4f); });
AddListener<MouseOutEvent>([=](Event&) { SetOpacity(1.f); }); AddListener<MouseOutEvent>([=](Event*) { SetOpacity(1.f); });
} }
DebugActor::~DebugActor() DebugActor::~DebugActor() {}
{
}
void DebugActor::OnRender(RenderTarget* rt) void DebugActor::OnRender(RenderContext& ctx)
{ {
rt->SetCurrentBrush(background_brush_); ctx.SetCurrentBrush(background_brush_);
rt->FillRoundedRectangle(GetBounds(), Vec2{ 5.f, 5.f }); ctx.FillRoundedRectangle(GetBounds(), Vec2{ 5.f, 5.f });
} ctx.DrawTextLayout(debug_text_, Point(10, 10));
}
void DebugActor::OnUpdate(Duration dt) void DebugActor::OnUpdate(Duration dt)
{ {
KGE_NOT_USED(dt); KGE_NOT_USED(dt);
frame_time_.push_back(Time::Now()); frame_time_.push_back(Time::Now());
while (frame_time_.back() - frame_time_.front() >= Duration::Second) while (frame_time_.back() - frame_time_.front() >= Duration::Second)
{ {
frame_time_.erase(frame_time_.begin()); frame_time_.erase(frame_time_.begin());
} }
StringStream ss; StringStream ss;
// For formatting integers with commas // For formatting integers with commas
(void)ss.imbue(comma_locale); (void)ss.imbue(comma_locale_);
ss << "Fps: " << frame_time_.size() << std::endl; ss << "Fps: " << frame_time_.size() << std::endl;
#if defined(KGE_DEBUG) #if defined(KGE_DEBUG)
if (ObjectBase::IsTracingLeaks()) if (ObjectBase::IsTracingLeaks())
{ {
ss << "Objects: " << ObjectBase::GetTracingObjects().size() << std::endl; ss << "Objects: " << ObjectBase::GetTracingObjects().size() << std::endl;
} }
#endif #endif
ss << "Render: " << Renderer::instance().GetStatus().duration.Milliseconds() << "ms" << std::endl; ss << "Render: " << Renderer::Instance().GetStatus().duration.Milliseconds() << "ms" << std::endl;
ss << "Primitives / sec: " << std::fixed << Renderer::instance().GetStatus().primitives * frame_time_.size() << std::endl; ss << "Primitives / sec: " << std::fixed << Renderer::Instance().GetStatus().primitives * frame_time_.size()
<< std::endl;
ss << "Memory: "; ss << "Memory: ";
{ {
PROCESS_MEMORY_COUNTERS_EX pmc; PROCESS_MEMORY_COUNTERS_EX pmc;
GetProcessMemoryInfo(GetCurrentProcess(), (PROCESS_MEMORY_COUNTERS*)&pmc, sizeof(pmc)); GetProcessMemoryInfo(GetCurrentProcess(), (PROCESS_MEMORY_COUNTERS*)&pmc, sizeof(pmc));
if (pmc.PrivateUsage > 1024 * 1024) if (pmc.PrivateUsage > 1024 * 1024)
{ {
ss << pmc.PrivateUsage / (1024 * 1024) << "Mb "; ss << pmc.PrivateUsage / (1024 * 1024) << "Mb ";
pmc.PrivateUsage %= (1024 * 1024); pmc.PrivateUsage %= (1024 * 1024);
} }
ss << pmc.PrivateUsage / 1024 << "Kb"; ss << pmc.PrivateUsage / 1024 << "Kb";
} }
debug_text_->SetText(ss.str()); debug_text_.SetText(ss.str());
debug_text_.Update();
if (debug_text_->GetWidth() > GetWidth() - 20) Size layout_size = debug_text_.GetLayoutSize();
{ if (layout_size.x > GetWidth() - 20)
SetWidth(20 + debug_text_->GetWidth()); {
} SetWidth(20 + layout_size.x);
}
if (debug_text_->GetHeight() > GetHeight() - 20)
{
SetHeight(20 + debug_text_->GetHeight());
}
}
bool DebugActor::CheckVisibilty(RenderTarget* rt) const
{
return true;
}
if (layout_size.y > GetHeight() - 20)
{
SetHeight(20 + layout_size.y);
}
} }
bool DebugActor::CheckVisibility(RenderContext& ctx) const
{
return true;
}
} // namespace kiwano

View File

@ -1,15 +1,15 @@
// Copyright (c) 2016-2018 Kiwano - Nomango // Copyright (c) 2016-2018 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -20,42 +20,39 @@
#pragma once #pragma once
#include <kiwano/2d/Actor.h> #include <kiwano/2d/Actor.h>
#include <kiwano/2d/TextActor.h> #include <kiwano/render/TextLayout.h>
#include <kiwano/renderer/Color.h>
#include <kiwano/renderer/Brush.h>
namespace kiwano namespace kiwano
{ {
/** /**
* \addtogroup Actors * \addtogroup Actors
* @{ * @{
*/ */
/** /**
* \~chinese * \~chinese
* @brief µ÷ÊÔ½Úµã * @brief µ÷ÊÔ½Úµã
*/ */
class KGE_API DebugActor class KGE_API DebugActor : public Actor
: public Actor {
{ public:
public: DebugActor();
DebugActor();
virtual ~DebugActor(); virtual ~DebugActor();
void OnRender(RenderTarget* rt) override; void OnRender(RenderContext& ctx) override;
void OnUpdate(Duration dt) override; void OnUpdate(Duration dt) override;
protected: protected:
bool CheckVisibilty(RenderTarget* rt) const override; bool CheckVisibility(RenderContext& ctx) const override;
private: private:
BrushPtr background_brush_; std::locale comma_locale_;
TextActorPtr debug_text_; BrushPtr background_brush_;
Vector<Time> frame_time_; TextLayout debug_text_;
}; Vector<Time> frame_time_;
};
/** @} */ /** @} */
} // namespace kiwano
}

View File

@ -1,15 +1,15 @@
// Copyright (c) 2016-2018 Kiwano - Nomango // Copyright (c) 2016-2018 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -19,56 +19,54 @@
// THE SOFTWARE. // THE SOFTWARE.
#include <kiwano/2d/Frame.h> #include <kiwano/2d/Frame.h>
#include <kiwano/renderer/TextureCache.h> #include <kiwano/render/TextureCache.h>
namespace kiwano namespace kiwano
{ {
Frame::Frame() Frame::Frame() {}
{
}
bool Frame::Load(String const& file_path) bool Frame::Load(String const& file_path)
{ {
TexturePtr texture = TextureCache::instance().AddOrGetTexture(file_path); TexturePtr texture = TextureCache::Instance().AddOrGetTexture(file_path);
if (texture->IsValid()) if (texture->IsValid())
{ {
SetTexture(texture); SetTexture(texture);
return true; return true;
} }
return false; return false;
}
bool Frame::Load(Resource const& res)
{
TexturePtr texture = TextureCache::instance().AddOrGetTexture(res);
if (texture->IsValid())
{
SetTexture(texture);
return true;
}
return false;
}
void Frame::SetCropRect(Rect const& crop_rect)
{
if (texture_->IsValid())
{
auto bitmap_size = texture_->GetSize();
crop_rect_.left_top.x = std::min(std::max(crop_rect.left_top.x, 0.f), bitmap_size.x);
crop_rect_.left_top.y = std::min(std::max(crop_rect.left_top.y, 0.f), bitmap_size.y);
crop_rect_.right_bottom.x = std::min(std::max(crop_rect.right_bottom.x, 0.f), bitmap_size.x);
crop_rect_.right_bottom.y = std::min(std::max(crop_rect.right_bottom.y, 0.f), bitmap_size.y);
}
}
void Frame::SetTexture(TexturePtr texture)
{
texture_ = texture;
if (texture_->IsValid())
{
crop_rect_.left_top.x = crop_rect_.left_top.y = 0;
crop_rect_.right_bottom.x = texture_->GetWidth();
crop_rect_.right_bottom.y = texture_->GetHeight();
}
}
} }
bool Frame::Load(Resource const& res)
{
TexturePtr texture = TextureCache::Instance().AddOrGetTexture(res);
if (texture->IsValid())
{
SetTexture(texture);
return true;
}
return false;
}
void Frame::SetCropRect(Rect const& crop_rect)
{
if (texture_->IsValid())
{
auto bitmap_size = texture_->GetSize();
crop_rect_.left_top.x = std::min(std::max(crop_rect.left_top.x, 0.f), bitmap_size.x);
crop_rect_.left_top.y = std::min(std::max(crop_rect.left_top.y, 0.f), bitmap_size.y);
crop_rect_.right_bottom.x = std::min(std::max(crop_rect.right_bottom.x, 0.f), bitmap_size.x);
crop_rect_.right_bottom.y = std::min(std::max(crop_rect.right_bottom.y, 0.f), bitmap_size.y);
}
}
void Frame::SetTexture(TexturePtr texture)
{
texture_ = texture;
if (texture_->IsValid())
{
crop_rect_.left_top.x = crop_rect_.left_top.y = 0;
crop_rect_.right_bottom.x = texture_->GetWidth();
crop_rect_.right_bottom.y = texture_->GetHeight();
}
}
} // namespace kiwano

View File

@ -1,15 +1,15 @@
// Copyright (c) 2016-2018 Kiwano - Nomango // Copyright (c) 2016-2018 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -20,82 +20,102 @@
#pragma once #pragma once
#include <kiwano/core/ObjectBase.h> #include <kiwano/core/ObjectBase.h>
#include <kiwano/renderer/Texture.h> #include <kiwano/render/Texture.h>
namespace kiwano namespace kiwano
{ {
KGE_DECLARE_SMART_PTR(Frame); KGE_DECLARE_SMART_PTR(Frame);
/** /**
* \~chinese * \~chinese
* @brief * @brief
*/ */
class KGE_API Frame class KGE_API Frame : public virtual ObjectBase
: public ObjectBase {
{ public:
public: /// \~chinese
/// \~chinese /// @brief 构建空图像帧
/// @brief 构建空图像帧 Frame();
Frame();
/// \~chinese /// \~chinese
/// @brief 加载图像 /// @brief 加载图像
/// @param file_path 图像路径 /// @param file_path 图像路径
bool Load(String const& file_path); bool Load(String const& file_path);
/// \~chinese /// \~chinese
/// @brief 加载图像 /// @brief 加载图像
/// @param res 图像资源 /// @param res 图像资源
bool Load(Resource const& res); bool Load(Resource const& res);
/// \~chinese /// \~chinese
/// @brief 裁剪图像帧为矩形 /// @brief 裁剪图像帧为矩形
/// @param crop_rect 裁剪矩形定义 /// @param crop_rect 裁剪矩形定义
void SetCropRect(Rect const& crop_rect); void SetCropRect(Rect const& crop_rect);
/// \~chinese /// \~chinese
/// @brief 设置纹理 /// @brief 设置纹理
/// @param texture 纹理 /// @param texture 纹理
void SetTexture(TexturePtr texture); void SetTexture(TexturePtr texture);
/// \~chinese /// \~chinese
/// @brief 是否有效 /// @brief 是否有效
bool IsValid() const; bool IsValid() const;
/// \~chinese /// \~chinese
/// @brief 获取宽度 /// @brief 获取宽度
float GetWidth() const; float GetWidth() const;
/// \~chinese /// \~chinese
/// @brief 获取高度 /// @brief 获取高度
float GetHeight() const; float GetHeight() const;
/// \~chinese /// \~chinese
/// @brief 获取大小 /// @brief 获取大小
Size GetSize() const; Size GetSize() const;
/// \~chinese /// \~chinese
/// @brief 获取裁剪位置 /// @brief 获取裁剪位置
Point GetCropPoint() const; Point GetCropPoint() const;
/// \~chinese /// \~chinese
/// @brief 获取裁剪矩形 /// @brief 获取裁剪矩形
Rect const& GetCropRect() const; Rect const& GetCropRect() const;
/// \~chinese /// \~chinese
/// @brief 获取纹理 /// @brief 获取纹理
TexturePtr GetTexture() const; TexturePtr GetTexture() const;
private: private:
TexturePtr texture_; TexturePtr texture_;
Rect crop_rect_; Rect crop_rect_;
}; };
inline bool Frame::IsValid() const { return texture_ && texture_->IsValid(); } inline bool Frame::IsValid() const
inline float Frame::GetWidth() const { return crop_rect_.GetWidth(); } {
inline float Frame::GetHeight() const { return crop_rect_.GetHeight(); } return texture_ && texture_->IsValid();
inline Size Frame::GetSize() const { return crop_rect_.GetSize(); }
inline Point Frame::GetCropPoint() const { return crop_rect_.GetLeftTop(); }
inline Rect const& Frame::GetCropRect() const { return crop_rect_; }
inline TexturePtr Frame::GetTexture() const { return texture_; }
} }
inline float Frame::GetWidth() const
{
return crop_rect_.GetWidth();
}
inline float Frame::GetHeight() const
{
return crop_rect_.GetHeight();
}
inline Size Frame::GetSize() const
{
return crop_rect_.GetSize();
}
inline Point Frame::GetCropPoint() const
{
return crop_rect_.GetLeftTop();
}
inline Rect const& Frame::GetCropRect() const
{
return crop_rect_;
}
inline TexturePtr Frame::GetTexture() const
{
return texture_;
}
} // namespace kiwano

View File

@ -1,15 +1,15 @@
// Copyright (c) 2016-2018 Kiwano - Nomango // Copyright (c) 2016-2018 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -23,79 +23,75 @@
namespace kiwano namespace kiwano
{ {
FrameSequence::FrameSequence() FrameSequence::FrameSequence() {}
{
}
FrameSequence::FrameSequence(Vector<FramePtr> const& frames)
{
this->AddFrames(frames);
}
FrameSequence::~FrameSequence()
{
}
void FrameSequence::AddFrame(FramePtr frame)
{
KGE_ASSERT(frame && "FrameSequence::Add failed, NULL pointer exception");
if (frame)
{
frames_.push_back(frame);
}
}
void FrameSequence::AddFrames(Vector<FramePtr> const& frames)
{
if (frames_.empty())
frames_ = frames;
else
{
frames_.reserve(frames_.size() + frames.size());
for (const auto& texture : frames)
AddFrame(texture);
}
}
FramePtr FrameSequence::GetFrame(size_t index) const
{
KGE_ASSERT(index < frames_.size());
return frames_[index];
}
Vector<FramePtr> const& FrameSequence::GetFrames() const
{
return frames_;
}
size_t FrameSequence::GetFramesCount() const
{
return frames_.size();
}
FrameSequencePtr FrameSequence::Clone() const
{
auto frame_seq = new (std::nothrow) FrameSequence;
if (frame_seq)
{
frame_seq->AddFrames(frames_);
}
return frame_seq;
}
FrameSequencePtr FrameSequence::Reverse() const
{
auto frame_seq = new (std::nothrow) FrameSequence;
if (!frames_.empty())
{
for (auto iter = frames_.crbegin(), crend = frames_.crend(); iter != crend; ++iter)
{
if (*iter)
frame_seq->AddFrame(*iter);
}
}
return frame_seq;
}
FrameSequence::FrameSequence(Vector<FramePtr> const& frames)
{
this->AddFrames(frames);
} }
FrameSequence::~FrameSequence() {}
void FrameSequence::AddFrame(FramePtr frame)
{
KGE_ASSERT(frame && "FrameSequence::Add failed, NULL pointer exception");
if (frame)
{
frames_.push_back(frame);
}
}
void FrameSequence::AddFrames(Vector<FramePtr> const& frames)
{
if (frames_.empty())
frames_ = frames;
else
{
frames_.reserve(frames_.size() + frames.size());
for (const auto& texture : frames)
AddFrame(texture);
}
}
FramePtr FrameSequence::GetFrame(size_t index) const
{
KGE_ASSERT(index < frames_.size());
return frames_[index];
}
Vector<FramePtr> const& FrameSequence::GetFrames() const
{
return frames_;
}
size_t FrameSequence::GetFramesCount() const
{
return frames_.size();
}
FrameSequencePtr FrameSequence::Clone() const
{
auto frame_seq = new (std::nothrow) FrameSequence;
if (frame_seq)
{
frame_seq->AddFrames(frames_);
}
return frame_seq;
}
FrameSequencePtr FrameSequence::Reverse() const
{
auto frame_seq = new (std::nothrow) FrameSequence;
if (!frames_.empty())
{
for (auto iter = frames_.crbegin(), crend = frames_.crend(); iter != crend; ++iter)
{
if (*iter)
frame_seq->AddFrame(*iter);
}
}
return frame_seq;
}
} // namespace kiwano

View File

@ -1,15 +1,15 @@
// Copyright (c) 2016-2018 Kiwano - Nomango // Copyright (c) 2016-2018 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -19,65 +19,64 @@
// THE SOFTWARE. // THE SOFTWARE.
#pragma once #pragma once
#include <kiwano/core/common.h>
#include <kiwano/core/time.h>
#include <kiwano/2d/Frame.h> #include <kiwano/2d/Frame.h>
#include <kiwano/core/Common.h>
#include <kiwano/core/Time.h>
namespace kiwano namespace kiwano
{ {
KGE_DECLARE_SMART_PTR(FrameSequence); KGE_DECLARE_SMART_PTR(FrameSequence);
/** /**
* \~chinese * \~chinese
* @brief * @brief
*/ */
class KGE_API FrameSequence class KGE_API FrameSequence : public virtual ObjectBase
: public ObjectBase {
{ public:
public: /// \~chinese
/// \~chinese /// @brief 构建空序列帧
/// @brief 构建空序列帧 FrameSequence();
FrameSequence();
/// \~chinese /// \~chinese
/// @brief 构建序列帧 /// @brief 构建序列帧
/// @param frames 图像帧集合 /// @param frames 图像帧集合
explicit FrameSequence(Vector<FramePtr> const& frames); explicit FrameSequence(Vector<FramePtr> const& frames);
virtual ~FrameSequence(); virtual ~FrameSequence();
/// \~chinese /// \~chinese
/// @brief 添加关键帧 /// @brief 添加关键帧
/// @param frame 图像帧 /// @param frame 图像帧
void AddFrame(FramePtr frame); void AddFrame(FramePtr frame);
/// \~chinese /// \~chinese
/// @brief 添加多个关键帧 /// @brief 添加多个关键帧
/// @param frames 图像帧集合 /// @param frames 图像帧集合
void AddFrames(Vector<FramePtr> const& frames); void AddFrames(Vector<FramePtr> const& frames);
/// \~chinese /// \~chinese
/// @brief 获取关键帧 /// @brief 获取关键帧
/// @param index 图像帧下标 /// @param index 图像帧下标
FramePtr GetFrame(size_t index) const; FramePtr GetFrame(size_t index) const;
/// \~chinese /// \~chinese
/// @brief 获取所有关键帧 /// @brief 获取所有关键帧
Vector<FramePtr> const& GetFrames() const; Vector<FramePtr> const& GetFrames() const;
/// \~chinese /// \~chinese
/// @brief 获取关键帧数量 /// @brief 获取关键帧数量
size_t GetFramesCount() const; size_t GetFramesCount() const;
/// \~chinese /// \~chinese
/// @brief 获取序列帧的拷贝对象 /// @brief 获取序列帧的拷贝对象
FrameSequencePtr Clone() const; FrameSequencePtr Clone() const;
/// \~chinese /// \~chinese
/// @brief 获取序列帧的倒转 /// @brief 获取序列帧的倒转
FrameSequencePtr Reverse() const; FrameSequencePtr Reverse() const;
private: private:
Vector<FramePtr> frames_; Vector<FramePtr> frames_;
}; };
} } // namespace kiwano

View File

@ -1,15 +1,15 @@
// Copyright (c) 2016-2018 Kiwano - Nomango // Copyright (c) 2016-2018 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -19,225 +19,226 @@
// THE SOFTWARE. // THE SOFTWARE.
#include <kiwano/2d/GifSprite.h> #include <kiwano/2d/GifSprite.h>
#include <kiwano/renderer/TextureCache.h> #include <kiwano/render/Renderer.h>
#include <kiwano/renderer/Renderer.h> #include <kiwano/render/TextureCache.h>
namespace kiwano namespace kiwano
{ {
GifSprite::GifSprite() GifSprite::GifSprite()
: animating_(false) : animating_(false)
, next_index_(0) , next_index_(0)
, total_loop_count_(1) , total_loop_count_(1)
, loop_count_(0) , loop_count_(0)
{ {
}
bool GifSprite::Load(String const& file_path)
{
GifImagePtr image = TextureCache::instance().AddOrGetGifImage(file_path);
return Load(image);
}
bool GifSprite::Load(Resource const& res)
{
GifImagePtr image = TextureCache::instance().AddOrGetGifImage(res);
return Load(image);
}
bool GifSprite::Load(GifImagePtr gif)
{
if (gif && gif->IsValid())
{
gif_ = gif;
next_index_ = 0;
loop_count_ = 0;
frame_.disposal_type = GifImage::DisposalType::None;
SetSize(Size{ static_cast<float>(gif_->GetWidthInPixels()), static_cast<float>(gif_->GetHeightInPixels()) });
if (!frame_rt_)
{
Renderer::instance().CreateTextureRenderTarget(frame_rt_);
}
if (gif_->GetFramesCount() > 0)
{
ComposeNextFrame();
}
return true;
}
return false;
}
void GifSprite::OnRender(RenderTarget* rt)
{
if (frame_to_render_ && CheckVisibilty(rt))
{
PrepareToRender(rt);
rt->DrawTexture(*frame_to_render_, &frame_.rect, nullptr);
}
}
void GifSprite::Update(Duration dt)
{
Actor::Update(dt);
if (gif_ && gif_->IsValid() && animating_)
{
frame_elapsed_ += dt;
if (frame_.delay <= frame_elapsed_)
{
frame_.delay -= frame_elapsed_;
frame_elapsed_ = 0;
ComposeNextFrame();
}
}
}
void GifSprite::SetGifImage(GifImagePtr gif)
{
gif_ = gif;
RestartAnimation();
}
void GifSprite::RestartAnimation()
{
animating_ = true;
next_index_ = 0;
loop_count_ = 0;
frame_.disposal_type = GifImage::DisposalType::None;
}
void GifSprite::ComposeNextFrame()
{
KGE_ASSERT(frame_rt_);
KGE_ASSERT(gif_);
if (frame_rt_->IsValid())
{
do
{
DisposeCurrentFrame();
OverlayNextFrame();
} while (frame_.delay.IsZero() && !IsLastFrame());
animating_ = (!EndOfAnimation() && gif_->GetFramesCount() > 1);
}
}
void GifSprite::DisposeCurrentFrame()
{
switch (frame_.disposal_type)
{
case GifImage::DisposalType::Unknown:
case GifImage::DisposalType::None:
break;
case GifImage::DisposalType::Background:
ClearCurrentFrameArea();
break;
case GifImage::DisposalType::Previous:
RestoreSavedFrame();
break;
}
}
void GifSprite::OverlayNextFrame()
{
KGE_ASSERT(frame_rt_);
KGE_ASSERT(gif_ && gif_->IsValid());
frame_ = gif_->GetFrame(next_index_);
if (frame_.disposal_type == GifImage::DisposalType::Previous)
{
SaveComposedFrame();
}
if (frame_rt_->IsValid())
{
frame_rt_->BeginDraw();
if (next_index_ == 0)
{
loop_count_++;
}
if (frame_.texture)
{
frame_rt_->DrawTexture(*frame_.texture, nullptr, &frame_.rect);
}
frame_rt_->EndDraw();
if (!frame_to_render_)
{
frame_to_render_ = new Texture;
}
if (frame_rt_->GetOutput(*frame_to_render_))
{
next_index_ = (++next_index_) % gif_->GetFramesCount();
}
}
if (IsLastFrame() && loop_cb_)
{
loop_cb_(loop_count_ - 1);
}
if (EndOfAnimation() && done_cb_)
{
done_cb_();
}
}
void GifSprite::SaveComposedFrame()
{
KGE_ASSERT(frame_rt_);
TexturePtr frame_to_be_saved = new Texture;
if (frame_rt_->GetOutput(*frame_to_be_saved))
{
if (!saved_frame_)
{
saved_frame_ = new Texture;
frame_rt_->CreateTexture(*saved_frame_, frame_to_be_saved->GetSizeInPixels(), frame_to_be_saved->GetPixelFormat());
}
saved_frame_->CopyFrom(frame_to_be_saved);
}
}
void GifSprite::RestoreSavedFrame()
{
KGE_ASSERT(frame_rt_);
if (saved_frame_)
{
TexturePtr frame_to_copy_to = new Texture;
if (frame_rt_->GetOutput(*frame_to_copy_to))
{
frame_to_copy_to->CopyFrom(saved_frame_);
}
}
}
void GifSprite::ClearCurrentFrameArea()
{
KGE_ASSERT(frame_rt_);
frame_rt_->BeginDraw();
frame_rt_->PushClipRect(frame_.rect);
frame_rt_->Clear();
frame_rt_->PopClipRect();
return frame_rt_->EndDraw();
}
} }
bool GifSprite::Load(String const& file_path)
{
GifImagePtr image = TextureCache::Instance().AddOrGetGifImage(file_path);
return Load(image);
}
bool GifSprite::Load(Resource const& res)
{
GifImagePtr image = TextureCache::Instance().AddOrGetGifImage(res);
return Load(image);
}
bool GifSprite::Load(GifImagePtr gif)
{
if (gif && gif->IsValid())
{
gif_ = gif;
next_index_ = 0;
loop_count_ = 0;
frame_.disposal_type = GifImage::DisposalType::None;
SetSize(Size{ static_cast<float>(gif_->GetWidthInPixels()), static_cast<float>(gif_->GetHeightInPixels()) });
if (!frame_rt_)
{
Renderer::Instance().CreateTextureRenderTarget(frame_rt_);
}
if (gif_->GetFramesCount() > 0)
{
ComposeNextFrame();
}
return true;
}
return false;
}
void GifSprite::OnRender(RenderContext& ctx)
{
if (frame_to_render_ && CheckVisibility(ctx))
{
PrepareToRender(ctx);
ctx.DrawTexture(*frame_to_render_, &frame_.rect, nullptr);
}
}
void GifSprite::Update(Duration dt)
{
Actor::Update(dt);
if (gif_ && gif_->IsValid() && animating_)
{
frame_elapsed_ += dt;
if (frame_.delay <= frame_elapsed_)
{
frame_.delay -= frame_elapsed_;
frame_elapsed_ = 0;
ComposeNextFrame();
}
}
}
void GifSprite::SetGifImage(GifImagePtr gif)
{
gif_ = gif;
RestartAnimation();
}
void GifSprite::RestartAnimation()
{
animating_ = true;
next_index_ = 0;
loop_count_ = 0;
frame_.disposal_type = GifImage::DisposalType::None;
}
void GifSprite::ComposeNextFrame()
{
KGE_ASSERT(frame_rt_);
KGE_ASSERT(gif_);
if (frame_rt_->IsValid())
{
do
{
DisposeCurrentFrame();
OverlayNextFrame();
} while (frame_.delay.IsZero() && !IsLastFrame());
animating_ = (!EndOfAnimation() && gif_->GetFramesCount() > 1);
}
}
void GifSprite::DisposeCurrentFrame()
{
switch (frame_.disposal_type)
{
case GifImage::DisposalType::Unknown:
case GifImage::DisposalType::None:
break;
case GifImage::DisposalType::Background:
ClearCurrentFrameArea();
break;
case GifImage::DisposalType::Previous:
RestoreSavedFrame();
break;
}
}
void GifSprite::OverlayNextFrame()
{
KGE_ASSERT(frame_rt_);
KGE_ASSERT(gif_ && gif_->IsValid());
frame_ = gif_->GetFrame(next_index_);
if (frame_.disposal_type == GifImage::DisposalType::Previous)
{
SaveComposedFrame();
}
if (frame_rt_->IsValid())
{
frame_rt_->BeginDraw();
if (next_index_ == 0)
{
loop_count_++;
}
if (frame_.texture)
{
frame_rt_->DrawTexture(*frame_.texture, nullptr, &frame_.rect);
}
frame_rt_->EndDraw();
if (!frame_to_render_)
{
frame_to_render_ = new Texture;
}
if (frame_rt_->GetOutput(*frame_to_render_))
{
next_index_ = (++next_index_) % gif_->GetFramesCount();
}
}
if (IsLastFrame() && loop_cb_)
{
loop_cb_(loop_count_ - 1);
}
if (EndOfAnimation() && done_cb_)
{
done_cb_();
}
}
void GifSprite::SaveComposedFrame()
{
KGE_ASSERT(frame_rt_);
TexturePtr frame_to_be_saved = new Texture;
if (frame_rt_->GetOutput(*frame_to_be_saved))
{
if (!saved_frame_)
{
saved_frame_ = new Texture;
frame_rt_->CreateTexture(*saved_frame_, frame_to_be_saved->GetSizeInPixels(),
frame_to_be_saved->GetPixelFormat());
}
saved_frame_->CopyFrom(frame_to_be_saved);
}
}
void GifSprite::RestoreSavedFrame()
{
KGE_ASSERT(frame_rt_);
if (saved_frame_)
{
TexturePtr frame_to_copy_to = new Texture;
if (frame_rt_->GetOutput(*frame_to_copy_to))
{
frame_to_copy_to->CopyFrom(saved_frame_);
}
}
}
void GifSprite::ClearCurrentFrameArea()
{
KGE_ASSERT(frame_rt_);
frame_rt_->BeginDraw();
frame_rt_->PushClipRect(frame_.rect);
frame_rt_->Clear();
frame_rt_->PopClipRect();
return frame_rt_->EndDraw();
}
} // namespace kiwano

View File

@ -1,15 +1,15 @@
// Copyright (c) 2016-2018 Kiwano - Nomango // Copyright (c) 2016-2018 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -21,150 +21,173 @@
#pragma once #pragma once
#include <kiwano/2d/Actor.h> #include <kiwano/2d/Actor.h>
#include <kiwano/core/Resource.h> #include <kiwano/core/Resource.h>
#include <kiwano/renderer/RenderTarget.h> #include <kiwano/render/GifImage.h>
#include <kiwano/renderer/GifImage.h> #include <kiwano/render/RenderContext.h>
namespace kiwano namespace kiwano
{ {
KGE_DECLARE_SMART_PTR(GifSprite); KGE_DECLARE_SMART_PTR(GifSprite);
/** /**
* \addtogroup Actors * \addtogroup Actors
* @{ * @{
*/ */
/** /**
* \~chinese * \~chinese
* @brief GIF * @brief GIF
*/ */
class KGE_API GifSprite class KGE_API GifSprite : public Actor
: public Actor {
{ public:
public: /// \~chinese
/// \~chinese /// @brief GIF播放循环结束回调
/// @brief GIF播放循环结束回调 using LoopDoneCallback = Function<void(int /* times */)>;
using LoopDoneCallback = Function<void(int /* times */)>;
/// \~chinese /// \~chinese
/// @brief GIF播放结束回调 /// @brief GIF播放结束回调
using DoneCallback = Function<void()>; using DoneCallback = Function<void()>;
GifSprite(); GifSprite();
/// \~chinese /// \~chinese
/// @brief 加载GIF图片 /// @brief 加载GIF图片
/// @param file_path GIF图片路径 /// @param file_path GIF图片路径
bool Load(String const& file_path); bool Load(String const& file_path);
/// \~chinese /// \~chinese
/// @brief 加载GIF图片 /// @brief 加载GIF图片
/// @param res GIF图片资源 /// @param res GIF图片资源
bool Load(Resource const& res); bool Load(Resource const& res);
/// \~chinese /// \~chinese
/// @brief 加载GIF图片 /// @brief 加载GIF图片
/// @param gif GIF图片 /// @param gif GIF图片
bool Load(GifImagePtr gif); bool Load(GifImagePtr gif);
/// \~chinese /// \~chinese
/// @brief 设置 GIF 动画循环次数 /// @brief 设置 GIF 动画循环次数
void SetLoopCount(int loops); void SetLoopCount(int loops);
/// \~chinese /// \~chinese
/// @brief 设置 GIF 动画每次循环结束回调函数 /// @brief 设置 GIF 动画每次循环结束回调函数
void SetLoopDoneCallback(LoopDoneCallback const& cb); void SetLoopDoneCallback(LoopDoneCallback const& cb);
/// \~chinese /// \~chinese
/// @brief 设置 GIF 动画结束回调函数 /// @brief 设置 GIF 动画结束回调函数
void SetDoneCallback(DoneCallback const& cb); void SetDoneCallback(DoneCallback const& cb);
/// \~chinese /// \~chinese
/// @brief 设置 GIF 图像 /// @brief 设置 GIF 图像
void SetGifImage(GifImagePtr gif); void SetGifImage(GifImagePtr gif);
/// \~chinese /// \~chinese
/// @brief 重新播放 GIF 动画 /// @brief 重新播放 GIF 动画
void RestartAnimation(); void RestartAnimation();
/// \~chinese /// \~chinese
/// @brief 获取 GIF 动画循环结束回调 /// @brief 获取 GIF 动画循环结束回调
LoopDoneCallback GetLoopDoneCallback() const; LoopDoneCallback GetLoopDoneCallback() const;
/// \~chinese /// \~chinese
/// @brief 获取 GIF 动画播放结束回调 /// @brief 获取 GIF 动画播放结束回调
DoneCallback GetDoneCallback() const; DoneCallback GetDoneCallback() const;
/// \~chinese /// \~chinese
/// @brief 获取 GIF 图片 /// @brief 获取 GIF 图片
GifImagePtr GetGifImage() const; GifImagePtr GetGifImage() const;
void OnRender(RenderTarget* rt) override; void OnRender(RenderContext& ctx) override;
private: private:
void Update(Duration dt) override; void Update(Duration dt) override;
/// \~chinese /// \~chinese
/// @brief 是否是最后一帧 /// @brief 是否是最后一帧
bool IsLastFrame() const; bool IsLastFrame() const;
/// \~chinese /// \~chinese
/// @brief 动画是否已结束 /// @brief 动画是否已结束
bool EndOfAnimation() const; bool EndOfAnimation() const;
/// \~chinese /// \~chinese
/// @brief 合成下一帧 /// @brief 合成下一帧
void ComposeNextFrame(); void ComposeNextFrame();
/// \~chinese /// \~chinese
/// @brief 解析当前图像帧 /// @brief 解析当前图像帧
void DisposeCurrentFrame(); void DisposeCurrentFrame();
/// \~chinese /// \~chinese
/// @brief 覆盖下一帧 /// @brief 覆盖下一帧
void OverlayNextFrame(); void OverlayNextFrame();
/// \~chinese /// \~chinese
/// @brief 保存合成后的图像帧 /// @brief 保存合成后的图像帧
void SaveComposedFrame(); void SaveComposedFrame();
/// \~chinese /// \~chinese
/// @brief 恢复已保存的图像帧 /// @brief 恢复已保存的图像帧
void RestoreSavedFrame(); void RestoreSavedFrame();
/// \~chinese /// \~chinese
/// @brief 清空当前图像区域 /// @brief 清空当前图像区域
void ClearCurrentFrameArea(); void ClearCurrentFrameArea();
private: private:
bool animating_; bool animating_;
int total_loop_count_; int total_loop_count_;
int loop_count_; int loop_count_;
size_t next_index_; size_t next_index_;
Duration frame_elapsed_; Duration frame_elapsed_;
LoopDoneCallback loop_cb_; LoopDoneCallback loop_cb_;
DoneCallback done_cb_; DoneCallback done_cb_;
GifImagePtr gif_; GifImagePtr gif_;
GifImage::Frame frame_; GifImage::Frame frame_;
TexturePtr saved_frame_; TexturePtr saved_frame_;
TexturePtr frame_to_render_; TexturePtr frame_to_render_;
TextureRenderTargetPtr frame_rt_; TextureRenderContextPtr frame_rt_;
}; };
/** @} */ /** @} */
inline void GifSprite::SetLoopCount(int loops) { total_loop_count_ = loops; } inline void GifSprite::SetLoopCount(int loops)
{
inline void GifSprite::SetLoopDoneCallback(LoopDoneCallback const& cb) { loop_cb_ = cb; } total_loop_count_ = loops;
inline void GifSprite::SetDoneCallback(DoneCallback const& cb) { done_cb_ = cb; }
inline GifSprite::LoopDoneCallback GifSprite::GetLoopDoneCallback() const { return loop_cb_; }
inline GifSprite::DoneCallback GifSprite::GetDoneCallback() const { return done_cb_; }
inline GifImagePtr GifSprite::GetGifImage() const { return gif_; }
inline bool GifSprite::IsLastFrame() const { return (next_index_ == 0); }
inline bool GifSprite::EndOfAnimation() const { return IsLastFrame() && loop_count_ == total_loop_count_ + 1; }
} }
inline void GifSprite::SetLoopDoneCallback(LoopDoneCallback const& cb)
{
loop_cb_ = cb;
}
inline void GifSprite::SetDoneCallback(DoneCallback const& cb)
{
done_cb_ = cb;
}
inline GifSprite::LoopDoneCallback GifSprite::GetLoopDoneCallback() const
{
return loop_cb_;
}
inline GifSprite::DoneCallback GifSprite::GetDoneCallback() const
{
return done_cb_;
}
inline GifImagePtr GifSprite::GetGifImage() const
{
return gif_;
}
inline bool GifSprite::IsLastFrame() const
{
return (next_index_ == 0);
}
inline bool GifSprite::EndOfAnimation() const
{
return IsLastFrame() && loop_count_ == total_loop_count_ + 1;
}
} // namespace kiwano

View File

@ -1,15 +1,15 @@
// Copyright (c) 2016-2018 Kiwano - Nomango // Copyright (c) 2016-2018 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -20,71 +20,63 @@
#pragma once #pragma once
#include <kiwano/2d/Layer.h> #include <kiwano/2d/Layer.h>
#include <kiwano/renderer/Renderer.h> #include <kiwano/render/Renderer.h>
namespace kiwano namespace kiwano
{ {
Layer::Layer() Layer::Layer()
: swallow_(false) : swallow_(false)
{ {
}
Layer::~Layer()
{
}
void Layer::SetClipRect(Rect const& clip_rect)
{
area_.SetAreaRect(clip_rect);
}
void Layer::SetOpacity(float opacity)
{
// Actor::SetOpacity(opacity);
area_.SetOpacity(opacity);
}
void Layer::SetMaskGeometry(Geometry const& mask)
{
area_.SetMaskGeometry(mask);
}
void Layer::SetMaskTransform(Matrix3x2 const& transform)
{
area_.SetMaskTransform(transform);
}
void Layer::Dispatch(Event& evt)
{
if (!IsVisible())
return;
if (!swallow_)
{
ActorPtr prev;
for (auto child = GetAllChildren().last_item(); child; child = prev)
{
prev = child->prev_item();
child->Dispatch(evt);
}
}
EventDispatcher::Dispatch(evt);
}
void Layer::Render(RenderTarget* rt)
{
rt->PushLayer(area_);
Actor::Render(rt);
rt->PopLayer();
}
bool Layer::CheckVisibilty(RenderTarget* rt) const
{
// Do not need to render Layer
return false;
}
} }
Layer::~Layer() {}
void Layer::SetClipRect(Rect const& clip_rect)
{
area_.SetAreaRect(clip_rect);
}
void Layer::SetOpacity(float opacity)
{
// Actor::SetOpacity(opacity);
area_.SetOpacity(opacity);
}
void Layer::SetMaskGeometry(Geometry const& mask)
{
area_.SetMaskGeometry(mask);
}
void Layer::SetMaskTransform(Matrix3x2 const& transform)
{
area_.SetMaskTransform(transform);
}
bool Layer::DispatchEvent(Event* evt)
{
if (!IsVisible())
return true;
if (swallow_)
{
return EventDispatcher::DispatchEvent(evt);
}
return Actor::DispatchEvent(evt);
}
void Layer::Render(RenderContext& ctx)
{
ctx.PushLayer(area_);
Actor::Render(ctx);
ctx.PopLayer();
}
bool Layer::CheckVisibility(RenderContext& ctx) const
{
// Do not need to render Layer
return false;
}
} // namespace kiwano

View File

@ -1,15 +1,15 @@
// Copyright (c) 2016-2018 Kiwano - Nomango // Copyright (c) 2016-2018 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -20,88 +20,98 @@
#pragma once #pragma once
#include <kiwano/2d/Actor.h> #include <kiwano/2d/Actor.h>
#include <kiwano/renderer/LayerArea.h> #include <kiwano/render/LayerArea.h>
#include <kiwano/renderer/RenderTarget.h> #include <kiwano/render/RenderContext.h>
namespace kiwano namespace kiwano
{ {
KGE_DECLARE_SMART_PTR(Layer); KGE_DECLARE_SMART_PTR(Layer);
/** /**
* \addtogroup Actors * \addtogroup Actors
* @{ * @{
*/ */
/** /**
* \~chinese * \~chinese
* @brief * @brief
*/ */
class KGE_API Layer class KGE_API Layer : public Actor
: public Actor {
{ public:
public: Layer();
Layer();
virtual ~Layer(); virtual ~Layer();
/// \~chinese /// \~chinese
/// @brief 是否开启消息吞没 /// @brief 是否开启消息吞没
bool IsSwallowEventsEnabled() const; bool IsSwallowEventsEnabled() const;
/// \~chinese /// \~chinese
/// @brief 设置消息吞没功能 /// @brief 设置消息吞没功能
/// @param enabled 是否启用 /// @param enabled 是否启用
void SetSwallowEvents(bool enabled); void SetSwallowEvents(bool enabled);
/// \~chinese /// \~chinese
/// @brief 设置裁剪区域 /// @brief 设置裁剪区域
/// @param clip_rect 裁剪矩形 /// @param clip_rect 裁剪矩形
void SetClipRect(Rect const& clip_rect); void SetClipRect(Rect const& clip_rect);
/// \~chinese /// \~chinese
/// @brief 设置图层透明度 /// @brief 设置图层透明度
/// @param opacity 透明度 /// @param opacity 透明度
void SetOpacity(float opacity) override; void SetOpacity(float opacity) override;
/// \~chinese /// \~chinese
/// @brief 设置几何蒙层 /// @brief 设置几何蒙层
/// @param mask 蒙层的几何形状 /// @param mask 蒙层的几何形状
void SetMaskGeometry(Geometry const& mask); void SetMaskGeometry(Geometry const& mask);
/// \~chinese /// \~chinese
/// @brief 设置几何蒙层的二维变换 /// @brief 设置几何蒙层的二维变换
/// @param transform 应用于蒙层的二维变换 /// @param transform 应用于蒙层的二维变换
void SetMaskTransform(Matrix3x2 const& transform); void SetMaskTransform(Matrix3x2 const& transform);
/// \~chinese /// \~chinese
/// @brief 设置图层区域 /// @brief 设置图层区域
/// @param area 图层区域属性 /// @param area 图层区域属性
void SetArea(LayerArea const& area); void SetArea(LayerArea const& area);
/// \~chinese /// \~chinese
/// @brief 获取图层区域 /// @brief 获取图层区域
LayerArea const& GetArea() const; LayerArea const& GetArea() const;
void Dispatch(Event& evt) override; bool DispatchEvent(Event* evt) override;
protected: protected:
void Render(RenderTarget* rt) override; void Render(RenderContext& ctx) override;
bool CheckVisibilty(RenderTarget* rt) const override; bool CheckVisibility(RenderContext& ctx) const override;
private: private:
bool swallow_; bool swallow_;
LayerArea area_; LayerArea area_;
}; };
/** @} */ /** @} */
inline bool Layer::IsSwallowEventsEnabled() const { return swallow_; }
inline void Layer::SetSwallowEvents(bool enabled) { swallow_ = enabled; }
inline void Layer::SetArea(LayerArea const& area) { area_ = area; }
inline LayerArea const& Layer::GetArea() const { return area_; }
inline bool Layer::IsSwallowEventsEnabled() const
{
return swallow_;
} }
inline void Layer::SetSwallowEvents(bool enabled)
{
swallow_ = enabled;
}
inline void Layer::SetArea(LayerArea const& area)
{
area_ = area;
}
inline LayerArea const& Layer::GetArea() const
{
return area_;
}
} // namespace kiwano

View File

@ -1,15 +1,15 @@
// Copyright (c) 2016-2018 Kiwano - Nomango // Copyright (c) 2016-2018 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -20,291 +20,252 @@
#include <kiwano/2d/ShapeActor.h> #include <kiwano/2d/ShapeActor.h>
#include <kiwano/core/Logger.h> #include <kiwano/core/Logger.h>
#include <kiwano/renderer/Renderer.h> #include <kiwano/render/Renderer.h>
namespace kiwano namespace kiwano
{ {
ShapeActor::ShapeActor() ShapeActor::ShapeActor()
: stroke_width_(1.f) : stroke_width_(1.f)
, stroke_style_(StrokeStyle::Miter) , stroke_style_()
{ {
}
ShapeActor::~ShapeActor()
{
}
Rect ShapeActor::GetBounds() const
{
return bounds_;
}
Rect ShapeActor::GetBoundingBox() const
{
if (!geo_.IsValid())
return Rect{};
return geo_.GetBoundingBox(GetTransformMatrix());
}
bool ShapeActor::ContainsPoint(const Point& point) const
{
return geo_.ContainsPoint(point, &GetTransformMatrix());
}
void ShapeActor::SetStrokeWidth(float width)
{
stroke_width_ = std::max(width, 0.f);
}
void ShapeActor::SetStrokeStyle(StrokeStyle stroke_style)
{
stroke_style_ = stroke_style;
}
void ShapeActor::SetGeometry(Geometry const& geometry)
{
geo_ = geometry;
if (geo_.IsValid())
{
bounds_ = geo_.GetBoundingBox();
SetSize(bounds_.GetSize());
}
else
{
bounds_ = Rect{};
SetSize(0.f, 0.f);
}
}
void ShapeActor::OnRender(RenderTarget* rt)
{
// Create default brush
if (!fill_brush_)
{
fill_brush_ = new Brush;
fill_brush_->SetColor(Color::White);
}
if (!stroke_brush_)
{
stroke_brush_ = new Brush;
stroke_brush_->SetColor(Color::Transparent);
}
rt->SetCurrentBrush(stroke_brush_);
rt->DrawGeometry(geo_, stroke_width_ * 2 /* twice width for widening */, stroke_style_);
rt->SetCurrentBrush(fill_brush_);
rt->FillGeometry(geo_);
}
bool ShapeActor::CheckVisibilty(RenderTarget* rt) const
{
return geo_.IsValid() && Actor::CheckVisibilty(rt);
}
//-------------------------------------------------------
// LineActor
//-------------------------------------------------------
LineActor::LineActor()
{
}
LineActor::~LineActor()
{
}
void LineActor::SetLine(Point const& begin, Point const& end)
{
if (begin_ != begin || end_ != end)
{
begin_ = begin;
end_ = end;
SetGeometry(Geometry::CreateLine(begin, end));
}
}
//-------------------------------------------------------
// RectActor
//-------------------------------------------------------
RectActor::RectActor()
{
}
RectActor::~RectActor()
{
}
void RectActor::SetRectSize(Size const& size)
{
if (size != rect_size_)
{
rect_size_ = size;
SetGeometry(Geometry::CreateRect(Rect{ Point{}, size }));
}
}
//-------------------------------------------------------
// RoundRectActor
//-------------------------------------------------------
RoundRectActor::RoundRectActor()
{
}
RoundRectActor::~RoundRectActor()
{
}
void RoundRectActor::SetRadius(Vec2 const& radius)
{
SetRoundedRect(GetSize(), radius);
}
void RoundRectActor::SetRectSize(Size const& size)
{
SetRoundedRect(size, radius_);
}
void RoundRectActor::SetRoundedRect(Size const& size, Vec2 const& radius)
{
if (rect_size_ != size || radius_ != radius)
{
rect_size_ = size;
radius_ = radius;
SetGeometry(Geometry::CreateRoundedRect(Rect{ Point{}, size }, radius));
}
}
//-------------------------------------------------------
// CircleActor
//-------------------------------------------------------
CircleActor::CircleActor()
: radius_(0.f)
{
}
CircleActor::~CircleActor()
{
}
void CircleActor::SetRadius(float radius)
{
if (radius_ != radius)
{
radius_ = radius;
SetGeometry(Geometry::CreateCircle(Point{ radius, radius }, radius));
}
}
//-------------------------------------------------------
// EllipseActor
//-------------------------------------------------------
EllipseActor::EllipseActor()
{
}
EllipseActor::~EllipseActor()
{
}
void EllipseActor::SetRadius(Vec2 const& radius)
{
if (radius_ != radius)
{
radius_ = radius;
SetGeometry(Geometry::CreateEllipse(radius, radius));
}
}
//-------------------------------------------------------
// PolygonActor
//-------------------------------------------------------
PolygonActor::PolygonActor()
{
}
PolygonActor::~PolygonActor()
{
}
void PolygonActor::SetVertices(Vector<Point> const& points)
{
if (points.size() > 1)
{
SetGeometry(
GeometrySink()
.BeginPath(points[0])
.AddLines(&points[1], points.size() - 1)
.EndPath(true)
.GetGeometry()
);
}
}
//-------------------------------------------------------
// PathShapeActor
//-------------------------------------------------------
PathShapeActor::PathShapeActor()
{
}
PathShapeActor::~PathShapeActor()
{
}
void PathShapeActor::BeginPath(Point const& begin_pos)
{
sink_.BeginPath(begin_pos);
}
void PathShapeActor::EndPath(bool closed)
{
sink_.EndPath(closed);
Geometry geo = sink_.GetGeometry();
if (geo.IsValid())
{
SetGeometry(geo);
}
}
void PathShapeActor::AddLine(Point const& point)
{
sink_.AddLine(point);
}
void PathShapeActor::AddLines(Vector<Point> const& points)
{
sink_.AddLines(points);
}
void PathShapeActor::AddBezier(Point const& point1, Point const& point2, Point const& point3)
{
sink_.AddBezier(point1, point2, point3);
}
void PathShapeActor::AddArc(Point const& point, Size const& radius, float rotation, bool clockwise, bool is_small)
{
sink_.AddArc(point, radius, rotation, clockwise, is_small);
}
void PathShapeActor::ClearPath()
{
SetGeometry(Geometry());
}
} }
ShapeActor::~ShapeActor() {}
Rect ShapeActor::GetBounds() const
{
return bounds_;
}
Rect ShapeActor::GetBoundingBox() const
{
if (!geo_.IsValid())
return Rect{};
return geo_.GetBoundingBox(GetTransformMatrix());
}
bool ShapeActor::ContainsPoint(const Point& point) const
{
return geo_.ContainsPoint(point, &GetTransformMatrix());
}
void ShapeActor::SetStrokeWidth(float width)
{
stroke_width_ = std::max(width, 0.f);
}
void ShapeActor::SetStrokeStyle(const StrokeStyle& stroke_style)
{
stroke_style_ = stroke_style;
}
void ShapeActor::SetGeometry(Geometry const& geometry)
{
geo_ = geometry;
if (geo_.IsValid())
{
bounds_ = geo_.GetBoundingBox();
SetSize(bounds_.GetSize());
}
else
{
bounds_ = Rect{};
SetSize(0.f, 0.f);
}
}
void ShapeActor::OnRender(RenderContext& ctx)
{
// Create default brush
if (!fill_brush_)
{
fill_brush_ = new Brush;
fill_brush_->SetColor(Color::White);
}
if (!stroke_brush_)
{
stroke_brush_ = new Brush;
stroke_brush_->SetColor(Color::Transparent);
}
ctx.SetCurrentBrush(stroke_brush_);
ctx.DrawGeometry(geo_, stroke_width_ * 2 /* twice width for widening */, stroke_style_);
ctx.SetCurrentBrush(fill_brush_);
ctx.FillGeometry(geo_);
}
bool ShapeActor::CheckVisibility(RenderContext& ctx) const
{
return geo_.IsValid() && Actor::CheckVisibility(ctx);
}
//-------------------------------------------------------
// LineActor
//-------------------------------------------------------
LineActor::LineActor() {}
LineActor::~LineActor() {}
void LineActor::SetLine(Point const& begin, Point const& end)
{
if (begin_ != begin || end_ != end)
{
begin_ = begin;
end_ = end;
SetGeometry(Geometry::CreateLine(begin, end));
}
}
//-------------------------------------------------------
// RectActor
//-------------------------------------------------------
RectActor::RectActor() {}
RectActor::~RectActor() {}
void RectActor::SetRectSize(Size const& size)
{
if (size != rect_size_)
{
rect_size_ = size;
SetGeometry(Geometry::CreateRect(Rect{ Point{}, size }));
}
}
//-------------------------------------------------------
// RoundRectActor
//-------------------------------------------------------
RoundRectActor::RoundRectActor() {}
RoundRectActor::~RoundRectActor() {}
void RoundRectActor::SetRadius(Vec2 const& radius)
{
SetRoundedRect(GetSize(), radius);
}
void RoundRectActor::SetRectSize(Size const& size)
{
SetRoundedRect(size, radius_);
}
void RoundRectActor::SetRoundedRect(Size const& size, Vec2 const& radius)
{
if (rect_size_ != size || radius_ != radius)
{
rect_size_ = size;
radius_ = radius;
SetGeometry(Geometry::CreateRoundedRect(Rect{ Point{}, size }, radius));
}
}
//-------------------------------------------------------
// CircleActor
//-------------------------------------------------------
CircleActor::CircleActor()
: radius_(0.f)
{
}
CircleActor::~CircleActor() {}
void CircleActor::SetRadius(float radius)
{
if (radius_ != radius)
{
radius_ = radius;
SetGeometry(Geometry::CreateCircle(Point{ radius, radius }, radius));
}
}
//-------------------------------------------------------
// EllipseActor
//-------------------------------------------------------
EllipseActor::EllipseActor() {}
EllipseActor::~EllipseActor() {}
void EllipseActor::SetRadius(Vec2 const& radius)
{
if (radius_ != radius)
{
radius_ = radius;
SetGeometry(Geometry::CreateEllipse(radius, radius));
}
}
//-------------------------------------------------------
// PolygonActor
//-------------------------------------------------------
PolygonActor::PolygonActor() {}
PolygonActor::~PolygonActor() {}
void PolygonActor::SetVertices(Vector<Point> const& points)
{
if (points.size() > 1)
{
SetGeometry(
GeometrySink().BeginPath(points[0]).AddLines(&points[1], points.size() - 1).EndPath(true).GetGeometry());
}
}
//-------------------------------------------------------
// PathShapeActor
//-------------------------------------------------------
PathShapeActor::PathShapeActor() {}
PathShapeActor::~PathShapeActor() {}
void PathShapeActor::BeginPath(Point const& begin_pos)
{
sink_.BeginPath(begin_pos);
}
void PathShapeActor::EndPath(bool closed)
{
sink_.EndPath(closed);
Geometry geo = sink_.GetGeometry();
if (geo.IsValid())
{
SetGeometry(geo);
}
}
void PathShapeActor::AddLine(Point const& point)
{
sink_.AddLine(point);
}
void PathShapeActor::AddLines(Vector<Point> const& points)
{
sink_.AddLines(points);
}
void PathShapeActor::AddBezier(Point const& point1, Point const& point2, Point const& point3)
{
sink_.AddBezier(point1, point2, point3);
}
void PathShapeActor::AddArc(Point const& point, Size const& radius, float rotation, bool clockwise, bool is_small)
{
sink_.AddArc(point, radius, rotation, clockwise, is_small);
}
void PathShapeActor::ClearPath()
{
SetGeometry(Geometry());
}
} // namespace kiwano

View File

@ -1,15 +1,15 @@
// Copyright (c) 2016-2018 Kiwano - Nomango // Copyright (c) 2016-2018 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -20,383 +20,415 @@
#pragma once #pragma once
#include <kiwano/2d/Actor.h> #include <kiwano/2d/Actor.h>
#include <kiwano/renderer/Brush.h> #include <kiwano/render/Brush.h>
#include <kiwano/renderer/Geometry.h> #include <kiwano/render/Geometry.h>
#include <kiwano/renderer/GeometrySink.h> #include <kiwano/render/GeometrySink.h>
#include <kiwano/renderer/StrokeStyle.h> #include <kiwano/render/StrokeStyle.h>
namespace kiwano namespace kiwano
{ {
KGE_DECLARE_SMART_PTR(ShapeActor); KGE_DECLARE_SMART_PTR(ShapeActor);
KGE_DECLARE_SMART_PTR(LineActor); KGE_DECLARE_SMART_PTR(LineActor);
KGE_DECLARE_SMART_PTR(RectActor); KGE_DECLARE_SMART_PTR(RectActor);
KGE_DECLARE_SMART_PTR(RoundRectActor); KGE_DECLARE_SMART_PTR(RoundRectActor);
KGE_DECLARE_SMART_PTR(CircleActor); KGE_DECLARE_SMART_PTR(CircleActor);
KGE_DECLARE_SMART_PTR(EllipseActor); KGE_DECLARE_SMART_PTR(EllipseActor);
KGE_DECLARE_SMART_PTR(PolygonActor); KGE_DECLARE_SMART_PTR(PolygonActor);
KGE_DECLARE_SMART_PTR(PathShapeActor); KGE_DECLARE_SMART_PTR(PathShapeActor);
/** /**
* \addtogroup Actors * \addtogroup Actors
* @{ * @{
*/ */
/** /**
* \~chinese * \~chinese
* @brief * @brief
*/ */
class KGE_API ShapeActor class KGE_API ShapeActor : public Actor
: public Actor {
{ public:
public: /// \~chinese
/// \~chinese /// @brief 构造二维形状角色
/// @brief 构造二维形状角色 ShapeActor();
ShapeActor();
virtual ~ShapeActor();
virtual ~ShapeActor();
/// \~chinese
/// \~chinese /// @brief 获取填充画刷
/// @brief 获取填充画刷 BrushPtr GetFillBrush() const;
BrushPtr GetFillBrush() const;
/// \~chinese
/// \~chinese /// @brief 获取轮廓画刷
/// @brief 获取轮廓画刷 BrushPtr GetStrokeBrush() const;
BrushPtr GetStrokeBrush() const;
/// \~chinese
/// \~chinese /// @brief 获取线条宽度
/// @brief 获取线条宽度 float GetStrokeWidth() const;
float GetStrokeWidth() const;
/// \~chinese
/// \~chinese /// @brief 获取线条样式
/// @brief 获取线条样式 const StrokeStyle& GetStrokeStyle() const;
StrokeStyle SetStrokeStyle() const;
/// \~chinese
/// \~chinese /// @brief 获取形状
/// @brief 获取形状 Geometry GetGeometry() const;
Geometry GetGeometry() const;
/// \~chinese
/// \~chinese /// @brief 获取边界
/// @brief 获取边界 Rect GetBounds() const override;
Rect GetBounds() const override;
/// \~chinese
/// \~chinese /// @brief 获取外切包围盒
/// @brief 获取外切包围盒 Rect GetBoundingBox() const override;
Rect GetBoundingBox() const override;
/// \~chinese
/// \~chinese /// @brief 判断点是否在形状内
/// @brief 判断点是否在形状内 bool ContainsPoint(const Point& point) const override;
bool ContainsPoint(const Point& point) const override;
/// \~chinese
/// \~chinese /// @brief 设置填充颜色
/// @brief 设置填充颜色 /// @param color 填充颜色
/// @param color 填充颜色 void SetFillColor(Color const& color);
void SetFillColor(Color const& color);
/// \~chinese
/// \~chinese /// @brief 设置填充画刷
/// @brief 设置填充画刷 /// @param[in] brush 填充画刷
/// @param[in] brush 填充画刷 void SetFillBrush(BrushPtr brush);
void SetFillBrush(BrushPtr brush);
/// \~chinese
/// \~chinese /// @brief 设置轮廓颜色
/// @brief 设置轮廓颜色 /// @param color 轮廓颜色
/// @param color 轮廓颜色 void SetStrokeColor(Color const& color);
void SetStrokeColor(Color const& color);
/// \~chinese
/// \~chinese /// @brief 设置轮廓画刷
/// @brief 设置轮廓画刷 /// @param[in] brush 轮廓画刷
/// @param[in] brush 轮廓画刷 void SetStrokeBrush(BrushPtr brush);
void SetStrokeBrush(BrushPtr brush);
/// \~chinese
/// \~chinese /// @brief 设置线条宽度,默认为 1.0
/// @brief 设置线条宽度,默认为 1.0 void SetStrokeWidth(float width);
void SetStrokeWidth(float width);
/// \~chinese
/// \~chinese /// @brief 设置线条样式
/// @brief 设置线条样式 void SetStrokeStyle(const StrokeStyle& stroke_style);
void SetStrokeStyle(StrokeStyle stroke_style);
/// \~chinese
/// \~chinese /// @brief 设置几何形状
/// @brief 设置几何形状 void SetGeometry(Geometry const& geometry);
void SetGeometry(Geometry const& geometry);
void OnRender(RenderContext& ctx) override;
void OnRender(RenderTarget* rt) override;
protected:
protected: bool CheckVisibility(RenderContext& ctx) const override;
bool CheckVisibilty(RenderTarget* rt) const override;
private:
private: BrushPtr fill_brush_;
BrushPtr fill_brush_; BrushPtr stroke_brush_;
BrushPtr stroke_brush_; float stroke_width_;
float stroke_width_; StrokeStyle stroke_style_;
StrokeStyle stroke_style_; Rect bounds_;
Rect bounds_; Geometry geo_;
Geometry geo_; };
};
/// \~chinese
/// @brief 线段图形角色
/// \~chinese class KGE_API LineActor : public ShapeActor
/// @brief 线段图形角色 {
class KGE_API LineActor public:
: public ShapeActor LineActor();
{
public: virtual ~LineActor();
LineActor();
/// \~chinese
virtual ~LineActor(); /// @brief 获取线段起点
Point const& GetBeginPoint() const;
/// \~chinese
/// @brief 获取线段起点 /// \~chinese
Point const& GetBeginPoint() const; /// @brief 获取线段终点
Point const& GetEndPoint() const;
/// \~chinese
/// @brief 获取线段终点 /// \~chinese
Point const& GetEndPoint() const; /// @brief 设置线段起点
/// @param begin 线段起点
/// \~chinese void SetBeginPoint(Point const& begin);
/// @brief 设置线段起点
/// @param begin 线段起点 /// \~chinese
void SetBeginPoint(Point const& begin); /// @brief 设置线段终点
/// @param end 线段终点
/// \~chinese void SetEndPoint(Point const& end);
/// @brief 设置线段终点
/// @param end 线段终点 /// \~chinese
void SetEndPoint(Point const& end); /// @brief 设置矩形大小
/// @param begin 线段起点
/// \~chinese /// @param end 线段终点
/// @brief 设置矩形大小 void SetLine(Point const& begin, Point const& end);
/// @param begin 线段起点
/// @param end 线段终点 private:
void SetLine(Point const& begin, Point const& end); Point begin_;
Point end_;
private: };
Point begin_;
Point end_; /// \~chinese
}; /// @brief 矩形角色
class KGE_API RectActor : public ShapeActor
{
/// \~chinese public:
/// @brief 矩形角色 RectActor();
class KGE_API RectActor
: public ShapeActor virtual ~RectActor();
{
public: /// \~chinese
RectActor(); /// @brief 获取矩形大小
Size const& GetRectSize() const;
virtual ~RectActor();
/// \~chinese
/// \~chinese /// @brief 设置矩形大小
/// @brief 获取矩形大小 /// @param size 矩形大小
Size const& GetRectSize() const; void SetRectSize(Size const& size);
/// \~chinese private:
/// @brief 设置矩形大小 Size rect_size_;
/// @param size 矩形大小 };
void SetRectSize(Size const& size);
/// \~chinese
private: /// @brief 圆角矩形角色
Size rect_size_; class KGE_API RoundRectActor : public ShapeActor
}; {
public:
RoundRectActor();
/// \~chinese virtual ~RoundRectActor();
/// @brief 圆角矩形角色
class KGE_API RoundRectActor /// \~chinese
: public ShapeActor /// @brief 获取圆角半径
{ Vec2 GetRadius() const;
public:
RoundRectActor(); /// \~chinese
/// @brief 获取圆角矩形大小
virtual ~RoundRectActor(); Size GetRectSize() const;
/// \~chinese /// \~chinese
/// @brief 获取圆角半径 /// @brief 设置圆角半径
Vec2 GetRadius() const; /// @param radius 圆角半径
void SetRadius(Vec2 const& radius);
/// \~chinese
/// @brief 获取圆角矩形大小 /// \~chinese
Size GetRectSize() const; /// @brief 设置圆角矩形大小
/// @param size 圆角矩形大小
/// \~chinese void SetRectSize(Size const& size);
/// @brief 设置圆角半径
/// @param radius 圆角半径 /// \~chinese
void SetRadius(Vec2 const& radius); /// @brief 设置圆角矩形
/// @param size 圆角矩形大小
/// \~chinese /// @param radius 圆角半径
/// @brief 设置圆角矩形大小 void SetRoundedRect(Size const& size, Vec2 const& radius);
/// @param size 圆角矩形大小
void SetRectSize(Size const& size); private:
Size rect_size_;
/// \~chinese Vec2 radius_;
/// @brief 设置圆角矩形 };
/// @param size 圆角矩形大小
/// @param radius 圆角半径 /// \~chinese
void SetRoundedRect(Size const& size, Vec2 const& radius); /// @brief 圆形角色
class KGE_API CircleActor : public ShapeActor
private: {
Size rect_size_; public:
Vec2 radius_; CircleActor();
};
virtual ~CircleActor();
/// \~chinese /// \~chinese
/// @brief 圆形角色 /// @brief 获取圆形半径
class KGE_API CircleActor float GetRadius() const;
: public ShapeActor
{ /// \~chinese
public: /// @brief 设置圆形半径
CircleActor(); /// @param radius 圆形半径
void SetRadius(float radius);
virtual ~CircleActor();
private:
/// \~chinese float radius_;
/// @brief 获取圆形半径 };
float GetRadius() const;
/// \~chinese
/// \~chinese /// @brief 椭圆角色
/// @brief 设置圆形半径 class KGE_API EllipseActor : public ShapeActor
/// @param radius 圆形半径 {
void SetRadius(float radius); public:
EllipseActor();
private:
float radius_; virtual ~EllipseActor();
};
/// \~chinese
/// @brief 获取椭圆半径
/// \~chinese Vec2 GetRadius() const;
/// @brief 椭圆角色
class KGE_API EllipseActor /// \~chinese
: public ShapeActor /// @brief 设置椭圆半径
{ /// @param radius 椭圆半径
public: void SetRadius(Vec2 const& radius);
EllipseActor();
private:
virtual ~EllipseActor(); Vec2 radius_;
};
/// \~chinese
/// @brief 获取椭圆半径 /// \~chinese
Vec2 GetRadius() const; /// @brief 多边形角色
class KGE_API PolygonActor : public ShapeActor
/// \~chinese {
/// @brief 设置椭圆半径 public:
/// @param radius 椭圆半径 PolygonActor();
void SetRadius(Vec2 const& radius);
virtual ~PolygonActor();
private:
Vec2 radius_; /// \~chinese
}; /// @brief 设置多边形端点
/// @param points 多边形端点集合
void SetVertices(Vector<Point> const& points);
/// \~chinese };
/// @brief 多边形角色
class KGE_API PolygonActor /// \~chinese
: public ShapeActor /// @brief 路径图形角色
{ class KGE_API PathShapeActor : public ShapeActor
public: {
PolygonActor(); public:
PathShapeActor();
virtual ~PolygonActor();
virtual ~PathShapeActor();
/// \~chinese
/// @brief 设置多边形端点 /// \~chinese
/// @param points 多边形端点集合 /// @brief 开始添加路径
void SetVertices(Vector<Point> const& points); /// @param begin_pos 起始点
}; void BeginPath(Point const& begin_pos = Point());
/// \~chinese
/// \~chinese /// @brief 结束添加路径
/// @brief 路径图形角色 /// @param closed 路径是否闭合
class KGE_API PathShapeActor void EndPath(bool closed = true);
: public ShapeActor
{ /// \~chinese
public: /// @brief 添加一条线段
PathShapeActor(); /// @param point 线段端点
void AddLine(Point const& point);
virtual ~PathShapeActor();
/// \~chinese
/// \~chinese /// @brief 添加多条线段
/// @brief 开始添加路径 /// @param points 线段端点集合
/// @param begin_pos 起始点 void AddLines(Vector<Point> const& points);
void BeginPath(Point const& begin_pos = Point());
/// \~chinese
/// \~chinese /// @brief 添加一条三次方贝塞尔曲线
/// @brief 结束添加路径 /// @param point1 贝塞尔曲线的第一个控制点
/// @param closed 路径是否闭合 /// @param point2 贝塞尔曲线的第二个控制点
void EndPath(bool closed = true); /// @param point3 贝塞尔曲线的终点
void AddBezier(Point const& point1, Point const& point2, Point const& point3);
/// \~chinese
/// @brief 添加一条线段 /// \~chinese
/// @param point 线段端点 /// @brief 添加弧线
void AddLine(Point const& point); /// @param point 椭圆圆心
/// @param radius 椭圆半径
/// \~chinese /// @param rotation 椭圆旋转角度
/// @brief 添加多条线段 /// @param clockwise 顺时针 or 逆时针
/// @param points 线段端点集合 /// @param is_small 是否取小于 180° 的弧
void AddLines(Vector<Point> const& points); void AddArc(Point const& point, Size const& radius, float rotation, bool clockwise = true, bool is_small = true);
/// \~chinese /// \~chinese
/// @brief 添加一条三次方贝塞尔曲线 /// @brief 清除路径
/// @param point1 贝塞尔曲线的第一个控制点 void ClearPath();
/// @param point2 贝塞尔曲线的第二个控制点
/// @param point3 贝塞尔曲线的终点 private:
void AddBezier(Point const& point1, Point const& point2, Point const& point3); GeometrySink sink_;
};
/// \~chinese
/// @brief 添加弧线 /** @} */
/// @param point 椭圆圆心
/// @param radius 椭圆半径 inline void ShapeActor::SetStrokeColor(Color const& color)
/// @param rotation 椭圆旋转角度 {
/// @param clockwise 顺时针 or 逆时针 if (!stroke_brush_)
/// @param is_small 是否取小于 180° 的弧 {
void AddArc(Point const& point, Size const& radius, float rotation, bool clockwise = true, bool is_small = true); stroke_brush_ = new Brush;
}
/// \~chinese stroke_brush_->SetColor(color);
/// @brief 清除路径
void ClearPath();
private:
GeometrySink sink_;
};
/** @} */
inline void ShapeActor::SetStrokeColor(Color const& color)
{
if (!stroke_brush_)
{
stroke_brush_ = new Brush;
}
stroke_brush_->SetColor(color);
}
inline void ShapeActor::SetFillColor(Color const& color)
{
if (!fill_brush_)
{
fill_brush_ = new Brush;
}
fill_brush_->SetColor(color);
}
inline void ShapeActor::SetFillBrush(BrushPtr brush) { fill_brush_ = brush; }
inline void ShapeActor::SetStrokeBrush(BrushPtr brush) { stroke_brush_ = brush; }
inline BrushPtr ShapeActor::GetFillBrush() const { return fill_brush_; }
inline BrushPtr ShapeActor::GetStrokeBrush() const { return stroke_brush_; }
inline float ShapeActor::GetStrokeWidth() const { return stroke_width_; }
inline StrokeStyle ShapeActor::SetStrokeStyle() const { return stroke_style_; }
inline Geometry ShapeActor::GetGeometry() const { return geo_; }
inline Point const& LineActor::GetBeginPoint() const { return begin_; }
inline Point const& LineActor::GetEndPoint() const { return end_; }
inline void LineActor::SetBeginPoint(Point const& begin) { SetLine(begin, end_); }
inline void LineActor::SetEndPoint(Point const& end) { SetLine(begin_, end); }
inline Size const& RectActor::GetRectSize() const { return rect_size_; }
inline Vec2 RoundRectActor::GetRadius() const { return radius_; }
inline Size RoundRectActor::GetRectSize() const { return GetSize(); }
inline float CircleActor::GetRadius() const { return radius_; }
inline Vec2 EllipseActor::GetRadius() const { return radius_; }
} }
inline void ShapeActor::SetFillColor(Color const& color)
{
if (!fill_brush_)
{
fill_brush_ = new Brush;
}
fill_brush_->SetColor(color);
}
inline void ShapeActor::SetFillBrush(BrushPtr brush)
{
fill_brush_ = brush;
}
inline void ShapeActor::SetStrokeBrush(BrushPtr brush)
{
stroke_brush_ = brush;
}
inline BrushPtr ShapeActor::GetFillBrush() const
{
return fill_brush_;
}
inline BrushPtr ShapeActor::GetStrokeBrush() const
{
return stroke_brush_;
}
inline float ShapeActor::GetStrokeWidth() const
{
return stroke_width_;
}
inline const StrokeStyle& ShapeActor::GetStrokeStyle() const
{
return stroke_style_;
}
inline Geometry ShapeActor::GetGeometry() const
{
return geo_;
}
inline Point const& LineActor::GetBeginPoint() const
{
return begin_;
}
inline Point const& LineActor::GetEndPoint() const
{
return end_;
}
inline void LineActor::SetBeginPoint(Point const& begin)
{
SetLine(begin, end_);
}
inline void LineActor::SetEndPoint(Point const& end)
{
SetLine(begin_, end);
}
inline Size const& RectActor::GetRectSize() const
{
return rect_size_;
}
inline Vec2 RoundRectActor::GetRadius() const
{
return radius_;
}
inline Size RoundRectActor::GetRectSize() const
{
return GetSize();
}
inline float CircleActor::GetRadius() const
{
return radius_;
}
inline Vec2 EllipseActor::GetRadius() const
{
return radius_;
}
} // namespace kiwano

View File

@ -1,15 +1,15 @@
// Copyright (c) 2016-2018 Kiwano - Nomango // Copyright (c) 2016-2018 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -19,68 +19,64 @@
// THE SOFTWARE. // THE SOFTWARE.
#include <kiwano/2d/Sprite.h> #include <kiwano/2d/Sprite.h>
#include <kiwano/renderer/Renderer.h> #include <kiwano/render/Renderer.h>
namespace kiwano namespace kiwano
{ {
Sprite::Sprite() Sprite::Sprite() {}
{
}
Sprite::~Sprite() Sprite::~Sprite() {}
{
}
bool Sprite::Load(String const& file_path) bool Sprite::Load(String const& file_path)
{ {
FramePtr frame = new (std::nothrow) Frame; FramePtr frame = new (std::nothrow) Frame;
if (frame->Load(file_path)) if (frame->Load(file_path))
{ {
SetFrame(frame); SetFrame(frame);
return true; return true;
} }
return false; return false;
}
bool Sprite::Load(Resource const& res)
{
FramePtr frame = new (std::nothrow) Frame;
if (frame->Load(res))
{
SetFrame(frame);
return true;
}
return false;
}
void Sprite::SetCropRect(const Rect& crop_rect)
{
if (frame_)
{
frame_->SetCropRect(crop_rect);
SetSize(Size{ frame_->GetWidth(), frame_->GetHeight() });
}
}
void Sprite::SetFrame(FramePtr frame)
{
if (frame_ != frame)
{
frame_ = frame;
if (frame_)
{
SetSize(Size{ frame_->GetWidth(), frame_->GetHeight() });
}
}
}
void Sprite::OnRender(RenderTarget* rt)
{
rt->DrawTexture(*frame_->GetTexture(), &frame_->GetCropRect(), &GetBounds());
}
bool Sprite::CheckVisibilty(RenderTarget* rt) const
{
return frame_ && frame_->IsValid() && Actor::CheckVisibilty(rt);
}
} }
bool Sprite::Load(Resource const& res)
{
FramePtr frame = new (std::nothrow) Frame;
if (frame->Load(res))
{
SetFrame(frame);
return true;
}
return false;
}
void Sprite::SetCropRect(const Rect& crop_rect)
{
if (frame_)
{
frame_->SetCropRect(crop_rect);
SetSize(Size{ frame_->GetWidth(), frame_->GetHeight() });
}
}
void Sprite::SetFrame(FramePtr frame)
{
if (frame_ != frame)
{
frame_ = frame;
if (frame_)
{
SetSize(Size{ frame_->GetWidth(), frame_->GetHeight() });
}
}
}
void Sprite::OnRender(RenderContext& ctx)
{
ctx.DrawTexture(*frame_->GetTexture(), &frame_->GetCropRect(), &GetBounds());
}
bool Sprite::CheckVisibility(RenderContext& ctx) const
{
return frame_ && frame_->IsValid() && Actor::CheckVisibility(ctx);
}
} // namespace kiwano

View File

@ -1,15 +1,15 @@
// Copyright (c) 2016-2018 Kiwano - Nomango // Copyright (c) 2016-2018 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -24,60 +24,61 @@
namespace kiwano namespace kiwano
{ {
KGE_DECLARE_SMART_PTR(Sprite); KGE_DECLARE_SMART_PTR(Sprite);
/** /**
* \addtogroup Actors * \addtogroup Actors
* @{ * @{
*/ */
/** /**
* \~chinese * \~chinese
* @brief * @brief
*/ */
class KGE_API Sprite class KGE_API Sprite : public Actor
: public Actor {
{ public:
public: Sprite();
Sprite();
virtual ~Sprite(); virtual ~Sprite();
/// \~chinese /// \~chinese
/// @brief 加载本地图片 /// @brief 加载本地图片
/// @param file_path 本地图片路径 /// @param file_path 本地图片路径
bool Load(String const& file_path); bool Load(String const& file_path);
/// \~chinese /// \~chinese
/// @brief 加载图像资源 /// @brief 加载图像资源
/// @param res 图片资源 /// @param res 图片资源
bool Load(Resource const& res); bool Load(Resource const& res);
/// \~chinese /// \~chinese
/// @brief 使用矩形区域裁剪精灵 /// @brief 使用矩形区域裁剪精灵
/// @param crop_rect 裁剪矩形 /// @param crop_rect 裁剪矩形
void SetCropRect(const Rect& crop_rect); void SetCropRect(const Rect& crop_rect);
/// \~chinese /// \~chinese
/// @brief 获取帧图像 /// @brief 获取帧图像
FramePtr GetFrame() const; FramePtr GetFrame() const;
/// \~chinese /// \~chinese
/// @brief 设置图像帧 /// @brief 设置图像帧
/// @param[in] frame 图像帧 /// @param[in] frame 图像帧
void SetFrame(FramePtr frame); void SetFrame(FramePtr frame);
void OnRender(RenderTarget* rt) override; void OnRender(RenderContext& ctx) override;
protected: protected:
bool CheckVisibilty(RenderTarget* rt) const override; bool CheckVisibility(RenderContext& ctx) const override;
private: private:
FramePtr frame_; FramePtr frame_;
}; };
/** @} */ /** @} */
inline FramePtr Sprite::GetFrame() const { return frame_; }
inline FramePtr Sprite::GetFrame() const
{
return frame_;
} }
} // namespace kiwano

View File

@ -1,15 +1,15 @@
// Copyright (c) 2016-2018 Kiwano - Nomango // Copyright (c) 2016-2018 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -20,49 +20,47 @@
#include <kiwano/2d/Stage.h> #include <kiwano/2d/Stage.h>
#include <kiwano/core/Logger.h> #include <kiwano/core/Logger.h>
#include <kiwano/renderer/Renderer.h> #include <kiwano/render/Renderer.h>
namespace kiwano namespace kiwano
{ {
Stage::Stage() Stage::Stage()
{ {
SetStage(this); SetStage(this);
SetAnchor(Vec2{ 0, 0 });
SetSize(Renderer::instance().GetOutputSize());
}
Stage::~Stage()
{
}
void Stage::OnEnter()
{
KGE_SYS_LOG(L"Stage entered");
}
void Stage::OnExit()
{
KGE_SYS_LOG(L"Stage exited");
}
void Stage::RenderBorder(RenderTarget* rt)
{
rt->SetBrushOpacity(1.0f);
if (!border_fill_brush_)
{
border_fill_brush_ = new Brush;
border_fill_brush_->SetColor(Color(Color::Red, .4f));
}
if (!border_stroke_brush_)
{
border_stroke_brush_ = new Brush;
border_stroke_brush_->SetColor(Color(Color::Red, .8f));
}
Actor::RenderBorder(rt);
}
SetAnchor(Vec2{ 0, 0 });
SetSize(Renderer::Instance().GetOutputSize());
} }
Stage::~Stage() {}
void Stage::OnEnter()
{
KGE_SYS_LOG(L"Stage entered");
}
void Stage::OnExit()
{
KGE_SYS_LOG(L"Stage exited");
}
void Stage::RenderBorder(RenderContext& ctx)
{
ctx.SetBrushOpacity(GetDisplayedOpacity());
if (!border_fill_brush_)
{
border_fill_brush_ = new Brush;
border_fill_brush_->SetColor(Color(Color::Red, .4f));
}
if (!border_stroke_brush_)
{
border_stroke_brush_ = new Brush;
border_stroke_brush_->SetColor(Color(Color::Red, .8f));
}
Actor::RenderBorder(ctx);
}
} // namespace kiwano

View File

@ -1,15 +1,15 @@
// Copyright (c) 2016-2018 Kiwano - Nomango // Copyright (c) 2016-2018 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -20,90 +20,88 @@
#pragma once #pragma once
#include <kiwano/2d/Actor.h> #include <kiwano/2d/Actor.h>
#include <kiwano/renderer/Brush.h> #include <kiwano/render/Brush.h>
namespace kiwano namespace kiwano
{ {
KGE_DECLARE_SMART_PTR(Stage); KGE_DECLARE_SMART_PTR(Stage);
/** /**
* \addtogroup Actors * \addtogroup Actors
* @{ * @{
*/ */
/** /**
* \~chinese * \~chinese
* @brief * @brief
* @details * @details
* @see kiwano::Actor kiwano::Director * @see kiwano::Actor kiwano::Director
*/ */
class KGE_API Stage class KGE_API Stage : public Actor
: public Actor {
{ friend class Transition;
friend class Transition; friend class Director;
friend class Director;
public: public:
Stage(); Stage();
virtual ~Stage(); virtual ~Stage();
/// \~chinese /// \~chinese
/// @brief 进入舞台时 /// @brief 进入舞台时
/// @details 重载该函数以处理进入舞台前的行为 /// @details 重载该函数以处理进入舞台前的行为
virtual void OnEnter(); virtual void OnEnter();
/// \~chinese /// \~chinese
/// @brief 退出舞台时 /// @brief 退出舞台时
/// @details 重载该函数以处理退出舞台前的行为 /// @details 重载该函数以处理退出舞台前的行为
virtual void OnExit(); virtual void OnExit();
/// \~chinese /// \~chinese
/// @brief 获取角色边界填充画刷 /// @brief 获取角色边界填充画刷
BrushPtr GetBorderFillBrush() const; BrushPtr GetBorderFillBrush() const;
/// \~chinese /// \~chinese
/// @brief 获取角色边界轮廓画刷 /// @brief 获取角色边界轮廓画刷
BrushPtr GetBorderStrokeBrush() const; BrushPtr GetBorderStrokeBrush() const;
/// \~chinese /// \~chinese
/// @brief 设置角色边界填充画刷 /// @brief 设置角色边界填充画刷
void SetBorderFillBrush(BrushPtr brush); void SetBorderFillBrush(BrushPtr brush);
/// \~chinese /// \~chinese
/// @brief 设置角色边界轮廓画刷 /// @brief 设置角色边界轮廓画刷
void SetBorderStrokeBrush(BrushPtr brush); void SetBorderStrokeBrush(BrushPtr brush);
protected: protected:
/// \~chinese /// \~chinese
/// @brief 绘制所有子角色的边界 /// @brief 绘制所有子角色的边界
void RenderBorder(RenderTarget* rt) override; void RenderBorder(RenderContext& ctx) override;
private: private:
BrushPtr border_fill_brush_; BrushPtr border_fill_brush_;
BrushPtr border_stroke_brush_; BrushPtr border_stroke_brush_;
}; };
/** @} */ /** @} */
inline BrushPtr Stage::GetBorderFillBrush() const
{
return border_fill_brush_;
}
inline BrushPtr Stage::GetBorderStrokeBrush() const
{
return border_stroke_brush_;
}
inline void Stage::SetBorderFillBrush(BrushPtr brush)
{
border_fill_brush_ = brush;
}
inline void Stage::SetBorderStrokeBrush(BrushPtr brush)
{
border_stroke_brush_ = brush;
}
inline BrushPtr Stage::GetBorderFillBrush() const
{
return border_fill_brush_;
} }
inline BrushPtr Stage::GetBorderStrokeBrush() const
{
return border_stroke_brush_;
}
inline void Stage::SetBorderFillBrush(BrushPtr brush)
{
border_fill_brush_ = brush;
}
inline void Stage::SetBorderStrokeBrush(BrushPtr brush)
{
border_stroke_brush_ = brush;
}
} // namespace kiwano

View File

@ -1,15 +1,15 @@
// Copyright (c) 2016-2018 Kiwano - Nomango // Copyright (c) 2016-2018 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -20,110 +20,113 @@
#include <kiwano/2d/TextActor.h> #include <kiwano/2d/TextActor.h>
#include <kiwano/core/Logger.h> #include <kiwano/core/Logger.h>
#include <kiwano/renderer/Renderer.h> #include <kiwano/render/Renderer.h>
namespace kiwano namespace kiwano
{ {
namespace namespace
{ {
TextStyle text_default_style; TextStyle text_default_style;
void InitDefaultTextStyle() void InitDefaultTextStyle()
{ {
static bool inited = false; static bool inited = false;
if (!inited) if (!inited)
{ {
inited = true; inited = true;
// 默认使用白色画刷填充文字 // 默认使用白色画刷填充文字
text_default_style.fill_brush = new Brush; text_default_style.fill_brush = new Brush;
text_default_style.fill_brush->SetColor(Color::White); text_default_style.fill_brush->SetColor(Color::White);
} }
}
}
void TextActor::SetDefaultStyle(TextStyle const & style)
{
text_default_style = style;
}
const TextStyle& TextActor::GetDefaultStyle()
{
return text_default_style;
}
TextActor::TextActor()
: TextActor(String())
{
}
TextActor::TextActor(String const& text)
: TextActor(text, text_default_style)
{
}
TextActor::TextActor(String const& text, const TextStyle& style)
: show_underline_(false)
, show_strikethrough_(false)
{
InitDefaultTextStyle();
SetText(text);
SetStyle(style);
}
TextActor::~TextActor()
{
}
void TextActor::OnRender(RenderTarget* rt)
{
rt->DrawTextLayout(text_layout_);
}
void TextActor::OnUpdate(Duration dt)
{
UpdateLayout();
}
void TextActor::UpdateLayout()
{
if (text_layout_.IsDirty())
{
text_layout_.Update();
if (show_underline_)
text_layout_.SetUnderline(true, 0, text_layout_.GetText().length());
if (show_strikethrough_)
text_layout_.SetStrikethrough(true, 0, text_layout_.GetText().length());
SetSize(text_layout_.GetLayoutSize());
}
}
bool TextActor::CheckVisibilty(RenderTarget* rt) const
{
return text_layout_.IsValid() && Actor::CheckVisibilty(rt);
}
void TextActor::SetFillColor(Color const& color)
{
if (!text_layout_.GetFillBrush())
{
BrushPtr brush = new Brush;
text_layout_.SetFillBrush(brush);
}
text_layout_.GetFillBrush()->SetColor(color);
}
void TextActor::SetOutlineColor(Color const& outline_color)
{
if (!text_layout_.GetOutlineBrush())
{
BrushPtr brush = new Brush;
text_layout_.SetOutlineBrush(brush);
}
text_layout_.GetOutlineBrush()->SetColor(outline_color);
}
} }
} // namespace
void TextActor::SetDefaultStyle(TextStyle const& style)
{
text_default_style = style;
}
const TextStyle& TextActor::GetDefaultStyle()
{
InitDefaultTextStyle();
return text_default_style;
}
TextActor::TextActor()
: TextActor(String())
{
}
TextActor::TextActor(String const& text)
: TextActor(text, GetDefaultStyle())
{
}
TextActor::TextActor(String const& text, const TextStyle& style)
: show_underline_(false)
, show_strikethrough_(false)
{
SetText(text);
SetStyle(style);
}
TextActor::~TextActor() {}
void TextActor::OnRender(RenderContext& ctx)
{
ctx.DrawTextLayout(text_layout_);
}
void TextActor::OnUpdate(Duration dt)
{
UpdateLayout();
}
void TextActor::UpdateLayout()
{
if (text_layout_.IsDirty())
{
text_layout_.Update();
}
if (text_layout_.GetDirtyFlag() & TextLayout::DirtyFlag::Updated)
{
text_layout_.SetDirtyFlag(TextLayout::DirtyFlag::Clean);
if (show_underline_)
text_layout_.SetUnderline(true, 0, text_layout_.GetText().length());
if (show_strikethrough_)
text_layout_.SetStrikethrough(true, 0, text_layout_.GetText().length());
SetSize(text_layout_.GetLayoutSize());
}
}
bool TextActor::CheckVisibility(RenderContext& ctx) const
{
return text_layout_.IsValid() && Actor::CheckVisibility(ctx);
}
void TextActor::SetFillColor(Color const& color)
{
if (!text_layout_.GetFillBrush() || text_layout_.GetFillBrush() == GetDefaultStyle().fill_brush)
{
BrushPtr brush = new Brush;
text_layout_.SetFillBrush(brush);
}
text_layout_.GetFillBrush()->SetColor(color);
}
void TextActor::SetOutlineColor(Color const& outline_color)
{
if (!text_layout_.GetOutlineBrush() || text_layout_.GetOutlineBrush() == GetDefaultStyle().outline_brush)
{
BrushPtr brush = new Brush;
text_layout_.SetOutlineBrush(brush);
}
text_layout_.GetOutlineBrush()->SetColor(outline_color);
}
} // namespace kiwano

View File

@ -1,15 +1,15 @@
// Copyright (c) 2016-2018 Kiwano - Nomango // Copyright (c) 2016-2018 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -20,275 +20,282 @@
#pragma once #pragma once
#include <kiwano/2d/Actor.h> #include <kiwano/2d/Actor.h>
#include <kiwano/renderer/Color.h> #include <kiwano/render/Color.h>
#include <kiwano/renderer/TextLayout.h> #include <kiwano/render/TextLayout.h>
namespace kiwano namespace kiwano
{ {
KGE_DECLARE_SMART_PTR(TextActor); KGE_DECLARE_SMART_PTR(TextActor);
/** /**
* \addtogroup Actors * \addtogroup Actors
* @{ * @{
*/ */
/** /**
* \~chinese * \~chinese
* @brief * @brief
*/ */
class KGE_API TextActor class KGE_API TextActor : public Actor
: public Actor {
{ public:
public: /// \~chinese
/// \~chinese /// @brief 构建空的文本角色
/// @brief 构建空的文本角色 TextActor();
TextActor();
/// \~chinese /// \~chinese
/// @brief 构建文本角色 /// @brief 构建文本角色
/// @param text 文字内容 /// @param text 文字内容
explicit TextActor(const String& text); explicit TextActor(const String& text);
/// \~chinese /// \~chinese
/// @brief 构建文本角色 /// @brief 构建文本角色
/// @param text 文字内容 /// @param text 文字内容
/// @param style 文本样式 /// @param style 文本样式
TextActor(const String& text, const TextStyle& style); TextActor(const String& text, const TextStyle& style);
virtual ~TextActor(); virtual ~TextActor();
/// \~chinese /// \~chinese
/// @brief 获取文本 /// @brief 获取文本
const String& GetText() const; const String& GetText() const;
/// \~chinese /// \~chinese
/// @brief 获取文本样式 /// @brief 获取文本样式
const TextStyle& GetStyle() const; const TextStyle& GetStyle() const;
/// \~chinese /// \~chinese
/// @brief 获取文本布局 /// @brief 获取文本布局
const TextLayout& GetLayout() const; const TextLayout& GetLayout() const;
/// \~chinese /// \~chinese
/// @brief 获取填充画刷 /// @brief 获取文本布局大小
BrushPtr GetFillBrush() const; Size GetLayoutSize() const;
/// \~chinese /// \~chinese
/// @brief 获取描边画刷 /// @brief 获取填充画刷
BrushPtr GetOutlineBrush() const; BrushPtr GetFillBrush() const;
/// \~chinese /// \~chinese
/// @brief 获取字体 /// @brief 获取描边画刷
FontPtr GetFont() const; BrushPtr GetOutlineBrush() const;
/// \~chinese /// \~chinese
/// @brief 设置文本 /// @brief 获取字体
void SetText(String const& text); FontPtr GetFont() const;
/// \~chinese /// \~chinese
/// @brief 设置文本样式 /// @brief 设置文本
void SetStyle(const TextStyle& style); void SetText(String const& text);
/// \~chinese /// \~chinese
/// @brief 设置字体 /// @brief 设置文本样式
void SetFont(FontPtr font); void SetStyle(const TextStyle& style);
/// \~chinese /// \~chinese
/// @brief 设置字体族 /// @brief 设置字体
void SetFontFamily(String const& family); void SetFont(FontPtr font);
/// \~chinese /// \~chinese
/// @brief 设置字号(默认值为 18 /// @brief 设置字体族
void SetFontSize(float size); void SetFontFamily(String const& family);
/// \~chinese /// \~chinese
/// @brief 设置字体粗细值(默认值为 FontWeight::Normal /// @brief 设置字号(默认值为 18
void SetFontWeight(uint32_t weight); void SetFontSize(float size);
/// \~chinese /// \~chinese
/// @brief 设置文字填充画刷 /// @brief 设置字体粗细值(默认值为 FontWeight::Normal
void SetFillBrush(BrushPtr brush); void SetFontWeight(uint32_t weight);
/// \~chinese /// \~chinese
/// @brief 设置文字填充颜色(默认值为 Color::White /// @brief 设置文字填充画刷
void SetFillColor(Color const& color); void SetFillBrush(BrushPtr brush);
/// \~chinese /// \~chinese
/// @brief 设置文字斜体(默认值为 false /// @brief 设置文字填充颜色(默认值为 Color::White
void SetItalic(bool italic); void SetFillColor(Color const& color);
/// \~chinese /// \~chinese
/// @brief 设置文本自动换行的宽度(默认为 0 /// @brief 设置文字斜体(默认值为 false
void SetWrapWidth(float wrap_width); void SetItalic(bool italic);
/// \~chinese /// \~chinese
/// @brief 设置行间距(默认为 0 /// @brief 设置文本自动换行的宽度(默认为 0
void SetLineSpacing(float line_spacing); void SetWrapWidth(float wrap_width);
/// \~chinese /// \~chinese
/// @brief 设置对齐方式(默认为 TextAlign::Left /// @brief 设置行间距(默认为 0
void SetAlignment(TextAlign align); void SetLineSpacing(float line_spacing);
/// \~chinese /// \~chinese
/// @brief 设置文字描边画刷 /// @brief 设置对齐方式(默认为 TextAlign::Left
void SetOutlineBrush(BrushPtr brush); void SetAlignment(TextAlign align);
/// \~chinese /// \~chinese
/// @brief 设置文字描边颜色 /// @brief 设置文字描边画刷
void SetOutlineColor(Color const& outline_color); void SetOutlineBrush(BrushPtr brush);
/// \~chinese /// \~chinese
/// @brief 设置文字描边线宽 /// @brief 设置文字描边颜色
void SetOutlineWidth(float outline_width); void SetOutlineColor(Color const& outline_color);
/// \~chinese /// \~chinese
/// @brief 设置文字描边线相交样式 /// @brief 设置文字描边线宽
void SetOutlineStroke(StrokeStyle outline_stroke); void SetOutlineWidth(float outline_width);
/// \~chinese /// \~chinese
/// @brief 设置是否显示下划线(默认值为 false /// @brief 设置文字描边线相交样式
void SetUnderline(bool enable); void SetOutlineStroke(const StrokeStyle& outline_stroke);
/// \~chinese /// \~chinese
/// @brief 设置是否显示删除线(默认值为 false /// @brief 设置是否显示下划线(默认值为 false
void SetStrikethrough(bool enable); void SetUnderline(bool enable);
/// \~chinese /// \~chinese
/// @brief 更新文字布局 /// @brief 设置是否显示删除线(默认值为 false
/// @details 文字布局是懒更新的,手动更新文字布局以更新节点状态 void SetStrikethrough(bool enable);
void UpdateLayout();
/// \~chinese /// \~chinese
/// @brief 设置默认文字样式 /// @brief 更新文字布局
static void SetDefaultStyle(TextStyle const& style); /// @details 文字布局是懒更新的,手动更新文字布局以更新节点状态
void UpdateLayout();
/// \~chinese /// \~chinese
/// @brief 获取默认文字样式 /// @brief 设置默认文字样式
static const TextStyle& GetDefaultStyle(); static void SetDefaultStyle(TextStyle const& style);
void OnRender(RenderTarget* rt) override; /// \~chinese
/// @brief 获取默认文字样式
static const TextStyle& GetDefaultStyle();
void OnUpdate(Duration dt) override; void OnRender(RenderContext& ctx) override;
protected: void OnUpdate(Duration dt) override;
bool CheckVisibilty(RenderTarget* rt) const override;
private: protected:
bool show_underline_; bool CheckVisibility(RenderContext& ctx) const override;
bool show_strikethrough_;
TextLayout text_layout_;
};
/** @} */ private:
bool show_underline_;
bool show_strikethrough_;
TextLayout text_layout_;
};
inline const String& TextActor::GetText() const /** @} */
{
return text_layout_.GetText();
}
inline FontPtr TextActor::GetFont() const
{
return text_layout_.GetStyle().font;
}
inline const TextStyle& TextActor::GetStyle() const
{
return text_layout_.GetStyle();
}
inline const TextLayout& TextActor::GetLayout() const
{
return text_layout_;
}
inline BrushPtr TextActor::GetFillBrush() const
{
return text_layout_.GetFillBrush();
}
inline BrushPtr TextActor::GetOutlineBrush() const
{
return text_layout_.GetOutlineBrush();
}
inline void TextActor::SetText(String const& text)
{
text_layout_.SetText(text);
}
inline void TextActor::SetStyle(const TextStyle& style)
{
text_layout_.SetStyle(style);
}
inline void TextActor::SetFont(FontPtr font)
{
text_layout_.SetFont(font);
}
inline void TextActor::SetFontFamily(String const& family)
{
text_layout_.SetFontFamily(family);
}
inline void TextActor::SetFontSize(float size)
{
text_layout_.SetFontSize(size);
}
inline void TextActor::SetFontWeight(uint32_t weight)
{
text_layout_.SetFontWeight(weight);
}
inline void TextActor::SetItalic(bool italic)
{
text_layout_.SetItalic(italic);
}
inline void TextActor::SetWrapWidth(float wrap_width)
{
text_layout_.SetWrapWidth(wrap_width);
}
inline void TextActor::SetLineSpacing(float line_spacing)
{
text_layout_.SetLineSpacing(line_spacing);
}
inline void TextActor::SetAlignment(TextAlign align)
{
text_layout_.SetAlignment(align);
}
inline void TextActor::SetUnderline(bool enable)
{
show_underline_ = enable;
}
inline void TextActor::SetStrikethrough(bool enable)
{
show_strikethrough_ = enable;
}
inline void TextActor::SetFillBrush(BrushPtr brush)
{
text_layout_.SetFillBrush(brush);
}
inline void TextActor::SetOutlineBrush(BrushPtr brush)
{
text_layout_.SetOutlineBrush(brush);
}
inline void TextActor::SetOutlineWidth(float outline_width)
{
text_layout_.SetOutlineWidth(outline_width);
}
inline void TextActor::SetOutlineStroke(StrokeStyle outline_stroke)
{
text_layout_.SetOutlineStroke(outline_stroke);
}
inline const String& TextActor::GetText() const
{
return text_layout_.GetText();
} }
inline FontPtr TextActor::GetFont() const
{
return text_layout_.GetStyle().font;
}
inline const TextStyle& TextActor::GetStyle() const
{
return text_layout_.GetStyle();
}
inline const TextLayout& TextActor::GetLayout() const
{
return text_layout_;
}
inline Size TextActor::GetLayoutSize() const
{
return text_layout_.GetLayoutSize();
}
inline BrushPtr TextActor::GetFillBrush() const
{
return text_layout_.GetFillBrush();
}
inline BrushPtr TextActor::GetOutlineBrush() const
{
return text_layout_.GetOutlineBrush();
}
inline void TextActor::SetText(String const& text)
{
text_layout_.SetText(text);
}
inline void TextActor::SetStyle(const TextStyle& style)
{
text_layout_.SetStyle(style);
}
inline void TextActor::SetFont(FontPtr font)
{
text_layout_.SetFont(font);
}
inline void TextActor::SetFontFamily(String const& family)
{
text_layout_.SetFontFamily(family);
}
inline void TextActor::SetFontSize(float size)
{
text_layout_.SetFontSize(size);
}
inline void TextActor::SetFontWeight(uint32_t weight)
{
text_layout_.SetFontWeight(weight);
}
inline void TextActor::SetItalic(bool italic)
{
text_layout_.SetItalic(italic);
}
inline void TextActor::SetWrapWidth(float wrap_width)
{
text_layout_.SetWrapWidth(wrap_width);
}
inline void TextActor::SetLineSpacing(float line_spacing)
{
text_layout_.SetLineSpacing(line_spacing);
}
inline void TextActor::SetAlignment(TextAlign align)
{
text_layout_.SetAlignment(align);
}
inline void TextActor::SetUnderline(bool enable)
{
show_underline_ = enable;
}
inline void TextActor::SetStrikethrough(bool enable)
{
show_strikethrough_ = enable;
}
inline void TextActor::SetFillBrush(BrushPtr brush)
{
text_layout_.SetFillBrush(brush);
}
inline void TextActor::SetOutlineBrush(BrushPtr brush)
{
text_layout_.SetOutlineBrush(brush);
}
inline void TextActor::SetOutlineWidth(float outline_width)
{
text_layout_.SetOutlineWidth(outline_width);
}
inline void TextActor::SetOutlineStroke(const StrokeStyle& outline_stroke)
{
text_layout_.SetOutlineStroke(outline_stroke);
}
} // namespace kiwano

View File

@ -1,15 +1,15 @@
// Copyright (c) 2016-2018 Kiwano - Nomango // Copyright (c) 2016-2018 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -22,28 +22,25 @@
namespace kiwano namespace kiwano
{ {
Transform::Transform() Transform::Transform()
: position() : position()
, rotation(0.f) , rotation(0.f)
, scale(1.f, 1.f) , scale(1.f, 1.f)
, skew(0.f, 0.f) , skew(0.f, 0.f)
{ {
}
Matrix3x2 Transform::ToMatrix() const
{
if (!skew.IsOrigin())
{
return Matrix3x2::Skewing(skew) * Matrix3x2::SRT(position, scale, rotation);
}
return Matrix3x2::SRT(position, scale, rotation);
}
bool Transform::operator== (Transform const& rhs) const
{
return position == rhs.position &&
rotation == rhs.rotation &&
scale == rhs.scale &&
skew == rhs.skew;
}
} }
Matrix3x2 Transform::ToMatrix() const
{
if (!skew.IsOrigin())
{
return Matrix3x2::Skewing(skew) * Matrix3x2::SRT(position, scale, rotation);
}
return Matrix3x2::SRT(position, scale, rotation);
}
bool Transform::operator==(Transform const& rhs) const
{
return position == rhs.position && rotation == rhs.rotation && scale == rhs.scale && skew == rhs.skew;
}
} // namespace kiwano

View File

@ -1,15 +1,15 @@
// Copyright (c) 2016-2018 Kiwano - Nomango // Copyright (c) 2016-2018 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -23,25 +23,25 @@
namespace kiwano namespace kiwano
{ {
/** /**
* \~chinese * \~chinese
* @brief * @brief
*/ */
class Transform class Transform
{ {
public: public:
float rotation; ///< 旋转 float rotation; ///< 旋转
Point position; ///< 坐标 Point position; ///< 坐标
Point scale; ///< 缩放 Point scale; ///< 缩放
Point skew; ///< 错切角度 Point skew; ///< 错切角度
public: public:
Transform(); Transform();
/// \~chinese /// \~chinese
/// @brief 将二维放射变换转换为矩阵 /// @brief 将二维放射变换转换为矩阵
Matrix3x2 ToMatrix() const; Matrix3x2 ToMatrix() const;
bool operator== (const Transform& rhs) const; bool operator==(const Transform& rhs) const;
}; };
} } // namespace kiwano

View File

@ -1,15 +1,15 @@
// Copyright (c) 2016-2018 Kiwano - Nomango // Copyright (c) 2016-2018 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -18,369 +18,355 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE. // THE SOFTWARE.
#include <kiwano/2d/Transition.h>
#include <kiwano/2d/Actor.h> #include <kiwano/2d/Actor.h>
#include <kiwano/2d/Stage.h> #include <kiwano/2d/Stage.h>
#include <kiwano/platform/Window.h> #include <kiwano/2d/Transition.h>
#include <kiwano/core/Logger.h> #include <kiwano/core/Logger.h>
#include <kiwano/renderer/Renderer.h> #include <kiwano/platform/Window.h>
#include <kiwano/render/Renderer.h>
namespace kiwano namespace kiwano
{ {
//------------------------------------------------------- //-------------------------------------------------------
// Transition // Transition
//------------------------------------------------------- //-------------------------------------------------------
Transition::Transition(Duration duration) Transition::Transition(Duration duration)
: done_(false) : done_(false)
, duration_(duration) , duration_(duration)
, delta_() , delta_()
, process_(0) , process_(0)
, window_size_() , window_size_()
, out_stage_(nullptr) , out_stage_(nullptr)
, in_stage_(nullptr) , in_stage_(nullptr)
, out_layer_() , out_layer_()
, in_layer_() , in_layer_()
{ {
}
Transition::~Transition()
{
}
bool Transition::IsDone()
{
return done_;
}
void Transition::Init(StagePtr prev, StagePtr next)
{
process_ = 0;
delta_ = Duration{};
out_stage_ = prev;
in_stage_ = next;
window_size_ = Renderer::instance().GetOutputSize();
if (in_stage_)
{
in_layer_.SetAreaRect(Rect{ Point(), window_size_ });
}
if (out_stage_)
{
out_layer_.SetAreaRect(Rect{ Point(), window_size_ });
}
}
void Transition::Update(Duration dt)
{
if (duration_.IsZero())
{
process_ = 1;
}
else
{
delta_ += dt;
process_ = std::min(delta_ / duration_, 1.f);
}
if (process_ >= 1)
{
this->Stop();
}
}
void Transition::Render(RenderTarget* rt)
{
if (out_stage_)
{
out_stage_->PrepareToRender(rt);
rt->PushClipRect(Rect{ Point{}, window_size_ });
rt->PushLayer(out_layer_);
out_stage_->Render(rt);
rt->PopLayer();
rt->PopClipRect();
}
if (in_stage_)
{
in_stage_->PrepareToRender(rt);
rt->PushClipRect(Rect{ Point{}, window_size_ });
rt->PushLayer(in_layer_);
in_stage_->Render(rt);
rt->PopLayer();
rt->PopClipRect();
}
}
void Transition::Stop()
{
done_ = true;
Reset();
}
//-------------------------------------------------------
// BoxTransition
//-------------------------------------------------------
BoxTransition::BoxTransition(Duration duration)
: Transition(duration)
{
}
void BoxTransition::Init(StagePtr prev, StagePtr next)
{
Transition::Init(prev, next);
in_layer_.SetOpacity(0.f);
}
void BoxTransition::Update(Duration dt)
{
Transition::Update(dt);
if (process_ < .5f)
{
out_layer_.SetAreaRect(
Rect(
window_size_.x * process_,
window_size_.y * process_,
window_size_.x * (1 - process_),
window_size_.y * (1 - process_)
)
);
}
else
{
out_layer_.SetOpacity(0.f);
in_layer_.SetOpacity(1.f);
in_layer_.SetAreaRect(
Rect(
window_size_.x * (1 - process_),
window_size_.y * (1 - process_),
window_size_.x * process_,
window_size_.y * process_
)
);
}
}
//-------------------------------------------------------
// EmergeTransition
//-------------------------------------------------------
EmergeTransition::EmergeTransition(Duration duration)
: Transition(duration)
{
}
void EmergeTransition::Init(StagePtr prev, StagePtr next)
{
Transition::Init(prev, next);
out_layer_.SetOpacity(1.f);
in_layer_.SetOpacity(0.f);
}
void EmergeTransition::Update(Duration dt)
{
Transition::Update(dt);
out_layer_.SetOpacity(1 - process_);
in_layer_.SetOpacity(process_);
}
//-------------------------------------------------------
// FadeTransition
//-------------------------------------------------------
FadeTransition::FadeTransition(Duration duration)
: Transition(duration)
{
}
void FadeTransition::Init(StagePtr prev, StagePtr next)
{
Transition::Init(prev, next);
out_layer_.SetOpacity(1.f);
in_layer_.SetOpacity(0.f);
}
void FadeTransition::Update(Duration dt)
{
Transition::Update(dt);
if (process_ < 0.5)
{
out_layer_.SetOpacity(1 - process_ * 2);
in_layer_.SetOpacity(0.f);
}
else
{
out_layer_.SetOpacity(0.f);
in_layer_.SetOpacity((process_ - 0.5f) * 2);
}
}
//-------------------------------------------------------
// MoveTransition
//-------------------------------------------------------
MoveTransition::MoveTransition(Duration duration, Type type)
: Transition(duration)
, type_(type)
{
}
void MoveTransition::Init(StagePtr prev, StagePtr next)
{
Transition::Init(prev, next);
switch (type_)
{
case Type::Up:
pos_delta_ = Point(0, -window_size_.y);
start_pos_ = Point(0, window_size_.y);
break;
case Type::Down:
pos_delta_ = Point(0, window_size_.y);
start_pos_ = Point(0, -window_size_.y);
break;
case Type::Left:
pos_delta_ = Point(-window_size_.x, 0);
start_pos_ = Point(window_size_.x, 0);
break;
case Type::Right:
pos_delta_ = Point(window_size_.x, 0);
start_pos_ = Point(-window_size_.x, 0);
break;
}
if (out_stage_)
{
out_stage_->SetTransform(Transform{});
}
if (in_stage_)
{
auto transform = Transform{};
transform.position = start_pos_;
in_stage_->SetTransform(transform);
}
}
void MoveTransition::Update(Duration dt)
{
Transition::Update(dt);
if (out_stage_)
{
auto transform = Transform{};
transform.position = pos_delta_ * process_;
out_stage_->SetTransform(transform);
}
if (in_stage_)
{
auto transform = Transform{};
transform.position = start_pos_ + pos_delta_ * process_;
in_stage_->SetTransform(transform);
}
}
void MoveTransition::Reset()
{
if (out_stage_)
{
out_stage_->SetTransform(Transform{});
}
if (in_stage_)
{
in_stage_->SetTransform(Transform{});
}
}
//-------------------------------------------------------
// RotationTransition
//-------------------------------------------------------
RotationTransition::RotationTransition(Duration duration, float rotation)
: Transition(duration)
, rotation_(rotation)
{
}
void RotationTransition::Init(StagePtr prev, StagePtr next)
{
Transition::Init(prev, next);
auto transform = Transform{};
transform.position = Point{ window_size_.x / 2, window_size_.y / 2 };
if (out_stage_)
{
out_stage_->SetTransform(transform);
out_stage_->SetAnchor(Vec2{ 0.5f, 0.5f });
}
if (in_stage_)
{
in_stage_->SetTransform(transform);
in_stage_->SetAnchor(Vec2{ 0.5f, 0.5f });
}
in_layer_.SetOpacity(0.f);
}
void RotationTransition::Update(Duration dt)
{
Transition::Update(dt);
if (process_ < .5f)
{
if (out_stage_)
{
auto transform = out_stage_->GetTransform();
transform.scale = Point{ (.5f - process_) * 2, (.5f - process_) * 2 };
transform.rotation = rotation_ * (.5f - process_) * 2;
out_stage_->SetTransform(transform);
}
}
else
{
if (in_stage_)
{
out_layer_.SetOpacity(0.f);
in_layer_.SetOpacity(1.f);
auto transform = in_stage_->GetTransform();
transform.scale = Point{ (process_ - .5f) * 2, (process_ - .5f) * 2 };
transform.rotation = rotation_ * (process_ - .5f) * 2;
in_stage_->SetTransform(transform);
}
}
}
void RotationTransition::Reset()
{
if (out_stage_)
{
out_stage_->SetTransform(Transform{});
out_stage_->SetAnchor(Vec2{ 0.f, 0.f });
}
if (in_stage_)
{
in_stage_->SetTransform(Transform{});
in_stage_->SetAnchor(Vec2{ 0.f, 0.f });
}
}
} }
Transition::~Transition() {}
bool Transition::IsDone()
{
return done_;
}
void Transition::Init(StagePtr prev, StagePtr next)
{
process_ = 0;
delta_ = Duration{};
out_stage_ = prev;
in_stage_ = next;
window_size_ = Renderer::Instance().GetOutputSize();
if (in_stage_)
{
in_layer_.SetAreaRect(Rect{ Point(), window_size_ });
}
if (out_stage_)
{
out_layer_.SetAreaRect(Rect{ Point(), window_size_ });
}
}
void Transition::Update(Duration dt)
{
if (duration_.IsZero())
{
process_ = 1;
}
else
{
delta_ += dt;
process_ = std::min(delta_ / duration_, 1.f);
}
if (process_ >= 1)
{
this->Stop();
}
}
void Transition::Render(RenderContext& ctx)
{
if (out_stage_)
{
out_stage_->PrepareToRender(ctx);
ctx.PushClipRect(Rect{ Point{}, window_size_ });
ctx.PushLayer(out_layer_);
out_stage_->Render(ctx);
ctx.PopLayer();
ctx.PopClipRect();
}
if (in_stage_)
{
in_stage_->PrepareToRender(ctx);
ctx.PushClipRect(Rect{ Point{}, window_size_ });
ctx.PushLayer(in_layer_);
in_stage_->Render(ctx);
ctx.PopLayer();
ctx.PopClipRect();
}
}
void Transition::Stop()
{
done_ = true;
Reset();
}
//-------------------------------------------------------
// BoxTransition
//-------------------------------------------------------
BoxTransition::BoxTransition(Duration duration)
: Transition(duration)
{
}
void BoxTransition::Init(StagePtr prev, StagePtr next)
{
Transition::Init(prev, next);
in_layer_.SetOpacity(0.f);
}
void BoxTransition::Update(Duration dt)
{
Transition::Update(dt);
if (process_ < .5f)
{
out_layer_.SetAreaRect(Rect(window_size_.x * process_, window_size_.y * process_,
window_size_.x * (1 - process_), window_size_.y * (1 - process_)));
}
else
{
out_layer_.SetOpacity(0.f);
in_layer_.SetOpacity(1.f);
in_layer_.SetAreaRect(Rect(window_size_.x * (1 - process_), window_size_.y * (1 - process_),
window_size_.x * process_, window_size_.y * process_));
}
}
//-------------------------------------------------------
// EmergeTransition
//-------------------------------------------------------
EmergeTransition::EmergeTransition(Duration duration)
: Transition(duration)
{
}
void EmergeTransition::Init(StagePtr prev, StagePtr next)
{
Transition::Init(prev, next);
out_layer_.SetOpacity(1.f);
in_layer_.SetOpacity(0.f);
}
void EmergeTransition::Update(Duration dt)
{
Transition::Update(dt);
out_layer_.SetOpacity(1 - process_);
in_layer_.SetOpacity(process_);
}
//-------------------------------------------------------
// FadeTransition
//-------------------------------------------------------
FadeTransition::FadeTransition(Duration duration)
: Transition(duration)
{
}
void FadeTransition::Init(StagePtr prev, StagePtr next)
{
Transition::Init(prev, next);
out_layer_.SetOpacity(1.f);
in_layer_.SetOpacity(0.f);
}
void FadeTransition::Update(Duration dt)
{
Transition::Update(dt);
if (process_ < 0.5)
{
out_layer_.SetOpacity(1 - process_ * 2);
in_layer_.SetOpacity(0.f);
}
else
{
out_layer_.SetOpacity(0.f);
in_layer_.SetOpacity((process_ - 0.5f) * 2);
}
}
//-------------------------------------------------------
// MoveTransition
//-------------------------------------------------------
MoveTransition::MoveTransition(Duration duration, Type type)
: Transition(duration)
, type_(type)
{
}
void MoveTransition::Init(StagePtr prev, StagePtr next)
{
Transition::Init(prev, next);
switch (type_)
{
case Type::Up:
pos_delta_ = Point(0, -window_size_.y);
start_pos_ = Point(0, window_size_.y);
break;
case Type::Down:
pos_delta_ = Point(0, window_size_.y);
start_pos_ = Point(0, -window_size_.y);
break;
case Type::Left:
pos_delta_ = Point(-window_size_.x, 0);
start_pos_ = Point(window_size_.x, 0);
break;
case Type::Right:
pos_delta_ = Point(window_size_.x, 0);
start_pos_ = Point(-window_size_.x, 0);
break;
}
if (out_stage_)
{
out_stage_->SetTransform(Transform{});
}
if (in_stage_)
{
auto transform = Transform{};
transform.position = start_pos_;
in_stage_->SetTransform(transform);
}
}
void MoveTransition::Update(Duration dt)
{
Transition::Update(dt);
if (out_stage_)
{
auto transform = Transform{};
transform.position = pos_delta_ * process_;
out_stage_->SetTransform(transform);
}
if (in_stage_)
{
auto transform = Transform{};
transform.position = start_pos_ + pos_delta_ * process_;
in_stage_->SetTransform(transform);
}
}
void MoveTransition::Reset()
{
if (out_stage_)
{
out_stage_->SetTransform(Transform{});
}
if (in_stage_)
{
in_stage_->SetTransform(Transform{});
}
}
//-------------------------------------------------------
// RotationTransition
//-------------------------------------------------------
RotationTransition::RotationTransition(Duration duration, float rotation)
: Transition(duration)
, rotation_(rotation)
{
}
void RotationTransition::Init(StagePtr prev, StagePtr next)
{
Transition::Init(prev, next);
auto transform = Transform{};
transform.position = Point{ window_size_.x / 2, window_size_.y / 2 };
if (out_stage_)
{
out_stage_->SetTransform(transform);
out_stage_->SetAnchor(Vec2{ 0.5f, 0.5f });
}
if (in_stage_)
{
in_stage_->SetTransform(transform);
in_stage_->SetAnchor(Vec2{ 0.5f, 0.5f });
}
in_layer_.SetOpacity(0.f);
}
void RotationTransition::Update(Duration dt)
{
Transition::Update(dt);
if (process_ < .5f)
{
if (out_stage_)
{
auto transform = out_stage_->GetTransform();
transform.scale = Point{ (.5f - process_) * 2, (.5f - process_) * 2 };
transform.rotation = rotation_ * (.5f - process_) * 2;
out_stage_->SetTransform(transform);
}
}
else
{
if (in_stage_)
{
out_layer_.SetOpacity(0.f);
in_layer_.SetOpacity(1.f);
auto transform = in_stage_->GetTransform();
transform.scale = Point{ (process_ - .5f) * 2, (process_ - .5f) * 2 };
transform.rotation = rotation_ * (process_ - .5f) * 2;
in_stage_->SetTransform(transform);
}
}
}
void RotationTransition::Reset()
{
if (out_stage_)
{
out_stage_->SetTransform(Transform{});
out_stage_->SetAnchor(Vec2{ 0.f, 0.f });
}
if (in_stage_)
{
in_stage_->SetTransform(Transform{});
in_stage_->SetAnchor(Vec2{ 0.f, 0.f });
}
}
} // namespace kiwano

View File

@ -1,15 +1,15 @@
// Copyright (c) 2016-2018 Kiwano - Nomango // Copyright (c) 2016-2018 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -20,262 +20,219 @@
#pragma once #pragma once
#include <kiwano/2d/Stage.h> #include <kiwano/2d/Stage.h>
#include <kiwano/renderer/LayerArea.h> #include <kiwano/render/LayerArea.h>
namespace kiwano namespace kiwano
{ {
class Director; class Director;
class RenderTarget; class RenderContext;
KGE_DECLARE_SMART_PTR(Transition); KGE_DECLARE_SMART_PTR(Transition);
KGE_DECLARE_SMART_PTR(FadeTransition); KGE_DECLARE_SMART_PTR(FadeTransition);
KGE_DECLARE_SMART_PTR(EmergeTransition); KGE_DECLARE_SMART_PTR(EmergeTransition);
KGE_DECLARE_SMART_PTR(BoxTransition); KGE_DECLARE_SMART_PTR(BoxTransition);
KGE_DECLARE_SMART_PTR(MoveTransition); KGE_DECLARE_SMART_PTR(MoveTransition);
KGE_DECLARE_SMART_PTR(RotationTransition); KGE_DECLARE_SMART_PTR(RotationTransition);
/** /**
* \~chinese * \~chinese
* @brief * @brief
*/ */
class KGE_API Transition class KGE_API Transition : public virtual ObjectBase
: public ObjectBase {
{ friend class Director;
friend class Director;
public: public:
/** /**
* \~chinese * \~chinese
* @brief * @brief
* @param duration * @param duration
*/ */
explicit Transition( explicit Transition(Duration duration);
Duration duration
);
virtual ~Transition(); virtual ~Transition();
/** /**
* \~chinese * \~chinese
* @brief * @brief
*/ */
bool IsDone(); bool IsDone();
protected: protected:
/** /**
* \~chinese * \~chinese
* @brief * @brief
* @param[in] prev * @param[in] prev
* @param[in] next * @param[in] next
*/ */
virtual void Init( virtual void Init(StagePtr prev, StagePtr next);
StagePtr prev,
StagePtr next
);
/** /**
* \~chinese * \~chinese
* @brief * @brief
* @param dt * @param dt
*/ */
virtual void Update(Duration dt); virtual void Update(Duration dt);
/** /**
* \~chinese * \~chinese
* @brief * @brief
* @param[in] rt * @param[in] ctx
*/ */
virtual void Render(RenderTarget* rt); virtual void Render(RenderContext& ctx);
/** /**
* \~chinese * \~chinese
* @brief * @brief
*/ */
virtual void Stop(); virtual void Stop();
/** /**
* \~chinese * \~chinese
* @brief * @brief
*/ */
virtual void Reset() {} virtual void Reset() {}
protected: protected:
bool done_; bool done_;
float process_; float process_;
Duration duration_; Duration duration_;
Duration delta_; Duration delta_;
Size window_size_; Size window_size_;
StagePtr out_stage_; StagePtr out_stage_;
StagePtr in_stage_; StagePtr in_stage_;
LayerArea out_layer_; LayerArea out_layer_;
LayerArea in_layer_; LayerArea in_layer_;
}; };
/**
* \~chinese
* @brief
* @details
*/
class FadeTransition : public Transition
{
public:
/**
* \~chinese
* @brief
* @param duration
*/
explicit FadeTransition(Duration duration);
/** protected:
* \~chinese void Update(Duration dt) override;
* @brief
* @details
*/
class FadeTransition
: public Transition
{
public:
/**
* \~chinese
* @brief
* @param duration
*/
explicit FadeTransition(
Duration duration
);
protected: virtual void Init(StagePtr prev, StagePtr next) override;
void Update(Duration dt) override; };
virtual void Init( /**
StagePtr prev, * \~chinese
StagePtr next * @brief
) override; * @details
}; */
class EmergeTransition : public Transition
{
public:
/**
* \~chinese
* @brief
* @param duration
*/
explicit EmergeTransition(Duration duration);
protected:
void Update(Duration dt) override;
/** virtual void Init(StagePtr prev, StagePtr next) override;
* \~chinese };
* @brief
* @details
*/
class EmergeTransition
: public Transition
{
public:
/**
* \~chinese
* @brief
* @param duration
*/
explicit EmergeTransition(
Duration duration
);
protected: /**
void Update(Duration dt) override; * \~chinese
* @brief
* @details
*/
class BoxTransition : public Transition
{
public:
/**
* \~chinese
* @brief
* @param duration
*/
explicit BoxTransition(Duration duration);
virtual void Init( protected:
StagePtr prev, void Update(Duration dt) override;
StagePtr next
) override;
};
virtual void Init(StagePtr prev, StagePtr next) override;
};
/** /**
* \~chinese * \~chinese
* @brief * @brief
* @details * @details
*/ */
class BoxTransition class MoveTransition : public Transition
: public Transition {
{ public:
public: /**
/** * \~chinese
* \~chinese * @brief
* @brief */
* @param duration enum class Type : int
*/ {
explicit BoxTransition( Up, ///< 上移
Duration duration Down, ///< 下移
); Left, ///< 左移
Right ///< 右移
};
protected: /**
void Update(Duration dt) override; * \~chinese
* @brief
* @param duration
* @param type
*/
explicit MoveTransition(Duration duration, Type type);
virtual void Init( protected:
StagePtr prev, void Update(Duration dt) override;
StagePtr next
) override;
};
virtual void Init(StagePtr prev, StagePtr next) override;
/** void Reset() override;
* \~chinese
* @brief
* @details
*/
class MoveTransition
: public Transition
{
public:
/**
* \~chinese
* @brief
*/
enum class Type : int
{
Up, ///< 上移
Down, ///< 下移
Left, ///< 左移
Right ///< 右移
};
/** private:
* \~chinese Type type_;
* @brief Point pos_delta_;
* @param duration Point start_pos_;
* @param type };
*/
explicit MoveTransition(
Duration duration,
Type type
);
protected: /**
void Update(Duration dt) override; * \~chinese
* @brief
* @details
*/
class RotationTransition : public Transition
{
public:
/**
* \~chinese
* @brief
* @param duration
* @param rotation
*/
explicit RotationTransition(Duration duration, float rotation = 360);
virtual void Init( protected:
StagePtr prev, void Update(Duration dt) override;
StagePtr next
) override;
void Reset() override; virtual void Init(StagePtr prev, StagePtr next) override;
private: void Reset() override;
Type type_;
Point pos_delta_;
Point start_pos_;
};
private:
/** float rotation_;
* \~chinese };
* @brief } // namespace kiwano
* @details
*/
class RotationTransition
: public Transition
{
public:
/**
* \~chinese
* @brief
* @param duration
* @param rotation
*/
explicit RotationTransition(
Duration duration,
float rotation = 360
);
protected:
void Update(Duration dt) override;
virtual void Init(
StagePtr prev,
StagePtr next
) override;
void Reset() override;
private:
float rotation_;
};
}

View File

@ -1,15 +1,15 @@
// Copyright (c) 2016-2018 Kiwano - Nomango // Copyright (c) 2016-2018 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -18,96 +18,91 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE. // THE SOFTWARE.
#include <kiwano/2d/action/Action.h>
#include <kiwano/2d/Actor.h> #include <kiwano/2d/Actor.h>
#include <kiwano/2d/action/Action.h>
namespace kiwano namespace kiwano
{ {
Action::Action() Action::Action()
: running_(true) : running_(true)
, detach_target_(false) , detach_target_(false)
, loops_done_(0) , loops_done_(0)
, loops_(0) , loops_(0)
, status_(Status::NotStarted) , status_(Status::NotStarted)
{ {
}
Action::~Action()
{
}
void Action::Init(Actor* target)
{
}
void Action::Update(Actor* target, Duration dt)
{
Complete(target);
}
void Action::UpdateStep(Actor* target, Duration dt)
{
KGE_ASSERT(target != nullptr && "Action target should NOT be nullptr!");
elapsed_ += dt;
if (status_ == Status::NotStarted)
{
status_ = delay_.IsZero() ? Status::Started : Status::Delayed;
Init(target);
}
switch (status_)
{
case Status::Delayed:
if (elapsed_ >= delay_)
{
status_ = Status::Started;
}
break;
case Status::Started:
Update(target, dt);
break;
}
if (status_ == Status::Done)
{
if (cb_done_)
cb_done_(target);
if (detach_target_)
target->RemoveFromParent();
status_ = Status::Removeable;
}
}
void Action::Complete(Actor* target)
{
if (cb_loop_done_)
cb_loop_done_(target);
if (loops_ >= 0
&& loops_done_ >= loops_)
{
Done();
}
else
{
Init(target); // reinit when a loop is done
}
++loops_done_;
}
void Action::Restart(Actor* target)
{
status_ = Status::NotStarted;
elapsed_ = 0;
loops_done_ = 0;
Init(target);
}
} }
Action::~Action() {}
void Action::Init(Actor* target) {}
void Action::Update(Actor* target, Duration dt)
{
Complete(target);
}
void Action::UpdateStep(Actor* target, Duration dt)
{
KGE_ASSERT(target != nullptr && "Action target should NOT be nullptr!");
elapsed_ += dt;
if (status_ == Status::NotStarted)
{
status_ = delay_.IsZero() ? Status::Started : Status::Delayed;
Init(target);
}
switch (status_)
{
case Status::Delayed:
if (elapsed_ >= delay_)
{
status_ = Status::Started;
}
break;
case Status::Started:
Update(target, dt);
break;
}
if (status_ == Status::Done)
{
if (cb_done_)
cb_done_(target);
if (detach_target_)
target->RemoveFromParent();
status_ = Status::Removeable;
}
}
void Action::Complete(Actor* target)
{
if (cb_loop_done_)
cb_loop_done_(target);
if (loops_ >= 0 && loops_done_ >= loops_)
{
Done();
}
else
{
Init(target); // reinit when a loop is done
}
++loops_done_;
}
void Action::Restart(Actor* target)
{
status_ = Status::NotStarted;
elapsed_ = 0;
loops_done_ = 0;
Init(target);
}
} // namespace kiwano

View File

@ -1,15 +1,15 @@
// Copyright (c) 2016-2018 Kiwano - Nomango // Copyright (c) 2016-2018 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -19,272 +19,271 @@
// THE SOFTWARE. // THE SOFTWARE.
#pragma once #pragma once
#include <kiwano/core/common.h> #include <kiwano/core/Common.h>
#include <kiwano/core/time.h>
#include <kiwano/core/SmartPtr.hpp>
#include <kiwano/core/ObjectBase.h> #include <kiwano/core/ObjectBase.h>
#include <kiwano/core/SmartPtr.hpp>
#include <kiwano/core/Time.h>
#include <kiwano/math/math.h> #include <kiwano/math/math.h>
namespace kiwano namespace kiwano
{ {
class Actor; class Actor;
class ActionManager; class ActionManager;
KGE_DECLARE_SMART_PTR(Action); KGE_DECLARE_SMART_PTR(Action);
/** /**
* \~chinese * \~chinese
* \defgroup Actions * \defgroup Actions
*/ */
/** /**
* \addtogroup Actions * \addtogroup Actions
* @{ * @{
*/ */
/// \~chinese /// \~chinese
/// @brief 动画 /// @brief 动画
class KGE_API Action class KGE_API Action
: public ObjectBase : public virtual ObjectBase
, protected IntrusiveListItem<ActionPtr> , protected IntrusiveListItem<ActionPtr>
{ {
friend class ActionManager; friend class ActionManager;
friend class ActionGroup; friend class ActionGroup;
friend IntrusiveList<ActionPtr>; friend IntrusiveList<ActionPtr>;
public: public:
/// \~chinese /// \~chinese
/// @brief 动画结束时的回调函数 /// @brief 动画结束时的回调函数
using DoneCallback = Function<void(Actor* /* target */)>; using DoneCallback = Function<void(Actor* /* target */)>;
Action(); Action();
virtual ~Action(); virtual ~Action();
/// \~chinese /// \~chinese
/// @brief 继续动画 /// @brief 继续动画
void Resume(); void Resume();
/// \~chinese /// \~chinese
/// @brief 暂停动画 /// @brief 暂停动画
void Pause(); void Pause();
/// \~chinese /// \~chinese
/// @brief 停止动画 /// @brief 停止动画
void Stop(); void Stop();
/// \~chinese /// \~chinese
/// @brief 设置动画延时 /// @brief 设置动画延时
void SetDelay(Duration delay); void SetDelay(Duration delay);
/// \~chinese /// \~chinese
/// @brief 设置循环次数 /// @brief 设置循环次数
/// @param loops 循环次数,-1 为永久循环 /// @param loops 循环次数,-1 为永久循环
void SetLoops(int loops); void SetLoops(int loops);
/// \~chinese /// \~chinese
/// @brief 动画结束时移除目标角色 /// @brief 动画结束时移除目标角色
void RemoveTargetWhenDone(); void RemoveTargetWhenDone();
/// \~chinese /// \~chinese
/// @brief 设置动画结束时的回调函数 /// @brief 设置动画结束时的回调函数
void SetDoneCallback(DoneCallback const& cb); void SetDoneCallback(DoneCallback const& cb);
/// \~chinese /// \~chinese
/// @brief 设置动画循环结束时的回调函数 /// @brief 设置动画循环结束时的回调函数
void SetLoopDoneCallback(DoneCallback const& cb); void SetLoopDoneCallback(DoneCallback const& cb);
/// \~chinese /// \~chinese
/// @brief 获取动画的拷贝 /// @brief 获取动画的拷贝
virtual ActionPtr Clone() const = 0; virtual ActionPtr Clone() const = 0;
/// \~chinese /// \~chinese
/// @brief 获取动画的倒转 /// @brief 获取动画的倒转
virtual ActionPtr Reverse() const = 0; virtual ActionPtr Reverse() const = 0;
/// \~chinese /// \~chinese
/// @brief 获取动画的运行状态 /// @brief 获取动画的运行状态
bool IsRunning() const; bool IsRunning() const;
/// \~chinese /// \~chinese
/// @brief 获取动画的循环次数 /// @brief 获取动画的循环次数
int GetLoops() const; int GetLoops() const;
/// \~chinese /// \~chinese
/// @brief 获取动画的延时 /// @brief 获取动画的延时
Duration GetDelay() const; Duration GetDelay() const;
/// \~chinese /// \~chinese
/// @brief 获取动画结束时的回调函数 /// @brief 获取动画结束时的回调函数
DoneCallback GetDoneCallback() const; DoneCallback GetDoneCallback() const;
/// \~chinese /// \~chinese
/// @brief 获取动画循环结束时的回调函数 /// @brief 获取动画循环结束时的回调函数
DoneCallback GetLoopDoneCallback() const; DoneCallback GetLoopDoneCallback() const;
protected: protected:
/// \~chinese /// \~chinese
/// @brief 初始化动画 /// @brief 初始化动画
virtual void Init(Actor* target); virtual void Init(Actor* target);
/// \~chinese /// \~chinese
/// @brief 更新动画 /// @brief 更新动画
virtual void Update(Actor* target, Duration dt); virtual void Update(Actor* target, Duration dt);
/// \~chinese /// \~chinese
/// @brief 更新一个时间步 /// @brief 更新一个时间步
void UpdateStep(Actor* target, Duration dt); void UpdateStep(Actor* target, Duration dt);
/// \~chinese /// \~chinese
/// @brief 完成动画 /// @brief 完成动画
void Complete(Actor* target); void Complete(Actor* target);
/// \~chinese /// \~chinese
/// @brief 重新开始动画 /// @brief 重新开始动画
void Restart(Actor* target); void Restart(Actor* target);
/// \~chinese /// \~chinese
/// @brief 动画状态 /// @brief 动画状态
enum class Status enum class Status
{ {
NotStarted, ///< 未开始 NotStarted, ///< 未开始
Delayed, ///< 等待延时 Delayed, ///< 等待延时
Started, ///< 已开始 Started, ///< 已开始
Done, ///< 已结束 Done, ///< 已结束
Removeable ///< 可移除 Removeable ///< 可移除
}; };
/// \~chinese /// \~chinese
/// @brief 获取动画状态 /// @brief 获取动画状态
Status GetStatus() const; Status GetStatus() const;
/// \~chinese /// \~chinese
/// @brief 获取消逝时间 /// @brief 获取消逝时间
Duration GetElapsed() const; Duration GetElapsed() const;
/// \~chinese /// \~chinese
/// @brief 获取完成的循环次数 /// @brief 获取完成的循环次数
int GetLoopsDone() const; int GetLoopsDone() const;
/// \~chinese /// \~chinese
/// @brief 结束动画 /// @brief 结束动画
void Done(); void Done();
/// \~chinese /// \~chinese
/// @brief 是否已结束 /// @brief 是否已结束
bool IsDone() const; bool IsDone() const;
/// \~chinese /// \~chinese
/// @brief 是否可移除 /// @brief 是否可移除
bool IsRemoveable() const; bool IsRemoveable() const;
private: private:
Status status_; Status status_;
bool running_; bool running_;
bool detach_target_; bool detach_target_;
int loops_; int loops_;
int loops_done_; int loops_done_;
Duration delay_; Duration delay_;
Duration elapsed_; Duration elapsed_;
DoneCallback cb_done_; DoneCallback cb_done_;
DoneCallback cb_loop_done_; DoneCallback cb_loop_done_;
}; };
/** @} */ /** @} */
inline void Action::Resume()
inline void Action::Resume() {
{ running_ = true;
running_ = true;
}
inline void Action::Pause()
{
running_ = false;
}
inline void Action::Stop()
{
Done();
}
inline void Action::SetDelay(Duration delay)
{
delay_ = delay;
}
inline void Action::SetLoops(int loops)
{
loops_ = loops;
}
inline void Action::RemoveTargetWhenDone()
{
detach_target_ = true;
}
inline void Action::SetDoneCallback(DoneCallback const& cb)
{
cb_done_ = cb;
}
inline void Action::SetLoopDoneCallback(DoneCallback const& cb)
{
cb_loop_done_ = cb;
}
inline void Action::Done()
{
status_ = Status::Done;
}
inline Action::Status Action::GetStatus() const
{
return status_;
}
inline bool Action::IsRunning() const
{
return running_;
}
inline bool Action::IsDone() const
{
return status_ == Status::Done || status_ == Status::Removeable;
}
inline bool Action::IsRemoveable() const
{
return status_ == Status::Removeable;
}
inline int Action::GetLoops() const
{
return loops_;
}
inline Duration Action::GetDelay() const
{
return delay_;
}
inline Duration Action::GetElapsed() const
{
return elapsed_;
}
inline int Action::GetLoopsDone() const
{
return loops_done_;
}
inline Action::DoneCallback Action::GetDoneCallback() const
{
return cb_done_;
}
inline Action::DoneCallback Action::GetLoopDoneCallback() const
{
return cb_loop_done_;
}
} }
inline void Action::Pause()
{
running_ = false;
}
inline void Action::Stop()
{
Done();
}
inline void Action::SetDelay(Duration delay)
{
delay_ = delay;
}
inline void Action::SetLoops(int loops)
{
loops_ = loops;
}
inline void Action::RemoveTargetWhenDone()
{
detach_target_ = true;
}
inline void Action::SetDoneCallback(DoneCallback const& cb)
{
cb_done_ = cb;
}
inline void Action::SetLoopDoneCallback(DoneCallback const& cb)
{
cb_loop_done_ = cb;
}
inline void Action::Done()
{
status_ = Status::Done;
}
inline Action::Status Action::GetStatus() const
{
return status_;
}
inline bool Action::IsRunning() const
{
return running_;
}
inline bool Action::IsDone() const
{
return status_ == Status::Done || status_ == Status::Removeable;
}
inline bool Action::IsRemoveable() const
{
return status_ == Status::Removeable;
}
inline int Action::GetLoops() const
{
return loops_;
}
inline Duration Action::GetDelay() const
{
return delay_;
}
inline Duration Action::GetElapsed() const
{
return elapsed_;
}
inline int Action::GetLoopsDone() const
{
return loops_done_;
}
inline Action::DoneCallback Action::GetDoneCallback() const
{
return cb_done_;
}
inline Action::DoneCallback Action::GetLoopDoneCallback() const
{
return cb_loop_done_;
}
} // namespace kiwano

View File

@ -1,15 +1,15 @@
// Copyright (c) 2016-2018 Kiwano - Nomango // Copyright (c) 2016-2018 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -22,19 +22,19 @@
namespace kiwano namespace kiwano
{ {
ActionDelay::ActionDelay(Duration delay) ActionDelay::ActionDelay(Duration delay)
{ {
SetDelay(delay); SetDelay(delay);
}
ActionPtr ActionDelay::Clone() const
{
return new ActionDelay(GetDelay());
}
ActionPtr ActionDelay::Reverse() const
{
return new ActionDelay(GetDelay());
}
} }
ActionPtr ActionDelay::Clone() const
{
return new ActionDelay(GetDelay());
}
ActionPtr ActionDelay::Reverse() const
{
return new ActionDelay(GetDelay());
}
} // namespace kiwano

View File

@ -1,15 +1,15 @@
// Copyright (c) 2016-2018 Kiwano - Nomango // Copyright (c) 2016-2018 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -23,32 +23,29 @@
namespace kiwano namespace kiwano
{ {
/** /**
* \addtogroup Actions * \addtogroup Actions
* @{ * @{
*/ */
/// \~chinese /// \~chinese
/// @brief 延时动画 /// @brief 延时动画
class KGE_API ActionDelay class KGE_API ActionDelay : public Action
: public Action {
{ public:
public: /// \~chinese
/// \~chinese /// @brief 构建延时动画
/// @brief 构建延时动画 /// @param delay 延时时长
/// @param delay 延时时长 ActionDelay(Duration delay);
ActionDelay(
Duration delay
);
/// \~chinese /// \~chinese
/// @brief 获取该动画的拷贝对象 /// @brief 获取该动画的拷贝对象
ActionPtr Clone() const override; ActionPtr Clone() const override;
/// \~chinese /// \~chinese
/// @brief 获取该动画的倒转 /// @brief 获取该动画的倒转
ActionPtr Reverse() const override; ActionPtr Reverse() const override;
}; };
/** @} */ /** @} */
} } // namespace kiwano

View File

@ -1,15 +1,15 @@
// Copyright (c) 2016-2018 Kiwano - Nomango // Copyright (c) 2016-2018 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -18,131 +18,129 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE. // THE SOFTWARE.
#include <kiwano/2d/action/ActionGroup.h>
#include <kiwano/2d/Actor.h> #include <kiwano/2d/Actor.h>
#include <kiwano/2d/action/ActionGroup.h>
#include <kiwano/core/Logger.h> #include <kiwano/core/Logger.h>
namespace kiwano namespace kiwano
{ {
//------------------------------------------------------- //-------------------------------------------------------
// ActionGroup // ActionGroup
//------------------------------------------------------- //-------------------------------------------------------
ActionGroup::ActionGroup()
: sequence_(true)
{
}
ActionGroup::ActionGroup(Vector<ActionPtr> const& actions, bool sequence)
: sequence_(sequence)
{
this->Add(actions);
}
ActionGroup::~ActionGroup()
{
}
void ActionGroup::Init(Actor* target)
{
if (actions_.empty())
{
Done();
return;
}
current_ = actions_.first_item();
current_->Restart(target); // init first action
if (!sequence_)
{
// init all actions
for (; current_; current_ = current_->next_item())
{
current_->Restart(target);
}
}
}
void ActionGroup::Update(Actor* target, Duration dt)
{
if (sequence_)
{
if (current_)
{
current_->UpdateStep(target, dt);
if (current_->IsDone())
{
current_ = current_->next_item();
if (current_)
current_->Restart(target); // init next action
else
Complete(target);
}
}
}
else
{
bool done = true;
for (current_ = actions_.first_item(); current_; current_ = current_->next_item())
{
if (!current_->IsDone())
{
done = false;
current_->UpdateStep(target, dt);
}
}
if (done)
{
Complete(target);
}
}
}
void ActionGroup::Add(ActionPtr action)
{
if (action)
{
actions_.push_back(action);
}
}
void ActionGroup::Add(Vector<ActionPtr> const& actions)
{
for (const auto& action : actions)
Add(action);
}
ActionPtr ActionGroup::Clone() const
{
auto group = new (std::nothrow) ActionGroup();
if (group)
{
for (auto action = actions_.first_item(); action; action = action->next_item())
{
if (action)
{
group->Add(action->Clone());
}
}
}
return group;
}
ActionPtr ActionGroup::Reverse() const
{
auto group = new (std::nothrow) ActionGroup();
if (group && !actions_.empty())
{
for (auto action = actions_.last_item(); action; action = action->prev_item())
{
group->Add(action->Reverse());
}
}
return group;
}
ActionGroup::ActionGroup()
: sequence_(true)
{
} }
ActionGroup::ActionGroup(Vector<ActionPtr> const& actions, bool sequence)
: sequence_(sequence)
{
this->Add(actions);
}
ActionGroup::~ActionGroup() {}
void ActionGroup::Init(Actor* target)
{
if (actions_.empty())
{
Done();
return;
}
current_ = actions_.first_item();
current_->Restart(target); // init first action
if (!sequence_)
{
// init all actions
for (; current_; current_ = current_->next_item())
{
current_->Restart(target);
}
}
}
void ActionGroup::Update(Actor* target, Duration dt)
{
if (sequence_)
{
if (current_)
{
current_->UpdateStep(target, dt);
if (current_->IsDone())
{
current_ = current_->next_item();
if (current_)
current_->Restart(target); // init next action
else
Complete(target);
}
}
}
else
{
bool done = true;
for (current_ = actions_.first_item(); current_; current_ = current_->next_item())
{
if (!current_->IsDone())
{
done = false;
current_->UpdateStep(target, dt);
}
}
if (done)
{
Complete(target);
}
}
}
void ActionGroup::Add(ActionPtr action)
{
if (action)
{
actions_.push_back(action);
}
}
void ActionGroup::Add(Vector<ActionPtr> const& actions)
{
for (const auto& action : actions)
Add(action);
}
ActionPtr ActionGroup::Clone() const
{
auto group = new (std::nothrow) ActionGroup();
if (group)
{
for (auto action = actions_.first_item(); action; action = action->next_item())
{
if (action)
{
group->Add(action->Clone());
}
}
}
return group;
}
ActionPtr ActionGroup::Reverse() const
{
auto group = new (std::nothrow) ActionGroup();
if (group && !actions_.empty())
{
for (auto action = actions_.last_item(); action; action = action->prev_item())
{
group->Add(action->Reverse());
}
}
return group;
}
} // namespace kiwano

View File

@ -1,15 +1,15 @@
// Copyright (c) 2016-2018 Kiwano - Nomango // Copyright (c) 2016-2018 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -23,66 +23,68 @@
namespace kiwano namespace kiwano
{ {
KGE_DECLARE_SMART_PTR(ActionGroup); KGE_DECLARE_SMART_PTR(ActionGroup);
/** /**
* \addtogroup Actions * \addtogroup Actions
* @{ * @{
*/ */
/// \~chinese /// \~chinese
/// @brief 动画组合 /// @brief 动画组合
class KGE_API ActionGroup class KGE_API ActionGroup : public Action
: public Action {
{ public:
public: using ActionList = IntrusiveList<ActionPtr>;
using ActionList = IntrusiveList<ActionPtr>;
ActionGroup(); ActionGroup();
/// \~chinese /// \~chinese
/// @brief 动画组合 /// @brief 动画组合
/// @param actions 动画集合 /// @param actions 动画集合
/// @param sequence 动画按顺序依次执行或同时执行 /// @param sequence 动画按顺序依次执行或同时执行
explicit ActionGroup(Vector<ActionPtr> const& actions, bool sequence = true); explicit ActionGroup(Vector<ActionPtr> const& actions, bool sequence = true);
virtual ~ActionGroup(); virtual ~ActionGroup();
/// \~chinese /// \~chinese
/// @brief 添加动画 /// @brief 添加动画
/// @param action 动画 /// @param action 动画
void Add(ActionPtr action); void Add(ActionPtr action);
/// \~chinese /// \~chinese
/// @brief 添加多个动画 /// @brief 添加多个动画
/// @param actions 动画集合 /// @param actions 动画集合
void Add(Vector<ActionPtr> const& actions); void Add(Vector<ActionPtr> const& actions);
/// \~chinese /// \~chinese
/// @brief 获取所有动画 /// @brief 获取所有动画
ActionList const& GetActions() const; ActionList const& GetActions() const;
/// \~chinese /// \~chinese
/// @brief 获取该动画的拷贝对象 /// @brief 获取该动画的拷贝对象
ActionPtr Clone() const override; ActionPtr Clone() const override;
/// \~chinese /// \~chinese
/// @brief 获取该动画的倒转 /// @brief 获取该动画的倒转
ActionPtr Reverse() const override; ActionPtr Reverse() const override;
protected: protected:
void Init(Actor* target) override; void Init(Actor* target) override;
void Update(Actor* target, Duration dt) override; void Update(Actor* target, Duration dt) override;
private: private:
bool sequence_; bool sequence_;
ActionPtr current_; ActionPtr current_;
ActionList actions_; ActionList actions_;
}; };
/** @} */ /** @} */
inline ActionGroup::ActionList const& ActionGroup::GetActions() const { return actions_; }
inline ActionGroup::ActionList const& ActionGroup::GetActions() const
{
return actions_;
} }
} // namespace kiwano

View File

@ -1,15 +1,15 @@
// Copyright (c) 2016-2018 Kiwano - Nomango // Copyright (c) 2016-2018 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -19,293 +19,354 @@
// THE SOFTWARE. // THE SOFTWARE.
#pragma once #pragma once
#include <kiwano/2d/action/ActionTween.h>
#include <kiwano/2d/action/ActionWalk.h>
#include <kiwano/2d/action/ActionDelay.h> #include <kiwano/2d/action/ActionDelay.h>
#include <kiwano/2d/action/ActionGroup.h> #include <kiwano/2d/action/ActionGroup.h>
#include <kiwano/2d/action/ActionTween.h>
#include <kiwano/2d/action/ActionWalk.h>
#include <kiwano/2d/action/Animation.h> #include <kiwano/2d/action/Animation.h>
namespace kiwano namespace kiwano
{ {
/** /**
* \addtogroup Actions * \addtogroup Actions
* @{ * @{
*/ */
/// \~chinese /// \~chinese
/// @brief 动画辅助类 /// @brief 动画辅助类
struct ActionHelper struct ActionHelper
{ {
using DoneCallback = Action::DoneCallback; using DoneCallback = Action::DoneCallback;
/// \~chinese /// \~chinese
/// @brief 设置循环次数 /// @brief 设置循环次数
inline ActionHelper& SetLoops(int loops) { core->SetLoops(loops); return (*this); } inline ActionHelper& SetLoops(int loops)
{
core->SetLoops(loops);
return (*this);
}
/// \~chinese /// \~chinese
/// @brief 设置动画延迟 /// @brief 设置动画延迟
inline ActionHelper& SetDelay(Duration delay) { core->SetDelay(delay); return (*this); } inline ActionHelper& SetDelay(Duration delay)
{
core->SetDelay(delay);
return (*this);
}
/// \~chinese /// \~chinese
/// @brief 设置动画结束回调函数 /// @brief 设置动画结束回调函数
inline ActionHelper& SetDoneCallback(DoneCallback const& cb) { core->SetDoneCallback(cb); return (*this); } inline ActionHelper& SetDoneCallback(DoneCallback const& cb)
{
core->SetDoneCallback(cb);
return (*this);
}
/// \~chinese /// \~chinese
/// @brief 设置动画循环结束时的回调函数 /// @brief 设置动画循环结束时的回调函数
inline ActionHelper& SetLoopDoneCallback(DoneCallback const& cb) { core->SetLoopDoneCallback(cb); return (*this); } inline ActionHelper& SetLoopDoneCallback(DoneCallback const& cb)
{
core->SetLoopDoneCallback(cb);
return (*this);
}
/// \~chinese /// \~chinese
/// @brief 动画结束时移除目标角色 /// @brief 动画结束时移除目标角色
inline ActionHelper& RemoveTargetWhenDone() { core->RemoveTargetWhenDone(); return (*this); } inline ActionHelper& RemoveTargetWhenDone()
{
core->RemoveTargetWhenDone();
return (*this);
}
/// \~chinese /// \~chinese
/// @brief 设置名称 /// @brief 设置名称
inline ActionHelper& SetName(String const& name) { core->SetName(name); return (*this); } inline ActionHelper& SetName(String const& name)
{
core->SetName(name);
return (*this);
}
/// \~chinese /// \~chinese
/// @brief 获取指针 /// @brief 获取指针
inline ActionPtr Get() const { return core; } inline ActionPtr Get() const
{
return core;
}
inline ActionHelper(ActionPtr core) : core(core) {} inline ActionHelper(ActionPtr core)
: core(core)
{
}
inline operator ActionPtr() const { return core; } inline operator ActionPtr() const
{
return core;
}
private: private:
ActionPtr core; ActionPtr core;
}; };
/// \~chinese /// \~chinese
/// @brief 补间动画辅助类 /// @brief 补间动画辅助类
struct TweenHelper struct TweenHelper
{ {
using DoneCallback = Action::DoneCallback; using DoneCallback = Action::DoneCallback;
/// \~chinese /// \~chinese
/// @brief 设置动画持续时长 /// @brief 设置动画持续时长
inline TweenHelper& SetDuration(Duration dur) { core->SetDuration(dur); return (*this); } inline TweenHelper& SetDuration(Duration dur)
{
core->SetDuration(dur);
return (*this);
}
/// \~chinese /// \~chinese
/// @brief 设置循环次数 /// @brief 设置循环次数
inline TweenHelper& SetLoops(int loops) { core->SetLoops(loops); return (*this); } inline TweenHelper& SetLoops(int loops)
{
core->SetLoops(loops);
return (*this);
}
/// \~chinese /// \~chinese
/// @brief 设置缓动函数 /// @brief 设置缓动函数
inline TweenHelper& SetEaseFunc(EaseFunc ease) { core->SetEaseFunc(ease); return (*this); } inline TweenHelper& SetEaseFunc(EaseFunc ease)
{
core->SetEaseFunc(ease);
return (*this);
}
/// \~chinese /// \~chinese
/// @brief 设置动画延迟 /// @brief 设置动画延迟
inline TweenHelper& SetDelay(Duration delay) { core->SetDelay(delay); return (*this); } inline TweenHelper& SetDelay(Duration delay)
{
core->SetDelay(delay);
return (*this);
}
/// \~chinese /// \~chinese
/// @brief 设置动画结束回调函数 /// @brief 设置动画结束回调函数
inline TweenHelper& SetDoneCallback(DoneCallback const& cb) { core->SetDoneCallback(cb); return (*this); } inline TweenHelper& SetDoneCallback(DoneCallback const& cb)
{
core->SetDoneCallback(cb);
return (*this);
}
/// \~chinese /// \~chinese
/// @brief 设置动画循环结束时的回调函数 /// @brief 设置动画循环结束时的回调函数
inline TweenHelper& SetLoopDoneCallback(DoneCallback const& cb) { core->SetLoopDoneCallback(cb); return (*this); } inline TweenHelper& SetLoopDoneCallback(DoneCallback const& cb)
{
core->SetLoopDoneCallback(cb);
return (*this);
}
/// \~chinese /// \~chinese
/// @brief 动画结束时移除目标角色 /// @brief 动画结束时移除目标角色
inline TweenHelper& RemoveTargetWhenDone() { core->RemoveTargetWhenDone(); return (*this); } inline TweenHelper& RemoveTargetWhenDone()
{
core->RemoveTargetWhenDone();
return (*this);
}
/// \~chinese /// \~chinese
/// @brief 设置名称 /// @brief 设置名称
inline TweenHelper& SetName(String const& name) { core->SetName(name); return (*this); } inline TweenHelper& SetName(String const& name)
{
core->SetName(name);
return (*this);
}
/// \~chinese /// \~chinese
/// @brief 获取指针 /// @brief 获取指针
inline ActionTweenPtr Get() const { return core; } inline ActionTweenPtr Get() const
{
inline TweenHelper(ActionTweenPtr core) : core(core) {} return core;
}
inline operator ActionPtr() const { return core; } inline TweenHelper(ActionTweenPtr core)
: core(core)
{
}
inline operator ActionTweenPtr() const { return core; } inline operator ActionPtr() const
{
return core;
}
private: inline operator ActionTweenPtr() const
ActionTweenPtr core; {
}; return core;
}
/// \~chinese private:
/// @brief 动画构造器 ActionTweenPtr core;
struct Tween };
{
public:
/// \~chinese
/// @brief 构造相对位移动画
/// @param duration 动画时长
/// @param vector 移动向量
static inline TweenHelper
MoveBy(Duration dur, Point const& vector)
{
return TweenHelper(new kiwano::ActionMoveBy(dur, vector));
}
/// \~chinese /// \~chinese
/// @brief 构造位移动画 /// @brief 动画构造器
/// @param duration 动画时长 struct Tween
/// @param pos 目的坐标 {
static inline TweenHelper public:
MoveTo(Duration dur, Point const& pos) /// \~chinese
{ /// @brief 构造相对位移动画
return TweenHelper(new kiwano::ActionMoveTo(dur, pos)); /// @param duration 动画时长
} /// @param vector 移动向量
static inline TweenHelper MoveBy(Duration dur, Point const& vector)
{
return TweenHelper(new kiwano::ActionMoveBy(dur, vector));
}
/// \~chinese /// \~chinese
/// @brief 构造相对跳跃动画 /// @brief 构造位移动画
/// @param duration 动画时长 /// @param duration 动画时长
/// @param vec 跳跃位移向量 /// @param pos 目的坐标
/// @param height 跳跃高度 static inline TweenHelper MoveTo(Duration dur, Point const& pos)
/// @param jumps 跳跃次数 {
static inline TweenHelper return TweenHelper(new kiwano::ActionMoveTo(dur, pos));
JumpBy(Duration duration, Vec2 const& vec, float height, int jumps = 1) }
{
return TweenHelper(new kiwano::ActionJumpBy(duration, vec, height, jumps));
}
/// \~chinese /// \~chinese
/// @brief 构造跳跃动画 /// @brief 构造相对跳跃动画
/// @param duration 动画时长 /// @param duration 动画时长
/// @param pos 目的坐标 /// @param vec 跳跃位移向量
/// @param height 跳跃高度 /// @param height 跳跃高度
/// @param jumps 跳跃次数 /// @param jumps 跳跃次数
static inline TweenHelper static inline TweenHelper JumpBy(Duration duration, Vec2 const& vec, float height, int jumps = 1)
JumpTo(Duration duration, Point const& pos, float height, int jumps = 1) {
{ return TweenHelper(new kiwano::ActionJumpBy(duration, vec, height, jumps));
return TweenHelper(new kiwano::ActionJumpTo(duration, pos, height, jumps)); }
}
/// \~chinese /// \~chinese
/// @brief 构造相对缩放动画 /// @brief 构造跳跃动画
/// @param duration 动画时长 /// @param duration 动画时长
/// @param scale_x 横向缩放相对变化值 /// @param pos 目的坐标
/// @param scale_y 纵向缩放相对变化值 /// @param height 跳跃高度
static inline TweenHelper /// @param jumps 跳跃次数
ScaleBy(Duration dur, float scale_x, float scale_y) static inline TweenHelper JumpTo(Duration duration, Point const& pos, float height, int jumps = 1)
{ {
return TweenHelper(new kiwano::ActionScaleBy(dur, scale_x, scale_y)); return TweenHelper(new kiwano::ActionJumpTo(duration, pos, height, jumps));
} }
/// \~chinese /// \~chinese
/// @brief 构造缩放动画 /// @brief 构造相对缩放动画
/// @param duration 动画时长 /// @param duration 动画时长
/// @param scale_x 横向缩放目标值 /// @param scale_x 横向缩放相对变化值
/// @param scale_y 纵向缩放目标值 /// @param scale_y 纵向缩放相对变化值
static inline TweenHelper static inline TweenHelper ScaleBy(Duration dur, float scale_x, float scale_y)
ScaleTo(Duration dur, float scale_x, float scale_y) {
{ return TweenHelper(new kiwano::ActionScaleBy(dur, scale_x, scale_y));
return TweenHelper(new kiwano::ActionScaleTo(dur, scale_x, scale_y)); }
}
/// \~chinese /// \~chinese
/// @brief 构造透明度渐变动画 /// @brief 构造缩放动画
/// @param duration 动画时长 /// @param duration 动画时长
/// @param opacity 目标透明度 /// @param scale_x 横向缩放目标值
static inline TweenHelper /// @param scale_y 纵向缩放目标值
FadeTo(Duration dur, float opacity) static inline TweenHelper ScaleTo(Duration dur, float scale_x, float scale_y)
{ {
return TweenHelper(new kiwano::ActionFadeTo(dur, opacity)); return TweenHelper(new kiwano::ActionScaleTo(dur, scale_x, scale_y));
} }
/// \~chinese /// \~chinese
/// @brief 构造淡入动画 /// @brief 构造透明度渐变动画
/// @param duration 动画时长 /// @param duration 动画时长
static inline TweenHelper /// @param opacity 目标透明度
FadeIn(Duration dur) static inline TweenHelper FadeTo(Duration dur, float opacity)
{ {
return TweenHelper(new kiwano::ActionFadeIn(dur)); return TweenHelper(new kiwano::ActionFadeTo(dur, opacity));
} }
/// \~chinese /// \~chinese
/// @brief 构造淡出动画 /// @brief 构造淡入动画
/// @param duration 动画时长 /// @param duration 动画时长
static inline TweenHelper static inline TweenHelper FadeIn(Duration dur)
FadeOut(Duration dur) {
{ return TweenHelper(new kiwano::ActionFadeIn(dur));
return TweenHelper(new kiwano::ActionFadeOut(dur)); }
}
/// \~chinese /// \~chinese
/// @brief 构造相对旋转动画 /// @brief 构造淡出动画
/// @param duration 动画时长 /// @param duration 动画时长
/// @param rotation 角度相对变化值 static inline TweenHelper FadeOut(Duration dur)
static inline TweenHelper {
RotateBy(Duration dur, float rotation) return TweenHelper(new kiwano::ActionFadeOut(dur));
{ }
return TweenHelper(new kiwano::ActionRotateBy(dur, rotation));
}
/// \~chinese /// \~chinese
/// @brief 构造旋转动画 /// @brief 构造相对旋转动画
/// @param duration 动画时长 /// @param duration 动画时长
/// @param rotation 目标角度 /// @param rotation 角度相对变化值
static inline TweenHelper static inline TweenHelper RotateBy(Duration dur, float rotation)
RotateTo(Duration dur, float rotation) {
{ return TweenHelper(new kiwano::ActionRotateBy(dur, rotation));
return TweenHelper(new kiwano::ActionRotateTo(dur, rotation)); }
}
/// \~chinese /// \~chinese
/// @brief 构造路径行走动画 /// @brief 构造旋转动画
/// @param duration 持续时长 /// @param duration 动画时长
/// @param path 路径几何形状 /// @param rotation 目标角度
/// @param rotating 是否沿路径切线方向旋转 static inline TweenHelper RotateTo(Duration dur, float rotation)
/// @param start 路径起点(百分比) {
/// @param end 路径终点(百分比) return TweenHelper(new kiwano::ActionRotateTo(dur, rotation));
static inline TweenHelper }
Walk(Duration duration, Geometry const& path, bool rotating = false, float start = 0.f, float end = 1.f)
{
return TweenHelper(new kiwano::ActionWalk(duration, path, rotating, start, end));
}
/// \~chinese /// \~chinese
/// @brief 构建帧动画 /// @brief 构造路径行走动画
/// @param duration 动画时长 /// @param duration 持续时长
/// @param[in] frame_seq 序列帧 /// @param path 路径几何形状
static inline TweenHelper /// @param rotating 是否沿路径切线方向旋转
Animation(Duration dur, FrameSequencePtr frames) /// @param start 路径起点(百分比)
{ /// @param end 路径终点(百分比)
return TweenHelper(new kiwano::Animation(dur, frames)); static inline TweenHelper Walk(Duration duration, Geometry const& path, bool rotating = false, float start = 0.f,
} float end = 1.f)
{
return TweenHelper(new kiwano::ActionWalk(duration, path, rotating, start, end));
}
/// \~chinese /// \~chinese
/// @brief 构造自定义动画 /// @brief 构建帧动画
/// @param duration 动画时长 /// @param duration 动画时长
/// @param tween_func 动画回调函数 /// @param[in] frame_seq 序列帧
static inline TweenHelper static inline TweenHelper Animation(Duration dur, FrameSequencePtr frames)
Custom(Duration dur, ActionCustom::TweenFunc tween_func) {
{ return TweenHelper(new kiwano::Animation(dur, frames));
return TweenHelper(new kiwano::ActionCustom(dur, tween_func)); }
}
/// \~chinese /// \~chinese
/// @brief 构建延时动画 /// @brief 构造自定义动画
/// @param delay 延时时长 /// @param duration 动画时长
static inline ActionHelper /// @param tween_func 动画回调函数
Delay(Duration delay) static inline TweenHelper Custom(Duration dur, ActionCustom::TweenFunc tween_func)
{ {
return ActionHelper(new kiwano::ActionDelay(delay)); return TweenHelper(new kiwano::ActionCustom(dur, tween_func));
} }
/// \~chinese /// \~chinese
/// @brief 动画组合 /// @brief 构建延时动画
/// @param actions 动画集合 /// @param delay 延时时长
/// @param sequence 动画按顺序依次执行或同时执行 static inline ActionHelper Delay(Duration delay)
static inline ActionHelper {
Group(Vector<ActionPtr> const& actions, bool sequence = true) return ActionHelper(new kiwano::ActionDelay(delay));
{ }
return ActionHelper(new kiwano::ActionGroup(actions, sequence));
}
/// \~chinese /// \~chinese
/// @brief 同步动画组合 /// @brief 动画组合
/// @param actions 动画集合 /// @param actions 动画集合
static inline ActionHelper /// @param sequence 动画按顺序依次执行或同时执行
Multiple(Vector<ActionPtr> const& actions) static inline ActionHelper Group(Vector<ActionPtr> const& actions, bool sequence = true)
{ {
return ActionHelper(new kiwano::ActionGroup(actions, false)); return ActionHelper(new kiwano::ActionGroup(actions, sequence));
} }
};
/** @} */ /// \~chinese
} /// @brief 同步动画组合
/// @param actions 动画集合
static inline ActionHelper Multiple(Vector<ActionPtr> const& actions)
{
return ActionHelper(new kiwano::ActionGroup(actions, false));
}
};
/** @} */
} // namespace kiwano

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