Update Audio & Network & Imgui

This commit is contained in:
Nomango 2019-12-31 10:37:29 +08:00
parent f8db6f3550
commit 56dea4c055
45 changed files with 810 additions and 1818 deletions

View File

@ -55,7 +55,8 @@ EXCLUDE = src/3rd-party \
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = YES
PREDEFINED = KGE_API=
PREDEFINED = KGE_API= \
KGE_DISABLE_DOXYGEN=
# The INCLUDE_PATH tag can be used to specify one or more directories that
# contain include files that are not input files but should be processed by the

View File

@ -185,4 +185,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>

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\StackWalker\StackWalker.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\..\src\3rd-party\StackWalker\StackWalker.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>{3A3948DC-9865-46B3-B7B9-7E5572704ED2}</ProjectGuid>
<RootNamespace>libStackWalker</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\StackWalker\StackWalker.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\..\src\3rd-party\StackWalker\StackWalker.h" />
</ItemGroup>
</Project>

View File

@ -102,4 +102,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>

View File

@ -102,4 +102,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>

View File

@ -94,4 +94,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>

View File

@ -14,8 +14,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "kiwano-physics", "kiwano-ph
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "3rd-party", "3rd-party", "{2D8919F2-8922-4B3F-8F68-D4127C6BCBB7}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libStackWalker", "3rd-party\StackWalker\libStackWalker.vcxproj", "{3A3948DC-9865-46B3-B7B9-7E5572704ED2}"
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}"
@ -47,10 +45,10 @@ Global
{A7062ED8-8910-48A5-A3BC-C1612672571F}.Debug|Win32.Build.0 = Debug|Win32
{A7062ED8-8910-48A5-A3BC-C1612672571F}.Release|Win32.ActiveCfg = Release|Win32
{A7062ED8-8910-48A5-A3BC-C1612672571F}.Release|Win32.Build.0 = Release|Win32
{3A3948DC-9865-46B3-B7B9-7E5572704ED2}.Debug|Win32.ActiveCfg = Debug|Win32
{3A3948DC-9865-46B3-B7B9-7E5572704ED2}.Debug|Win32.Build.0 = Debug|Win32
{3A3948DC-9865-46B3-B7B9-7E5572704ED2}.Release|Win32.ActiveCfg = Release|Win32
{3A3948DC-9865-46B3-B7B9-7E5572704ED2}.Release|Win32.Build.0 = Release|Win32
{DF599AFB-744F-41E5-AF0C-2146F90575C8}.Debug|Win32.ActiveCfg = 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.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
@ -67,16 +65,11 @@ Global
{0CBA9295-F14D-4966-A7C4-1DD68158176C}.Debug|Win32.Build.0 = Debug|Win32
{0CBA9295-F14D-4966-A7C4-1DD68158176C}.Release|Win32.ActiveCfg = Release|Win32
{0CBA9295-F14D-4966-A7C4-1DD68158176C}.Release|Win32.Build.0 = Release|Win32
{DF599AFB-744F-41E5-AF0C-2146F90575C8}.Debug|Win32.ActiveCfg = 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.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{3A3948DC-9865-46B3-B7B9-7E5572704ED2} = {2D8919F2-8922-4B3F-8F68-D4127C6BCBB7}
{AB47E875-85E5-4105-A71E-88930EAAB910} = {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}

View File

@ -39,7 +39,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>false</WholeProgramOptimization>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
</PropertyGroup>
@ -108,4 +108,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>

View File

@ -38,7 +38,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>false</WholeProgramOptimization>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
</PropertyGroup>
@ -110,4 +110,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>

View File

@ -34,7 +34,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>false</WholeProgramOptimization>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
</PropertyGroup>
@ -106,4 +106,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>

View File

@ -44,7 +44,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>false</WholeProgramOptimization>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
</PropertyGroup>
@ -116,4 +116,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>

View File

@ -123,6 +123,7 @@
<ClCompile Include="..\..\src\kiwano\platform\FileSystem.cpp" />
<ClCompile Include="..\..\src\kiwano\platform\Input.cpp" />
<ClCompile Include="..\..\src\kiwano\platform\win32\libraries.cpp" />
<ClCompile Include="..\..\src\kiwano\platform\win32\StackWalker.cpp" />
<ClCompile Include="..\..\src\kiwano\platform\Window.cpp" />
<ClCompile Include="..\..\src\kiwano\renderer\Brush.cpp" />
<ClCompile Include="..\..\src\kiwano\renderer\Color.cpp" />
@ -158,9 +159,6 @@
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\3rd-party\StackWalker\libStackWalker.vcxproj">
<Project>{3a3948dc-9865-46b3-b7b9-7e5572704ed2}</Project>
</ProjectReference>
<ProjectReference Include="..\3rd-party\tinyxml2\libtinyxml2.vcxproj">
<Project>{ab47e875-85e5-4105-a71e-88930eaab910}</Project>
</ProjectReference>
@ -179,7 +177,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>false</WholeProgramOptimization>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
</PropertyGroup>
@ -241,4 +239,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>

View File

@ -458,5 +458,8 @@
<ClCompile Include="..\..\src\kiwano\platform\win32\libraries.cpp">
<Filter>platform\win32</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\platform\win32\StackWalker.cpp">
<Filter>platform\win32</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@ -3,14 +3,19 @@ function Set-FileConfiguration {
[string]$filePath
)
$replace = "<DebugInformationFormat>(EditAndContinue|ProgramDatabase)</DebugInformationFormat>"
$replaceTo = "<DebugInformationFormat>None</DebugInformationFormat>"
$debugInfoReplace = "<DebugInformationFormat>(EditAndContinue|ProgramDatabase)</DebugInformationFormat>"
$debugInfoReplaceTo = "<DebugInformationFormat>None</DebugInformationFormat>"
$optimizationReplace = "<WholeProgramOptimization>true</WholeProgramOptimization>"
$optimizationReplaceTo = "<WholeProgramOptimization>false</WholeProgramOptimization>"
# Create a copy of .vcxproj file
Copy-Item -Path $filePath -Destination ($filePath + '.template')
# Overlay some configurations
Get-Content ($filePath + '.template') -Encoding UTF8 | ForEach-Object { $_ -replace $replace, $replaceTo } | Out-File $filePath -Encoding UTF8
Get-Content ($filePath + '.template') -Encoding UTF8 | ForEach-Object {
( $_ -replace $debugInfoReplace, $debugInfoReplaceTo ) -replace $optimizationReplace, $optimizationReplaceTo
} | Out-File $filePath -Encoding UTF8
# Delete the copy file
Remove-Item -Path ($filePath + '.template')
@ -24,3 +29,12 @@ Get-ChildItem -Path 'projects\' -Directory | ForEach-Object {
Set-FileConfiguration ($dirPath + '\' + $_)
}
}
Get-ChildItem -Path 'projects\3rd-party' -Directory | ForEach-Object {
$dirPath = "projects\3rd-party\$($_)"
# Search all vcxproj files
Get-ChildItem -Path $dirPath *.vcxproj -File | ForEach-Object {
Set-FileConfiguration ($dirPath + '\' + $_)
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,187 +0,0 @@
/**********************************************************************
*
* StackWalker.h
*
*
* History:
* 2005-07-27 v1 - First public release on http://www.codeproject.com/
* (for additional changes see History in 'StackWalker.cpp'!
*
**********************************************************************/
// #pragma once is supported starting with _MCS_VER 1000,
// so we need not to check the version (because we only support _MSC_VER >= 1100)!
#pragma once
// special defines for VC5/6 (if no actual PSDK is installed):
#if _MSC_VER < 1300
typedef unsigned __int64 DWORD64, *PDWORD64;
#if defined(_WIN64)
typedef unsigned __int64 SIZE_T, *PSIZE_T;
#else
typedef unsigned long SIZE_T, *PSIZE_T;
#endif
#endif // _MSC_VER < 1300
class StackWalkerInternal; // forward
class StackWalker
{
public:
typedef enum StackWalkOptions
{
// No addition info will be retrived
// (only the address is available)
RetrieveNone = 0,
// Try to get the symbol-name
RetrieveSymbol = 1,
// Try to get the line for this symbol
RetrieveLine = 2,
// Try to retrieve the module-infos
RetrieveModuleInfo = 4,
// Also retrieve the version for the DLL/EXE
RetrieveFileVersion = 8,
// Contains all the abouve
RetrieveVerbose = 0xF,
// Generate a "good" symbol-search-path
SymBuildPath = 0x10,
// Also use the public Microsoft-Symbol-Server
SymUseSymSrv = 0x20,
// Contains all the abouve "Sym"-options
SymAll = 0x30,
// Contains all options (default)
OptionsAll = 0x3F
} StackWalkOptions;
StackWalker(
int options = OptionsAll, // 'int' is by design, to combine the enum-flags
LPCSTR szSymPath = NULL,
DWORD dwProcessId = GetCurrentProcessId(),
HANDLE hProcess = GetCurrentProcess()
);
StackWalker(DWORD dwProcessId, HANDLE hProcess);
virtual ~StackWalker();
typedef BOOL (__stdcall *PReadProcessMemoryRoutine)(
HANDLE hProcess,
DWORD64 qwBaseAddress,
PVOID lpBuffer,
DWORD nSize,
LPDWORD lpNumberOfBytesRead,
LPVOID pUserData // optional data, which was passed in "ShowCallstack"
);
BOOL LoadModules();
BOOL ShowCallstack(
HANDLE hThread = GetCurrentThread(),
const CONTEXT *context = NULL,
PReadProcessMemoryRoutine readMemoryFunction = NULL,
LPVOID pUserData = NULL // optional to identify some data in the 'readMemoryFunction'-callback
);
#if _MSC_VER >= 1300
// due to some reasons, the "STACKWALK_MAX_NAMELEN" must be declared as "public"
// in older compilers in order to use it... starting with VC7 we can declare it as "protected"
protected:
#endif
enum { STACKWALK_MAX_NAMELEN = 1024 }; // max name length for found symbols
protected:
// Entry for each Callstack-Entry
typedef struct CallstackEntry
{
DWORD64 offset; // if 0, we have no valid entry
CHAR name[STACKWALK_MAX_NAMELEN];
CHAR undName[STACKWALK_MAX_NAMELEN];
CHAR undFullName[STACKWALK_MAX_NAMELEN];
DWORD64 offsetFromSmybol;
DWORD offsetFromLine;
DWORD lineNumber;
CHAR lineFileName[STACKWALK_MAX_NAMELEN];
DWORD symType;
LPCSTR symTypeString;
CHAR moduleName[STACKWALK_MAX_NAMELEN];
DWORD64 baseOfImage;
CHAR loadedImageName[STACKWALK_MAX_NAMELEN];
} CallstackEntry;
enum CallstackEntryType {firstEntry, nextEntry, lastEntry};
virtual void OnSymInit(LPCSTR szSearchPath, DWORD symOptions, LPCSTR szUserName);
virtual void OnLoadModule(LPCSTR img, LPCSTR mod, DWORD64 baseAddr, DWORD size, DWORD result, LPCSTR symType, LPCSTR pdbName, ULONGLONG fileVersion);
virtual void OnCallstackEntry(CallstackEntryType eType, CallstackEntry &entry);
virtual void OnDbgHelpErr(LPCSTR szFuncName, DWORD gle, DWORD64 addr);
virtual void OnOutput(LPCSTR szText);
StackWalkerInternal *m_sw;
HANDLE m_hProcess;
DWORD m_dwProcessId;
BOOL m_modulesLoaded;
LPSTR m_szSymPath;
int m_options;
static BOOL __stdcall myReadProcMem(HANDLE hProcess, DWORD64 qwBaseAddress, PVOID lpBuffer, DWORD nSize, LPDWORD lpNumberOfBytesRead);
friend StackWalkerInternal;
};
// The "ugly" assembler-implementation is needed for systems before XP
// If you have a new PSDK and you only compile for XP and later, then you can use
// the "RtlCaptureContext"
// Currently there is no define which determines the PSDK-Version...
// So we just use the compiler-version (and assumes that the PSDK is
// the one which was installed by the VS-IDE)
// INFO: If you want, you can use the RtlCaptureContext if you only target XP and later...
// But I currently use it in x64/IA64 environments...
//#if defined(_M_IX86) && (_WIN32_WINNT <= 0x0500) && (_MSC_VER < 1400)
#if defined(_M_IX86)
#ifdef CURRENT_THREAD_VIA_EXCEPTION
// TODO: The following is not a "good" implementation,
// because the callstack is only valid in the "__except" block...
#define GET_CURRENT_CONTEXT(c, contextFlags) \
do { \
memset(&c, 0, sizeof(CONTEXT)); \
EXCEPTION_POINTERS *pExp = NULL; \
__try { \
throw 0; \
} __except( ( (pExp = GetExceptionInformation()) ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_EXECUTE_HANDLER)) {} \
if (pExp != NULL) \
memcpy(&c, pExp->ContextRecord, sizeof(CONTEXT)); \
c.ContextFlags = contextFlags; \
} while(0);
#else
// The following should be enough for walking the callstack...
#define GET_CURRENT_CONTEXT(c, contextFlags) \
do { \
memset(&c, 0, sizeof(CONTEXT)); \
c.ContextFlags = contextFlags; \
__asm call x \
__asm x: pop eax \
__asm mov c.Eip, eax \
__asm mov c.Ebp, ebp \
__asm mov c.Esp, esp \
} while(0);
#endif
#else
// The following is defined for x86 (XP and higher), x64 and IA64:
#define GET_CURRENT_CONTEXT(c, contextFlags) \
do { \
memset(&c, 0, sizeof(CONTEXT)); \
c.ContextFlags = contextFlags; \
RtlCaptureContext(&c); \
} while(0);
#endif

View File

@ -75,36 +75,51 @@ namespace kiwano
dlls::MediaFoundation::Get().MFShutdown();
}
HRESULT AudioEngine::CreateVoice(IXAudio2SourceVoice** voice, const Transcoder::Buffer& buffer)
bool AudioEngine::CreateSound(Sound& sound, const Transcoder::Buffer& buffer)
{
KGE_ASSERT(x_audio2_ && "AudioEngine hasn't been initialized!");
if (voice == nullptr)
HRESULT hr = S_OK;
if (buffer.format == nullptr)
hr = E_INVALIDARG;
if (SUCCEEDED(hr))
{
return E_INVALIDARG;
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);
}
}
if (*voice)
{
(*voice)->DestroyVoice();
(*voice) = nullptr;
}
return x_audio2_->CreateSourceVoice(voice, buffer.format, 0, XAUDIO2_DEFAULT_FREQ_RATIO);
win32::WarnIfFailed(hr);
return SUCCEEDED(hr);
}
void AudioEngine::Open()
{
KGE_ASSERT(x_audio2_ && "AudioEngine hasn't been initialized!");
x_audio2_->StartEngine();
if (x_audio2_)
x_audio2_->StartEngine();
}
void AudioEngine::Close()
{
KGE_ASSERT(x_audio2_ && "AudioEngine hasn't been initialized!");
x_audio2_->StopEngine();
if (x_audio2_)
x_audio2_->StopEngine();
}
}
}

View File

@ -22,12 +22,27 @@
#include <kiwano/core/common.h>
#include <kiwano/core/Component.h>
#include <kiwano-audio/Transcoder.h>
#include <kiwano-audio/Sound.h>
#include <xaudio2.h>
namespace kiwano
{
namespace audio
{
/**
* \~chinese
* \defgroup Audio
*/
/**
* \addtogroup Audio
* @{
*/
/**
* \~chinese
* @brief
*/
class KGE_API AudioEngine
: public Singleton<AudioEngine>
, public ComponentBase
@ -35,16 +50,17 @@ namespace kiwano
friend Singleton<AudioEngine>;
public:
// 开启设备
/// \~chinese
/// @brief 开启音频设备
void Open();
// 关闭设备
/// \~chinese
/// @brief 关闭音频设备
void Close();
HRESULT CreateVoice(
IXAudio2SourceVoice** voice,
const Transcoder::Buffer& buffer
);
/// \~chinese
/// @brief 从解码器数据缓冲中创建音频对象
bool CreateSound(Sound& sound, const Transcoder::Buffer& buffer);
public:
void SetupComponent() override;
@ -60,5 +76,7 @@ namespace kiwano
IXAudio2* x_audio2_;
IXAudio2MasteringVoice* mastering_voice_;
};
/** @} */
}
}

View File

@ -35,18 +35,6 @@ namespace kiwano
{
}
Sound::Sound(String const& file_path)
: Sound()
{
Load(file_path);
}
Sound::Sound(Resource const& res)
: Sound()
{
Load(res);
}
Sound::~Sound()
{
Close();
@ -68,19 +56,15 @@ namespace kiwano
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;
}
hr = AudioEngine::instance().CreateVoice(&voice_, transcoder_.GetBuffer());
if (FAILED(hr))
if (!AudioEngine::instance().CreateSound(*this, transcoder_.GetBuffer()))
{
Close();
KGE_ERROR(L"Create source voice failed with HRESULT of %08X", hr);
return false;
}
@ -96,19 +80,15 @@ namespace kiwano
}
HRESULT hr = transcoder_.LoadMediaResource(res);
if (FAILED(hr))
{
KGE_ERROR(L"Load media resource failed with HRESULT of %08X", hr);
return false;
}
hr = AudioEngine::instance().CreateVoice(&voice_, transcoder_.GetBuffer());
if (FAILED(hr))
if (!AudioEngine::instance().CreateSound(*this, transcoder_.GetBuffer()))
{
Close();
KGE_ERROR(L"Create source voice failed with HRESULT of %08X", hr);
return false;
}
@ -116,6 +96,11 @@ namespace kiwano
return true;
}
bool Sound::IsValid() const
{
return voice_ != nullptr;
}
void Sound::Play(int loop_count)
{
if (!opened_)

View File

@ -21,6 +21,7 @@
#pragma once
#include <kiwano/core/ObjectBase.h>
#include <kiwano/core/Resource.h>
#include <kiwano/platform/win32/ComPtr.hpp>
#include <kiwano-audio/Transcoder.h>
#include <xaudio2.h>
@ -28,68 +29,100 @@ namespace kiwano
{
namespace audio
{
class AudioEngine;
KGE_DECLARE_SMART_PTR(Sound);
/**
* \addtogroup Audio
* @{
*/
/**
* \~chinese
* @brief
*/
class KGE_API Sound
: public ObjectBase
{
friend class AudioEngine;
public:
Sound();
Sound(
String const& file_path /* 本地音频文件 */
);
Sound(
Resource const& res /* 音乐资源 */
);
virtual ~Sound();
// 打开本地音频文件
bool Load(
String const& file_path
);
/// \~chinese
/// @brief 打开本地音频文件
/// @param res 本地音频文件路径
bool Load(String const& file_path);
// 打开音乐资源
bool Load(
Resource const& res /* 音乐资源 */
);
/// \~chinese
/// @brief 打开音频资源
/// @param res 音频资源
bool Load(Resource const& res);
// 播放
void Play(
int loop_count = 0 /* 播放循环次数 (-1 为循环播放) */
);
/// \~chinese
/// @brief 是否有效
bool IsValid() const;
// 暂停
/// \~chinese
/// @brief 播放
/// @param loop_count 播放循环次数,设置 -1 为循环播放
void Play(int loop_count = 0);
/// \~chinese
/// @brief 暂停
void Pause();
// 继续
/// \~chinese
/// @brief 继续
void Resume();
// 停止
/// \~chinese
/// @brief 停止
void Stop();
// 关闭并回收资源
/// \~chinese
/// @brief 关闭并销毁资源
void Close();
// 是否正在播放
/// \~chinese
/// @brief 是否正在播放
bool IsPlaying() const;
// 获取音量
/// \~chinese
/// @brief 获取音量
float GetVolume() const;
// 设置音量
void SetVolume(
float volume /* 1 为原始音量, 大于 1 为放大音量, 0 为最小音量 */
);
/// \~chinese
/// @brief 设置音量
/// @param volume 音量大小1.0 为原始音量, 大于 1 为放大音量, 0 为最小音量
void SetVolume(float volume);
private:
bool opened_;
bool playing_;
Transcoder transcoder_;
IXAudio2SourceVoice* GetXAudio2Voice() const;
void SetXAudio2Voice(IXAudio2SourceVoice* voice);
private:
bool opened_;
bool playing_;
Transcoder transcoder_;
IXAudio2SourceVoice* voice_;
};
/** @} */
inline IXAudio2SourceVoice* Sound::GetXAudio2Voice() const
{
return voice_;
}
inline void Sound::SetXAudio2Voice(IXAudio2SourceVoice* voice)
{
voice_ = voice;
}
}
}

View File

@ -28,69 +28,84 @@ namespace kiwano
{
KGE_DECLARE_SMART_PTR(SoundPlayer);
// 音乐播放器
/**
* \addtogroup Audio
* @{
*/
/**
* \~chinese
* @brief
*/
class KGE_API SoundPlayer
: protected ObjectBase
: public ObjectBase
{
public:
SoundPlayer();
~SoundPlayer();
// 加载本地音频文件, 返回该资源的标识符
size_t Load(
String const& file_path
);
/// \~chinese
/// @brief 加载本地音频文件
/// @param file_path 本地音频文件路径
/// @return 音频标识符
size_t Load(String const& file_path);
// 加载音乐资源, 返回该资源的标识符
size_t Load(
Resource const& res /* 音乐资源 */
);
/// \~chinese
/// @brief 加载音频资源
/// @param res 音频资源
/// @return 音频标识符
size_t Load(Resource const& res);
// 播放音乐
void Play(
size_t id, /* 标识符 */
int loop_count = 0 /* 播放循环次数 (-1 为循环播放) */
);
/// \~chinese
/// @brief 播放音频
/// @param id 音频标识符
/// @param loop_count 播放循环次数,设置 -1 为循环播放
void Play(size_t id, int loop_count = 0);
// 暂停音乐
void Pause(
size_t id /* 标识符 */
);
/// \~chinese
/// @brief 暂停音频
/// @param id 音频标识符
void Pause(size_t id);
// 继续播放音乐
void Resume(
size_t id /* 标识符 */
);
/// \~chinese
/// @brief 继续播放音频
/// @param id 音频标识符
void Resume(size_t id);
// 停止音乐
void Stop(
size_t id /* 标识符 */
);
/// \~chinese
/// @brief 停止音频
/// @param id 音频标识符
void Stop(size_t id);
// 获取音乐播放状态
bool IsPlaying(
size_t id /* 标识符 */
);
/// \~chinese
/// @brief 获取音频播放状态
/// @param id 音频标识符
bool IsPlaying(size_t id);
// 获取音量
/// \~chinese
/// @brief 获取音量
float GetVolume() const;
// 设置音量
void SetVolume(
float volume /* 1.0 为原始音量 */
);
/// \~chinese
/// @brief 设置音量
/// @param volume 音量大小1.0 为原始音量, 大于 1 为放大音量, 0 为最小音量
void SetVolume(float volume);
// 暂停所有音乐
/// \~chinese
/// @brief 暂停所有音频
void PauseAll();
// 继续播放所有音乐
/// \~chinese
/// @brief 继续播放所有音频
void ResumeAll();
// 停止所有音乐
/// \~chinese
/// @brief 停止所有音频
void StopAll();
// 清除缓存
/// \~chinese
/// @brief 清除缓存
void ClearCache();
private:
@ -99,5 +114,7 @@ namespace kiwano
using SoundMap = Map<size_t, SoundPtr>;
SoundMap sound_cache_;
};
/** @} */
}
}

View File

@ -28,41 +28,64 @@ namespace kiwano
{
namespace audio
{
class Sound;
/**
* \addtogroup Audio
* @{
*/
/**
* \~chinese
* @brief
*/
class KGE_API Transcoder
{
friend class Sound;
public:
/**
* \~chinese
* @brief
*/
struct Buffer
{
BYTE* data;
uint32_t size;
const WAVEFORMATEX* format;
BYTE* data; ///< 音频数据
uint32_t size; ///< 音频数据大小
const WAVEFORMATEX* format; ///< 音频数据格式
};
Transcoder();
~Transcoder();
/// \~chinese
/// @brief 获取数据缓冲
Buffer GetBuffer() const;
/// \~chinese
/// @brief 清空数据缓冲
void ClearBuffer();
HRESULT LoadMediaFile(
String const& file_path
);
private:
/// \~chinese
/// @brief 解码本地音频文件
HRESULT LoadMediaFile(String const& file_path);
HRESULT LoadMediaResource(
Resource const& res
);
/// \~chinese
/// @brief 解码音频资源
HRESULT LoadMediaResource(Resource const& res);
HRESULT ReadSource(
IMFSourceReader* reader
);
/// \~chinese
/// @brief 读取音频源数据
HRESULT ReadSource(IMFSourceReader* reader);
private:
BYTE* wave_data_;
uint32_t wave_size_;
WAVEFORMATEX* wave_format_;
};
/** @} */
}
}

View File

@ -33,9 +33,9 @@ namespace kiwano
{
const auto xaudio2_dll_names =
{
L"xaudio2_9.dll", // for Windows 10
L"xaudio2_8.dll", // for Windows 8
L"xaudio2_7.dll" // for DirectX SDK
"xaudio2_9.dll", // for Windows 10
"xaudio2_8.dll", // for Windows 8
"xaudio2_7.dll" // for DirectX SDK
};
for (const auto& name : xaudio2_dll_names)
@ -48,7 +48,7 @@ namespace kiwano
if (xaudio2.IsValid())
{
XAudio2Create = xaudio2.GetProcess<PFN_XAudio2Create>(L"XAudio2Create");
XAudio2Create = xaudio2.GetProcess<PFN_XAudio2Create>("XAudio2Create");
}
else
{
@ -68,28 +68,28 @@ namespace kiwano
, MFCreateSourceReaderFromByteStream(nullptr)
, MFCreateMFByteStreamOnStream(nullptr)
{
if (mfplat.Load(L"Mfplat.dll"))
if (mfplat.Load("Mfplat.dll"))
{
MFStartup = mfplat.GetProcess<PFN_MFStartup>(L"MFStartup");
MFShutdown = mfplat.GetProcess<PFN_MFShutdown>(L"MFShutdown");
MFCreateMediaType = mfplat.GetProcess<PFN_MFCreateMediaType>(L"MFCreateMediaType");
MFCreateWaveFormatExFromMFMediaType = mfplat.GetProcess<PFN_MFCreateWaveFormatExFromMFMediaType>(L"MFCreateWaveFormatExFromMFMediaType");
MFCreateMFByteStreamOnStream = mfplat.GetProcess<PFN_MFCreateMFByteStreamOnStream>(L"MFCreateMFByteStreamOnStream");
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_SYS_LOG(L"Load Mfplat.dll failed");
KGE_ERROR(L"Load Mfplat.dll failed");
throw std::runtime_error("Load Mfplat.dll failed");
}
if (mfreadwrite.Load(L"Mfreadwrite.dll"))
if (mfreadwrite.Load("Mfreadwrite.dll"))
{
MFCreateSourceReaderFromURL = mfreadwrite.GetProcess<PFN_MFCreateSourceReaderFromURL>(L"MFCreateSourceReaderFromURL");
MFCreateSourceReaderFromByteStream = mfreadwrite.GetProcess<PFN_MFCreateSourceReaderFromByteStream>(L"MFCreateSourceReaderFromByteStream");
MFCreateSourceReaderFromURL = mfreadwrite.GetProcess<PFN_MFCreateSourceReaderFromURL>("MFCreateSourceReaderFromURL");
MFCreateSourceReaderFromByteStream = mfreadwrite.GetProcess<PFN_MFCreateSourceReaderFromByteStream>("MFCreateSourceReaderFromByteStream");
}
else
{
KGE_SYS_LOG(L"Load Mfreadwrite.dll failed");
KGE_ERROR(L"Load Mfreadwrite.dll failed");
throw std::runtime_error("Load Mfreadwrite.dll failed");
}
}

View File

@ -25,6 +25,8 @@
#include <mfidl.h>
#include <mfreadwrite.h>
#ifndef KGE_DOXYGEN_DO_NOT_INCLUDE
namespace kiwano
{
namespace audio
@ -93,3 +95,5 @@ namespace kiwano
}
}
}
#endif

View File

@ -27,8 +27,14 @@ namespace kiwano
{
KGE_DECLARE_SMART_PTR(ImGuiLayer);
/// \~chinese
/// @brief ImGui管道
using ImGuiPipeline = Function<void()>;
/**
* \~chinese
* @brief ImGui图层
*/
class ImGuiLayer
: public Layer
{
@ -37,18 +43,20 @@ namespace kiwano
virtual ~ImGuiLayer();
// Ìí¼Ó ImGui ÔªËØ
void AddItem(
ImGuiPipeline const& item,
String const& name
);
/// \~chinese
/// @brief 添加 ImGui 元素
/// @param item 管道
/// @param name 元素名称
void AddItem(ImGuiPipeline const& item, String const& name);
// ÒÆ³ý ImGui ÔªËØ
void RemoveItem(
String const& name
);
/// \~chinese
/// @brief 移除 ImGui 元素
/// @param name 元素名称
void RemoveItem(String const& name);
// 移除所有元素
/// \~chinese
/// @brief 移除所有元素
void RemoveAllItems();
public:

View File

@ -26,6 +26,10 @@ namespace kiwano
{
namespace imgui
{
/**
* \~chinese
* @brief ImGuiÄ£¿é
*/
class ImGuiModule
: public Singleton<ImGuiModule>
, public RenderComponent
@ -34,13 +38,6 @@ namespace kiwano
{
friend Singleton<ImGuiModule>;
private:
void Init(HWND hwnd);
void NewFrame();
void Render();
public:
ImGuiModule();
@ -48,14 +45,21 @@ namespace kiwano
void DestroyComponent() override;
void OnUpdate(Duration dt) override;
void BeforeRender() override;
void AfterRender() override;
void HandleMessage(HWND hwnd, UINT32 msg, WPARAM wparam, LPARAM lparam) override;
void OnUpdate(Duration dt) override;
private:
void Init(HWND hwnd);
void NewFrame();
void Render();
void UpdateMousePos();
void UpdateMouseCursor();

View File

@ -2,6 +2,8 @@
#pragma once
#ifndef KGE_DOXYGEN_DO_NOT_INCLUDE
#if !defined(KGE_USE_DIRECTX10)
#include <kiwano-imgui/imgui_impl_dx11.h>
@ -27,3 +29,5 @@ inline void ImGui_Impl_InvalidateDeviceObjects() { ImGui_ImplDX10_Invalid
inline bool ImGui_Impl_CreateDeviceObjects() { return ImGui_ImplDX10_CreateDeviceObjects(); }
#endif
#endif

View File

@ -3,6 +3,8 @@
#pragma once
#include <3rd-party/imgui/imgui.h>
#ifndef KGE_DOXYGEN_DO_NOT_INCLUDE
struct ID3D10Device;
IMGUI_IMPL_API bool ImGui_ImplDX10_Init(ID3D10Device* device);
@ -13,3 +15,5 @@ IMGUI_IMPL_API void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data);
// Use if you want to reset your rendering device without losing ImGui state.
IMGUI_IMPL_API void ImGui_ImplDX10_InvalidateDeviceObjects();
IMGUI_IMPL_API bool ImGui_ImplDX10_CreateDeviceObjects();
#endif

View File

@ -3,6 +3,8 @@
#pragma once
#include <3rd-party/imgui/imgui.h>
#ifndef KGE_DOXYGEN_DO_NOT_INCLUDE
struct ID3D11Device;
struct ID3D11DeviceContext;
@ -14,3 +16,5 @@ IMGUI_IMPL_API void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data);
// Use if you want to reset your rendering device without losing ImGui state.
IMGUI_IMPL_API void ImGui_ImplDX11_InvalidateDeviceObjects();
IMGUI_IMPL_API bool ImGui_ImplDX11_CreateDeviceObjects();
#endif

View File

@ -36,7 +36,7 @@ namespace
uint32_t write_data(void* buffer, uint32_t size, uint32_t nmemb, void* userp)
{
oc::string* recv_buffer = (oc::string*)userp;
ByteString* recv_buffer = (ByteString*)userp;
uint32_t total = size * nmemb;
// add data to the end of recv_buffer
@ -46,10 +46,10 @@ namespace
return total;
}
oc::string convert_to_utf8(oc::wstring const& str)
ByteString convert_to_utf8(String const& str)
{
std::wstring_convert<std::codecvt_utf8<wchar_t>> utf8_conv;
oc::string result;
ByteString result;
try
{
@ -58,15 +58,15 @@ namespace
catch (std::range_error&)
{
// bad conversion
result = wide_to_string(str);
result = WideToMultiByte(str);
}
return result;
}
oc::wstring convert_from_utf8(oc::string const& str)
String convert_from_utf8(ByteString const& str)
{
oc::string_convert<std::codecvt_utf8<wchar_t>> utf8_conv;
oc::wstring result;
String result;
try
{
@ -75,7 +75,7 @@ namespace
catch (std::range_error&)
{
// bad conversion
result = string_to_wide(str);
result = MultiByteToWide(str);
}
return result;
}
@ -104,7 +104,7 @@ namespace
}
}
bool Init(HttpClient* client, Vector<oc::string> const& headers, oc::string const& url, oc::string* response_data, oc::string* response_header, char* error_buffer)
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;
@ -170,11 +170,11 @@ namespace
public:
static inline bool GetRequest(
HttpClient* client,
Vector<oc::string> const& headers,
oc::string const& url,
Vector<ByteString> const& headers,
ByteString const& url,
long* response_code,
oc::string* response_data,
oc::string* response_header,
ByteString* response_data,
ByteString* response_header,
char* error_buffer)
{
Curl curl;
@ -185,12 +185,12 @@ namespace
static inline bool PostRequest(
HttpClient* client,
Vector<oc::string> const& headers,
oc::string const& url,
oc::string const& request_data,
Vector<ByteString> const& headers,
ByteString const& url,
ByteString const& request_data,
long* response_code,
oc::string* response_data,
oc::string* response_header,
ByteString* response_data,
ByteString* response_header,
char* error_buffer)
{
Curl curl;
@ -203,12 +203,12 @@ namespace
static inline bool PutRequest(
HttpClient* client,
Vector<oc::string> const& headers,
oc::string const& url,
oc::string const& request_data,
Vector<ByteString> const& headers,
ByteString const& url,
ByteString const& request_data,
long* response_code,
oc::string* response_data,
oc::string* response_header,
ByteString* response_data,
ByteString* response_header,
char* error_buffer)
{
Curl curl;
@ -221,11 +221,11 @@ namespace
static inline bool DeleteRequest(
HttpClient* client,
Vector<oc::string> const& headers,
oc::string const& url,
Vector<ByteString> const& headers,
ByteString const& url,
long* response_code,
oc::string* response_data,
oc::string* response_header,
ByteString* response_data,
ByteString* response_header,
char* error_buffer)
{
Curl curl;
@ -307,13 +307,13 @@ namespace kiwano
bool ok = false;
long response_code = 0;
char error_message[256] = { 0 };
oc::string response_header;
oc::string response_data;
ByteString response_header;
ByteString response_data;
oc::string url = convert_to_utf8(request->GetUrl());
oc::string data = convert_to_utf8(request->GetData());
ByteString url = convert_to_utf8(request->GetUrl());
ByteString data = convert_to_utf8(request->GetData());
Vector<oc::string> headers;
Vector<ByteString> headers;
headers.reserve(request->GetHeaders().size());
for (const auto& pair : request->GetHeaders())
{
@ -340,12 +340,12 @@ namespace kiwano
}
response->SetResponseCode(response_code);
response->SetHeader(oc::string_to_wide(response_header));
response->SetHeader(MultiByteToWide(response_header));
response->SetData(convert_from_utf8(response_data));
if (!ok)
{
response->SetSucceed(false);
response->SetError(oc::string_to_wide(error_message));
response->SetError(MultiByteToWide(error_message));
}
else
{

View File

@ -28,6 +28,20 @@ namespace kiwano
{
namespace network
{
/**
* \~chinese
* \defgroup Network
*/
/**
* \addtogroup Network
* @{
*/
/**
* \~chinese
* @brief HTTP客户端
*/
class KGE_API HttpClient
: public Singleton<HttpClient>
, public ComponentBase
@ -35,18 +49,34 @@ namespace kiwano
friend Singleton<HttpClient>;
public:
/// \~chinese
/// @brief 发送HTTP请求
/// @param[in] request HTTP请求
/// @details 发送请求后,无论结束或失败都将调用请求的响应回调函数
void Send(HttpRequestPtr request);
/// \~chinese
/// @brief 设置连接超时时长
void SetTimeoutForConnect(Duration timeout);
/// \~chinese
/// @brief 获取连接超时时长
Duration GetTimeoutForConnect() const;
/// \~chinese
/// @brief 设置读取超时时长
void SetTimeoutForRead(Duration timeout);
/// \~chinese
/// @brief 获取读取超时时长
Duration GetTimeoutForRead() const;
/// \~chinese
/// @brief 设置SSL证书地址
void SetSSLVerification(String const& root_certificate_path);
/// \~chinese
/// @brief 获取SSL证书地址
String const& GetSSLVerification() const;
public:
@ -59,10 +89,7 @@ namespace kiwano
void NetworkThread();
void Perform(
HttpRequestPtr request,
HttpResponsePtr response
);
void Perform(HttpRequestPtr request, HttpResponsePtr response);
void DispatchResponseCallback();
@ -81,6 +108,8 @@ namespace kiwano
std::condition_variable_any sleep_condition_;
};
/** @} */
inline void HttpClient::SetTimeoutForConnect(Duration timeout)
{

View File

@ -31,46 +31,88 @@ namespace kiwano
KGE_DECLARE_SMART_PTR(HttpRequest);
/**
* \addtogroup Network
* @{
*/
/**
* \~chinese
* @brief HTTP请求
*/
class KGE_API HttpRequest
: public ObjectBase
{
public:
using ResponseCallback = Function<void(HttpRequest*, HttpResponse*)>;
/// \~chinese
/// @brief 响应回调函数
using ResponseCallback = Function<void(HttpRequest* /* request */, HttpResponse* /* response */)>;
/// \~chinese
/// @brief 请求类型
enum class Type
{
Unknown,
Get,
Post,
Put,
Delete
Unknown, ///< 未知
Get, ///< HTTP GET请求
Post, ///< HTTP POST请求
Put, ///< HTTP PUT请求
Delete ///< HTTP DELETE请求
};
HttpRequest();
HttpRequest(Type type);
// 请求地址
/// \~chinese
/// @brief 设置请求地址
void SetUrl(String const& url);
/// \~chinese
/// @brief 设置请求类型
void SetType(Type type);
/// \~chinese
/// @brief 设置请求携带的数据
void SetData(String const& data);
/// \~chinese
/// @brief 设置请求携带的JSON数据
void SetJsonData(Json const& json);
/// \~chinese
/// @brief 设置HTTP头
void SetHeaders(Map<String, String> const& headers);
/// \~chinese
/// @brief 设置HTTP头
void SetHeader(String const& field, String const& content);
/// \~chinese
/// @brief 设置响应回调函数
void SetResponseCallback(ResponseCallback const& callback);
/// \~chinese
/// @brief 获取请求地址
String const& GetUrl() const;
// 请求类型
void SetType(Type type);
/// \~chinese
/// @brief 获取请求类型
Type GetType() const;
// 请求数据
void SetData(String const& data);
void SetJsonData(Json const& json);
/// \~chinese
/// @brief 获取请求数据
String const& GetData() const;
// 请求头
void SetHeaders(Map<String, String> const& headers);
void SetHeader(String const& field, String const& content);
/// \~chinese
/// @brief 获取HTTP头
Map<String, String>& GetHeaders();
/// \~chinese
/// @brief 获取HTTP头
String const& GetHeader(String const& header) const;
// 响应回调
void SetResponseCallback(ResponseCallback const& callback);
/// \~chinese
/// @brief 获取响应回调函数
ResponseCallback const& GetResponseCallback() const;
private:
@ -81,6 +123,8 @@ namespace kiwano
ResponseCallback response_cb_;
};
/** @} */
inline HttpRequest::HttpRequest() : type_(Type::Unknown) {}
inline HttpRequest::HttpRequest(Type type) : type_(type) {}

View File

@ -27,33 +27,63 @@ namespace kiwano
{
KGE_DECLARE_SMART_PTR(HttpResponse);
/**
* \addtogroup Network
* @{
*/
/**
* \~chinese
* @brief HTTP响应
*/
class KGE_API HttpResponse
: public ObjectBase
{
public:
HttpResponse(HttpRequestPtr request);
// 获取请求
/// \~chinese
/// @brief 获取对应的HTTP请求
HttpRequestPtr GetRequest() const;
// 响应状态
/// \~chinese
/// @brief 获取响应状态
bool IsSucceed() const;
/// \~chinese
/// @brief 获取HTTP状态码
long GetResponseCode() const;
/// \~chinese
/// @brief 获取响应头
String GetHeader() const;
/// \~chinese
/// @brief 获取响应数据
String const& GetData() const;
/// \~chinese
/// @brief 获取错误信息
String const& GetError() const;
/// \~chinese
/// @brief 设置响应状态
void SetSucceed(bool succeed);
// 响应状态码
long GetResponseCode() const;
/// \~chinese
/// @brief 设置HTTP状态码
void SetResponseCode(long response_code);
// 响应头
String GetHeader() const;
/// \~chinese
/// @brief 设置响应头
void SetHeader(String const& response_header);
// 响应数据
String const& GetData() const;
/// \~chinese
/// @brief 设置响应数据
void SetData(String const& response_data);
// 错误信息
String const& GetError() const;
/// \~chinese
/// @brief 设置错误信息
void SetError(String const& error_buffer);
private:
@ -66,6 +96,8 @@ namespace kiwano
String error_buffer_;
};
/** @} */
inline HttpResponse::HttpResponse(HttpRequestPtr request) : request_(request), succeed_(false), response_code_(0) {}
inline HttpRequestPtr HttpResponse::GetRequest() const { return request_; }

View File

@ -38,7 +38,7 @@ namespace kiwano
/**
* \~chinese
* \defgroup Actors
* \defgroup Actors
*/
/**
@ -63,8 +63,13 @@ namespace kiwano
friend IntrusiveList<ActorPtr>;
public:
using Children = IntrusiveList<ActorPtr>;
using UpdateCallback = Function<void(Duration)>;
/// \~chinese
/// @brief 子成员列表
using Children = IntrusiveList<ActorPtr>;
/// \~chinese
/// @brief 角色更新回调函数
using UpdateCallback = Function<void(Duration)>;
Actor();
@ -395,15 +400,15 @@ namespace kiwano
protected:
/// \~chinese
/// @brief 更新自身和所有子节点
/// @brief 更新自身和所有子角色
virtual void Update(Duration dt);
/// \~chinese
/// @brief 渲染自身和所有子节点
/// @brief 渲染自身和所有子角色
virtual void Render(RenderTarget* rt);
/// \~chinese
/// @brief 绘制自身和所有子节点的边界
/// @brief 绘制自身和所有子角色的边界
virtual void RenderBorder(RenderTarget* rt);
/// \~chinese
@ -415,15 +420,15 @@ namespace kiwano
virtual void PrepareToRender(RenderTarget* rt);
/// \~chinese
/// @brief 更新自己的二维变换,并通知所有子节点
/// @brief 更新自己的二维变换,并通知所有子角色
void UpdateTransform() const;
/// \~chinese
/// @brief 更新自己和所有子节点的透明度
/// @brief 更新自己和所有子角色的透明度
void UpdateOpacity();
/// \~chinese
/// @brief 将所有子节点按Z轴顺序排序
/// @brief 将所有子角色按Z轴顺序排序
void Reorder();
/// \~chinese

View File

@ -76,7 +76,7 @@ namespace kiwano
protected:
/// \~chinese
/// @brief 绘制所有子节点的边界
/// @brief 绘制所有子角色的边界
void RenderBorder(RenderTarget* rt) override;
private:

View File

@ -45,6 +45,12 @@ namespace kiwano
return IsValid();
}
bool Library::Load(ByteString const& lib)
{
instance_ = ::LoadLibraryA(lib.c_str());
return IsValid();
}
bool Library::IsValid() const
{
return instance_ != nullptr;
@ -59,10 +65,13 @@ namespace kiwano
}
}
FARPROC Library::GetProcess(String const& proc_name)
FARPROC Library::GetProcess(ByteString const& proc_name)
{
KGE_ASSERT(instance_ != nullptr);
return GetProcAddress(instance_, oc::wide_to_string(proc_name).c_str());
if (!IsValid())
return nullptr;
return GetProcAddress(instance_, proc_name.c_str());
}
}

View File

@ -47,6 +47,11 @@ namespace kiwano
/// @param lib DLL文件路径
bool Load(String const& lib);
/// \~chinese
/// @brief 加载DLL
/// @param lib DLL文件路径
bool Load(ByteString const& lib);
/// \~chinese
/// @brief 是否有效
bool IsValid() const;
@ -58,13 +63,13 @@ namespace kiwano
/// \~chinese
/// @brief 检索指定的DLL中的输出库函数地址
/// @param proc_name 函数名
FARPROC GetProcess(String const& proc_name);
FARPROC GetProcess(ByteString const& proc_name);
/// \~chinese
/// @brief 检索指定的DLL中的输出库函数地址
/// @param proc_name 函数名
template <typename _Proc>
inline _Proc GetProcess(String const& proc_name)
inline _Proc GetProcess(ByteString const& proc_name)
{
return reinterpret_cast<_Proc>(GetProcess(proc_name));
}

View File

@ -201,32 +201,29 @@ namespace kiwano
void Logger::Prepare(Level level, StringStream& sstream)
{
String prompt;
String prefix;
switch (level)
{
case Level::Info:
prompt = L"[INFO] ";
prefix = L"[INFO] ";
break;
case Level::System:
prompt = L"[SYSTEM] ";
prefix = L"[SYSTEM] ";
break;
case Level::Warning:
prompt = L"[WARNING] ";
prefix = L"[WARN] ";
break;
case Level::Error:
prompt = L"[ERROR] ";
prefix = L"[ERROR] ";
break;
}
// Prefix
sstream << L"[KIWANO] " << prompt;
// Timestamp
time_t unix = std::time(nullptr);
std::tm tmbuf;
localtime_s(&tmbuf, &unix);
sstream << std::put_time(&tmbuf, L"%H:%M:%S ");
sstream << prefix << std::put_time(&tmbuf, L"%H:%M:%S ");
}
void Logger::Output(Level level, StringStream& sstream)

View File

@ -78,18 +78,6 @@ namespace kiwano
/// @brief 控制台颜色
using ConsoleColor = Function<OutputStream& (OutputStream&)>;
/// \~chinese
/// @brief 显示或关闭控制台
void ShowConsole(bool show);
/// \~chinese
/// @brief 启用日志
void Enable();
/// \~chinese
/// @brief 禁用日志
void Disable();
/// \~chinese
/// @brief 打印日志
/// @param level 日志级别
@ -110,6 +98,19 @@ namespace kiwano
template <typename ..._Args>
void Println(Level level, _Args&& ... args);
/// \~chinese
/// @brief 显示或关闭控制台
/// @note 此操作会重置输出流
void ShowConsole(bool show);
/// \~chinese
/// @brief 启用日志
void Enable();
/// \~chinese
/// @brief 禁用日志
void Disable();
/// \~chinese
/// @brief 获取输出流
std::wostream& GetOutputStream();

View File

@ -37,6 +37,10 @@ namespace kiwano
/// @brief 字符串容器
using String = oc::wstring;
/// \~chinese
/// @brief 窄字符串容器
using ByteString = oc::string;
/// \~chinese
/// @brief 字符串流
using StringStream = std::wstringstream;
@ -149,4 +153,14 @@ namespace kiwano
{
return oc::closure(ptr, func);
}
inline ByteString WideToMultiByte(const String& str)
{
return oc::wide_to_string(str);
}
inline String MultiByteToWide(const ByteString& str)
{
return oc::string_to_wide(str);
}
}

View File

@ -128,13 +128,7 @@ namespace kiwano
uint32_t screenh = monitor_info_ex.rcWork.bottom - monitor_info_ex.rcWork.top;
uint32_t win_width, win_height;
AdjustWindow(
width,
height,
GetWindowStyle(),
&win_width,
&win_height
);
AdjustWindow(width, height, GetWindowStyle(), &win_width, &win_height);
left = monitor_info_ex.rcWork.left + (screenw - win_width) / 2;
top = monitor_info_ex.rcWork.top + (screenh - win_height) / 2;

View File

@ -0,0 +1,235 @@
// 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/macros.h>
#include <kiwano/core/Logger.h>
#include <kiwano/core/Library.h>
#include <dbghelp.h>
namespace kiwano
{
namespace win32
{
namespace
{
// SymInitialize()
typedef BOOL(__stdcall* PFN_SymInitialize)(IN HANDLE hProcess, IN PSTR UserSearchPath, IN BOOL fInvadeProcess);
// SymCleanup()
typedef BOOL(__stdcall* PFN_SymCleanup)(IN HANDLE hProcess);
// SymGetLineFromAddr64()
typedef BOOL(__stdcall* PFN_SymGetLineFromAddr64)(IN HANDLE hProcess, IN DWORD64 dwAddr,
OUT PDWORD pdwDisplacement, OUT PIMAGEHLP_LINE64 Line);
// SymGetSymFromAddr64()
typedef BOOL(__stdcall* PFN_SymGetSymFromAddr64)(IN HANDLE hProcess, IN DWORD64 dwAddr,
OUT PDWORD64 pdwDisplacement, OUT PIMAGEHLP_SYMBOL64 Symbol);
// StackWalk64()
typedef BOOL(__stdcall* PFN_StackWalk64)(DWORD MachineType, HANDLE hProcess, HANDLE hThread,
LPSTACKFRAME64 StackFrame, PVOID ContextRecord, PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine,
PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine, PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine,
PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress);
// SymFunctionTableAccess64()
typedef PVOID(__stdcall* PFN_SymFunctionTableAccess64)(HANDLE hProcess, DWORD64 AddrBase);
// SymGetModuleBase64()
typedef DWORD64(__stdcall* PFN_SymGetModuleBase64)(IN HANDLE hProcess, IN DWORD64 dwAddr);
struct DbgHelp
{
Library dbgLib;
PFN_SymInitialize SymInitialize;
PFN_SymCleanup SymCleanup;
PFN_SymGetLineFromAddr64 SymGetLineFromAddr64;
PFN_SymGetSymFromAddr64 SymGetSymFromAddr64;
PFN_StackWalk64 StackWalk64;
PFN_SymFunctionTableAccess64 SymFunctionTableAccess64;
PFN_SymGetModuleBase64 SymGetModuleBase64;
DbgHelp()
: SymInitialize(nullptr)
, SymCleanup(nullptr)
, SymGetLineFromAddr64(nullptr)
, SymGetSymFromAddr64(nullptr)
, StackWalk64(nullptr)
, SymFunctionTableAccess64(nullptr)
, SymGetModuleBase64(nullptr)
{
}
bool Load()
{
if (IsValid())
return true;
if (!dbgLib.Load("dbghelp.dll"))
return false;
SymInitialize = dbgLib.GetProcess<PFN_SymInitialize>("SymInitialize");
SymCleanup = dbgLib.GetProcess<PFN_SymCleanup>("SymCleanup");
SymGetLineFromAddr64 = dbgLib.GetProcess<PFN_SymGetLineFromAddr64>("SymGetLineFromAddr64");
SymGetSymFromAddr64 = dbgLib.GetProcess<PFN_SymGetSymFromAddr64>("SymGetSymFromAddr64");
StackWalk64 = dbgLib.GetProcess<PFN_StackWalk64>("StackWalk64");
SymFunctionTableAccess64 = dbgLib.GetProcess<PFN_SymFunctionTableAccess64>("SymFunctionTableAccess64");
SymGetModuleBase64 = dbgLib.GetProcess<PFN_SymGetModuleBase64>("SymGetModuleBase64");
if (!IsValid())
{
dbgLib.Free();
return false;
}
return true;
}
bool IsValid() const
{
return SymInitialize && SymCleanup && SymGetLineFromAddr64 && SymGetSymFromAddr64
&& StackWalk64 && SymFunctionTableAccess64 && SymGetModuleBase64;
}
};
DbgHelp g_DbgHelp;
}
void PrintErrorCode(LPCWSTR lpszFunction)
{
KGE_ERROR(L"%s failed with HRESULT of %08X", lpszFunction, HRESULT_FROM_WIN32(GetLastError()));
}
void PrintCallStackOnContext(PCONTEXT pContext)
{
if (!g_DbgHelp.Load())
return;
if (pContext == nullptr)
return;
DWORD dwMachineType;
STACKFRAME64 sf;
HANDLE hProcess = GetCurrentProcess();
HANDLE hThread = GetCurrentThread();
ZeroMemory(&sf, sizeof(sf));
sf.AddrPC.Mode = AddrModeFlat;
sf.AddrFrame.Mode = AddrModeFlat;
sf.AddrStack.Mode = AddrModeFlat;
sf.AddrBStore.Mode = AddrModeFlat;
#ifdef _M_IX86
dwMachineType = IMAGE_FILE_MACHINE_I386;
sf.AddrPC.Offset = pContext->Eip;
sf.AddrFrame.Offset = pContext->Ebp;
sf.AddrStack.Offset = pContext->Esp;
#elif _M_X64
dwMachineType = IMAGE_FILE_MACHINE_AMD64;
sf.AddrPC.Offset = pContext->Rip;
sf.AddrFrame.Offset = pContext->Rsp;
sf.AddrStack.Offset = pContext->Rsp;
#elif _M_IA64
dwMachineType = IMAGE_FILE_MACHINE_IA64;
sf.AddrPC.Offset = pContext->StIIP;
sf.AddrFrame.Offset = pContext->IntSp;
sf.AddrBStore.Offset = pContext->RsBSP;
sf.AddrStack.Offset = pContext->IntSp;
#else
#error "Platform not supported!"
#endif
constexpr int STACKWALK_MAX_NAMELEN = 1024;
BYTE symbolBuffer[sizeof(IMAGEHLP_SYMBOL64) + STACKWALK_MAX_NAMELEN];
KGE_ERROR(L"========== Stack trace ==========");
while (true)
{
if (!g_DbgHelp.StackWalk64(dwMachineType, hProcess, hThread, &sf, pContext, NULL,
g_DbgHelp.SymFunctionTableAccess64, g_DbgHelp.SymGetModuleBase64, NULL))
{
PrintErrorCode(L"StackWalk64");
break;
}
if (sf.AddrFrame.Offset == 0)
{
break;
}
ZeroMemory(symbolBuffer, sizeof(symbolBuffer));
IMAGEHLP_SYMBOL64* pSymbol = reinterpret_cast<IMAGEHLP_SYMBOL64*>(symbolBuffer);
pSymbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
pSymbol->MaxNameLength = STACKWALK_MAX_NAMELEN;
DWORD64 dwDisplacement;
if (!g_DbgHelp.SymGetSymFromAddr64(hProcess, sf.AddrPC.Offset, &dwDisplacement, pSymbol))
{
PrintErrorCode(L"SymGetSymFromAddr64");
break;
}
IMAGEHLP_LINE64 lineInfo;
ZeroMemory(&lineInfo, sizeof(IMAGEHLP_LINE64));
lineInfo.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
DWORD dwLineDisplacement;
if (g_DbgHelp.SymGetLineFromAddr64(hProcess, sf.AddrPC.Offset, &dwLineDisplacement, &lineInfo))
{
String functionName = MultiByteToWide(pSymbol->Name);
String fileName = MultiByteToWide(lineInfo.FileName);
KGE_ERROR(L"%s (%d): %s", fileName.c_str(), lineInfo.LineNumber, functionName.c_str());
}
else
{
String functionName = MultiByteToWide(pSymbol->Name);
KGE_ERROR(L"(filename not available): %s", functionName.c_str());
}
if (sf.AddrReturn.Offset == 0)
{
SetLastError(ERROR_SUCCESS);
break;
}
}
}
void PrintCallStack()
{
CONTEXT ctx;
HANDLE hProcess = GetCurrentProcess();
if (!g_DbgHelp.Load())
return;
if (!g_DbgHelp.SymInitialize(hProcess, NULL, TRUE))
return;
RtlCaptureContext(&ctx);
PrintCallStackOnContext(&ctx);
g_DbgHelp.SymCleanup(hProcess);
}
}
}

View File

@ -21,22 +21,37 @@
#pragma once
#include <stdexcept>
#include <kiwano/macros.h>
#include <3rd-party/StackWalker/StackWalker.h>
#include <kiwano/core/Logger.h>
namespace kiwano
{
namespace win32
{
void PrintCallStack();
void PrintCallStackOnContext(PCONTEXT pContext);
inline void ThrowIfFailed(HRESULT hr)
{
if (FAILED(hr))
{
StackWalker().ShowCallstack();
PrintCallStack();
static char buffer[1024 + 1];
static char buffer[32];
sprintf_s(buffer, "Failed with HRESULT of %08X", hr);
throw std::runtime_error(buffer);
}
}
inline void WarnIfFailed(HRESULT hr)
{
if (FAILED(hr))
{
PrintCallStack();
KGE_WARN(L"Failed with HRESULT of %08X", hr);
}
}
}
}

View File

@ -32,10 +32,10 @@ namespace kiwano
, PathFileExistsW(nullptr)
, SHCreateMemStream(nullptr)
{
if (shlwapi.Load(L"shlwapi.dll"))
if (shlwapi.Load("shlwapi.dll"))
{
PathFileExistsW = shlwapi.GetProcess<PFN_PathFileExistsW>(L"PathFileExistsW");
SHCreateMemStream = shlwapi.GetProcess<PFN_SHCreateMemStream>(L"SHCreateMemStream");
PathFileExistsW = shlwapi.GetProcess<PFN_PathFileExistsW>("PathFileExistsW");
SHCreateMemStream = shlwapi.GetProcess<PFN_SHCreateMemStream>("SHCreateMemStream");
}
else
{