2019.2
This commit is contained in:
parent
3a391f11f5
commit
9455594fb7
|
@ -0,0 +1,321 @@
|
||||||
|
## Ignore Visual Studio temporary files, build results, and
|
||||||
|
## files generated by popular Visual Studio add-ons.
|
||||||
|
##
|
||||||
|
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
||||||
|
|
||||||
|
# User-specific files
|
||||||
|
*.suo
|
||||||
|
*.user
|
||||||
|
*.userosscache
|
||||||
|
*.sln.docstates
|
||||||
|
|
||||||
|
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||||
|
*.userprefs
|
||||||
|
|
||||||
|
# Build results
|
||||||
|
[Dd]ebug/
|
||||||
|
[Dd]ebugPublic/
|
||||||
|
[Rr]elease/
|
||||||
|
[Rr]eleases/
|
||||||
|
x64/
|
||||||
|
x86/
|
||||||
|
bld/
|
||||||
|
[Bb]in/
|
||||||
|
[Oo]bj/
|
||||||
|
[Ll]og/
|
||||||
|
|
||||||
|
# Visual Studio 2015/2017 cache/options directory
|
||||||
|
.vs/
|
||||||
|
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||||
|
#wwwroot/
|
||||||
|
|
||||||
|
# Visual Studio 2017 auto generated files
|
||||||
|
Generated\ Files/
|
||||||
|
|
||||||
|
# MSTest test Results
|
||||||
|
[Tt]est[Rr]esult*/
|
||||||
|
[Bb]uild[Ll]og.*
|
||||||
|
|
||||||
|
# NUNIT
|
||||||
|
*.VisualState.xml
|
||||||
|
TestResult.xml
|
||||||
|
|
||||||
|
# Build Results of an ATL Project
|
||||||
|
[Dd]ebugPS/
|
||||||
|
[Rr]eleasePS/
|
||||||
|
dlldata.c
|
||||||
|
|
||||||
|
# Benchmark Results
|
||||||
|
BenchmarkDotNet.Artifacts/
|
||||||
|
|
||||||
|
# .NET Core
|
||||||
|
project.lock.json
|
||||||
|
project.fragment.lock.json
|
||||||
|
artifacts/
|
||||||
|
**/Properties/launchSettings.json
|
||||||
|
|
||||||
|
# StyleCop
|
||||||
|
StyleCopReport.xml
|
||||||
|
|
||||||
|
# Files built by Visual Studio
|
||||||
|
*_i.c
|
||||||
|
*_p.c
|
||||||
|
*_i.h
|
||||||
|
*.ilk
|
||||||
|
*.meta
|
||||||
|
*.obj
|
||||||
|
*.pch
|
||||||
|
*.pdb
|
||||||
|
*.pgc
|
||||||
|
*.pgd
|
||||||
|
*.rsp
|
||||||
|
*.sbr
|
||||||
|
*.tlb
|
||||||
|
*.tli
|
||||||
|
*.tlh
|
||||||
|
*.tmp
|
||||||
|
*.tmp_proj
|
||||||
|
*.log
|
||||||
|
*.vspscc
|
||||||
|
*.vssscc
|
||||||
|
.builds
|
||||||
|
*.pidb
|
||||||
|
*.svclog
|
||||||
|
*.scc
|
||||||
|
|
||||||
|
# Chutzpah Test files
|
||||||
|
_Chutzpah*
|
||||||
|
|
||||||
|
# Visual C++ cache files
|
||||||
|
ipch/
|
||||||
|
*.aps
|
||||||
|
*.ncb
|
||||||
|
*.opendb
|
||||||
|
*.opensdf
|
||||||
|
*.sdf
|
||||||
|
*.cachefile
|
||||||
|
*.VC.db
|
||||||
|
*.VC.VC.opendb
|
||||||
|
|
||||||
|
# Visual Studio profiler
|
||||||
|
*.psess
|
||||||
|
*.vsp
|
||||||
|
*.vspx
|
||||||
|
*.sap
|
||||||
|
|
||||||
|
# Visual Studio Trace Files
|
||||||
|
*.e2e
|
||||||
|
|
||||||
|
# TFS 2012 Local Workspace
|
||||||
|
$tf/
|
||||||
|
|
||||||
|
# Guidance Automation Toolkit
|
||||||
|
*.gpState
|
||||||
|
|
||||||
|
# ReSharper is a .NET coding add-in
|
||||||
|
_ReSharper*/
|
||||||
|
*.[Rr]e[Ss]harper
|
||||||
|
*.DotSettings.user
|
||||||
|
|
||||||
|
# JustCode is a .NET coding add-in
|
||||||
|
.JustCode
|
||||||
|
|
||||||
|
# TeamCity is a build add-in
|
||||||
|
_TeamCity*
|
||||||
|
|
||||||
|
# DotCover is a Code Coverage Tool
|
||||||
|
*.dotCover
|
||||||
|
|
||||||
|
# AxoCover is a Code Coverage Tool
|
||||||
|
.axoCover/*
|
||||||
|
!.axoCover/settings.json
|
||||||
|
|
||||||
|
# Visual Studio code coverage results
|
||||||
|
*.coverage
|
||||||
|
*.coveragexml
|
||||||
|
|
||||||
|
# NCrunch
|
||||||
|
_NCrunch_*
|
||||||
|
.*crunch*.local.xml
|
||||||
|
nCrunchTemp_*
|
||||||
|
|
||||||
|
# MightyMoose
|
||||||
|
*.mm.*
|
||||||
|
AutoTest.Net/
|
||||||
|
|
||||||
|
# Web workbench (sass)
|
||||||
|
.sass-cache/
|
||||||
|
|
||||||
|
# Installshield output folder
|
||||||
|
[Ee]xpress/
|
||||||
|
|
||||||
|
# DocProject is a documentation generator add-in
|
||||||
|
DocProject/buildhelp/
|
||||||
|
DocProject/Help/*.HxT
|
||||||
|
DocProject/Help/*.HxC
|
||||||
|
DocProject/Help/*.hhc
|
||||||
|
DocProject/Help/*.hhk
|
||||||
|
DocProject/Help/*.hhp
|
||||||
|
DocProject/Help/Html2
|
||||||
|
DocProject/Help/html
|
||||||
|
|
||||||
|
# Click-Once directory
|
||||||
|
publish/
|
||||||
|
|
||||||
|
# Publish Web Output
|
||||||
|
*.[Pp]ublish.xml
|
||||||
|
*.azurePubxml
|
||||||
|
# Note: Comment the next line if you want to checkin your web deploy settings,
|
||||||
|
# but database connection strings (with potential passwords) will be unencrypted
|
||||||
|
*.pubxml
|
||||||
|
*.publishproj
|
||||||
|
|
||||||
|
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||||
|
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||||
|
# in these scripts will be unencrypted
|
||||||
|
PublishScripts/
|
||||||
|
|
||||||
|
# NuGet Packages
|
||||||
|
*.nupkg
|
||||||
|
# The packages folder can be ignored because of Package Restore
|
||||||
|
**/[Pp]ackages/*
|
||||||
|
# except build/, which is used as an MSBuild target.
|
||||||
|
!**/[Pp]ackages/build/
|
||||||
|
# Uncomment if necessary however generally it will be regenerated when needed
|
||||||
|
#!**/[Pp]ackages/repositories.config
|
||||||
|
# NuGet v3's project.json files produces more ignorable files
|
||||||
|
*.nuget.props
|
||||||
|
*.nuget.targets
|
||||||
|
|
||||||
|
# Microsoft Azure Build Output
|
||||||
|
csx/
|
||||||
|
*.build.csdef
|
||||||
|
|
||||||
|
# Microsoft Azure Emulator
|
||||||
|
ecf/
|
||||||
|
rcf/
|
||||||
|
|
||||||
|
# Windows Store app package directories and files
|
||||||
|
AppPackages/
|
||||||
|
BundleArtifacts/
|
||||||
|
Package.StoreAssociation.xml
|
||||||
|
_pkginfo.txt
|
||||||
|
*.appx
|
||||||
|
|
||||||
|
# Visual Studio cache files
|
||||||
|
# files ending in .cache can be ignored
|
||||||
|
*.[Cc]ache
|
||||||
|
# but keep track of directories ending in .cache
|
||||||
|
!*.[Cc]ache/
|
||||||
|
|
||||||
|
# Others
|
||||||
|
ClientBin/
|
||||||
|
~$*
|
||||||
|
*~
|
||||||
|
*.dbmdl
|
||||||
|
*.dbproj.schemaview
|
||||||
|
*.jfm
|
||||||
|
*.pfx
|
||||||
|
*.publishsettings
|
||||||
|
orleans.codegen.cs
|
||||||
|
|
||||||
|
# Including strong name files can present a security risk
|
||||||
|
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
||||||
|
#*.snk
|
||||||
|
|
||||||
|
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||||
|
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||||
|
#bower_components/
|
||||||
|
|
||||||
|
# RIA/Silverlight projects
|
||||||
|
Generated_Code/
|
||||||
|
|
||||||
|
# Backup & report files from converting an old project file
|
||||||
|
# to a newer Visual Studio version. Backup files are not needed,
|
||||||
|
# because we have git ;-)
|
||||||
|
_UpgradeReport_Files/
|
||||||
|
Backup*/
|
||||||
|
UpgradeLog*.XML
|
||||||
|
UpgradeLog*.htm
|
||||||
|
ServiceFabricBackup/
|
||||||
|
|
||||||
|
# SQL Server files
|
||||||
|
*.mdf
|
||||||
|
*.ldf
|
||||||
|
*.ndf
|
||||||
|
|
||||||
|
# Business Intelligence projects
|
||||||
|
*.rdl.data
|
||||||
|
*.bim.layout
|
||||||
|
*.bim_*.settings
|
||||||
|
|
||||||
|
# Microsoft Fakes
|
||||||
|
FakesAssemblies/
|
||||||
|
|
||||||
|
# GhostDoc plugin setting file
|
||||||
|
*.GhostDoc.xml
|
||||||
|
|
||||||
|
# Node.js Tools for Visual Studio
|
||||||
|
.ntvs_analysis.dat
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
# Visual Studio 6 build log
|
||||||
|
*.plg
|
||||||
|
|
||||||
|
# Visual Studio 6 workspace options file
|
||||||
|
*.opt
|
||||||
|
|
||||||
|
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||||
|
*.vbw
|
||||||
|
|
||||||
|
# Visual Studio LightSwitch build output
|
||||||
|
**/*.HTMLClient/GeneratedArtifacts
|
||||||
|
**/*.DesktopClient/GeneratedArtifacts
|
||||||
|
**/*.DesktopClient/ModelManifest.xml
|
||||||
|
**/*.Server/GeneratedArtifacts
|
||||||
|
**/*.Server/ModelManifest.xml
|
||||||
|
_Pvt_Extensions
|
||||||
|
|
||||||
|
# Paket dependency manager
|
||||||
|
.paket/paket.exe
|
||||||
|
paket-files/
|
||||||
|
|
||||||
|
# FAKE - F# Make
|
||||||
|
.fake/
|
||||||
|
|
||||||
|
# JetBrains Rider
|
||||||
|
.idea/
|
||||||
|
*.sln.iml
|
||||||
|
|
||||||
|
# CodeRush
|
||||||
|
.cr/
|
||||||
|
|
||||||
|
# Python Tools for Visual Studio (PTVS)
|
||||||
|
__pycache__/
|
||||||
|
*.pyc
|
||||||
|
|
||||||
|
# Cake - Uncomment if you are using it
|
||||||
|
# tools/**
|
||||||
|
# !tools/packages.config
|
||||||
|
|
||||||
|
# Tabs Studio
|
||||||
|
*.tss
|
||||||
|
|
||||||
|
# Telerik's JustMock configuration file
|
||||||
|
*.jmconfig
|
||||||
|
|
||||||
|
# BizTalk build output
|
||||||
|
*.btp.cs
|
||||||
|
*.btm.cs
|
||||||
|
*.odx.cs
|
||||||
|
*.xsd.cs
|
||||||
|
|
||||||
|
# OpenCover UI analysis results
|
||||||
|
OpenCover/
|
||||||
|
|
||||||
|
# Azure Stream Analytics local run output
|
||||||
|
ASALocalRun/
|
||||||
|
|
||||||
|
# MSBuild Binary and Structured Log
|
||||||
|
*.binlog
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
// RendererDirect3D12.cpp : Defines the exported functions for the DLL application.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,99 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
|
<ProjectConfiguration Include="Debug|x64">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|x64">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<VCProjectVersion>15.0</VCProjectVersion>
|
||||||
|
<ProjectGuid>{53923514-84B2-4B78-889A-8709C6BFA3A5}</ProjectGuid>
|
||||||
|
<Keyword>Win32Proj</Keyword>
|
||||||
|
<RootNamespace>RendererDirect3D12</RootNamespace>
|
||||||
|
<WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="Shared">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<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|x64'">
|
||||||
|
<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|x64'">
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>_DEBUG;RENDERERDIRECT3D12_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Windows</SubSystem>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>NDEBUG;RENDERERDIRECT3D12_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Windows</SubSystem>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="stdafx.h" />
|
||||||
|
<ClInclude Include="targetver.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="dllmain.cpp" />
|
||||||
|
<ClCompile Include="RendererDirect3D12.cpp" />
|
||||||
|
<ClCompile Include="stdafx.cpp">
|
||||||
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
||||||
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
</ImportGroup>
|
||||||
|
</Project>
|
|
@ -0,0 +1,36 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup>
|
||||||
|
<Filter Include="Source Files">
|
||||||
|
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||||
|
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Header Files">
|
||||||
|
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||||
|
<Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Resource Files">
|
||||||
|
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||||
|
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||||
|
</Filter>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="stdafx.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="targetver.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="stdafx.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="RendererDirect3D12.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="dllmain.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
|
@ -0,0 +1,19 @@
|
||||||
|
// dllmain.cpp : Defines the entry point for the DLL application.
|
||||||
|
#include "stdafx.h"
|
||||||
|
|
||||||
|
BOOL APIENTRY DllMain( HMODULE hModule,
|
||||||
|
DWORD ul_reason_for_call,
|
||||||
|
LPVOID lpReserved
|
||||||
|
)
|
||||||
|
{
|
||||||
|
switch (ul_reason_for_call)
|
||||||
|
{
|
||||||
|
case DLL_PROCESS_ATTACH:
|
||||||
|
case DLL_THREAD_ATTACH:
|
||||||
|
case DLL_THREAD_DETACH:
|
||||||
|
case DLL_PROCESS_DETACH:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
#include "stdafx.h"
|
|
@ -0,0 +1,16 @@
|
||||||
|
// stdafx.h : include file for standard system include files,
|
||||||
|
// or project specific include files that are used frequently, but
|
||||||
|
// are changed infrequently
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "targetver.h"
|
||||||
|
|
||||||
|
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
|
||||||
|
// Windows Header Files
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// reference additional headers your program requires here
|
|
@ -0,0 +1,8 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// Including SDKDDKVer.h defines the highest available Windows platform.
|
||||||
|
|
||||||
|
// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
|
||||||
|
// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
|
||||||
|
|
||||||
|
#include <SDKDDKVer.h>
|
|
@ -0,0 +1,6 @@
|
||||||
|
// RendererVulkan.cpp : Defines the exported functions for the DLL application.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,99 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
|
<ProjectConfiguration Include="Debug|x64">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|x64">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<VCProjectVersion>15.0</VCProjectVersion>
|
||||||
|
<ProjectGuid>{C9195A1C-9224-4B40-BBBC-AA90EF3BE3E0}</ProjectGuid>
|
||||||
|
<Keyword>Win32Proj</Keyword>
|
||||||
|
<RootNamespace>RendererVulkan</RootNamespace>
|
||||||
|
<WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="Shared">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<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|x64'">
|
||||||
|
<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|x64'">
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>_DEBUG;RENDERERVULKAN_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Windows</SubSystem>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>NDEBUG;RENDERERVULKAN_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Windows</SubSystem>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="stdafx.h" />
|
||||||
|
<ClInclude Include="targetver.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="dllmain.cpp" />
|
||||||
|
<ClCompile Include="RendererVulkan.cpp" />
|
||||||
|
<ClCompile Include="stdafx.cpp">
|
||||||
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
||||||
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
</ImportGroup>
|
||||||
|
</Project>
|
|
@ -0,0 +1,36 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup>
|
||||||
|
<Filter Include="Source Files">
|
||||||
|
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||||
|
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Header Files">
|
||||||
|
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||||
|
<Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Resource Files">
|
||||||
|
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||||
|
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||||
|
</Filter>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="stdafx.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="targetver.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="stdafx.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="RendererVulkan.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="dllmain.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
|
@ -0,0 +1,19 @@
|
||||||
|
// dllmain.cpp : Defines the entry point for the DLL application.
|
||||||
|
#include "stdafx.h"
|
||||||
|
|
||||||
|
BOOL APIENTRY DllMain( HMODULE hModule,
|
||||||
|
DWORD ul_reason_for_call,
|
||||||
|
LPVOID lpReserved
|
||||||
|
)
|
||||||
|
{
|
||||||
|
switch (ul_reason_for_call)
|
||||||
|
{
|
||||||
|
case DLL_PROCESS_ATTACH:
|
||||||
|
case DLL_THREAD_ATTACH:
|
||||||
|
case DLL_THREAD_DETACH:
|
||||||
|
case DLL_PROCESS_DETACH:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
#include "stdafx.h"
|
|
@ -0,0 +1,16 @@
|
||||||
|
// stdafx.h : include file for standard system include files,
|
||||||
|
// or project specific include files that are used frequently, but
|
||||||
|
// are changed infrequently
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "targetver.h"
|
||||||
|
|
||||||
|
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
|
||||||
|
// Windows Header Files
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// reference additional headers your program requires here
|
|
@ -0,0 +1,8 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// Including SDKDDKVer.h defines the highest available Windows platform.
|
||||||
|
|
||||||
|
// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
|
||||||
|
// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
|
||||||
|
|
||||||
|
#include <SDKDDKVer.h>
|
|
@ -0,0 +1,43 @@
|
||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio 15
|
||||||
|
VisualStudioVersion = 15.0.27130.2036
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Verus", "Verus\Verus.vcxproj", "{B154D670-E4B1-4D8A-885C-69546A5BD833}"
|
||||||
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VerusTest", "VerusTest\VerusTest.vcxproj", "{D7085182-35B9-4689-ADBA-B77087AD16BF}"
|
||||||
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RendererDirect3D12", "RendererDirect3D12\RendererDirect3D12.vcxproj", "{53923514-84B2-4B78-889A-8709C6BFA3A5}"
|
||||||
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RendererVulkan", "RendererVulkan\RendererVulkan.vcxproj", "{C9195A1C-9224-4B40-BBBC-AA90EF3BE3E0}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|x64 = Debug|x64
|
||||||
|
Release|x64 = Release|x64
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{B154D670-E4B1-4D8A-885C-69546A5BD833}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{B154D670-E4B1-4D8A-885C-69546A5BD833}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{B154D670-E4B1-4D8A-885C-69546A5BD833}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{B154D670-E4B1-4D8A-885C-69546A5BD833}.Release|x64.Build.0 = Release|x64
|
||||||
|
{D7085182-35B9-4689-ADBA-B77087AD16BF}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{D7085182-35B9-4689-ADBA-B77087AD16BF}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{D7085182-35B9-4689-ADBA-B77087AD16BF}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{D7085182-35B9-4689-ADBA-B77087AD16BF}.Release|x64.Build.0 = Release|x64
|
||||||
|
{53923514-84B2-4B78-889A-8709C6BFA3A5}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{53923514-84B2-4B78-889A-8709C6BFA3A5}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{53923514-84B2-4B78-889A-8709C6BFA3A5}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{53923514-84B2-4B78-889A-8709C6BFA3A5}.Release|x64.Build.0 = Release|x64
|
||||||
|
{C9195A1C-9224-4B40-BBBC-AA90EF3BE3E0}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{C9195A1C-9224-4B40-BBBC-AA90EF3BE3E0}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{C9195A1C-9224-4B40-BBBC-AA90EF3BE3E0}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{C9195A1C-9224-4B40-BBBC-AA90EF3BE3E0}.Release|x64.Build.0 = Release|x64
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {0D2FFAEF-1E59-46F0-BDDF-1634F6790F83}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
|
@ -0,0 +1,11 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ImportGroup Label="PropertySheets" />
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<PropertyGroup>
|
||||||
|
<IncludePath>C:\Home\Projects\Verus\verus\Verus\src;C:\Home\Middleware\bullet3-2.88\src;C:\Home\Middleware\bullet3-2.88\Extras;C:\Home\Middleware\glm-0.9.9.3\glm;C:\Home\Middleware\json-3.5.0;C:\Home\Middleware\libogg-1.3.3\include;C:\Home\Middleware\libvorbis-1.3.6\include;C:\Home\Middleware\SDL2-2.0.9\include;C:\Home\Middleware\tinyxml2-7.0.1;C:\Home\Middleware\vectormath;C:\Home\Middleware\zlib-1.2.11;C:\Program Files %28x86%29\OpenAL 1.1 SDK\include;$(IncludePath)</IncludePath>
|
||||||
|
<LibraryPath>C:\Home\Middleware\bullet3-2.88\lib\Debug;C:\Home\Middleware\libogg-1.3.3\lib;C:\Home\Middleware\libvorbis-1.3.6\lib2;C:\Home\Middleware\SDL2-2.0.9\lib\x64;C:\Home\Middleware\tinyxml2-7.0.1;C:\Home\Middleware\zlib-1.2.11;C:\Program Files %28x86%29\OpenAL 1.1 SDK\libs\Win64;$(LibraryPath)</LibraryPath>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemDefinitionGroup />
|
||||||
|
<ItemGroup />
|
||||||
|
</Project>
|
|
@ -0,0 +1,275 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
|
<ProjectConfiguration Include="Debug|x64">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|x64">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<VCProjectVersion>15.0</VCProjectVersion>
|
||||||
|
<ProjectGuid>{B154D670-E4B1-4D8A-885C-69546A5BD833}</ProjectGuid>
|
||||||
|
<Keyword>Win32Proj</Keyword>
|
||||||
|
<RootNamespace>Verus</RootNamespace>
|
||||||
|
<WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="Shared">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
<Import Project="Verus.props" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
<Import Project="Verus.props" />
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
<PrecompiledHeaderFile>verus.h</PrecompiledHeaderFile>
|
||||||
|
<AdditionalIncludeDirectories>$(ProjectDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Windows</SubSystem>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
<PrecompiledHeaderFile>verus.h</PrecompiledHeaderFile>
|
||||||
|
<AdditionalIncludeDirectories>$(ProjectDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Windows</SubSystem>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="src\AI\AI.h" />
|
||||||
|
<ClInclude Include="src\AI\TaskDriver.h" />
|
||||||
|
<ClInclude Include="src\AI\Turret.h" />
|
||||||
|
<ClInclude Include="src\Anim\Anim.h" />
|
||||||
|
<ClInclude Include="src\Anim\Animation.h" />
|
||||||
|
<ClInclude Include="src\Anim\Motion.h" />
|
||||||
|
<ClInclude Include="src\Anim\Skeleton.h" />
|
||||||
|
<ClInclude Include="src\App\App.h" />
|
||||||
|
<ClInclude Include="src\App\Settings.h" />
|
||||||
|
<ClInclude Include="src\App\Window.h" />
|
||||||
|
<ClInclude Include="src\Audio\Audio.h" />
|
||||||
|
<ClInclude Include="src\Audio\AudioSystem.h" />
|
||||||
|
<ClInclude Include="src\Audio\OggCallbacks.h" />
|
||||||
|
<ClInclude Include="src\Audio\Sound.h" />
|
||||||
|
<ClInclude Include="src\Audio\Source.h" />
|
||||||
|
<ClInclude Include="src\Audio\StreamPlayer.h" />
|
||||||
|
<ClInclude Include="src\CGI\BaseGeometry.h" />
|
||||||
|
<ClInclude Include="src\CGI\BasePipeline.h" />
|
||||||
|
<ClInclude Include="src\CGI\BaseShader.h" />
|
||||||
|
<ClInclude Include="src\CGI\BaseTexture.h" />
|
||||||
|
<ClInclude Include="src\CGI\CGI.h" />
|
||||||
|
<ClInclude Include="src\D\AssertionCompileTime.h" />
|
||||||
|
<ClInclude Include="src\D\AssertionRunTime.h" />
|
||||||
|
<ClInclude Include="src\D\D.h" />
|
||||||
|
<ClInclude Include="src\D\Log.h" />
|
||||||
|
<ClInclude Include="src\D\Recoverable.h" />
|
||||||
|
<ClInclude Include="src\D\RuntimeError.h" />
|
||||||
|
<ClInclude Include="src\Game\BaseGame.h" />
|
||||||
|
<ClInclude Include="src\Game\Game.h" />
|
||||||
|
<ClInclude Include="src\Game\State.h" />
|
||||||
|
<ClInclude Include="src\Game\StateMachine.h" />
|
||||||
|
<ClInclude Include="src\Global\AlignedAllocator.h" />
|
||||||
|
<ClInclude Include="src\Global\AllocatorAware.h" />
|
||||||
|
<ClInclude Include="src\Global\BaseAllocator.h" />
|
||||||
|
<ClInclude Include="src\Global\Basic.h" />
|
||||||
|
<ClInclude Include="src\Global\Blob.h" />
|
||||||
|
<ClInclude Include="src\Global\Convert.h" />
|
||||||
|
<ClInclude Include="src\Global\EngineInit.h" />
|
||||||
|
<ClInclude Include="src\Global\Linear.h" />
|
||||||
|
<ClInclude Include="src\Global\Lockable.h" />
|
||||||
|
<ClInclude Include="src\Global\Object.h" />
|
||||||
|
<ClInclude Include="src\Global\Parallel.h" />
|
||||||
|
<ClInclude Include="src\Global\QuickRefs.h" />
|
||||||
|
<ClInclude Include="src\Global\Random.h" />
|
||||||
|
<ClInclude Include="src\Global\Range.h" />
|
||||||
|
<ClInclude Include="src\Global\Singleton.h" />
|
||||||
|
<ClInclude Include="src\Global\Store.h" />
|
||||||
|
<ClInclude Include="src\Global\Str.h" />
|
||||||
|
<ClInclude Include="src\Global\Timer.h" />
|
||||||
|
<ClInclude Include="src\Global\Utils.h" />
|
||||||
|
<ClInclude Include="src\Input\Input.h" />
|
||||||
|
<ClInclude Include="src\Input\KeyMapper.h" />
|
||||||
|
<ClInclude Include="src\IO\Async.h" />
|
||||||
|
<ClInclude Include="src\IO\DDSHeader.h" />
|
||||||
|
<ClInclude Include="src\IO\File.h" />
|
||||||
|
<ClInclude Include="src\IO\FileSystem.h" />
|
||||||
|
<ClInclude Include="src\IO\IO.h" />
|
||||||
|
<ClInclude Include="src\IO\Json.h" />
|
||||||
|
<ClInclude Include="src\IO\Stream.h" />
|
||||||
|
<ClInclude Include="src\Global\EnumClass.h" />
|
||||||
|
<ClInclude Include="src\Global\Macros.h" />
|
||||||
|
<ClInclude Include="src\Global\Global.h" />
|
||||||
|
<ClInclude Include="src\Global\STL.h" />
|
||||||
|
<ClInclude Include="src\Global\SyntaxHighlight.h" />
|
||||||
|
<ClInclude Include="src\Global\Typedef.h" />
|
||||||
|
<ClInclude Include="src\IO\StreamPtr.h" />
|
||||||
|
<ClInclude Include="src\IO\Xml.h" />
|
||||||
|
<ClInclude Include="src\Math\Bounds.h" />
|
||||||
|
<ClInclude Include="src\Math\Frustum.h" />
|
||||||
|
<ClInclude Include="src\Math\Math.h" />
|
||||||
|
<ClInclude Include="src\Math\Matrix.h" />
|
||||||
|
<ClInclude Include="src\Math\NormalComputer.h" />
|
||||||
|
<ClInclude Include="src\Math\Plane.h" />
|
||||||
|
<ClInclude Include="src\Math\Quat.h" />
|
||||||
|
<ClInclude Include="src\Math\Sphere.h" />
|
||||||
|
<ClInclude Include="src\Math\Vector.h" />
|
||||||
|
<ClInclude Include="src\Net\Addr.h" />
|
||||||
|
<ClInclude Include="src\Net\HttpFile.h" />
|
||||||
|
<ClInclude Include="src\Net\Net.h" />
|
||||||
|
<ClInclude Include="src\Net\Socket.h" />
|
||||||
|
<ClInclude Include="src\Scene\BaseMesh.h" />
|
||||||
|
<ClInclude Include="src\Scene\Camera.h" />
|
||||||
|
<ClInclude Include="src\Scene\Mesh.h" />
|
||||||
|
<ClInclude Include="src\Scene\Scene.h" />
|
||||||
|
<ClInclude Include="src\Security\CipherRC4.h" />
|
||||||
|
<ClInclude Include="src\Security\Security.h" />
|
||||||
|
<ClInclude Include="src\ThirdParty\libb64\cdecode.h" />
|
||||||
|
<ClInclude Include="src\ThirdParty\libb64\cencode.h" />
|
||||||
|
<ClInclude Include="src\ThirdParty\md5.h" />
|
||||||
|
<ClInclude Include="src\ThirdParty\ThirdParty.h" />
|
||||||
|
<ClInclude Include="src\ThirdParty\utf8.h" />
|
||||||
|
<ClInclude Include="src\ThirdParty\utf8\checked.h" />
|
||||||
|
<ClInclude Include="src\ThirdParty\utf8\core.h" />
|
||||||
|
<ClInclude Include="src\ThirdParty\utf8\unchecked.h" />
|
||||||
|
<ClInclude Include="src\verus.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="src\AI\AI.cpp" />
|
||||||
|
<ClCompile Include="src\AI\TaskDriver.cpp" />
|
||||||
|
<ClCompile Include="src\AI\Turret.cpp" />
|
||||||
|
<ClCompile Include="src\Anim\Anim.cpp" />
|
||||||
|
<ClCompile Include="src\Anim\Animation.cpp" />
|
||||||
|
<ClCompile Include="src\Anim\Motion.cpp" />
|
||||||
|
<ClCompile Include="src\Anim\Skeleton.cpp" />
|
||||||
|
<ClCompile Include="src\App\App.cpp" />
|
||||||
|
<ClCompile Include="src\App\Settings.cpp" />
|
||||||
|
<ClCompile Include="src\App\Window.cpp" />
|
||||||
|
<ClCompile Include="src\Audio\Audio.cpp" />
|
||||||
|
<ClCompile Include="src\Audio\AudioSystem.cpp" />
|
||||||
|
<ClCompile Include="src\Audio\OggCallbacks.cpp" />
|
||||||
|
<ClCompile Include="src\Audio\Sound.cpp" />
|
||||||
|
<ClCompile Include="src\Audio\Source.cpp" />
|
||||||
|
<ClCompile Include="src\Audio\StreamPlayer.cpp" />
|
||||||
|
<ClCompile Include="src\CGI\BaseGeometry.cpp" />
|
||||||
|
<ClCompile Include="src\CGI\BasePipeline.cpp" />
|
||||||
|
<ClCompile Include="src\CGI\BaseShader.cpp" />
|
||||||
|
<ClCompile Include="src\CGI\BaseTexture.cpp" />
|
||||||
|
<ClCompile Include="src\D\Log.cpp" />
|
||||||
|
<ClCompile Include="src\Game\BaseGame.cpp" />
|
||||||
|
<ClCompile Include="src\Game\State.cpp" />
|
||||||
|
<ClCompile Include="src\Game\StateMachine.cpp" />
|
||||||
|
<ClCompile Include="src\Global\AllocatorAware.cpp" />
|
||||||
|
<ClCompile Include="src\Global\Convert.cpp" />
|
||||||
|
<ClCompile Include="src\Global\EngineInit.cpp" />
|
||||||
|
<ClCompile Include="src\Global\Global.cpp" />
|
||||||
|
<ClCompile Include="src\Global\Object.cpp" />
|
||||||
|
<ClCompile Include="src\Global\Random.cpp" />
|
||||||
|
<ClCompile Include="src\Global\Str.cpp" />
|
||||||
|
<ClCompile Include="src\Global\Timer.cpp" />
|
||||||
|
<ClCompile Include="src\Global\Utils.cpp" />
|
||||||
|
<ClCompile Include="src\Input\Input.cpp" />
|
||||||
|
<ClCompile Include="src\Input\KeyMapper.cpp" />
|
||||||
|
<ClCompile Include="src\IO\Async.cpp" />
|
||||||
|
<ClCompile Include="src\IO\DDSHeader.cpp" />
|
||||||
|
<ClCompile Include="src\IO\File.cpp" />
|
||||||
|
<ClCompile Include="src\IO\FileSystem.cpp" />
|
||||||
|
<ClCompile Include="src\IO\IO.cpp" />
|
||||||
|
<ClCompile Include="src\IO\Json.cpp" />
|
||||||
|
<ClCompile Include="src\IO\Xml.cpp" />
|
||||||
|
<ClCompile Include="src\Math\Bounds.cpp" />
|
||||||
|
<ClCompile Include="src\Math\Frustum.cpp" />
|
||||||
|
<ClCompile Include="src\Math\Math.cpp" />
|
||||||
|
<ClCompile Include="src\Math\Matrix.cpp" />
|
||||||
|
<ClCompile Include="src\Math\NormalComputer.cpp" />
|
||||||
|
<ClCompile Include="src\Math\Plane.cpp" />
|
||||||
|
<ClCompile Include="src\Math\Quat.cpp" />
|
||||||
|
<ClCompile Include="src\Math\Sphere.cpp" />
|
||||||
|
<ClCompile Include="src\Math\Vector.cpp" />
|
||||||
|
<ClCompile Include="src\Net\Addr.cpp" />
|
||||||
|
<ClCompile Include="src\Net\HttpFile.cpp" />
|
||||||
|
<ClCompile Include="src\Net\Net.cpp" />
|
||||||
|
<ClCompile Include="src\Net\Socket.cpp" />
|
||||||
|
<ClCompile Include="src\Scene\BaseMesh.cpp" />
|
||||||
|
<ClCompile Include="src\Scene\Camera.cpp" />
|
||||||
|
<ClCompile Include="src\Scene\Mesh.cpp" />
|
||||||
|
<ClCompile Include="src\Scene\Scene.cpp" />
|
||||||
|
<ClCompile Include="src\ThirdParty\libb64\cdecode.c">
|
||||||
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
|
||||||
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
|
||||||
|
<DisableSpecificWarnings Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">4244</DisableSpecificWarnings>
|
||||||
|
<DisableSpecificWarnings Condition="'$(Configuration)|$(Platform)'=='Release|x64'">4244</DisableSpecificWarnings>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\ThirdParty\libb64\cencode.c">
|
||||||
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
|
||||||
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
|
||||||
|
<DisableSpecificWarnings Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">4244</DisableSpecificWarnings>
|
||||||
|
<DisableSpecificWarnings Condition="'$(Configuration)|$(Platform)'=='Release|x64'">4244</DisableSpecificWarnings>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\ThirdParty\md5.cpp">
|
||||||
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
|
||||||
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
|
||||||
|
<DisableSpecificWarnings Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">4267</DisableSpecificWarnings>
|
||||||
|
<DisableSpecificWarnings Condition="'$(Configuration)|$(Platform)'=='Release|x64'">4267</DisableSpecificWarnings>
|
||||||
|
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\verus.cpp">
|
||||||
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
||||||
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
</ImportGroup>
|
||||||
|
</Project>
|
|
@ -0,0 +1,549 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup>
|
||||||
|
<Filter Include="Source Files">
|
||||||
|
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||||
|
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Header Files">
|
||||||
|
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||||
|
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Resource Files">
|
||||||
|
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||||
|
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="src">
|
||||||
|
<UniqueIdentifier>{6dd7f6ca-0929-4d46-9f6d-71ecf8c91abd}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="src\CGI">
|
||||||
|
<UniqueIdentifier>{f756df7f-0ce7-4098-895a-2c1d03fe386b}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="src\IO">
|
||||||
|
<UniqueIdentifier>{afbabad8-439c-4609-b622-a881c8d6d034}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="src\D">
|
||||||
|
<UniqueIdentifier>{9c9fdfe5-4d92-491c-bff1-7442a538ac24}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="src\Security">
|
||||||
|
<UniqueIdentifier>{d5e876a9-20a7-460a-89e4-c6b1cd902307}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="src\Global">
|
||||||
|
<UniqueIdentifier>{d44bf87b-c74b-42a1-9b54-dfe744447364}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="src\Math">
|
||||||
|
<UniqueIdentifier>{ebb05836-e3a7-452d-8e05-a9007ffe1320}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="src\Game">
|
||||||
|
<UniqueIdentifier>{5ece1220-9707-4688-9429-dcde547cb05f}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="src\Net">
|
||||||
|
<UniqueIdentifier>{bcb0dace-45fa-45b5-85d6-c80026a9577b}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="src\Audio">
|
||||||
|
<UniqueIdentifier>{b02345a2-66ea-4995-8a5b-b7b6df5e4470}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="src\ThirdParty">
|
||||||
|
<UniqueIdentifier>{779ebfcc-422d-4f9a-a3de-3d5d416612a0}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="src\ThirdParty\utf8">
|
||||||
|
<UniqueIdentifier>{9026283b-bf5f-489c-9008-4093adeb4ce6}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="src\ThirdParty\libb64">
|
||||||
|
<UniqueIdentifier>{2c793d5f-0a67-4166-8490-3ef154bdb4fc}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="src\Scene">
|
||||||
|
<UniqueIdentifier>{28848bdf-d48d-40a2-92a2-6946c609e14e}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="src\AI">
|
||||||
|
<UniqueIdentifier>{6c75fda0-ca2a-4925-9260-1d069a48b1b7}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="src\Anim">
|
||||||
|
<UniqueIdentifier>{35c65d58-6412-4aa5-bb70-9f3ab9ee37a2}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="src\Input">
|
||||||
|
<UniqueIdentifier>{b10e474d-ad34-4fb3-9a41-875a17a54d36}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="src\App">
|
||||||
|
<UniqueIdentifier>{8487cc8d-90f6-4f48-83f8-433947c79c5c}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="src\CGI\BaseGeometry.h">
|
||||||
|
<Filter>src\CGI</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\CGI\BasePipeline.h">
|
||||||
|
<Filter>src\CGI</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\CGI\BaseShader.h">
|
||||||
|
<Filter>src\CGI</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\CGI\BaseTexture.h">
|
||||||
|
<Filter>src\CGI</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\CGI\CGI.h">
|
||||||
|
<Filter>src\CGI</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\IO\File.h">
|
||||||
|
<Filter>src\IO</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\IO\IO.h">
|
||||||
|
<Filter>src\IO</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\IO\Stream.h">
|
||||||
|
<Filter>src\IO</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\verus.h">
|
||||||
|
<Filter>src</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\D\AssertionCompileTime.h">
|
||||||
|
<Filter>src\D</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\D\AssertionRunTime.h">
|
||||||
|
<Filter>src\D</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\D\Log.h">
|
||||||
|
<Filter>src\D</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\D\Recoverable.h">
|
||||||
|
<Filter>src\D</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\D\RuntimeError.h">
|
||||||
|
<Filter>src\D</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\D\D.h">
|
||||||
|
<Filter>src\D</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Security\CipherRC4.h">
|
||||||
|
<Filter>src\Security</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Security\Security.h">
|
||||||
|
<Filter>src\Security</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Global\EnumClass.h">
|
||||||
|
<Filter>src\Global</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Global\Macros.h">
|
||||||
|
<Filter>src\Global</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Global\STL.h">
|
||||||
|
<Filter>src\Global</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Global\SyntaxHighlight.h">
|
||||||
|
<Filter>src\Global</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Global\Typedef.h">
|
||||||
|
<Filter>src\Global</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Global\Global.h">
|
||||||
|
<Filter>src\Global</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Global\Singleton.h">
|
||||||
|
<Filter>src\Global</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Global\Basic.h">
|
||||||
|
<Filter>src\Global</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Global\AllocatorAware.h">
|
||||||
|
<Filter>src\Global</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Global\AlignedAllocator.h">
|
||||||
|
<Filter>src\Global</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Global\BaseAllocator.h">
|
||||||
|
<Filter>src\Global</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Global\Utils.h">
|
||||||
|
<Filter>src\Global</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Global\QuickRefs.h">
|
||||||
|
<Filter>src\Global</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Global\Parallel.h">
|
||||||
|
<Filter>src\Global</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Global\Range.h">
|
||||||
|
<Filter>src\Global</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Math\Math.h">
|
||||||
|
<Filter>src\Math</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Game\Game.h">
|
||||||
|
<Filter>src\Game</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Game\State.h">
|
||||||
|
<Filter>src\Game</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Game\StateMachine.h">
|
||||||
|
<Filter>src\Game</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Global\Object.h">
|
||||||
|
<Filter>src\Global</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Global\Random.h">
|
||||||
|
<Filter>src\Global</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Net\Addr.h">
|
||||||
|
<Filter>src\Net</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Net\Net.h">
|
||||||
|
<Filter>src\Net</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Net\Socket.h">
|
||||||
|
<Filter>src\Net</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Global\Lockable.h">
|
||||||
|
<Filter>src\Global</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Audio\OggCallbacks.h">
|
||||||
|
<Filter>src\Audio</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Audio\Sound.h">
|
||||||
|
<Filter>src\Audio</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Audio\Source.h">
|
||||||
|
<Filter>src\Audio</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Math\Matrix.h">
|
||||||
|
<Filter>src\Math</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Math\Quat.h">
|
||||||
|
<Filter>src\Math</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Math\Vector.h">
|
||||||
|
<Filter>src\Math</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Global\Store.h">
|
||||||
|
<Filter>src\Global</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\IO\Async.h">
|
||||||
|
<Filter>src\IO</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Global\Blob.h">
|
||||||
|
<Filter>src\Global</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Audio\StreamPlayer.h">
|
||||||
|
<Filter>src\Audio</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Global\Linear.h">
|
||||||
|
<Filter>src\Global</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Audio\AudioSystem.h">
|
||||||
|
<Filter>src\Audio</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Global\Str.h">
|
||||||
|
<Filter>src\Global</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Audio\Audio.h">
|
||||||
|
<Filter>src\Audio</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\ThirdParty\ThirdParty.h">
|
||||||
|
<Filter>src\ThirdParty</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\ThirdParty\utf8.h">
|
||||||
|
<Filter>src\ThirdParty</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\ThirdParty\utf8\checked.h">
|
||||||
|
<Filter>src\ThirdParty\utf8</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\ThirdParty\utf8\core.h">
|
||||||
|
<Filter>src\ThirdParty\utf8</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\ThirdParty\utf8\unchecked.h">
|
||||||
|
<Filter>src\ThirdParty\utf8</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Global\Convert.h">
|
||||||
|
<Filter>src\Global</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\ThirdParty\libb64\cdecode.h">
|
||||||
|
<Filter>src\ThirdParty\libb64</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\ThirdParty\libb64\cencode.h">
|
||||||
|
<Filter>src\ThirdParty\libb64</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\ThirdParty\md5.h">
|
||||||
|
<Filter>src\ThirdParty</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\IO\FileSystem.h">
|
||||||
|
<Filter>src\IO</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\IO\DDSHeader.h">
|
||||||
|
<Filter>src\IO</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Global\Timer.h">
|
||||||
|
<Filter>src\Global</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Scene\Camera.h">
|
||||||
|
<Filter>src\Scene</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Scene\Scene.h">
|
||||||
|
<Filter>src\Scene</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Math\Frustum.h">
|
||||||
|
<Filter>src\Math</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Math\Plane.h">
|
||||||
|
<Filter>src\Math</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Math\Sphere.h">
|
||||||
|
<Filter>src\Math</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Math\Bounds.h">
|
||||||
|
<Filter>src\Math</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\AI\AI.h">
|
||||||
|
<Filter>src\AI</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\AI\TaskDriver.h">
|
||||||
|
<Filter>src\AI</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\AI\Turret.h">
|
||||||
|
<Filter>src\AI</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Scene\BaseMesh.h">
|
||||||
|
<Filter>src\Scene</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Scene\Mesh.h">
|
||||||
|
<Filter>src\Scene</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\IO\StreamPtr.h">
|
||||||
|
<Filter>src\IO</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Math\NormalComputer.h">
|
||||||
|
<Filter>src\Math</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Anim\Anim.h">
|
||||||
|
<Filter>src\Anim</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Anim\Animation.h">
|
||||||
|
<Filter>src\Anim</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Anim\Motion.h">
|
||||||
|
<Filter>src\Anim</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Anim\Skeleton.h">
|
||||||
|
<Filter>src\Anim</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\IO\Xml.h">
|
||||||
|
<Filter>src\IO</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Net\HttpFile.h">
|
||||||
|
<Filter>src\Net</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Game\BaseGame.h">
|
||||||
|
<Filter>src\Game</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Global\EngineInit.h">
|
||||||
|
<Filter>src\Global</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Input\Input.h">
|
||||||
|
<Filter>src\Input</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Input\KeyMapper.h">
|
||||||
|
<Filter>src\Input</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\App\App.h">
|
||||||
|
<Filter>src\App</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\App\Settings.h">
|
||||||
|
<Filter>src\App</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\App\Window.h">
|
||||||
|
<Filter>src\App</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\IO\Json.h">
|
||||||
|
<Filter>src\IO</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="src\CGI\BaseGeometry.cpp">
|
||||||
|
<Filter>src\CGI</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\CGI\BasePipeline.cpp">
|
||||||
|
<Filter>src\CGI</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\CGI\BaseShader.cpp">
|
||||||
|
<Filter>src\CGI</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\CGI\BaseTexture.cpp">
|
||||||
|
<Filter>src\CGI</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\IO\File.cpp">
|
||||||
|
<Filter>src\IO</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\IO\IO.cpp">
|
||||||
|
<Filter>src\IO</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\verus.cpp">
|
||||||
|
<Filter>src</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\D\Log.cpp">
|
||||||
|
<Filter>src\D</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Global\AllocatorAware.cpp">
|
||||||
|
<Filter>src\Global</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Global\Utils.cpp">
|
||||||
|
<Filter>src\Global</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Global\Global.cpp">
|
||||||
|
<Filter>src\Global</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Math\Math.cpp">
|
||||||
|
<Filter>src\Math</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Game\State.cpp">
|
||||||
|
<Filter>src\Game</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Game\StateMachine.cpp">
|
||||||
|
<Filter>src\Game</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Global\Object.cpp">
|
||||||
|
<Filter>src\Global</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Global\Random.cpp">
|
||||||
|
<Filter>src\Global</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Net\Addr.cpp">
|
||||||
|
<Filter>src\Net</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Net\Net.cpp">
|
||||||
|
<Filter>src\Net</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Net\Socket.cpp">
|
||||||
|
<Filter>src\Net</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Audio\OggCallbacks.cpp">
|
||||||
|
<Filter>src\Audio</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Audio\Sound.cpp">
|
||||||
|
<Filter>src\Audio</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Audio\Source.cpp">
|
||||||
|
<Filter>src\Audio</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Math\Matrix.cpp">
|
||||||
|
<Filter>src\Math</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Math\Quat.cpp">
|
||||||
|
<Filter>src\Math</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Math\Vector.cpp">
|
||||||
|
<Filter>src\Math</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\IO\Async.cpp">
|
||||||
|
<Filter>src\IO</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Audio\StreamPlayer.cpp">
|
||||||
|
<Filter>src\Audio</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Audio\AudioSystem.cpp">
|
||||||
|
<Filter>src\Audio</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Global\Str.cpp">
|
||||||
|
<Filter>src\Global</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Audio\Audio.cpp">
|
||||||
|
<Filter>src\Audio</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Global\Convert.cpp">
|
||||||
|
<Filter>src\Global</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\ThirdParty\libb64\cdecode.c">
|
||||||
|
<Filter>src\ThirdParty\libb64</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\ThirdParty\libb64\cencode.c">
|
||||||
|
<Filter>src\ThirdParty\libb64</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\ThirdParty\md5.cpp">
|
||||||
|
<Filter>src\ThirdParty</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\IO\FileSystem.cpp">
|
||||||
|
<Filter>src\IO</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\IO\DDSHeader.cpp">
|
||||||
|
<Filter>src\IO</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Global\Timer.cpp">
|
||||||
|
<Filter>src\Global</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Scene\Camera.cpp">
|
||||||
|
<Filter>src\Scene</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Scene\Scene.cpp">
|
||||||
|
<Filter>src\Scene</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Math\Frustum.cpp">
|
||||||
|
<Filter>src\Math</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Math\Plane.cpp">
|
||||||
|
<Filter>src\Math</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Math\Sphere.cpp">
|
||||||
|
<Filter>src\Math</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Math\Bounds.cpp">
|
||||||
|
<Filter>src\Math</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\AI\AI.cpp">
|
||||||
|
<Filter>src\AI</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\AI\TaskDriver.cpp">
|
||||||
|
<Filter>src\AI</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\AI\Turret.cpp">
|
||||||
|
<Filter>src\AI</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Scene\BaseMesh.cpp">
|
||||||
|
<Filter>src\Scene</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Scene\Mesh.cpp">
|
||||||
|
<Filter>src\Scene</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Math\NormalComputer.cpp">
|
||||||
|
<Filter>src\Math</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Anim\Anim.cpp">
|
||||||
|
<Filter>src\Anim</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Anim\Animation.cpp">
|
||||||
|
<Filter>src\Anim</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Anim\Motion.cpp">
|
||||||
|
<Filter>src\Anim</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Anim\Skeleton.cpp">
|
||||||
|
<Filter>src\Anim</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\IO\Xml.cpp">
|
||||||
|
<Filter>src\IO</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Net\HttpFile.cpp">
|
||||||
|
<Filter>src\Net</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Game\BaseGame.cpp">
|
||||||
|
<Filter>src\Game</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Global\EngineInit.cpp">
|
||||||
|
<Filter>src\Global</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Input\Input.cpp">
|
||||||
|
<Filter>src\Input</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Input\KeyMapper.cpp">
|
||||||
|
<Filter>src\Input</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\App\App.cpp">
|
||||||
|
<Filter>src\App</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\App\Settings.cpp">
|
||||||
|
<Filter>src\App</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\App\Window.cpp">
|
||||||
|
<Filter>src\App</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\IO\Json.cpp">
|
||||||
|
<Filter>src\IO</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
|
@ -0,0 +1 @@
|
||||||
|
#include "verus.h"
|
|
@ -0,0 +1,4 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "TaskDriver.h"
|
||||||
|
#include "Turret.h"
|
|
@ -0,0 +1,72 @@
|
||||||
|
#include "verus.h"
|
||||||
|
|
||||||
|
using namespace verus;
|
||||||
|
using namespace verus::AI;
|
||||||
|
|
||||||
|
TaskDriver::TaskDriver()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
TaskDriver::~TaskDriver()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void TaskDriver::Update()
|
||||||
|
{
|
||||||
|
VERUS_QREF_TIMER;
|
||||||
|
VERUS_QREF_UTILS;
|
||||||
|
|
||||||
|
if (_cooldownTimer > 0)
|
||||||
|
{
|
||||||
|
_cooldownTimer -= dt;
|
||||||
|
if (_cooldownTimer < 0)
|
||||||
|
_cooldownTimer = 0;
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RMode mode = _mapModes.find(_currentMode)->second;
|
||||||
|
|
||||||
|
VERUS_FOREACH(TMapTasks, mode._mapTasks, it)
|
||||||
|
{
|
||||||
|
RTask task = it->second;
|
||||||
|
task._time += dt;
|
||||||
|
if (task._time >= task._deadline)
|
||||||
|
{
|
||||||
|
if (utils.GetRandom().NextFloat() * 100 < task._chance)
|
||||||
|
{
|
||||||
|
if (_pDelegate)
|
||||||
|
_pDelegate->TaskDriver_OnTask(_C(task._name), _C(_currentMode));
|
||||||
|
_cooldownTimer = _cooldown;
|
||||||
|
}
|
||||||
|
task._deadline = task._intervalMin + task._intervalSize*utils.GetRandom().NextFloat();
|
||||||
|
task._time = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TaskDriver::AddMode(CSZ name)
|
||||||
|
{
|
||||||
|
if (_mapModes.find(name) != _mapModes.end())
|
||||||
|
return;
|
||||||
|
Mode mode;
|
||||||
|
mode._name = name;
|
||||||
|
_mapModes[name] = mode;
|
||||||
|
_currentMode = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TaskDriver::AddTask(CSZ name, float chance, float intervalMin, float intervalMax, CSZ mode)
|
||||||
|
{
|
||||||
|
VERUS_QREF_UTILS;
|
||||||
|
|
||||||
|
RMode thisMode = _mapModes.find(mode ? mode : _currentMode)->second;
|
||||||
|
|
||||||
|
Task task;
|
||||||
|
task._name = name;
|
||||||
|
task._chance = chance;
|
||||||
|
task._intervalMin = intervalMin;
|
||||||
|
task._intervalSize = intervalMax - intervalMin;
|
||||||
|
task._deadline = task._intervalMin + task._intervalSize*utils.GetRandom().NextFloat();
|
||||||
|
|
||||||
|
thisMode._mapTasks[name] = task;
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace verus
|
||||||
|
{
|
||||||
|
namespace AI
|
||||||
|
{
|
||||||
|
struct TaskDriverDelegate
|
||||||
|
{
|
||||||
|
virtual void TaskDriver_OnTask(CSZ task, CSZ mode) = 0;
|
||||||
|
};
|
||||||
|
VERUS_TYPEDEFS(TaskDriverDelegate);
|
||||||
|
|
||||||
|
class TaskDriver
|
||||||
|
{
|
||||||
|
struct Task
|
||||||
|
{
|
||||||
|
String _name;
|
||||||
|
float _chance = 100;
|
||||||
|
float _time = 0;
|
||||||
|
float _deadline = 0;
|
||||||
|
float _intervalMin = 0;
|
||||||
|
float _intervalSize = 0;
|
||||||
|
};
|
||||||
|
VERUS_TYPEDEFS(Task);
|
||||||
|
|
||||||
|
typedef Map<String, Task> TMapTasks;
|
||||||
|
|
||||||
|
struct Mode
|
||||||
|
{
|
||||||
|
String _name;
|
||||||
|
TMapTasks _mapTasks;
|
||||||
|
};
|
||||||
|
VERUS_TYPEDEFS(Mode);
|
||||||
|
|
||||||
|
typedef Map<String, Mode> TMapModes;
|
||||||
|
|
||||||
|
TMapModes _mapModes;
|
||||||
|
String _currentMode;
|
||||||
|
PTaskDriverDelegate _pDelegate = nullptr;
|
||||||
|
float _cooldown = 1;
|
||||||
|
float _cooldownTimer = 0;
|
||||||
|
|
||||||
|
public:
|
||||||
|
TaskDriver();
|
||||||
|
~TaskDriver();
|
||||||
|
|
||||||
|
void Update();
|
||||||
|
|
||||||
|
Str GetCurrentMode() const { return _C(_currentMode); }
|
||||||
|
void SetCurrentMode(CSZ name) { _currentMode = name; }
|
||||||
|
void SetDelegate(PTaskDriverDelegate p) { _pDelegate = p; }
|
||||||
|
|
||||||
|
void AddMode(CSZ name);
|
||||||
|
void AddTask(CSZ name, float chance, float intervalMin, float intervalMax, CSZ mode = nullptr);
|
||||||
|
};
|
||||||
|
VERUS_TYPEDEFS(TaskDriver);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
#include "verus.h"
|
||||||
|
|
||||||
|
using namespace verus;
|
||||||
|
using namespace verus::AI;
|
||||||
|
|
||||||
|
void Turret::Update()
|
||||||
|
{
|
||||||
|
VERUS_QREF_TIMER;
|
||||||
|
|
||||||
|
float delta = _targetYaw - _actualYaw;
|
||||||
|
if (delta <= -VERUS_PI) delta += VERUS_2PI;
|
||||||
|
if (delta >= +VERUS_PI) delta -= VERUS_2PI;
|
||||||
|
if (delta < 0)
|
||||||
|
_actualYaw -= Math::Max(_yawSpeed*dt, -delta);
|
||||||
|
else
|
||||||
|
_actualYaw += Math::Min(_yawSpeed*dt, delta);
|
||||||
|
_actualYaw = Math::WrapAngle(_actualYaw);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Turret::LookAt(RcVector3 rayFromTurret, bool instantly)
|
||||||
|
{
|
||||||
|
_targetYaw = Math::WrapAngle(atan2(
|
||||||
|
static_cast<float>(rayFromTurret.getX()),
|
||||||
|
static_cast<float>(rayFromTurret.getZ())));
|
||||||
|
if (instantly)
|
||||||
|
_actualYaw = _targetYaw;
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace verus
|
||||||
|
{
|
||||||
|
namespace AI
|
||||||
|
{
|
||||||
|
class Turret
|
||||||
|
{
|
||||||
|
float _targetPitch = 0;
|
||||||
|
float _targetYaw = 0;
|
||||||
|
float _actualPitch = 0;
|
||||||
|
float _actualYaw = 0;
|
||||||
|
float _pitchSpeed = 1;
|
||||||
|
float _yawSpeed = 1;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void Update();
|
||||||
|
|
||||||
|
float GetTargetPitch() const { return _targetPitch; }
|
||||||
|
float GetTargetYaw() const { return _targetYaw; }
|
||||||
|
float GetActualPitch() const { return _actualPitch; }
|
||||||
|
float GetActualYaw() const { return _actualYaw; }
|
||||||
|
|
||||||
|
// Speed:
|
||||||
|
float GetPitchSpeed() const { return _pitchSpeed; }
|
||||||
|
float GetYawSpeed() const { return _yawSpeed; }
|
||||||
|
void SetPitchSpeed(float x) { _pitchSpeed = x; }
|
||||||
|
void SetYawSpeed(float x) { _yawSpeed = x; }
|
||||||
|
|
||||||
|
void LookAt(RcVector3 rayFromTurret, bool instantly = false);
|
||||||
|
};
|
||||||
|
VERUS_TYPEDEFS(Turret);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
#include "verus.h"
|
||||||
|
|
||||||
|
namespace verus
|
||||||
|
{
|
||||||
|
void Make_Anim()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void Free_Anim()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Motion.h"
|
||||||
|
#include "Skeleton.h"
|
||||||
|
#include "Animation.h"
|
||||||
|
|
||||||
|
namespace verus
|
||||||
|
{
|
||||||
|
void Make_Anim();
|
||||||
|
void Free_Anim();
|
||||||
|
}
|
|
@ -0,0 +1,309 @@
|
||||||
|
#include "verus.h"
|
||||||
|
|
||||||
|
using namespace verus;
|
||||||
|
using namespace verus::Anim;
|
||||||
|
|
||||||
|
// Collection:
|
||||||
|
|
||||||
|
Collection::Collection()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Collection::~Collection()
|
||||||
|
{
|
||||||
|
DeleteAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Collection::Async_Run(CSZ url, RcBlob blob)
|
||||||
|
{
|
||||||
|
IO::StreamPtr sp(blob);
|
||||||
|
CSZ niceName = strrchr(url, '/');
|
||||||
|
niceName = niceName ? niceName + 1 : url;
|
||||||
|
RMotionData md = _map[niceName];
|
||||||
|
md._motion.Init();
|
||||||
|
md._motion.Deserialize(sp);
|
||||||
|
if (md._duration)
|
||||||
|
md._motion.ComputePlaybackSpeed(md._duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Collection::AddMotion(CSZ name, bool loop, float duration)
|
||||||
|
{
|
||||||
|
CSZ niceName = strrchr(name, '/');
|
||||||
|
niceName = niceName ? niceName + 1 : name;
|
||||||
|
RMotionData md = _map[niceName];
|
||||||
|
md._duration = duration;
|
||||||
|
md._loop = loop;
|
||||||
|
IO::Async::I().Load(name, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Collection::DeleteAll()
|
||||||
|
{
|
||||||
|
IO::Async::Cancel(this);
|
||||||
|
_map.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
PMotionData Collection::Find(CSZ name)
|
||||||
|
{
|
||||||
|
return TStoreMotions::Find(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Collection::GetMaxBones()
|
||||||
|
{
|
||||||
|
int num = 0;
|
||||||
|
VERUS_FOREACH(TStoreMotions::TMap, _map, it)
|
||||||
|
num = Math::Max(num, it->second._motion.GetNumBones());
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Animation:
|
||||||
|
|
||||||
|
Animation::Animation()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Animation::~Animation()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Animation::Update(int numAlphaTracks, PAlphaTrack pAlphaTracks)
|
||||||
|
{
|
||||||
|
VERUS_QREF_TIMER;
|
||||||
|
|
||||||
|
// Async BindCollection():
|
||||||
|
if (_vTriggerStates.size() != _pCollection->GetMaxBones())
|
||||||
|
_vTriggerStates.resize(_pCollection->GetMaxBones());
|
||||||
|
|
||||||
|
// Async BindSkeleton():
|
||||||
|
if (!_blendMotion.GetNumBones() && _pSkeleton->GetNumBones())
|
||||||
|
_pSkeleton->InsertBonesIntoMotion(_blendMotion);
|
||||||
|
|
||||||
|
if (_playing)
|
||||||
|
{
|
||||||
|
if (_blending)
|
||||||
|
{
|
||||||
|
_blendTimer += dt;
|
||||||
|
if (_blendTimer >= _blendDuration)
|
||||||
|
_blending = false;
|
||||||
|
}
|
||||||
|
else if (!_currentMotion.empty())
|
||||||
|
{
|
||||||
|
RMotionData md = *_pCollection->Find(_C(_currentMotion));
|
||||||
|
const float len = md._motion.GetDuration();
|
||||||
|
if (_time < len + 0.5f)
|
||||||
|
{
|
||||||
|
_time += dt;
|
||||||
|
md._motion.ProcessTriggers(_time, this, GetTriggerStatesArray());
|
||||||
|
if (_time >= len)
|
||||||
|
{
|
||||||
|
if (_pDelegate)
|
||||||
|
_pDelegate->Animation_OnEnd(_C(_currentMotion));
|
||||||
|
_time = md._loop ? fmod(_time, len) : len + 1;
|
||||||
|
md._motion.ResetTriggers(GetTriggerStatesArray()); // New loop, reset triggers.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_currentMotion.empty() && numAlphaTracks >= 0) // Alpha track (-1) should not modify the skeleton.
|
||||||
|
{
|
||||||
|
RMotionData md = *_pCollection->Find(_C(_currentMotion));
|
||||||
|
|
||||||
|
int numAlphaMotions = 0;
|
||||||
|
Skeleton::AlphaMotion alphaMotions[4];
|
||||||
|
|
||||||
|
for (int i = 0; i < numAlphaTracks && i < 4; ++i)
|
||||||
|
{
|
||||||
|
alphaMotions[i]._pMotion = pAlphaTracks[i]._pAnimation->GetMotion(); // Can be in blend state.
|
||||||
|
alphaMotions[i]._rootBone = pAlphaTracks[i]._rootBone;
|
||||||
|
alphaMotions[i]._alpha = pAlphaTracks[i]._pAnimation->GetAlpha();
|
||||||
|
alphaMotions[i]._time = pAlphaTracks[i]._pAnimation->GetTime();
|
||||||
|
numAlphaMotions++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_blending)
|
||||||
|
{
|
||||||
|
md._motion.BindBlendMotion(&_blendMotion, _blendTimer / _blendDuration);
|
||||||
|
_pSkeleton->ApplyMotion(md._motion, _time, numAlphaMotions, alphaMotions);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#ifdef VERUS_COMPARE_MODE
|
||||||
|
_pSkeleton->ApplyMotion(md._motion, 0, numAlphaMotions, alphaMotions);
|
||||||
|
#else
|
||||||
|
_pSkeleton->ApplyMotion(md._motion, _time, numAlphaMotions, alphaMotions);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Animation::BindCollection(PCollection p)
|
||||||
|
{
|
||||||
|
_pCollection = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Animation::BindSkeleton(PSkeleton p)
|
||||||
|
{
|
||||||
|
_pSkeleton = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Animation::SetCurrentMotion(CSZ name)
|
||||||
|
{
|
||||||
|
// Reset triggers:
|
||||||
|
if (!_currentMotion.empty())
|
||||||
|
_pCollection->Find(_C(_currentMotion))->_motion.ResetTriggers(GetTriggerStatesArray());
|
||||||
|
if (name)
|
||||||
|
{
|
||||||
|
_pCollection->Find(name)->_motion.ResetTriggers(GetTriggerStatesArray());
|
||||||
|
_currentMotion = name;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
_currentMotion.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Animation::Play()
|
||||||
|
{
|
||||||
|
_playing = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Animation::Stop()
|
||||||
|
{
|
||||||
|
_playing = false;
|
||||||
|
_time = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Animation::Pause()
|
||||||
|
{
|
||||||
|
_playing = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Animation::BlendTo(CSZ name, Range<float> duration, int randTime, PMotion pMotionFrom)
|
||||||
|
{
|
||||||
|
VERUS_QREF_UTILS;
|
||||||
|
|
||||||
|
PMotion pMotion = pMotionFrom;
|
||||||
|
if (!_currentMotion.empty() || pMotionFrom)
|
||||||
|
{
|
||||||
|
if (!pMotionFrom)
|
||||||
|
pMotion = &_pCollection->Find(_C(_currentMotion))->_motion;
|
||||||
|
if (_blending) // Already blending?
|
||||||
|
pMotion->BindBlendMotion(&_blendMotion, _blendTimer / _blendDuration);
|
||||||
|
pMotion->BakeMotionAt(_time, _blendMotion); // Capture current pose.
|
||||||
|
pMotion->BindBlendMotion(nullptr, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((0 == duration._max) || (_currentMotion.empty() && name && _prevMotion == name && _blendTimer / _blendDuration < 0.5f))
|
||||||
|
{
|
||||||
|
_blending = false; // Special case for alpha tracks.
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_blending = true;
|
||||||
|
_blendDuration = (_currentMotion == (name ? name : "")) ? duration._min : duration._max;
|
||||||
|
_blendTimer = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
_prevMotion = _currentMotion;
|
||||||
|
_currentMotion = name ? name : "";
|
||||||
|
|
||||||
|
// Reset triggers:
|
||||||
|
if (pMotion)
|
||||||
|
pMotion->ResetTriggers(GetTriggerStatesArray());
|
||||||
|
if (name)
|
||||||
|
{
|
||||||
|
pMotion = &_pCollection->Find(name)->_motion;
|
||||||
|
pMotion->ResetTriggers(GetTriggerStatesArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset time:
|
||||||
|
_time = (randTime >= 0 && pMotion) ? (randTime / 255.f)*pMotion->GetDuration() : 0;
|
||||||
|
if (_time)
|
||||||
|
pMotion->SkipTriggers(_time, GetTriggerStatesArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Animation::BlendToNew(std::initializer_list<CSZ> names, Range<float> duration, int randTime, PMotion pMotionFrom)
|
||||||
|
{
|
||||||
|
for (auto name : names)
|
||||||
|
{
|
||||||
|
if (_currentMotion == name)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
BlendTo(*names.begin(), duration, randTime, pMotionFrom);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Animation::Motion_OnTrigger(CSZ name, int state)
|
||||||
|
{
|
||||||
|
if (_pDelegate)
|
||||||
|
_pDelegate->Animation_OnTrigger(name, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
PMotion Animation::GetMotion()
|
||||||
|
{
|
||||||
|
PMotion p = nullptr;
|
||||||
|
if (_currentMotion.empty())
|
||||||
|
{
|
||||||
|
if (!_prevMotion.empty())
|
||||||
|
p = &_pCollection->Find(_C(_prevMotion))->_motion;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p = &_pCollection->Find(_C(_currentMotion))->_motion;
|
||||||
|
}
|
||||||
|
if (p && _blending)
|
||||||
|
p->BindBlendMotion(&_blendMotion, _blendTimer / _blendDuration);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
float Animation::GetAlpha(CSZ name) const
|
||||||
|
{
|
||||||
|
bool matchCurrentMotion = false;
|
||||||
|
bool matchPrevMotion = false;
|
||||||
|
if (name)
|
||||||
|
{
|
||||||
|
matchCurrentMotion = Str::StartsWith(_C(_currentMotion), name);
|
||||||
|
matchPrevMotion = Str::StartsWith(_C(_prevMotion), name);
|
||||||
|
}
|
||||||
|
const bool doBlend = name ? (matchCurrentMotion || matchPrevMotion) : true;
|
||||||
|
if (_blending && doBlend)
|
||||||
|
{
|
||||||
|
bool fadeIn = _prevMotion.empty() && !_currentMotion.empty();
|
||||||
|
bool fadeOut = !_prevMotion.empty() && _currentMotion.empty();
|
||||||
|
if (name)
|
||||||
|
{
|
||||||
|
fadeIn = !matchPrevMotion && matchCurrentMotion;
|
||||||
|
fadeOut = matchPrevMotion && !matchCurrentMotion;
|
||||||
|
}
|
||||||
|
if (fadeIn)
|
||||||
|
return Math::SmoothStep(0, 1, _blendTimer / _blendDuration);
|
||||||
|
if (fadeOut)
|
||||||
|
return Math::SmoothStep(0, 1, 1 - _blendTimer / _blendDuration);
|
||||||
|
}
|
||||||
|
if (name)
|
||||||
|
return matchCurrentMotion ? 1.f : 0.f;
|
||||||
|
else
|
||||||
|
return _currentMotion.empty() ? 0.f : 1.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
float Animation::GetTime()
|
||||||
|
{
|
||||||
|
if (_currentMotion.empty())
|
||||||
|
{
|
||||||
|
if (_prevMotion.empty())
|
||||||
|
return _time;
|
||||||
|
else // When alpha goes to zero, use last motion frame:
|
||||||
|
return _pCollection->Find(_C(_prevMotion))->_motion.GetDuration();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return _time;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Animation::IsNearEdge(float t, Edge edge)
|
||||||
|
{
|
||||||
|
PMotion pMotion = GetMotion();
|
||||||
|
if (!pMotion)
|
||||||
|
return false;
|
||||||
|
const float at = _time / pMotion->GetDuration();
|
||||||
|
return ((edge&Edge::begin) && at < t) || ((edge&Edge::end) && at >= 1 - t);
|
||||||
|
}
|
|
@ -0,0 +1,109 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace verus
|
||||||
|
{
|
||||||
|
namespace Anim
|
||||||
|
{
|
||||||
|
struct AnimationDelegate
|
||||||
|
{
|
||||||
|
virtual void Animation_OnEnd(CSZ name) {}
|
||||||
|
virtual void Animation_OnTrigger(CSZ name, int state) {}
|
||||||
|
};
|
||||||
|
VERUS_TYPEDEFS(AnimationDelegate);
|
||||||
|
|
||||||
|
//! Objects of this type are stored in Collection.
|
||||||
|
struct MotionData
|
||||||
|
{
|
||||||
|
Motion _motion;
|
||||||
|
float _duration = 0;
|
||||||
|
bool _loop = true;
|
||||||
|
};
|
||||||
|
VERUS_TYPEDEFS(MotionData);
|
||||||
|
|
||||||
|
typedef StoreUnique<String, MotionData> TStoreMotions;
|
||||||
|
//! The collection of motion objects (Motion) that can be reused by multiple animation objects (Animation).
|
||||||
|
class Collection : private TStoreMotions, public IO::AsyncCallback
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Collection();
|
||||||
|
~Collection();
|
||||||
|
|
||||||
|
virtual void Async_Run(CSZ url, RcBlob blob) override;
|
||||||
|
|
||||||
|
void AddMotion(CSZ name, bool loop = true, float duration = 0);
|
||||||
|
void DeleteAll();
|
||||||
|
PMotionData Find(CSZ name);
|
||||||
|
int GetMaxBones();
|
||||||
|
};
|
||||||
|
VERUS_TYPEDEFS(Collection);
|
||||||
|
|
||||||
|
//! Holds the collection (Collection) of motion objects (Motion) and provides the ability to interpolate between them.
|
||||||
|
|
||||||
|
//! Note: triggers will work properly with 'multiple animations' + 'single
|
||||||
|
//! collection' only if you add motions before binding collection.
|
||||||
|
//!
|
||||||
|
class Animation : public MotionDelegate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum class Edge : int
|
||||||
|
{
|
||||||
|
begin = (1 << 0),
|
||||||
|
end = (1 << 1)
|
||||||
|
};
|
||||||
|
|
||||||
|
struct AlphaTrack
|
||||||
|
{
|
||||||
|
Animation* _pAnimation = nullptr;
|
||||||
|
CSZ _rootBone = nullptr;
|
||||||
|
};
|
||||||
|
VERUS_TYPEDEFS(AlphaTrack);
|
||||||
|
|
||||||
|
private:
|
||||||
|
PCollection _pCollection = nullptr;
|
||||||
|
PAnimationDelegate _pDelegate = nullptr;
|
||||||
|
PSkeleton _pSkeleton = nullptr;
|
||||||
|
Motion _blendMotion;
|
||||||
|
String _currentMotion;
|
||||||
|
String _prevMotion;
|
||||||
|
Vector<int> _vTriggerStates;
|
||||||
|
float _time = 0;
|
||||||
|
float _blendDuration = 0;
|
||||||
|
float _blendTimer = 0;
|
||||||
|
bool _blending = false;
|
||||||
|
bool _playing = false;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Animation();
|
||||||
|
~Animation();
|
||||||
|
|
||||||
|
void Update(int numAlphaTracks = 0, PAlphaTrack pAlphaTracks = nullptr);
|
||||||
|
|
||||||
|
void BindCollection(PCollection p);
|
||||||
|
void BindSkeleton(PSkeleton p);
|
||||||
|
void SetCurrentMotion(CSZ name);
|
||||||
|
PAnimationDelegate SetDelegate(PAnimationDelegate p) { return Utils::Swap(_pDelegate, p); }
|
||||||
|
|
||||||
|
void Play();
|
||||||
|
void Stop();
|
||||||
|
void Pause();
|
||||||
|
|
||||||
|
Str GetCurrentMotionName() const { return _C(_currentMotion); }
|
||||||
|
|
||||||
|
void BlendTo(CSZ name,
|
||||||
|
Range<float> duration = 0.5f, int randTime = -1, PMotion pMotionFrom = nullptr);
|
||||||
|
bool BlendToNew(std::initializer_list<CSZ> names,
|
||||||
|
Range<float> duration = 0.5f, int randTime = -1, PMotion pMotionFrom = nullptr);
|
||||||
|
bool IsBlending() const { return _blending; }
|
||||||
|
|
||||||
|
virtual void Motion_OnTrigger(CSZ name, int state) override;
|
||||||
|
|
||||||
|
PMotion GetMotion();
|
||||||
|
float GetAlpha(CSZ name = nullptr) const;
|
||||||
|
float GetTime();
|
||||||
|
bool IsNearEdge(float t = 0.1f, Edge edge = Edge::begin | Edge::end);
|
||||||
|
|
||||||
|
int* GetTriggerStatesArray() { return _vTriggerStates.empty() ? nullptr : _vTriggerStates.data(); }
|
||||||
|
};
|
||||||
|
VERUS_TYPEDEFS(Animation);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,972 @@
|
||||||
|
#include "verus.h"
|
||||||
|
|
||||||
|
using namespace verus;
|
||||||
|
using namespace verus::Anim;
|
||||||
|
|
||||||
|
// Motion::Bone::Rotation:
|
||||||
|
|
||||||
|
Motion::Bone::Rotation::Rotation()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Motion::Bone::Rotation::Rotation(RcQuat q)
|
||||||
|
{
|
||||||
|
_q = q;
|
||||||
|
}
|
||||||
|
|
||||||
|
Motion::Bone::Rotation::Rotation(RcVector3 euler)
|
||||||
|
{
|
||||||
|
euler.EulerToQuaternion(_q);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Motion::Bone:
|
||||||
|
|
||||||
|
Motion::Bone::Bone(PMotion pMotion) :
|
||||||
|
_pMotion(pMotion)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Motion::Bone::~Bone()
|
||||||
|
{
|
||||||
|
DeleteAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Motion::Bone::DeleteAll()
|
||||||
|
{
|
||||||
|
_mapRot.clear();
|
||||||
|
_mapPos.clear();
|
||||||
|
_mapScale.clear();
|
||||||
|
_mapTrigger.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert:
|
||||||
|
void Motion::Bone::InsertKeyframeRotation(int frame, RcQuat q)
|
||||||
|
{
|
||||||
|
_mapRot[frame] = Rotation(q);
|
||||||
|
}
|
||||||
|
void Motion::Bone::InsertKeyframeRotation(int frame, RcVector3 euler)
|
||||||
|
{
|
||||||
|
_mapRot[frame] = Rotation(euler);
|
||||||
|
}
|
||||||
|
void Motion::Bone::InsertKeyframePosition(int frame, RcVector3 pos)
|
||||||
|
{
|
||||||
|
_mapPos[frame] = pos;
|
||||||
|
}
|
||||||
|
void Motion::Bone::InsertKeyframeScale(int frame, RcVector3 scale)
|
||||||
|
{
|
||||||
|
_mapScale[frame] = scale;
|
||||||
|
}
|
||||||
|
void Motion::Bone::InsertKeyframeTrigger(int frame, int state)
|
||||||
|
{
|
||||||
|
_mapTrigger[frame] = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete:
|
||||||
|
void Motion::Bone::DeleteKeyframeRotation(int frame)
|
||||||
|
{
|
||||||
|
VERUS_IF_FOUND_IN(TMapRot, _mapRot, frame, it)
|
||||||
|
_mapRot.erase(it);
|
||||||
|
}
|
||||||
|
void Motion::Bone::DeleteKeyframePosition(int frame)
|
||||||
|
{
|
||||||
|
VERUS_IF_FOUND_IN(TMapPos, _mapPos, frame, it)
|
||||||
|
_mapPos.erase(it);
|
||||||
|
}
|
||||||
|
void Motion::Bone::DeleteKeyframeScale(int frame)
|
||||||
|
{
|
||||||
|
VERUS_IF_FOUND_IN(TMapScale, _mapScale, frame, it)
|
||||||
|
_mapScale.erase(it);
|
||||||
|
}
|
||||||
|
void Motion::Bone::DeleteKeyframeTrigger(int frame)
|
||||||
|
{
|
||||||
|
VERUS_IF_FOUND_IN(TMapTrigger, _mapTrigger, frame, it)
|
||||||
|
_mapTrigger.erase(it);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find:
|
||||||
|
bool Motion::Bone::FindKeyframeRotation(int frame, RVector3 euler, RQuat q) const
|
||||||
|
{
|
||||||
|
euler = Vector3(0);
|
||||||
|
q = Quat::identity();
|
||||||
|
VERUS_IF_FOUND_IN(TMapRot, _mapRot, frame, it)
|
||||||
|
{
|
||||||
|
euler.EulerFromQuaternion(it->second._q);
|
||||||
|
q = it->second._q;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool Motion::Bone::FindKeyframePosition(int frame, RVector3 pos) const
|
||||||
|
{
|
||||||
|
pos = Vector3(0);
|
||||||
|
VERUS_IF_FOUND_IN(TMapPos, _mapPos, frame, it)
|
||||||
|
{
|
||||||
|
pos = it->second;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool Motion::Bone::FindKeyframeScale(int frame, RVector3 scale) const
|
||||||
|
{
|
||||||
|
scale = Vector3(1, 1, 1);
|
||||||
|
VERUS_IF_FOUND_IN(TMapScale, _mapScale, frame, it)
|
||||||
|
{
|
||||||
|
scale = it->second;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool Motion::Bone::FindKeyframeTrigger(int frame, int& state) const
|
||||||
|
{
|
||||||
|
state = 0;
|
||||||
|
VERUS_IF_FOUND_IN(TMapTrigger, _mapTrigger, frame, it)
|
||||||
|
{
|
||||||
|
state = it->second;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Motion::Bone::ComputeRotationAt(float time, RVector3 euler, RQuat q) const
|
||||||
|
{
|
||||||
|
Rotation prev, next, null(Quat(0));
|
||||||
|
const float alpha = GetAlpha(_mapRot, prev, next, null, time);
|
||||||
|
q = VMath::slerp(alpha, prev._q, next._q);
|
||||||
|
|
||||||
|
PMotion pBlendMotion = _pMotion->GetBlendMotion();
|
||||||
|
if (pBlendMotion)
|
||||||
|
{
|
||||||
|
PBone pBone = pBlendMotion->FindBone(_C(_name));
|
||||||
|
if (pBone)
|
||||||
|
{
|
||||||
|
Vector3 eulerBlend;
|
||||||
|
Quat qBlend;
|
||||||
|
if (pBone->FindKeyframeRotation(0, eulerBlend, qBlend))
|
||||||
|
q = VMath::slerp(_pMotion->GetBlendAlpha(), qBlend, q);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
euler.EulerFromQuaternion(q);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Motion::Bone::ComputePositionAt(float time, RVector3 pos) const
|
||||||
|
{
|
||||||
|
Vector3 prev, next, null(0);
|
||||||
|
const float alpha = GetAlpha(_mapPos, prev, next, null, time);
|
||||||
|
pos = VMath::lerp(alpha, prev, next);
|
||||||
|
|
||||||
|
PMotion pBlendMotion = _pMotion->GetBlendMotion();
|
||||||
|
if (pBlendMotion)
|
||||||
|
{
|
||||||
|
PBone pBone = pBlendMotion->FindBone(_C(_name));
|
||||||
|
if (pBone)
|
||||||
|
{
|
||||||
|
Vector3 posBlend;
|
||||||
|
if (pBone->FindKeyframePosition(0, posBlend))
|
||||||
|
pos = VMath::lerp(_pMotion->GetBlendAlpha(), posBlend, pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Motion::Bone::ComputeScaleAt(float time, RVector3 scale) const
|
||||||
|
{
|
||||||
|
Vector3 prev, next, null(1, 1, 1);
|
||||||
|
const float alpha = GetAlpha(_mapScale, prev, next, null, time);
|
||||||
|
scale = VMath::lerp(alpha, prev, next);
|
||||||
|
|
||||||
|
PMotion pBlendMotion = _pMotion->GetBlendMotion();
|
||||||
|
if (pBlendMotion)
|
||||||
|
{
|
||||||
|
PBone pBone = pBlendMotion->FindBone(_C(_name));
|
||||||
|
if (pBone)
|
||||||
|
{
|
||||||
|
Vector3 scaleBlend;
|
||||||
|
if (pBone->FindKeyframeScale(0, scaleBlend))
|
||||||
|
scale = VMath::lerp(_pMotion->GetBlendAlpha(), scaleBlend, scale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Motion::Bone::ComputeTriggerAt(float time, int& state) const
|
||||||
|
{
|
||||||
|
if (_mapTrigger.empty())
|
||||||
|
{
|
||||||
|
state = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const int frame = int(_pMotion->GetFps()*time);
|
||||||
|
TMapTrigger::const_iterator it = _mapTrigger.upper_bound(frame); // Find frame after 'time'.
|
||||||
|
if (it != _mapTrigger.begin())
|
||||||
|
{
|
||||||
|
it--;
|
||||||
|
state = it->second;
|
||||||
|
}
|
||||||
|
else // All keyframes are after 'time':
|
||||||
|
{
|
||||||
|
state = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Motion::Bone::ComputeMatrixAt(float time, RTransform3 mat)
|
||||||
|
{
|
||||||
|
Quat q;
|
||||||
|
Vector3 scale, euler, pos;
|
||||||
|
ComputeRotationAt(time, euler, q);
|
||||||
|
ComputePositionAt(time, pos);
|
||||||
|
ComputeScaleAt(time, scale);
|
||||||
|
mat = VMath::appendScale(Transform3(q, pos), scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Motion::Bone::MoveKeyframe(int direction, Type type, int frame)
|
||||||
|
{
|
||||||
|
const int frameDest = (direction >= 0) ? frame + 1 : frame - 1;
|
||||||
|
if (frameDest < 0 || frameDest >= _pMotion->GetNumFrames())
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case Type::rotation:
|
||||||
|
{
|
||||||
|
VERUS_IF_FOUND_IN(TMapRot, _mapRot, frame, it)
|
||||||
|
{
|
||||||
|
if (_mapRot.find(frameDest) == _mapRot.end())
|
||||||
|
{
|
||||||
|
_mapRot[frameDest] = it->second;
|
||||||
|
_mapRot.erase(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Type::position:
|
||||||
|
{
|
||||||
|
VERUS_IF_FOUND_IN(TMapPos, _mapPos, frame, it)
|
||||||
|
{
|
||||||
|
if (_mapPos.find(frameDest) == _mapPos.end())
|
||||||
|
{
|
||||||
|
_mapPos[frameDest] = it->second;
|
||||||
|
_mapPos.erase(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Type::scale:
|
||||||
|
{
|
||||||
|
VERUS_IF_FOUND_IN(TMapScale, _mapScale, frame, it)
|
||||||
|
{
|
||||||
|
if (_mapScale.find(frameDest) == _mapScale.end())
|
||||||
|
{
|
||||||
|
_mapScale[frameDest] = it->second;
|
||||||
|
_mapScale.erase(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Type::trigger:
|
||||||
|
{
|
||||||
|
VERUS_IF_FOUND_IN(TMapTrigger, _mapTrigger, frame, it)
|
||||||
|
{
|
||||||
|
if (_mapTrigger.find(frameDest) == _mapTrigger.end())
|
||||||
|
{
|
||||||
|
_mapTrigger[frameDest] = it->second;
|
||||||
|
_mapTrigger.erase(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Motion::Bone::Serialize(IO::RStream stream)
|
||||||
|
{
|
||||||
|
const int numKeyframesRot = Utils::Cast32(_mapRot.size());
|
||||||
|
const int numKeyframesPos = Utils::Cast32(_mapPos.size());
|
||||||
|
const int numKeyframesScale = Utils::Cast32(_mapScale.size());
|
||||||
|
const int numKeyframesTrigger = Utils::Cast32(_mapTrigger.size());
|
||||||
|
|
||||||
|
stream << numKeyframesRot;
|
||||||
|
VERUS_FOREACH_CONST(TMapRot, _mapRot, it)
|
||||||
|
{
|
||||||
|
stream << it->first;
|
||||||
|
stream.Write(&it->second._q, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
stream << numKeyframesPos;
|
||||||
|
VERUS_FOREACH_CONST(TMapPos, _mapPos, it)
|
||||||
|
{
|
||||||
|
stream << it->first;
|
||||||
|
stream.Write(&it->second, 12);
|
||||||
|
}
|
||||||
|
|
||||||
|
stream << numKeyframesScale;
|
||||||
|
VERUS_FOREACH_CONST(TMapScale, _mapScale, it)
|
||||||
|
{
|
||||||
|
stream << it->first;
|
||||||
|
stream.Write(&it->second, 12);
|
||||||
|
}
|
||||||
|
|
||||||
|
stream << numKeyframesTrigger;
|
||||||
|
VERUS_FOREACH_CONST(TMapTrigger, _mapTrigger, it)
|
||||||
|
{
|
||||||
|
stream << it->first;
|
||||||
|
stream << it->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Motion::Bone::Deserialize(IO::RStream stream)
|
||||||
|
{
|
||||||
|
int numKeyframesRot, numKeyframesPos, numKeyframesScale, numKeyframesTrigger, frame, state;
|
||||||
|
Vector3 temp;
|
||||||
|
Quat q;
|
||||||
|
|
||||||
|
stream >> numKeyframesRot;
|
||||||
|
VERUS_FOR(i, numKeyframesRot)
|
||||||
|
{
|
||||||
|
stream >> frame;
|
||||||
|
stream.Read(&q, 16);
|
||||||
|
InsertKeyframeRotation(frame, q);
|
||||||
|
}
|
||||||
|
|
||||||
|
stream >> numKeyframesPos;
|
||||||
|
VERUS_FOR(i, numKeyframesPos)
|
||||||
|
{
|
||||||
|
stream >> frame;
|
||||||
|
stream.Read(&temp, 12);
|
||||||
|
InsertKeyframePosition(frame, temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
stream >> numKeyframesScale;
|
||||||
|
VERUS_FOR(i, numKeyframesScale)
|
||||||
|
{
|
||||||
|
stream >> frame;
|
||||||
|
stream.Read(&temp, 12);
|
||||||
|
InsertKeyframeScale(frame, temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
stream >> numKeyframesTrigger;
|
||||||
|
VERUS_FOR(i, numKeyframesTrigger)
|
||||||
|
{
|
||||||
|
stream >> frame;
|
||||||
|
stream >> state;
|
||||||
|
InsertKeyframeTrigger(frame, state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Motion::Bone::DeleteRedundantKeyframes()
|
||||||
|
{
|
||||||
|
if (2 == _mapRot.size())
|
||||||
|
{
|
||||||
|
if (!memcmp(
|
||||||
|
&_mapRot.begin()->second,
|
||||||
|
&_mapRot.rbegin()->second,
|
||||||
|
16))
|
||||||
|
_mapRot.erase(--_mapRot.end());
|
||||||
|
}
|
||||||
|
if (1 == _mapRot.size())
|
||||||
|
{
|
||||||
|
RQuat q = _mapRot.begin()->second._q;
|
||||||
|
if (q.IsIdentity())
|
||||||
|
_mapRot.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (2 == _mapPos.size())
|
||||||
|
{
|
||||||
|
if (!memcmp(
|
||||||
|
&_mapPos.begin()->second,
|
||||||
|
&_mapPos.rbegin()->second,
|
||||||
|
12))
|
||||||
|
_mapPos.erase(--_mapPos.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (2 == _mapScale.size())
|
||||||
|
{
|
||||||
|
if (!memcmp(
|
||||||
|
&_mapScale.begin()->second,
|
||||||
|
&_mapScale.rbegin()->second,
|
||||||
|
12))
|
||||||
|
_mapScale.erase(--_mapScale.end());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Motion::Bone::DeleteOddKeyframes()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
TMapRot::iterator it = _mapRot.begin();
|
||||||
|
while (it != _mapRot.end())
|
||||||
|
{
|
||||||
|
if (it->first & 0x1)
|
||||||
|
_mapRot.erase(it++);
|
||||||
|
else
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
TMapPos::iterator it = _mapPos.begin();
|
||||||
|
while (it != _mapPos.end())
|
||||||
|
{
|
||||||
|
if (it->first & 0x1)
|
||||||
|
_mapPos.erase(it++);
|
||||||
|
else
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
TMapScale::iterator it = _mapScale.begin();
|
||||||
|
while (it != _mapScale.end())
|
||||||
|
{
|
||||||
|
if (it->first & 0x1)
|
||||||
|
_mapScale.erase(it++);
|
||||||
|
else
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Motion::Bone::InsertLoopKeyframes()
|
||||||
|
{
|
||||||
|
if (!_mapRot.empty())
|
||||||
|
_mapRot[_pMotion->GetNumFrames()] = _mapRot.begin()->second;
|
||||||
|
if (!_mapPos.empty())
|
||||||
|
_mapPos[_pMotion->GetNumFrames()] = _mapPos.begin()->second;
|
||||||
|
if (!_mapScale.empty())
|
||||||
|
_mapScale[_pMotion->GetNumFrames()] = _mapScale.begin()->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Motion::Bone::Cut(int frame, bool before)
|
||||||
|
{
|
||||||
|
if (before && !frame)
|
||||||
|
return;
|
||||||
|
|
||||||
|
{
|
||||||
|
TMapRot::iterator it = _mapRot.begin();
|
||||||
|
while (it != _mapRot.end())
|
||||||
|
{
|
||||||
|
if (before)
|
||||||
|
{
|
||||||
|
if (it->first >= frame)
|
||||||
|
_mapRot[it->first - frame] = it->second;
|
||||||
|
_mapRot.erase(it++);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (it->first > frame)
|
||||||
|
_mapRot.erase(it++);
|
||||||
|
else
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
TMapPos::iterator it = _mapPos.begin();
|
||||||
|
while (it != _mapPos.end())
|
||||||
|
{
|
||||||
|
if (before)
|
||||||
|
{
|
||||||
|
if (it->first >= frame)
|
||||||
|
_mapPos[it->first - frame] = it->second;
|
||||||
|
_mapPos.erase(it++);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (it->first > frame)
|
||||||
|
_mapPos.erase(it++);
|
||||||
|
else
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
TMapScale::iterator it = _mapScale.begin();
|
||||||
|
while (it != _mapScale.end())
|
||||||
|
{
|
||||||
|
if (before)
|
||||||
|
{
|
||||||
|
if (it->first >= frame)
|
||||||
|
_mapScale[it->first - frame] = it->second;
|
||||||
|
_mapScale.erase(it++);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (it->first > frame)
|
||||||
|
_mapScale.erase(it++);
|
||||||
|
else
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Motion::Bone::Fix(bool speedLimit)
|
||||||
|
{
|
||||||
|
const float e = 0.02f;
|
||||||
|
|
||||||
|
// Remove rotation keyframes:
|
||||||
|
if (true)
|
||||||
|
{
|
||||||
|
Quat qBase(0);
|
||||||
|
TMapRot::iterator it = _mapRot.begin();
|
||||||
|
bool hasBroken = false;
|
||||||
|
while (it != _mapRot.end())
|
||||||
|
{
|
||||||
|
RcQuat q = it->second._q;
|
||||||
|
const bool broken =
|
||||||
|
Math::IsNaN(q.getX()) ||
|
||||||
|
Math::IsNaN(q.getY()) ||
|
||||||
|
Math::IsNaN(q.getZ()) ||
|
||||||
|
Math::IsNaN(q.getW());
|
||||||
|
if (broken)
|
||||||
|
hasBroken = true;
|
||||||
|
const bool same = qBase.IsEqual(q, e);
|
||||||
|
if (same || broken)
|
||||||
|
_mapRot.erase(it++);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
qBase = q;
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove position keyframes:
|
||||||
|
if (true)
|
||||||
|
{
|
||||||
|
Vector3 base(0);
|
||||||
|
TMapPos::iterator it = _mapPos.begin();
|
||||||
|
while (it != _mapPos.end())
|
||||||
|
{
|
||||||
|
RcVector3 pos = it->second;
|
||||||
|
const bool broken =
|
||||||
|
Math::IsNaN(pos.getX()) ||
|
||||||
|
Math::IsNaN(pos.getY()) ||
|
||||||
|
Math::IsNaN(pos.getZ());
|
||||||
|
const bool same = base.IsEqual(pos, e);
|
||||||
|
if (same || broken)
|
||||||
|
_mapPos.erase(it++);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
base = pos;
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Limit rotation speed:
|
||||||
|
if (speedLimit && Skeleton::IsKinectBone(_C(_name)))
|
||||||
|
{
|
||||||
|
VERUS_FOREACH(TMapRot, _mapRot, it)
|
||||||
|
{
|
||||||
|
RQuat q = it->second._q;
|
||||||
|
if (it->first >= 1)
|
||||||
|
{
|
||||||
|
Quat qPrev;
|
||||||
|
Vector3 euler;
|
||||||
|
ComputeRotationAt((it->first - 1)*_pMotion->GetFpsInv(), euler, qPrev);
|
||||||
|
const float threshold = 0.5f;
|
||||||
|
const Quat qPrevInv = VMath::inverse(Matrix3(qPrev));
|
||||||
|
const Quat qD = q * qPrevInv;
|
||||||
|
const float a = abs(glm::angle(qD.GLM()));
|
||||||
|
if (a > threshold)
|
||||||
|
{
|
||||||
|
const float back = Math::Clamp((a - threshold) / threshold, 0.f, 0.75f);
|
||||||
|
q = VMath::slerp(back, q, qPrev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Motion::Bone::ApplyScaleBias(RcVector3 scale, RcVector3 bias)
|
||||||
|
{
|
||||||
|
VERUS_FOREACH(TMapPos, _mapPos, it)
|
||||||
|
it->second = VMath::mulPerElem(it->second, scale) + bias;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Motion::Bone::Scatter(int srcFrom, int srcTo, int dMin, int dMax)
|
||||||
|
{
|
||||||
|
VERUS_QREF_UTILS;
|
||||||
|
int start = srcFrom;
|
||||||
|
const int range = dMax - dMin;
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
start += dMin + utils.GetRandom().Next() % range;
|
||||||
|
if (start >= _pMotion->GetNumFrames())
|
||||||
|
break;
|
||||||
|
for (int i = srcFrom; i < srcTo; ++i)
|
||||||
|
{
|
||||||
|
Quat q;
|
||||||
|
Vector3 euler, pos;
|
||||||
|
if (FindKeyframeRotation(i, euler, q))
|
||||||
|
InsertKeyframeRotation(i + start, q);
|
||||||
|
if (FindKeyframePosition(i, pos))
|
||||||
|
InsertKeyframePosition(i + start, pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int Motion::Bone::GetLastKeyframe() const
|
||||||
|
{
|
||||||
|
int frame = 0;
|
||||||
|
if (!_mapRot.empty())
|
||||||
|
frame = Math::Max(frame, _mapRot.rbegin()->first);
|
||||||
|
if (!_mapPos.empty())
|
||||||
|
frame = Math::Max(frame, _mapPos.rbegin()->first);
|
||||||
|
if (!_mapScale.empty())
|
||||||
|
frame = Math::Max(frame, _mapScale.rbegin()->first);
|
||||||
|
if (!_mapTrigger.empty())
|
||||||
|
frame = Math::Max(frame, _mapTrigger.rbegin()->first);
|
||||||
|
return frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Motion:
|
||||||
|
|
||||||
|
Motion::Motion()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Motion::~Motion()
|
||||||
|
{
|
||||||
|
Done();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Motion::Init()
|
||||||
|
{
|
||||||
|
VERUS_INIT();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Motion::Done()
|
||||||
|
{
|
||||||
|
DeleteAllBones();
|
||||||
|
VERUS_DONE(Motion);
|
||||||
|
}
|
||||||
|
|
||||||
|
Motion::PBone Motion::GetBoneByIndex(int index)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
for (auto& kv : _mapBones)
|
||||||
|
{
|
||||||
|
if (i == index)
|
||||||
|
return &kv.second;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Motion::GetBoneIndex(CSZ name) const
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
VERUS_FOREACH_CONST(TMapBones, _mapBones, it)
|
||||||
|
{
|
||||||
|
if (it->first == name)
|
||||||
|
return i;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Motion::PBone Motion::InsertBone(CSZ name)
|
||||||
|
{
|
||||||
|
PBone pBone = FindBone(name);
|
||||||
|
if (pBone)
|
||||||
|
return pBone;
|
||||||
|
Bone bone(this);
|
||||||
|
bone.Rename(name);
|
||||||
|
_mapBones[name] = bone;
|
||||||
|
return &_mapBones[name];
|
||||||
|
}
|
||||||
|
|
||||||
|
void Motion::DeleteBone(CSZ name)
|
||||||
|
{
|
||||||
|
VERUS_IF_FOUND_IN(TMapBones, _mapBones, name, it)
|
||||||
|
_mapBones.erase(it);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Motion::DeleteAllBones()
|
||||||
|
{
|
||||||
|
_mapBones.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
Motion::PBone Motion::FindBone(CSZ name)
|
||||||
|
{
|
||||||
|
VERUS_IF_FOUND_IN(TMapBones, _mapBones, name, it)
|
||||||
|
return &it->second;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Motion::Serialize(IO::RStream stream)
|
||||||
|
{
|
||||||
|
const UINT32 magic = '2NAX';
|
||||||
|
stream << magic;
|
||||||
|
|
||||||
|
const UINT16 version = xanVersion;
|
||||||
|
stream << version;
|
||||||
|
|
||||||
|
stream << _numFrames;
|
||||||
|
stream << _fps;
|
||||||
|
stream << GetNumBones();
|
||||||
|
|
||||||
|
for (auto& kv : _mapBones)
|
||||||
|
{
|
||||||
|
RBone bone = kv.second;
|
||||||
|
stream.WriteString(_C(bone.GetName()));
|
||||||
|
bone.Serialize(stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Motion::Deserialize(IO::RStream stream)
|
||||||
|
{
|
||||||
|
UINT32 magic = 0;
|
||||||
|
stream >> magic;
|
||||||
|
if ('2NAX' != magic)
|
||||||
|
throw VERUS_RECOVERABLE << "Deserialize(), Invalid XAN format";
|
||||||
|
|
||||||
|
UINT16 version = 0;
|
||||||
|
stream >> version;
|
||||||
|
if (xanVersion != version)
|
||||||
|
throw VERUS_RECOVERABLE << "Deserialize(), Invalid XAN version";
|
||||||
|
|
||||||
|
stream >> _numFrames;
|
||||||
|
stream >> _fps;
|
||||||
|
if (_numFrames < 0 || _numFrames > maxNumFrames)
|
||||||
|
throw VERUS_RECOVERABLE << "Deserialize(), Invalid number of frames in XAN";
|
||||||
|
if (_fps <= 0 || _fps > maxFps)
|
||||||
|
throw VERUS_RECOVERABLE << "Deserialize(), Invalid FPS in XAN";
|
||||||
|
|
||||||
|
SetFps(_fps);
|
||||||
|
|
||||||
|
int numBones = 0;
|
||||||
|
stream >> numBones;
|
||||||
|
if (numBones < 0 || numBones > maxNumBones)
|
||||||
|
throw VERUS_RECOVERABLE << "Deserialize(), Invalid number of bones in XAN";
|
||||||
|
|
||||||
|
char buffer[IO::Stream::bufferSize] = {};
|
||||||
|
VERUS_FOR(i, numBones)
|
||||||
|
{
|
||||||
|
stream.ReadString(buffer);
|
||||||
|
PBone pBone = InsertBone(buffer);
|
||||||
|
pBone->Deserialize(stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Motion::BakeMotionAt(float time, Motion& dest) const
|
||||||
|
{
|
||||||
|
float nativeTime = time * _playbackSpeed;
|
||||||
|
if (_reversed)
|
||||||
|
nativeTime = GetNativeDuration() - nativeTime;
|
||||||
|
|
||||||
|
VERUS_FOREACH_CONST(TMapBones, _mapBones, it)
|
||||||
|
{
|
||||||
|
PcBone pBone = &it->second;
|
||||||
|
PBone pBoneDest = dest.FindBone(_C(it->first));
|
||||||
|
if (pBoneDest)
|
||||||
|
{
|
||||||
|
Vector3 rot, pos, scale;
|
||||||
|
Quat q;
|
||||||
|
|
||||||
|
pBone->ComputeRotationAt(nativeTime, rot, q);
|
||||||
|
pBone->ComputePositionAt(nativeTime, pos);
|
||||||
|
pBone->ComputeScaleAt(nativeTime, scale);
|
||||||
|
|
||||||
|
pBoneDest->InsertKeyframeRotation(0, q);
|
||||||
|
pBoneDest->InsertKeyframePosition(0, pos);
|
||||||
|
pBoneDest->InsertKeyframeScale(0, scale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Motion::BindBlendMotion(PMotion p, float alpha)
|
||||||
|
{
|
||||||
|
_pBlendMotion = p;
|
||||||
|
_blendAlpha = alpha;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Motion::DeleteRedundantKeyframes()
|
||||||
|
{
|
||||||
|
for (auto& kv : _mapBones)
|
||||||
|
kv.second.DeleteRedundantKeyframes();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Motion::DeleteOddKeyframes()
|
||||||
|
{
|
||||||
|
for (auto& kv : _mapBones)
|
||||||
|
kv.second.DeleteOddKeyframes();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Motion::InsertLoopKeyframes()
|
||||||
|
{
|
||||||
|
for (auto& kv : _mapBones)
|
||||||
|
kv.second.InsertLoopKeyframes();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Motion::Cut(int frame, bool before)
|
||||||
|
{
|
||||||
|
for (auto& kv : _mapBones)
|
||||||
|
kv.second.Cut(frame, before);
|
||||||
|
_numFrames = before ? _numFrames - frame : frame + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Motion::Fix(bool speedLimit)
|
||||||
|
{
|
||||||
|
for (auto& kv : _mapBones)
|
||||||
|
kv.second.Fix(speedLimit);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Motion::ProcessTriggers(float time, PMotionDelegate p, int* pUserTriggerStates)
|
||||||
|
{
|
||||||
|
VERUS_RT_ASSERT(p);
|
||||||
|
|
||||||
|
float nativeTime = time * _playbackSpeed;
|
||||||
|
if (_reversed)
|
||||||
|
nativeTime = GetNativeDuration() - nativeTime;
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
for (auto& kv : _mapBones)
|
||||||
|
{
|
||||||
|
PBone pBone = &kv.second;
|
||||||
|
int state = 0;
|
||||||
|
if (!(_reversed && nativeTime < _fpsInv*0.5f)) // Avoid edge case for the first frame in reverse.
|
||||||
|
pBone->ComputeTriggerAt(nativeTime, state);
|
||||||
|
const int last = pUserTriggerStates ? pUserTriggerStates[i] : pBone->GetLastTriggerState();
|
||||||
|
if (state != last)
|
||||||
|
{
|
||||||
|
p->Motion_OnTrigger(_C(pBone->GetName()), state);
|
||||||
|
if (pUserTriggerStates)
|
||||||
|
pUserTriggerStates[i] = state;
|
||||||
|
else
|
||||||
|
pBone->SetLastTriggerState(state);
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Motion::ResetTriggers(int* pUserTriggerStates)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
for (auto& kv : _mapBones)
|
||||||
|
{
|
||||||
|
PBone pBone = &kv.second;
|
||||||
|
int state = 0;
|
||||||
|
if (_reversed)
|
||||||
|
pBone->ComputeTriggerAt(GetNativeDuration(), state);
|
||||||
|
if (pUserTriggerStates)
|
||||||
|
pUserTriggerStates[i] = state;
|
||||||
|
else
|
||||||
|
pBone->SetLastTriggerState(state);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Motion::SkipTriggers(float time, int* pUserTriggerStates)
|
||||||
|
{
|
||||||
|
float nativeTime = time * _playbackSpeed;
|
||||||
|
if (_reversed)
|
||||||
|
nativeTime = GetNativeDuration() - nativeTime;
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
for (auto& kv : _mapBones)
|
||||||
|
{
|
||||||
|
PBone pBone = &kv.second;
|
||||||
|
int state;
|
||||||
|
pBone->ComputeTriggerAt(nativeTime, state);
|
||||||
|
if (pUserTriggerStates)
|
||||||
|
pUserTriggerStates[i] = state;
|
||||||
|
else
|
||||||
|
pBone->SetLastTriggerState(state);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Motion::ApplyScaleBias(CSZ name, RcVector3 scale, RcVector3 bias)
|
||||||
|
{
|
||||||
|
PBone pBone = FindBone(name);
|
||||||
|
if (pBone)
|
||||||
|
pBone->ApplyScaleBias(scale, bias);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Motion::SetPlaybackSpeed(float x)
|
||||||
|
{
|
||||||
|
VERUS_RT_ASSERT(x != 0);
|
||||||
|
_playbackSpeed = x;
|
||||||
|
_reversed = x < 0;
|
||||||
|
if (_reversed)
|
||||||
|
_playbackSpeed = -_playbackSpeed;
|
||||||
|
_playbackSpeedInv = 1 / _playbackSpeed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Motion::ComputePlaybackSpeed(float duration)
|
||||||
|
{
|
||||||
|
VERUS_RT_ASSERT(duration != 0);
|
||||||
|
_playbackSpeed = GetNativeDuration() / duration;
|
||||||
|
_reversed = duration < 0;
|
||||||
|
if (_reversed)
|
||||||
|
_playbackSpeed = -_playbackSpeed;
|
||||||
|
_playbackSpeedInv = 1 / _playbackSpeed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Motion::Exec(CSZ code)
|
||||||
|
{
|
||||||
|
if (Str::StartsWith(code, "copy "))
|
||||||
|
{
|
||||||
|
char boneSrc[80] = {};
|
||||||
|
char boneDst[80] = {};
|
||||||
|
sscanf(code, "%*s %s %s", boneSrc, boneDst);
|
||||||
|
PBone pSrc = FindBone(boneSrc);
|
||||||
|
PBone pDst = FindBone(boneDst);
|
||||||
|
pDst->_mapRot = pSrc->_mapRot;
|
||||||
|
pDst->_mapPos = pSrc->_mapPos;
|
||||||
|
}
|
||||||
|
if (Str::StartsWith(code, "scatter "))
|
||||||
|
{
|
||||||
|
int srcFrom = 0, srcTo = 0;
|
||||||
|
int dMin = 0, dMax = 0;
|
||||||
|
char bone[80] = {};
|
||||||
|
sscanf(code, "%*s %d %d %d %d %s", &srcFrom, &srcTo, &dMin, &dMax, bone);
|
||||||
|
const int srcSize = srcTo - srcFrom;
|
||||||
|
if (dMin < srcSize)
|
||||||
|
{
|
||||||
|
const int d = srcSize - dMin;
|
||||||
|
dMin += d;
|
||||||
|
dMax += d;
|
||||||
|
}
|
||||||
|
PBone p = FindBone(bone + 5);
|
||||||
|
if (p)
|
||||||
|
p->Scatter(srcFrom, srcTo, dMin, dMax);
|
||||||
|
}
|
||||||
|
if (Str::StartsWith(code, "delete "))
|
||||||
|
{
|
||||||
|
char what[80] = {};
|
||||||
|
char name[80] = {};
|
||||||
|
sscanf(code, "%*s %s %s", what, name);
|
||||||
|
if (strlen(name) > 5)
|
||||||
|
{
|
||||||
|
PBone p = FindBone(name + 5);
|
||||||
|
if (p)
|
||||||
|
{
|
||||||
|
if (!strcmp(what, "rot"))
|
||||||
|
p->_mapRot.clear();
|
||||||
|
if (!strcmp(what, "pos"))
|
||||||
|
p->_mapPos.clear();
|
||||||
|
if (!strcmp(what, "scale"))
|
||||||
|
p->_mapScale.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (auto& bone : _mapBones)
|
||||||
|
{
|
||||||
|
if (!strcmp(what, "rot"))
|
||||||
|
bone.second._mapRot.clear();
|
||||||
|
if (!strcmp(what, "pos"))
|
||||||
|
bone.second._mapPos.clear();
|
||||||
|
if (!strcmp(what, "scale"))
|
||||||
|
bone.second._mapScale.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int Motion::GetLastKeyframe() const
|
||||||
|
{
|
||||||
|
int frame = 0;
|
||||||
|
VERUS_FOREACH_CONST(TMapBones, _mapBones, it)
|
||||||
|
frame = Math::Max(frame, it->second.GetLastKeyframe());
|
||||||
|
return frame;
|
||||||
|
}
|
|
@ -0,0 +1,237 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace verus
|
||||||
|
{
|
||||||
|
namespace Anim
|
||||||
|
{
|
||||||
|
struct MotionDelegate
|
||||||
|
{
|
||||||
|
virtual void Motion_OnTrigger(CSZ name, int state) = 0;
|
||||||
|
};
|
||||||
|
VERUS_TYPEDEFS(MotionDelegate);
|
||||||
|
|
||||||
|
//! Motion holds a series of keyframes and provides the ability to interpolate between them.
|
||||||
|
|
||||||
|
//! Motion can be stored in XAN format. Motion's rate can be
|
||||||
|
//! scaled and even reversed. Animation object (Animation) can be used to
|
||||||
|
//! handle multiple motion objects.
|
||||||
|
//!
|
||||||
|
class Motion : public Object
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
class Bone : public AllocatorAware
|
||||||
|
{
|
||||||
|
friend class Motion;
|
||||||
|
|
||||||
|
class Rotation
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Quat _q;
|
||||||
|
|
||||||
|
Rotation();
|
||||||
|
Rotation(RcQuat q);
|
||||||
|
Rotation(RcVector3 euler);
|
||||||
|
};
|
||||||
|
VERUS_TYPEDEFS(Rotation);
|
||||||
|
|
||||||
|
typedef Map<int, Rotation> TMapRot;
|
||||||
|
typedef Map<int, Vector3> TMapPos;
|
||||||
|
typedef Map<int, Vector3> TMapScale;
|
||||||
|
typedef Map<int, int> TMapTrigger;
|
||||||
|
|
||||||
|
String _name;
|
||||||
|
Motion* _pMotion = nullptr;
|
||||||
|
TMapRot _mapRot; //!< Rotation keyframes.
|
||||||
|
TMapPos _mapPos; //!< Position keyframes.
|
||||||
|
TMapScale _mapScale; //!< Scaling keyframes.
|
||||||
|
TMapTrigger _mapTrigger; //!< Trigger keyframes.
|
||||||
|
int _lastTriggerState = 0;
|
||||||
|
|
||||||
|
template<typename TMap, typename T>
|
||||||
|
float GetAlpha(const TMap& m, T& prev, T& next, const T& null, float time) const
|
||||||
|
{
|
||||||
|
if (m.empty()) // No frames at all, so return null.
|
||||||
|
{
|
||||||
|
prev = null;
|
||||||
|
next = null;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
float alpha;
|
||||||
|
const int frame = static_cast<int>(_pMotion->GetFps()*time); // Frame is before or at 'time'.
|
||||||
|
typename TMap::const_iterator it = m.upper_bound(frame); // Find frame after 'time'.
|
||||||
|
if (it != m.end()) // There are frames greater (after 'time'):
|
||||||
|
{
|
||||||
|
if (it != m.begin()) // And there are less than (before 'time'), full interpolation:
|
||||||
|
{
|
||||||
|
typename TMap::const_iterator itPrev = it;
|
||||||
|
itPrev--;
|
||||||
|
const float prevTime = itPrev->first*_pMotion->GetFpsInv();
|
||||||
|
const float nextTime = it->first*_pMotion->GetFpsInv();
|
||||||
|
const float delta = nextTime - prevTime;
|
||||||
|
const float offset = nextTime - time;
|
||||||
|
alpha = 1 - offset / delta;
|
||||||
|
prev = itPrev->second;
|
||||||
|
next = it->second;
|
||||||
|
}
|
||||||
|
else // But there are no less than:
|
||||||
|
{
|
||||||
|
const float nextTime = it->first*_pMotion->GetFpsInv();
|
||||||
|
const float delta = nextTime;
|
||||||
|
const float offset = time;
|
||||||
|
alpha = offset / delta;
|
||||||
|
prev = null;
|
||||||
|
next = it->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // There are no frames greater, but there are less than:
|
||||||
|
{
|
||||||
|
it--;
|
||||||
|
alpha = 0;
|
||||||
|
prev = it->second;
|
||||||
|
next = null;
|
||||||
|
}
|
||||||
|
return alpha;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum class Type : int
|
||||||
|
{
|
||||||
|
rotation,
|
||||||
|
position,
|
||||||
|
scale,
|
||||||
|
trigger
|
||||||
|
};
|
||||||
|
|
||||||
|
Bone(Motion* pMotion = nullptr);
|
||||||
|
~Bone();
|
||||||
|
|
||||||
|
Str GetName() const { return _C(_name); }
|
||||||
|
void Rename(CSZ name) { _name = name; }
|
||||||
|
|
||||||
|
int GetLastTriggerState() const { return _lastTriggerState; }
|
||||||
|
void SetLastTriggerState(int state) { _lastTriggerState = state; }
|
||||||
|
|
||||||
|
void DeleteAll();
|
||||||
|
|
||||||
|
void InsertKeyframeRotation(int frame, RcQuat q);
|
||||||
|
void InsertKeyframeRotation(int frame, RcVector3 euler);
|
||||||
|
void InsertKeyframePosition(int frame, RcVector3 pos);
|
||||||
|
void InsertKeyframeScale(int frame, RcVector3 scale);
|
||||||
|
void InsertKeyframeTrigger(int frame, int state);
|
||||||
|
|
||||||
|
void DeleteKeyframeRotation(int frame);
|
||||||
|
void DeleteKeyframePosition(int frame);
|
||||||
|
void DeleteKeyframeScale(int frame);
|
||||||
|
void DeleteKeyframeTrigger(int frame);
|
||||||
|
|
||||||
|
bool FindKeyframeRotation(int frame, RVector3 euler, RQuat q) const;
|
||||||
|
bool FindKeyframePosition(int frame, RVector3 pos) const;
|
||||||
|
bool FindKeyframeScale(int frame, RVector3 scale) const;
|
||||||
|
bool FindKeyframeTrigger(int frame, int& state) const;
|
||||||
|
|
||||||
|
void ComputeRotationAt(float time, RVector3 euler, RQuat q) const;
|
||||||
|
void ComputePositionAt(float time, RVector3 pos) const;
|
||||||
|
void ComputeScaleAt(float time, RVector3 scale) const;
|
||||||
|
void ComputeTriggerAt(float time, int& state) const;
|
||||||
|
void ComputeMatrixAt(float time, RTransform3 mat);
|
||||||
|
|
||||||
|
void MoveKeyframe(int direction, Type type, int frame);
|
||||||
|
|
||||||
|
int GetNumKeysRotation() const { return Utils::Cast32(_mapRot.size()); }
|
||||||
|
int GetNumKeysPosition() const { return Utils::Cast32(_mapPos.size()); }
|
||||||
|
int GetNumKeysScale() const { return Utils::Cast32(_mapScale.size()); }
|
||||||
|
int GetNumKeysTrigger() const { return Utils::Cast32(_mapTrigger.size()); }
|
||||||
|
|
||||||
|
VERUS_P(void Serialize(IO::RStream stream));
|
||||||
|
VERUS_P(void Deserialize(IO::RStream stream));
|
||||||
|
|
||||||
|
void DeleteRedundantKeyframes();
|
||||||
|
void DeleteOddKeyframes();
|
||||||
|
void InsertLoopKeyframes();
|
||||||
|
void Cut(int frame, bool before);
|
||||||
|
void Fix(bool speedLimit);
|
||||||
|
|
||||||
|
void ApplyScaleBias(RcVector3 scale, RcVector3 bias);
|
||||||
|
|
||||||
|
void Scatter(int srcFrom, int srcTo, int dMin, int dMax);
|
||||||
|
|
||||||
|
int GetLastKeyframe() const;
|
||||||
|
};
|
||||||
|
VERUS_TYPEDEFS(Bone);
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum { xanVersion = 0x0101, maxFps = 10000, maxNumBones = 10000, maxNumFrames = 32 * 1024 * 1024 };
|
||||||
|
|
||||||
|
typedef Map<String, Bone> TMapBones;
|
||||||
|
|
||||||
|
TMapBones _mapBones;
|
||||||
|
Motion* _pBlendMotion = nullptr;
|
||||||
|
int _numFrames = 50;
|
||||||
|
int _fps = 10;
|
||||||
|
float _fpsInv = 0.1f;
|
||||||
|
float _blendAlpha = 0;
|
||||||
|
float _playbackSpeed = 1;
|
||||||
|
float _playbackSpeedInv = 1;
|
||||||
|
bool _reversed = false;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Motion();
|
||||||
|
~Motion();
|
||||||
|
|
||||||
|
void Init();
|
||||||
|
void Done();
|
||||||
|
|
||||||
|
int GetFps() const { return _fps; }
|
||||||
|
float GetFpsInv() const { return _fpsInv; }
|
||||||
|
void SetFps(int fps) { _fps = fps; _fpsInv = 1.f / _fps; }
|
||||||
|
|
||||||
|
int GetNumFrames() const { return _numFrames; }
|
||||||
|
void SetNumFrames(int num) { _numFrames = num; }
|
||||||
|
|
||||||
|
int GetNumBones() const { return Utils::Cast32(_mapBones.size()); }
|
||||||
|
|
||||||
|
float GetDuration() const { return GetNativeDuration()*_playbackSpeedInv; }
|
||||||
|
float GetNativeDuration() const { return _numFrames * _fpsInv; }
|
||||||
|
|
||||||
|
PBone GetBoneByIndex(int index);
|
||||||
|
int GetBoneIndex(CSZ name) const;
|
||||||
|
|
||||||
|
PBone InsertBone(CSZ name);
|
||||||
|
void DeleteBone(CSZ name);
|
||||||
|
void DeleteAllBones();
|
||||||
|
PBone FindBone(CSZ name);
|
||||||
|
|
||||||
|
void Serialize(IO::RStream stream);
|
||||||
|
void Deserialize(IO::RStream stream);
|
||||||
|
|
||||||
|
void BakeMotionAt(float time, Motion& dest) const;
|
||||||
|
void BindBlendMotion(Motion* p, float alpha);
|
||||||
|
Motion* GetBlendMotion() const { return _pBlendMotion; }
|
||||||
|
float GetBlendAlpha() const { return _blendAlpha; }
|
||||||
|
|
||||||
|
void DeleteRedundantKeyframes();
|
||||||
|
void DeleteOddKeyframes();
|
||||||
|
void InsertLoopKeyframes();
|
||||||
|
void Cut(int frame, bool before = true);
|
||||||
|
void Fix(bool speedLimit);
|
||||||
|
|
||||||
|
// Triggers:
|
||||||
|
void ProcessTriggers(float time, PMotionDelegate p, int* pUserTriggerStates = nullptr);
|
||||||
|
void ResetTriggers(int* pUserTriggerStates = nullptr);
|
||||||
|
void SkipTriggers(float time, int* pUserTriggerStates = nullptr);
|
||||||
|
|
||||||
|
void ApplyScaleBias(CSZ name, RcVector3 scale, RcVector3 bias);
|
||||||
|
|
||||||
|
float GetPlaybackSpeed() const { return _playbackSpeed; }
|
||||||
|
float GetPlaybackSpeedInv() const { return _playbackSpeedInv; }
|
||||||
|
void SetPlaybackSpeed(float x);
|
||||||
|
void ComputePlaybackSpeed(float duration);
|
||||||
|
bool IsReversed() const { return _reversed; }
|
||||||
|
|
||||||
|
void Exec(CSZ code);
|
||||||
|
|
||||||
|
int GetLastKeyframe() const;
|
||||||
|
};
|
||||||
|
VERUS_TYPEDEFS(Motion);
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,153 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace verus
|
||||||
|
{
|
||||||
|
namespace Anim
|
||||||
|
{
|
||||||
|
//! Standard skeleton, which can be animated using motion object (Motion).
|
||||||
|
|
||||||
|
//! X3D format can support up to 256 bones, but the hardware has certain
|
||||||
|
//! limitations. With Shader Model 2.0 the shader can hold about 32 bone
|
||||||
|
//! matrices. Other bones must be remapped using Primary Bones concept.
|
||||||
|
//!
|
||||||
|
//! Alpha Motions (AlphaMotion) add the ability to mix multiple motions,
|
||||||
|
//! just like images are mixed with alpha channel. Alpha Motion affects
|
||||||
|
//! it's root bone and all descendants of that bone.
|
||||||
|
//!
|
||||||
|
//! A ragdoll can be created automatically or configured using XML .rig file.
|
||||||
|
//! Ragdoll's simulation can start from any motion frame and any simulated pose
|
||||||
|
//! can be baked back into motion object, allowing smooth transition to ragdoll
|
||||||
|
//! simulation and back to motion.
|
||||||
|
//!
|
||||||
|
class Skeleton : public Object
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
struct AlphaMotion
|
||||||
|
{
|
||||||
|
PMotion _pMotion = nullptr;
|
||||||
|
CSZ _rootBone = nullptr;
|
||||||
|
float _alpha = 0;
|
||||||
|
float _time = 0;
|
||||||
|
};
|
||||||
|
VERUS_TYPEDEFS(AlphaMotion);
|
||||||
|
|
||||||
|
struct Bone : public AllocatorAware
|
||||||
|
{
|
||||||
|
Transform3 _matToBoneSpace = Transform3::identity();
|
||||||
|
Transform3 _matFromBoneSpace = Transform3::identity();
|
||||||
|
Transform3 _matFinal = Transform3::identity();
|
||||||
|
Transform3 _matFinalInv = Transform3::identity();
|
||||||
|
Transform3 _matExternal = Transform3::identity();
|
||||||
|
Transform3 _matAdapt = Transform3::identity();
|
||||||
|
Transform3 _matToActorSpace = Transform3::identity();
|
||||||
|
Vector3 _rigRot = Vector3(0); //!< Rotation angles of ragdoll's rigid component.
|
||||||
|
Vector3 _cRot = Vector3(0); //!< Constraint's rotation angles.
|
||||||
|
Vector3 _cLimits = Vector3(0); //!< Constraint's limits.
|
||||||
|
Vector3 _boxSize = Vector3(0); //!< For a box shape.
|
||||||
|
String _name;
|
||||||
|
String _parentName;
|
||||||
|
btCollisionShape* _pShape = nullptr;
|
||||||
|
btRigidBody* _pBody = nullptr;
|
||||||
|
btTypedConstraint* _pConstraint = nullptr;
|
||||||
|
float _width = 0;
|
||||||
|
float _length = 0;
|
||||||
|
float _mass = 0;
|
||||||
|
int _shaderIndex = 0; //!< Index of a matrix in the vertex shader.
|
||||||
|
bool _ready = false;
|
||||||
|
bool _rigBone = true;
|
||||||
|
bool _hinge = false; //!< btHingeConstraint vs btConeTwistConstraint.
|
||||||
|
bool _noCollision = false;
|
||||||
|
};
|
||||||
|
VERUS_TYPEDEFS(Bone);
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef Map<String, Bone> TMapBones;
|
||||||
|
typedef Map<int, int> TMapPrimary;
|
||||||
|
|
||||||
|
Transform3 _matParents = Transform3::identity();
|
||||||
|
Transform3 _matRagdollToWorld = Transform3::identity();
|
||||||
|
Transform3 _matRagdollToWorldInv = Transform3::identity();
|
||||||
|
TMapBones _mapBones;
|
||||||
|
TMapPrimary _mapPrimary;
|
||||||
|
PBone _pCurrentBone = nullptr;
|
||||||
|
PMotion _pCurrentMotion = nullptr;
|
||||||
|
PAlphaMotion _pAlphaMotions = nullptr;
|
||||||
|
float _currentTime = 0;
|
||||||
|
float _mass = 0;
|
||||||
|
int _numPrimaryBones = 0;
|
||||||
|
int _numAlphaMotions = 0;
|
||||||
|
bool _ragdollMode = false;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Skeleton();
|
||||||
|
~Skeleton();
|
||||||
|
|
||||||
|
void operator=(const Skeleton& that);
|
||||||
|
|
||||||
|
void Init();
|
||||||
|
void Done();
|
||||||
|
|
||||||
|
void Draw(bool bindPose = true, int selected = -1);
|
||||||
|
|
||||||
|
static CSZ RootName() { return "$ROOT"; }
|
||||||
|
|
||||||
|
PBone InsertBone(RBone bone);
|
||||||
|
PBone FindBone(CSZ name);
|
||||||
|
PcBone FindBone(CSZ name) const;
|
||||||
|
//! Uses shader's array index to find a bone.
|
||||||
|
PBone FindBoneByIndex(int index);
|
||||||
|
|
||||||
|
//! Sets the current pose using motion object (Motion).
|
||||||
|
void ApplyMotion(RMotion motion, float time,
|
||||||
|
int numAlphaMotions = 0, PAlphaMotion pAlphaMotions = nullptr);
|
||||||
|
|
||||||
|
//! Fills the array of matrices that will be used by a shader.
|
||||||
|
void FillMatrixArray(mataff* p) const;
|
||||||
|
|
||||||
|
void ResetFinalPose();
|
||||||
|
|
||||||
|
VERUS_P(void ResetBones());
|
||||||
|
VERUS_P(void RecursiveBoneUpdate());
|
||||||
|
|
||||||
|
int GetNumBones() const { return _numPrimaryBones ? _numPrimaryBones : Utils::Cast32(_mapBones.size()); }
|
||||||
|
|
||||||
|
void VisitBones(std::function<Continue(RBone)> fn);
|
||||||
|
void VisitBones(std::function<Continue(RcBone)> fn) const;
|
||||||
|
|
||||||
|
//! Adds skeleton's bones to motion object (Motion).
|
||||||
|
void InsertBonesIntoMotion(RMotion motion) const;
|
||||||
|
//! Removes motion's bones, which are not skeleton's bones.
|
||||||
|
void DeleteOutsiders(RMotion motion) const;
|
||||||
|
|
||||||
|
void AdjustPrimaryBones(const Vector<String>& vPrimaryBones);
|
||||||
|
int RemapBoneIndex(int index) const;
|
||||||
|
|
||||||
|
bool IsParentOf(CSZ bone, CSZ parent) const;
|
||||||
|
|
||||||
|
void LoadRigInfo(CSZ url);
|
||||||
|
void LoadRigInfoFromPtr(const BYTE* p);
|
||||||
|
void BeginRagdoll(RcTransform3 matW, RcVector3 impulse = Vector3(0), CSZ bone = "Spine2");
|
||||||
|
void EndRagdoll();
|
||||||
|
bool IsRagdollMode() const { return _ragdollMode; }
|
||||||
|
RcTransform3 GetRagdollToWorldMatrix() { return _matRagdollToWorld; }
|
||||||
|
|
||||||
|
//! Saves the current pose into motion object (Motion) at some frame.
|
||||||
|
void BakeMotion(RMotion motion, int frame = 0, bool kinect = false);
|
||||||
|
void AdaptBindPoseOf(const Skeleton& that);
|
||||||
|
void SimpleIK(CSZ boneDriven, CSZ boneDriver, RcVector3 dirDriverSpace, RcVector3 dirDesiredMeshSpace, float limitDot, float alpha);
|
||||||
|
|
||||||
|
void ProcessKinectData(const BYTE* p, RMotion motion, int frame = 0);
|
||||||
|
void ProcessKinectJoint(const BYTE* p, CSZ name, RcVector3 skeletonPos);
|
||||||
|
void LoadKinectBindPose(CSZ xml);
|
||||||
|
static bool IsKinectBone(CSZ name);
|
||||||
|
static bool IsKinectLeafBone(CSZ name);
|
||||||
|
|
||||||
|
void FixateFeet(RMotion motion);
|
||||||
|
|
||||||
|
//! Tries to compute the highest speed at which a bone would move with this motion applied.
|
||||||
|
//! Can be used to sync animation and movement to fix the sliding feet problem.
|
||||||
|
Vector3 GetHighestSpeed(RMotion motion, CSZ name, RcVector3 scale = Vector3(1, 0, 1), bool positive = false);
|
||||||
|
};
|
||||||
|
VERUS_TYPEDEFS(Skeleton);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
#include "verus.h"
|
||||||
|
|
||||||
|
namespace verus
|
||||||
|
{
|
||||||
|
void Make_App()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void Free_App()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
using namespace verus;
|
||||||
|
|
||||||
|
void App::RunEventLoop()
|
||||||
|
{
|
||||||
|
SDL_Event event = {};
|
||||||
|
bool done = false;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
while (SDL_PollEvent(&event))
|
||||||
|
{
|
||||||
|
switch (event.type)
|
||||||
|
{
|
||||||
|
case SDL_QUIT:
|
||||||
|
{
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SDL_WINDOWEVENT:
|
||||||
|
{
|
||||||
|
switch (event.window.event)
|
||||||
|
{
|
||||||
|
case SDL_WINDOWEVENT_MINIMIZED:
|
||||||
|
break;
|
||||||
|
case SDL_WINDOWEVENT_RESTORED:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SDL_USEREVENT:
|
||||||
|
{
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (done)
|
||||||
|
break;
|
||||||
|
} while (!done);
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Settings.h"
|
||||||
|
#include "Window.h"
|
||||||
|
|
||||||
|
namespace verus
|
||||||
|
{
|
||||||
|
void Make_App();
|
||||||
|
void Free_App();
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace verus
|
||||||
|
{
|
||||||
|
namespace App
|
||||||
|
{
|
||||||
|
void RunEventLoop();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,272 @@
|
||||||
|
#include "verus.h"
|
||||||
|
|
||||||
|
using namespace verus;
|
||||||
|
using namespace verus::App;
|
||||||
|
|
||||||
|
Settings::Settings()
|
||||||
|
{
|
||||||
|
VERUS_ZERO_MEM(_commandLine);
|
||||||
|
#ifdef _WIN32
|
||||||
|
if (0x419 == GetUserDefaultUILanguage())
|
||||||
|
_uiLang = "RU";
|
||||||
|
#endif
|
||||||
|
SetQuality(Quality::medium);
|
||||||
|
}
|
||||||
|
|
||||||
|
Settings::~Settings()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Settings::LoadValidateSave()
|
||||||
|
{
|
||||||
|
Load();
|
||||||
|
Validate();
|
||||||
|
Save();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Settings::Load()
|
||||||
|
{
|
||||||
|
Json::Load();
|
||||||
|
|
||||||
|
_quality = static_cast<Quality>(GetI("quality", +_quality));
|
||||||
|
_direct3D = GetI("direct3D", _direct3D);
|
||||||
|
_gpuAnisotropyLevel = GetI("gpuAnisotropyLevel", _gpuAnisotropyLevel);
|
||||||
|
_gpuAntialiasingLevel = GetI("gpuAntialiasingLevel", _gpuAntialiasingLevel);
|
||||||
|
_gpuDepthTexture = GetI("gpuDepthTexture", _gpuDepthTexture);
|
||||||
|
_gpuForcedProfile = GetS("gpuForcedProfile", _C(_gpuForcedProfile));
|
||||||
|
_gpuOffscreenRender = GetB("gpuOffscreenRender", _gpuOffscreenRender);
|
||||||
|
_gpuParallaxMapping = GetB("gpuParallaxMapping", _gpuParallaxMapping);
|
||||||
|
_gpuPerPixelLighting = GetB("gpuPerPixelLighting", _gpuPerPixelLighting);
|
||||||
|
_gpuTextureLodLevel = GetI("gpuTextureLodLevel", _gpuTextureLodLevel);
|
||||||
|
_gpuTrilinearFilter = GetB("gpuTrilinearFilter", _gpuTrilinearFilter);
|
||||||
|
_inputMouseSensitivity = GetF("inputMouseSensitivity", _inputMouseSensitivity);
|
||||||
|
_postProcessBloom = GetB("postProcessBloom", _postProcessBloom);
|
||||||
|
_postProcessCinema = GetB("postProcessCinema", _postProcessCinema);
|
||||||
|
_postProcessMotionBlur = GetB("postProcessMotionBlur", _postProcessMotionBlur);
|
||||||
|
_postProcessSSAO = GetB("postProcessSSAO", _postProcessSSAO);
|
||||||
|
_sceneGrassDensity = GetI("sceneGrassDensity", _sceneGrassDensity);
|
||||||
|
_sceneShadowQuality = static_cast<ShadowQuality>(GetI("sceneShadowQuality", +_sceneShadowQuality));
|
||||||
|
_sceneWaterQuality = static_cast<WaterQuality>(GetI("sceneWaterQuality", +_sceneWaterQuality));
|
||||||
|
_screenFOV = GetF("screenFOV", _screenFOV);
|
||||||
|
_screenSizeHeight = GetI("screenSizeHeight", _screenSizeHeight);
|
||||||
|
_screenSizeWidth = GetI("screenSizeWidth", _screenSizeWidth);
|
||||||
|
_screenVSync = GetB("screenVSync", _screenVSync);
|
||||||
|
_screenWindowed = GetB("screenWindowed", _screenWindowed);
|
||||||
|
_uiLang = GetS("uiLang", _C(_uiLang));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Settings::Save()
|
||||||
|
{
|
||||||
|
Set("quality", +_quality);
|
||||||
|
Set("direct3D", _direct3D);
|
||||||
|
Set("gpuAnisotropyLevel", _gpuAnisotropyLevel);
|
||||||
|
Set("gpuAntialiasingLevel", _gpuAntialiasingLevel);
|
||||||
|
Set("gpuDepthTexture", _gpuDepthTexture);
|
||||||
|
Set("gpuForcedProfile", _C(_gpuForcedProfile));
|
||||||
|
Set("gpuOffscreenRender", _gpuOffscreenRender);
|
||||||
|
Set("gpuParallaxMapping", _gpuParallaxMapping);
|
||||||
|
Set("gpuPerPixelLighting", _gpuPerPixelLighting);
|
||||||
|
Set("gpuTextureLodLevel", _gpuTextureLodLevel);
|
||||||
|
Set("gpuTrilinearFilter", _gpuTrilinearFilter);
|
||||||
|
Set("inputMouseSensitivity", _inputMouseSensitivity);
|
||||||
|
Set("postProcessBloom", _postProcessBloom);
|
||||||
|
Set("postProcessCinema", _postProcessCinema);
|
||||||
|
Set("postProcessMotionBlur", _postProcessMotionBlur);
|
||||||
|
Set("postProcessSSAO", _postProcessSSAO);
|
||||||
|
Set("sceneGrassDensity", _sceneGrassDensity);
|
||||||
|
Set("sceneShadowQuality", +_sceneShadowQuality);
|
||||||
|
Set("sceneWaterQuality", +_sceneWaterQuality);
|
||||||
|
Set("screenFOV", _screenFOV);
|
||||||
|
Set("screenSizeHeight", _screenSizeHeight);
|
||||||
|
Set("screenSizeWidth", _screenSizeWidth);
|
||||||
|
Set("screenVSync", _screenVSync);
|
||||||
|
Set("screenWindowed", _screenWindowed);
|
||||||
|
Set("uiLang", _C(_uiLang));
|
||||||
|
|
||||||
|
Json::Save();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Settings::Validate()
|
||||||
|
{
|
||||||
|
_quality = Math::Clamp(_quality, Quality::low, Quality::ultra);
|
||||||
|
_gpuAnisotropyLevel = Math::Clamp(_gpuAnisotropyLevel, 0, 16);
|
||||||
|
_gpuAntialiasingLevel = Math::Clamp(_gpuAntialiasingLevel, 0, 16);
|
||||||
|
_gpuTextureLodLevel = Math::Clamp(_gpuTextureLodLevel, 0, 4);
|
||||||
|
_screenFOV = Math::Clamp<float>(_screenFOV, 60, 90);
|
||||||
|
_screenSizeHeight = Math::Clamp(_screenSizeHeight, 270, 0x2000);
|
||||||
|
_screenSizeWidth = Math::Clamp(_screenSizeWidth, 480, 0x2000);
|
||||||
|
|
||||||
|
if (_gpuForcedProfile == "sm_2_0")
|
||||||
|
{
|
||||||
|
_postProcessMotionBlur = false;
|
||||||
|
_postProcessSSAO = false;
|
||||||
|
_sceneShadowQuality = Math::Min(_sceneShadowQuality, ShadowQuality::filtered);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_gpuPerPixelLighting)
|
||||||
|
{
|
||||||
|
_gpuParallaxMapping = false;
|
||||||
|
_sceneWaterQuality = Math::Clamp(_sceneWaterQuality, WaterQuality::solidColor, WaterQuality::distortedReflection);
|
||||||
|
}
|
||||||
|
_postProcessBloom = _postProcessBloom && _gpuOffscreenRender;
|
||||||
|
_sceneGrassDensity = Math::Clamp(_sceneGrassDensity, 15, 1500);
|
||||||
|
_sceneShadowQuality = Math::Clamp(_sceneShadowQuality, ShadowQuality::none, ShadowQuality::cascaded);
|
||||||
|
_sceneWaterQuality = Math::Clamp(_sceneWaterQuality, WaterQuality::solidColor, WaterQuality::trueWavesRefraction);
|
||||||
|
|
||||||
|
if (_sceneShadowQuality >= ShadowQuality::cascaded)
|
||||||
|
_gpuDepthTexture = 1;
|
||||||
|
|
||||||
|
if (_uiLang != "RU" && _uiLang != "EN")
|
||||||
|
_uiLang = "EN";
|
||||||
|
}
|
||||||
|
|
||||||
|
void Settings::ParseCommandLineArgs(int argc, wchar_t* argv[])
|
||||||
|
{
|
||||||
|
Vector<String> v;
|
||||||
|
VERUS_FOR(i, argc)
|
||||||
|
v.push_back(Str::WideToUtf8(argv[i]));
|
||||||
|
|
||||||
|
Vector<SZ> vArgv;
|
||||||
|
VERUS_FOR(i, argc)
|
||||||
|
vArgv.push_back(const_cast<SZ>(_C(v[i])));
|
||||||
|
|
||||||
|
ParseCommandLineArgs(argc, vArgv.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Settings::ParseCommandLineArgs(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
auto IsArg = [&argv](int i, CSZ arg)
|
||||||
|
{
|
||||||
|
return !strcmp(argv[i], arg);
|
||||||
|
};
|
||||||
|
|
||||||
|
VERUS_FOR(i, argc)
|
||||||
|
{
|
||||||
|
_commandLine.normalMapOnlyLS = _commandLine.normalMapOnlyLS || IsArg(i, "--normal-map-only-ls");
|
||||||
|
_commandLine.physicsDebug = _commandLine.physicsDebug || IsArg(i, "--physics-debug");
|
||||||
|
_commandLine.physicsDebugFull = _commandLine.physicsDebugFull || IsArg(i, "--physics-debug-full");
|
||||||
|
_commandLine.profiler = _commandLine.profiler || IsArg(i, "--profiler");
|
||||||
|
_commandLine.testTexToPix = _commandLine.testTexToPix || IsArg(i, "--test-tex-to-pix");
|
||||||
|
}
|
||||||
|
|
||||||
|
VERUS_QREF_UTILS;
|
||||||
|
//utils.SetupPathsEx(); // Only now we can finally do this.
|
||||||
|
|
||||||
|
SetFilename("Settings.json");
|
||||||
|
const String pathName = _C(GetFilename());
|
||||||
|
|
||||||
|
VERUS_FOR(i, argc)
|
||||||
|
{
|
||||||
|
if (IsArg(i, "--q-low"))
|
||||||
|
{
|
||||||
|
const bool ret = IO::FileSystem::Delete(_C(pathName));
|
||||||
|
SetQuality(Quality::low);
|
||||||
|
}
|
||||||
|
if (IsArg(i, "--q-medium"))
|
||||||
|
{
|
||||||
|
const bool ret = IO::FileSystem::Delete(_C(pathName));
|
||||||
|
SetQuality(Quality::medium);
|
||||||
|
}
|
||||||
|
if (IsArg(i, "--q-high"))
|
||||||
|
{
|
||||||
|
const bool ret = IO::FileSystem::Delete(_C(pathName));
|
||||||
|
SetQuality(Quality::high);
|
||||||
|
}
|
||||||
|
if (IsArg(i, "--q-ultra"))
|
||||||
|
{
|
||||||
|
const bool ret = IO::FileSystem::Delete(_C(pathName));
|
||||||
|
SetQuality(Quality::ultra);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Settings::SetQuality(Quality q)
|
||||||
|
{
|
||||||
|
_quality = q;
|
||||||
|
_direct3D = 9;
|
||||||
|
_gpuAnisotropyLevel = 0;
|
||||||
|
_gpuAntialiasingLevel = 0;
|
||||||
|
_gpuDepthTexture = 0;
|
||||||
|
_gpuForcedProfile = "";
|
||||||
|
_gpuOffscreenRender = true;
|
||||||
|
_gpuParallaxMapping = false;
|
||||||
|
_gpuPerPixelLighting = true;
|
||||||
|
_gpuTextureLodLevel = 0;
|
||||||
|
_gpuTrilinearFilter = false;
|
||||||
|
_postProcessBloom = false;
|
||||||
|
_postProcessCinema = false;
|
||||||
|
_postProcessMotionBlur = false;
|
||||||
|
_postProcessSSAO = false;
|
||||||
|
_sceneGrassDensity = 1000;
|
||||||
|
_sceneShadowQuality = ShadowQuality::sharp;
|
||||||
|
_sceneWaterQuality = WaterQuality::distortedReflection;
|
||||||
|
_screenVSync = false;
|
||||||
|
_screenWindowed = true;
|
||||||
|
|
||||||
|
switch (q)
|
||||||
|
{
|
||||||
|
case Quality::low:
|
||||||
|
_gpuDepthTexture = -1;
|
||||||
|
_gpuForcedProfile = "sm_3_0";
|
||||||
|
_sceneGrassDensity = 500;
|
||||||
|
_sceneShadowQuality = ShadowQuality::none;
|
||||||
|
_sceneWaterQuality = WaterQuality::solidColor;
|
||||||
|
_screenSizeHeight = 600;
|
||||||
|
_screenSizeWidth = 800;
|
||||||
|
break;
|
||||||
|
case Quality::medium:
|
||||||
|
_gpuAnisotropyLevel = 4;
|
||||||
|
_gpuForcedProfile = "sm_3_0";
|
||||||
|
_screenSizeHeight = 768;
|
||||||
|
_screenSizeWidth = 1024;
|
||||||
|
break;
|
||||||
|
case Quality::high:
|
||||||
|
_direct3D = 11;
|
||||||
|
_gpuAnisotropyLevel = 8;
|
||||||
|
_gpuTrilinearFilter = true;
|
||||||
|
_postProcessBloom = true;
|
||||||
|
_postProcessCinema = true;
|
||||||
|
_postProcessSSAO = true;
|
||||||
|
_sceneGrassDensity = 1500;
|
||||||
|
_sceneShadowQuality = ShadowQuality::filtered;
|
||||||
|
_sceneWaterQuality = WaterQuality::trueWavesReflection;
|
||||||
|
_screenSizeHeight = 720;
|
||||||
|
_screenSizeWidth = 1280;
|
||||||
|
break;
|
||||||
|
case Quality::ultra:
|
||||||
|
_direct3D = 11;
|
||||||
|
_gpuAnisotropyLevel = 16;
|
||||||
|
_gpuDepthTexture = 1;
|
||||||
|
_gpuTrilinearFilter = true;
|
||||||
|
_postProcessBloom = true;
|
||||||
|
_postProcessCinema = true;
|
||||||
|
_postProcessMotionBlur = true;
|
||||||
|
_postProcessSSAO = true;
|
||||||
|
_sceneGrassDensity = 1500;
|
||||||
|
_sceneShadowQuality = ShadowQuality::cascaded;
|
||||||
|
_sceneWaterQuality = WaterQuality::trueWavesRefraction;
|
||||||
|
_screenSizeHeight = 1080;
|
||||||
|
_screenSizeWidth = 1980;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
# ifndef _DEBUG
|
||||||
|
_screenSizeHeight = GetSystemMetrics(SM_CYSCREEN);
|
||||||
|
_screenSizeWidth = GetSystemMetrics(SM_CXSCREEN);
|
||||||
|
_screenWindowed = false;
|
||||||
|
# endif
|
||||||
|
#else // Linux?
|
||||||
|
_direct3D = 0;
|
||||||
|
_gpuForcedProfile = "arb1";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void Settings::MatchScreen()
|
||||||
|
{
|
||||||
|
SDL_DisplayMode dm;
|
||||||
|
if (SDL_GetCurrentDisplayMode(0, &dm) < 0)
|
||||||
|
throw VERUS_RUNTIME_ERROR << "SDL_GetCurrentDisplayMode(), " << SDL_GetError();
|
||||||
|
_screenSizeWidth = dm.w;
|
||||||
|
_screenSizeHeight = dm.h;
|
||||||
|
}
|
|
@ -0,0 +1,86 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace verus
|
||||||
|
{
|
||||||
|
namespace App
|
||||||
|
{
|
||||||
|
class Settings : public Singleton<Settings>, public IO::Json
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum class Quality : int
|
||||||
|
{
|
||||||
|
low,
|
||||||
|
medium,
|
||||||
|
high,
|
||||||
|
ultra
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class ShadowQuality : int
|
||||||
|
{
|
||||||
|
none,
|
||||||
|
sharp,
|
||||||
|
filtered,
|
||||||
|
cascaded
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class WaterQuality : int
|
||||||
|
{
|
||||||
|
solidColor,
|
||||||
|
simpleReflection,
|
||||||
|
distortedReflection,
|
||||||
|
trueWavesReflection,
|
||||||
|
trueWavesRefraction
|
||||||
|
};
|
||||||
|
|
||||||
|
Quality _quality = Quality::medium;
|
||||||
|
int _direct3D = 9;
|
||||||
|
int _gpuAnisotropyLevel = 4;
|
||||||
|
int _gpuAntialiasingLevel = 0;
|
||||||
|
int _gpuDepthTexture = 0;
|
||||||
|
String _gpuForcedProfile = "sm_3_0";
|
||||||
|
bool _gpuOffscreenRender = false;
|
||||||
|
bool _gpuParallaxMapping = false;
|
||||||
|
bool _gpuPerPixelLighting = true;
|
||||||
|
int _gpuTextureLodLevel = 0;
|
||||||
|
bool _gpuTrilinearFilter = false;
|
||||||
|
float _inputMouseSensitivity = 1;
|
||||||
|
bool _postProcessBloom = false;
|
||||||
|
bool _postProcessCinema = false;
|
||||||
|
bool _postProcessMotionBlur = false;
|
||||||
|
bool _postProcessSSAO = false;
|
||||||
|
int _sceneGrassDensity = 1000;
|
||||||
|
ShadowQuality _sceneShadowQuality = ShadowQuality::sharp;
|
||||||
|
WaterQuality _sceneWaterQuality = WaterQuality::solidColor;
|
||||||
|
float _screenFOV = 70;
|
||||||
|
int _screenSizeHeight = 720;
|
||||||
|
int _screenSizeWidth = 1280;
|
||||||
|
bool _screenVSync = false;
|
||||||
|
bool _screenWindowed = true;
|
||||||
|
String _uiLang = "EN";
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
bool normalMapOnlyLS;
|
||||||
|
bool physicsDebug;
|
||||||
|
bool physicsDebugFull;
|
||||||
|
bool profiler;
|
||||||
|
bool testTexToPix;
|
||||||
|
} _commandLine;
|
||||||
|
|
||||||
|
Settings();
|
||||||
|
~Settings();
|
||||||
|
|
||||||
|
void LoadValidateSave();
|
||||||
|
void Load();
|
||||||
|
void Save();
|
||||||
|
void Validate();
|
||||||
|
|
||||||
|
void ParseCommandLineArgs(int argc, wchar_t* argv[]);
|
||||||
|
void ParseCommandLineArgs(int argc, char* argv[]);
|
||||||
|
|
||||||
|
void SetQuality(Quality q);
|
||||||
|
|
||||||
|
void MatchScreen();
|
||||||
|
};
|
||||||
|
VERUS_TYPEDEFS(Settings);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
#include "verus.h"
|
||||||
|
|
||||||
|
using namespace verus;
|
||||||
|
using namespace verus::App;
|
||||||
|
|
||||||
|
// Window::Desc:
|
||||||
|
|
||||||
|
void Window::Desc::ApplySettings()
|
||||||
|
{
|
||||||
|
VERUS_QREF_SETTINGS;
|
||||||
|
_width = settings._screenSizeWidth;
|
||||||
|
_height = settings._screenSizeHeight;
|
||||||
|
_fullscreen = !settings._screenWindowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Window:
|
||||||
|
|
||||||
|
Window::Window()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Window::~Window()
|
||||||
|
{
|
||||||
|
Done();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Window::Init(RcDesc descConst)
|
||||||
|
{
|
||||||
|
VERUS_INIT();
|
||||||
|
|
||||||
|
Desc desc = descConst;
|
||||||
|
if (desc._useSettings)
|
||||||
|
desc.ApplySettings();
|
||||||
|
|
||||||
|
Uint32 flags = 0;
|
||||||
|
if (desc._fullscreen)
|
||||||
|
flags |= SDL_WINDOW_FULLSCREEN;
|
||||||
|
|
||||||
|
_pWnd = SDL_CreateWindow(
|
||||||
|
desc._title ? desc._title : "",
|
||||||
|
SDL_WINDOWPOS_CENTERED,
|
||||||
|
SDL_WINDOWPOS_CENTERED,
|
||||||
|
desc._width,
|
||||||
|
desc._height,
|
||||||
|
flags);
|
||||||
|
if (!_pWnd)
|
||||||
|
throw VERUS_RECOVERABLE << "SDL_CreateWindow(), " << SDL_GetError();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Window::Done()
|
||||||
|
{
|
||||||
|
if (_pWnd)
|
||||||
|
{
|
||||||
|
SDL_DestroyWindow(_pWnd);
|
||||||
|
_pWnd = nullptr;
|
||||||
|
}
|
||||||
|
VERUS_DONE(Window);
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace verus
|
||||||
|
{
|
||||||
|
namespace App
|
||||||
|
{
|
||||||
|
class Window : public Object
|
||||||
|
{
|
||||||
|
SDL_Window* _pWnd = nullptr;
|
||||||
|
|
||||||
|
public:
|
||||||
|
struct Desc
|
||||||
|
{
|
||||||
|
CSZ _title = nullptr;
|
||||||
|
int _width = 0;
|
||||||
|
int _height = 0;
|
||||||
|
bool _fullscreen = false;
|
||||||
|
bool _useSettings = true;
|
||||||
|
|
||||||
|
void ApplySettings();
|
||||||
|
};
|
||||||
|
VERUS_TYPEDEFS(Desc);
|
||||||
|
|
||||||
|
Window();
|
||||||
|
~Window();
|
||||||
|
|
||||||
|
void Init(RcDesc desc = Desc());
|
||||||
|
void Done();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
#include "verus.h"
|
||||||
|
|
||||||
|
namespace verus
|
||||||
|
{
|
||||||
|
void Make_Audio()
|
||||||
|
{
|
||||||
|
Audio::AudioSystem::Make();
|
||||||
|
}
|
||||||
|
void Free_Audio()
|
||||||
|
{
|
||||||
|
Audio::AudioSystem::Free();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "OggCallbacks.h"
|
||||||
|
#include "Source.h"
|
||||||
|
#include "Sound.h"
|
||||||
|
#include "StreamPlayer.h"
|
||||||
|
#include "AudioSystem.h"
|
||||||
|
|
||||||
|
namespace verus
|
||||||
|
{
|
||||||
|
void Make_Audio();
|
||||||
|
void Free_Audio();
|
||||||
|
}
|
|
@ -0,0 +1,142 @@
|
||||||
|
#include "verus.h"
|
||||||
|
|
||||||
|
using namespace verus;
|
||||||
|
using namespace verus::Audio;
|
||||||
|
|
||||||
|
AudioSystem::AudioSystem()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
AudioSystem::~AudioSystem()
|
||||||
|
{
|
||||||
|
Done();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioSystem::Init()
|
||||||
|
{
|
||||||
|
VERUS_INIT();
|
||||||
|
|
||||||
|
const ALCchar* deviceName = nullptr;
|
||||||
|
#ifdef _WIN32
|
||||||
|
deviceName = "DirectSound3D";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!(_pDevice = alcOpenDevice(deviceName)))
|
||||||
|
throw VERUS_RUNTIME_ERROR << "alcOpenDevice()";
|
||||||
|
|
||||||
|
if (!(_pContext = alcCreateContext(_pDevice, nullptr)))
|
||||||
|
throw VERUS_RUNTIME_ERROR << "alcCreateContext(), " << alcGetError(_pDevice);
|
||||||
|
|
||||||
|
if (!alcMakeContextCurrent(_pContext))
|
||||||
|
throw VERUS_RUNTIME_ERROR << "alcMakeContextCurrent(), " << alcGetError(_pDevice);
|
||||||
|
|
||||||
|
int vMajor = 0, vMinor = 0;
|
||||||
|
alcGetIntegerv(_pDevice, ALC_MAJOR_VERSION, sizeof(vMajor), &vMajor);
|
||||||
|
alcGetIntegerv(_pDevice, ALC_MINOR_VERSION, sizeof(vMinor), &vMinor);
|
||||||
|
StringStream ss;
|
||||||
|
ss << vMajor << "." << vMinor;
|
||||||
|
_version = ss.str();
|
||||||
|
|
||||||
|
_deviceSpecifier = alcGetString(_pDevice, ALC_DEVICE_SPECIFIER);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioSystem::Done()
|
||||||
|
{
|
||||||
|
DeleteAllStreams();
|
||||||
|
DeleteAllSounds();
|
||||||
|
|
||||||
|
alcMakeContextCurrent(0);
|
||||||
|
if (_pContext)
|
||||||
|
{
|
||||||
|
alcDestroyContext(_pContext);
|
||||||
|
_pContext = nullptr;
|
||||||
|
}
|
||||||
|
if (_pDevice)
|
||||||
|
{
|
||||||
|
alcCloseDevice(_pDevice);
|
||||||
|
_pDevice = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
VERUS_DONE(AudioSystem);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioSystem::Update()
|
||||||
|
{
|
||||||
|
if (!IsInitialized())
|
||||||
|
return;
|
||||||
|
VERUS_UPDATE_ONCE_CHECK;
|
||||||
|
|
||||||
|
VERUS_QREF_TIMER;
|
||||||
|
|
||||||
|
VERUS_FOR(i, VERUS_ARRAY_LENGTH(_streamPlayers))
|
||||||
|
_streamPlayers[i].Update();
|
||||||
|
|
||||||
|
// Update every frame:
|
||||||
|
for (auto& x : TStoreSounds::_map)
|
||||||
|
x.second.Update();
|
||||||
|
|
||||||
|
// Update ~15 times per second:
|
||||||
|
if (timer.IsEventEvery(67))
|
||||||
|
{
|
||||||
|
for (auto& x : TStoreSounds::_map)
|
||||||
|
x.second.UpdateHRTF();
|
||||||
|
|
||||||
|
if (VMath::lengthSqr(_listenerDirection) > 0.1f &&
|
||||||
|
VMath::lengthSqr(_listenerUp) > 0.1f)
|
||||||
|
{
|
||||||
|
const float orien[6] =
|
||||||
|
{
|
||||||
|
_listenerDirection.getX(),
|
||||||
|
_listenerDirection.getY(),
|
||||||
|
_listenerDirection.getZ(),
|
||||||
|
_listenerUp.getX(),
|
||||||
|
_listenerUp.getY(),
|
||||||
|
_listenerUp.getZ()
|
||||||
|
};
|
||||||
|
alListenerfv(AL_POSITION, _listenerPosition.ToPointer());
|
||||||
|
alListenerfv(AL_VELOCITY, _listenerVelocity.ToPointer());
|
||||||
|
alListenerfv(AL_ORIENTATION, orien); // Zero-length vectors can crash OpenAL!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioSystem::DeleteAllStreams()
|
||||||
|
{
|
||||||
|
VERUS_FOR(i, VERUS_ARRAY_LENGTH(_streamPlayers))
|
||||||
|
_streamPlayers[i].Done();
|
||||||
|
}
|
||||||
|
|
||||||
|
PSound AudioSystem::InsertSound(CSZ url)
|
||||||
|
{
|
||||||
|
return TStoreSounds::Insert(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
PSound AudioSystem::FindSound(CSZ url)
|
||||||
|
{
|
||||||
|
return TStoreSounds::Find(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioSystem::DeleteSound(CSZ url)
|
||||||
|
{
|
||||||
|
TStoreSounds::Delete(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioSystem::DeleteAllSounds()
|
||||||
|
{
|
||||||
|
TStoreSounds::DeleteAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioSystem::UpdateListener(RcPoint3 pos, RcVector3 dir, RcVector3 vel, RcVector3 up)
|
||||||
|
{
|
||||||
|
_listenerPosition = pos;
|
||||||
|
_listenerDirection = dir;
|
||||||
|
_listenerVelocity = vel;
|
||||||
|
_listenerUp = up;
|
||||||
|
}
|
||||||
|
|
||||||
|
float AudioSystem::ComputeTravelDelay(RcPoint3 pos) const
|
||||||
|
{
|
||||||
|
const float speed = alGetFloat(AL_SPEED_OF_SOUND);
|
||||||
|
const float dist = VMath::dist(pos, _listenerPosition);
|
||||||
|
return Math::Clamp<float>(dist / speed, 0, 3);
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace verus
|
||||||
|
{
|
||||||
|
namespace Audio
|
||||||
|
{
|
||||||
|
typedef StoreUnique<String, Sound> TStoreSounds;
|
||||||
|
class AudioSystem : public Singleton<AudioSystem>, public Object, private TStoreSounds
|
||||||
|
{
|
||||||
|
Point3 _listenerPosition = Point3(0);
|
||||||
|
Vector3 _listenerDirection = Vector3(0, 0, 1);
|
||||||
|
Vector3 _listenerVelocity = Vector3(0);
|
||||||
|
Vector3 _listenerUp = Vector3(0, 1, 0);
|
||||||
|
ALCdevice* _pDevice = nullptr;
|
||||||
|
ALCcontext* _pContext = nullptr;
|
||||||
|
String _version;
|
||||||
|
String _deviceSpecifier;
|
||||||
|
StreamPlayer _streamPlayers[4];
|
||||||
|
|
||||||
|
public:
|
||||||
|
AudioSystem();
|
||||||
|
~AudioSystem();
|
||||||
|
|
||||||
|
void Init();
|
||||||
|
void Done();
|
||||||
|
|
||||||
|
void Update();
|
||||||
|
|
||||||
|
RStreamPlayer GetStreamPlayer(int index) { return _streamPlayers[index]; }
|
||||||
|
void DeleteAllStreams();
|
||||||
|
|
||||||
|
PSound InsertSound(CSZ url);
|
||||||
|
PSound FindSound(CSZ url);
|
||||||
|
void DeleteSound(CSZ url);
|
||||||
|
void DeleteAllSounds();
|
||||||
|
|
||||||
|
void UpdateListener(RcPoint3 pos, RcVector3 dir, RcVector3 vel, RcVector3 up);
|
||||||
|
float ComputeTravelDelay(RcPoint3 pos) const;
|
||||||
|
|
||||||
|
static CSZ GetSingletonFailMessage() { return "Make_Audio(); // FAIL.\r\n"; }
|
||||||
|
};
|
||||||
|
VERUS_TYPEDEFS(AudioSystem);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
#include "verus.h"
|
||||||
|
|
||||||
|
namespace verus
|
||||||
|
{
|
||||||
|
namespace Audio
|
||||||
|
{
|
||||||
|
size_t read_func(void* ptr, size_t size, size_t nmemb, void* datasource)
|
||||||
|
{
|
||||||
|
POggDataSource pDS = static_cast<POggDataSource>(datasource);
|
||||||
|
INT64 readLen = size * nmemb;
|
||||||
|
const INT64 maxLen = pDS->_size - pDS->_cursor;
|
||||||
|
if (readLen > maxLen)
|
||||||
|
readLen = maxLen;
|
||||||
|
memcpy(ptr, pDS->_p + pDS->_cursor, size_t(readLen));
|
||||||
|
pDS->_cursor += readLen;
|
||||||
|
return size_t(readLen);
|
||||||
|
}
|
||||||
|
|
||||||
|
int seek_func(void* datasource, ogg_int64_t offset, int whence)
|
||||||
|
{
|
||||||
|
POggDataSource pDS = static_cast<POggDataSource>(datasource);
|
||||||
|
switch (whence)
|
||||||
|
{
|
||||||
|
case SEEK_SET: pDS->_cursor = offset; return 0;
|
||||||
|
case SEEK_CUR: pDS->_cursor += offset; return 0;
|
||||||
|
case SEEK_END: pDS->_cursor = pDS->_size - offset; return 0;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int close_func(void* datasource)
|
||||||
|
{
|
||||||
|
POggDataSource pDS = static_cast<POggDataSource>(datasource);
|
||||||
|
pDS->_cursor = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
long tell_func(void* datasource)
|
||||||
|
{
|
||||||
|
POggDataSource pDS = static_cast<POggDataSource>(datasource);
|
||||||
|
return long(pDS->_cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
const ov_callbacks g_oggCallbacks = { read_func, seek_func, close_func, tell_func };
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace verus
|
||||||
|
{
|
||||||
|
namespace Audio
|
||||||
|
{
|
||||||
|
struct OggDataSource
|
||||||
|
{
|
||||||
|
const BYTE* _p = nullptr;
|
||||||
|
INT64 _size = 0;
|
||||||
|
INT64 _cursor = 0;
|
||||||
|
};
|
||||||
|
VERUS_TYPEDEFS(OggDataSource);
|
||||||
|
|
||||||
|
size_t read_func(void*, size_t, size_t, void*);
|
||||||
|
int seek_func(void*, ogg_int64_t, int);
|
||||||
|
int close_func(void*);
|
||||||
|
long tell_func(void*);
|
||||||
|
|
||||||
|
extern const ov_callbacks g_oggCallbacks;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,183 @@
|
||||||
|
#include "verus.h"
|
||||||
|
|
||||||
|
using namespace verus;
|
||||||
|
using namespace verus::Audio;
|
||||||
|
|
||||||
|
// Sound:
|
||||||
|
|
||||||
|
Sound::Sound()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Sound::~Sound()
|
||||||
|
{
|
||||||
|
Done();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sound::Init(RcDesc desc)
|
||||||
|
{
|
||||||
|
if (_refCount)
|
||||||
|
return;
|
||||||
|
|
||||||
|
VERUS_INIT();
|
||||||
|
|
||||||
|
_url = desc._url;
|
||||||
|
_refCount = 1;
|
||||||
|
if (desc._is3D) SetFlag(SoundFlags::is3D);
|
||||||
|
if (desc._loop) SetFlag(SoundFlags::loop);
|
||||||
|
_gain = desc._gain;
|
||||||
|
_pitch = desc._pitch;
|
||||||
|
_referenceDistance = desc._referenceDistance;
|
||||||
|
if (desc._randomOffset) SetFlag(SoundFlags::randOff);
|
||||||
|
|
||||||
|
IO::Async::I().Load(desc._url, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Sound::Done()
|
||||||
|
{
|
||||||
|
_refCount--;
|
||||||
|
if (_refCount <= 0)
|
||||||
|
{
|
||||||
|
IO::Async::Cancel(this);
|
||||||
|
VERUS_FOR(i, VERUS_ARRAY_LENGTH(_sources))
|
||||||
|
_sources[i].Done();
|
||||||
|
if (_buffer)
|
||||||
|
alDeleteBuffers(1, &_buffer);
|
||||||
|
VERUS_DONE(Sound);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sound::Async_Run(CSZ url, RcBlob blob)
|
||||||
|
{
|
||||||
|
VERUS_RT_ASSERT(_url == url);
|
||||||
|
VERUS_RT_ASSERT(!_buffer);
|
||||||
|
VERUS_RT_ASSERT(blob._size);
|
||||||
|
|
||||||
|
OggDataSource oggds;
|
||||||
|
oggds._p = blob._p;
|
||||||
|
oggds._size = blob._size;
|
||||||
|
|
||||||
|
OggVorbis_File ovf;
|
||||||
|
vorbis_info* povi;
|
||||||
|
const int ret = ov_open_callbacks(&oggds, &ovf, 0, 0, g_oggCallbacks);
|
||||||
|
if (ret < 0)
|
||||||
|
throw VERUS_RUNTIME_ERROR << "ov_open_callbacks(), " << ret;
|
||||||
|
|
||||||
|
povi = ov_info(&ovf, -1);
|
||||||
|
const ALenum format = (povi->channels == 1) ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16;
|
||||||
|
|
||||||
|
alGenBuffers(1, &_buffer);
|
||||||
|
|
||||||
|
_length = static_cast<float>(ov_time_total(&ovf, -1));
|
||||||
|
const INT64 pcmSize = ov_pcm_total(&ovf, -1) * 2 * povi->channels + 1;
|
||||||
|
Vector<BYTE> vRaw;
|
||||||
|
vRaw.resize(pcmSize);
|
||||||
|
int bitstream, offset = 0;
|
||||||
|
long num = ov_read(&ovf, reinterpret_cast<char*>(vRaw.data()), Utils::Cast32(vRaw.size()), 0, 2, 1, &bitstream);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
offset += num;
|
||||||
|
num = ov_read(&ovf, reinterpret_cast<char*>(&vRaw[offset]), Utils::Cast32(vRaw.size()) - offset, 0, 2, 1, &bitstream);
|
||||||
|
} while (num > 0);
|
||||||
|
alBufferData(_buffer, format, vRaw.data(), offset, povi->rate);
|
||||||
|
ov_clear(&ovf);
|
||||||
|
|
||||||
|
SetFlag(SoundFlags::loaded);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sound::Update()
|
||||||
|
{
|
||||||
|
if (!IsLoaded())
|
||||||
|
return;
|
||||||
|
VERUS_UPDATE_ONCE_CHECK;
|
||||||
|
|
||||||
|
VERUS_FOR(i, VERUS_ARRAY_LENGTH(_sources))
|
||||||
|
_sources[i].Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sound::UpdateHRTF()
|
||||||
|
{
|
||||||
|
if (!IsLoaded())
|
||||||
|
return;
|
||||||
|
const bool is3D = IsFlagSet(SoundFlags::is3D);
|
||||||
|
VERUS_FOR(i, VERUS_ARRAY_LENGTH(_sources))
|
||||||
|
_sources[i].UpdateHRTF(is3D);
|
||||||
|
}
|
||||||
|
|
||||||
|
SourcePtr Sound::NewSource(PSourcePtr pID, Source::RcDesc desc)
|
||||||
|
{
|
||||||
|
SourcePtr source;
|
||||||
|
if (IsLoaded())
|
||||||
|
{
|
||||||
|
source.Attach(_sources + _next, this);
|
||||||
|
VERUS_CIRCULAR_ADD(_next, VERUS_ARRAY_LENGTH(_sources));
|
||||||
|
|
||||||
|
if (source->_sid) // Delete existing?
|
||||||
|
alDeleteSources(1, &source->_sid);
|
||||||
|
|
||||||
|
alGenSources(1, &source->_sid);
|
||||||
|
const ALuint sid = source->_sid;
|
||||||
|
if (IsFlagSet(SoundFlags::is3D))
|
||||||
|
{
|
||||||
|
alSourcef(sid, AL_REFERENCE_DISTANCE, _referenceDistance);
|
||||||
|
alSourcef(sid, AL_ROLLOFF_FACTOR, 4);
|
||||||
|
}
|
||||||
|
else // No 3D effect?
|
||||||
|
{
|
||||||
|
alSourcei(sid, AL_SOURCE_RELATIVE, AL_TRUE);
|
||||||
|
alSource3f(sid, AL_POSITION, 0, 0, 0);
|
||||||
|
alSource3f(sid, AL_VELOCITY, 0, 0, 0);
|
||||||
|
alSourcef(sid, AL_ROLLOFF_FACTOR, 0);
|
||||||
|
}
|
||||||
|
alSourcef(sid, AL_PITCH, _pitch.GetRandomValue()*desc._pitch);
|
||||||
|
alSourcei(sid, AL_LOOPING, IsFlagSet(SoundFlags::loop) ? 1 : 0);
|
||||||
|
alSourcei(sid, AL_BUFFER, _buffer);
|
||||||
|
alSourcef(sid, AL_GAIN, _gain.GetRandomValue()*desc._gain);
|
||||||
|
|
||||||
|
if (desc._secOffset < 0)
|
||||||
|
{
|
||||||
|
VERUS_QREF_UTILS;
|
||||||
|
ALint size = 0;
|
||||||
|
alGetBufferi(_buffer, AL_SIZE, &size);
|
||||||
|
const ALint offset = utils.GetRandom().Next() % size;
|
||||||
|
alSourcei(sid, AL_BYTE_OFFSET, offset);
|
||||||
|
}
|
||||||
|
else if (desc._secOffset > 0)
|
||||||
|
{
|
||||||
|
alSourcef(sid, AL_SEC_OFFSET, desc._secOffset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (pID) // Adjust this source later?
|
||||||
|
{
|
||||||
|
if (desc._stopSource && *pID)
|
||||||
|
(*pID)->Stop();
|
||||||
|
*pID = source;
|
||||||
|
}
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
|
||||||
|
float Sound::GetRandomOffset() const
|
||||||
|
{
|
||||||
|
return _length * Utils::I().GetRandom().NextFloat();
|
||||||
|
}
|
||||||
|
|
||||||
|
// SoundPtr:
|
||||||
|
|
||||||
|
void SoundPtr::Init(Sound::RcDesc desc)
|
||||||
|
{
|
||||||
|
VERUS_QREF_ASYS;
|
||||||
|
VERUS_RT_ASSERT(!_p);
|
||||||
|
_p = asys.InsertSound(desc._url);
|
||||||
|
_p->Init(desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoundPwn::Done()
|
||||||
|
{
|
||||||
|
if (_p)
|
||||||
|
{
|
||||||
|
AudioSystem::I().DeleteSound(_C(_p->GetUrl()));
|
||||||
|
_p = nullptr;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,141 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace verus
|
||||||
|
{
|
||||||
|
namespace Audio
|
||||||
|
{
|
||||||
|
struct SoundFlags
|
||||||
|
{
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
loaded = (ObjectFlags::user << 0),
|
||||||
|
is3D = (ObjectFlags::user << 1),
|
||||||
|
loop = (ObjectFlags::user << 2),
|
||||||
|
randOff = (ObjectFlags::user << 3),
|
||||||
|
user = (ObjectFlags::user << 4)
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
class Sound : public Object, public IO::AsyncCallback
|
||||||
|
{
|
||||||
|
Source _sources[8];
|
||||||
|
String _url;
|
||||||
|
ALuint _buffer = 0;
|
||||||
|
int _next = 0;
|
||||||
|
int _refCount = 0;
|
||||||
|
Range<float> _gain = 1;
|
||||||
|
Range<float> _pitch = 1;
|
||||||
|
float _length = 0;
|
||||||
|
float _referenceDistance = 4;
|
||||||
|
|
||||||
|
public:
|
||||||
|
struct Desc
|
||||||
|
{
|
||||||
|
CSZ _url = nullptr;
|
||||||
|
Range<float> _gain = 0.8f;
|
||||||
|
Range<float> _pitch = 1;
|
||||||
|
float _referenceDistance = 4;
|
||||||
|
bool _is3D = false;
|
||||||
|
bool _loop = false;
|
||||||
|
bool _randomOffset = false;
|
||||||
|
|
||||||
|
Desc(CSZ url) : _url(url) {}
|
||||||
|
Desc& Set3D(bool b = true) { _is3D = b; return *this; }
|
||||||
|
Desc& SetLoop(bool b = true) { _loop = b; return *this; }
|
||||||
|
Desc& SetGain(const Range<float>& gain) { _gain = gain; return *this; }
|
||||||
|
Desc& SetPitch(const Range<float>& pitch) { _pitch = pitch; return *this; }
|
||||||
|
Desc& SetRandomOffset(bool b = true) { _randomOffset = b; return *this; }
|
||||||
|
Desc& SetReferenceDistance(float rd) { _referenceDistance = rd; return *this; }
|
||||||
|
};
|
||||||
|
VERUS_TYPEDEFS(Desc);
|
||||||
|
|
||||||
|
Sound();
|
||||||
|
~Sound();
|
||||||
|
|
||||||
|
void Init(RcDesc desc);
|
||||||
|
bool Done();
|
||||||
|
|
||||||
|
virtual void Async_Run(CSZ url, RcBlob blob) override;
|
||||||
|
bool IsLoaded() const { return IsFlagSet(SoundFlags::loaded); }
|
||||||
|
void AddRef() { _refCount++; }
|
||||||
|
|
||||||
|
Str GetUrl() const { return _C(_url); }
|
||||||
|
|
||||||
|
void Update();
|
||||||
|
void UpdateHRTF();
|
||||||
|
|
||||||
|
SourcePtr NewSource(PSourcePtr pID = nullptr, Source::RcDesc desc = Source::Desc());
|
||||||
|
|
||||||
|
const Range<float>& GetGain() const { return _gain; }
|
||||||
|
const Range<float>& GetPitch() const { return _pitch; }
|
||||||
|
|
||||||
|
float GetLength() const { return _length; }
|
||||||
|
|
||||||
|
float GetRandomOffset() const;
|
||||||
|
void SetRandomOffset(bool b) { b ? SetFlag(SoundFlags::randOff) : ResetFlag(SoundFlags::randOff); }
|
||||||
|
bool HasRandomOffset() const { return IsFlagSet(SoundFlags::randOff); }
|
||||||
|
};
|
||||||
|
VERUS_TYPEDEFS(Sound);
|
||||||
|
|
||||||
|
class SoundPtr : public Ptr<Sound>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void Init(Sound::RcDesc desc);
|
||||||
|
};
|
||||||
|
VERUS_TYPEDEFS(SoundPtr);
|
||||||
|
|
||||||
|
class SoundPwn : public SoundPtr
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
~SoundPwn() { Done(); }
|
||||||
|
void Done();
|
||||||
|
};
|
||||||
|
VERUS_TYPEDEFS(SoundPwn);
|
||||||
|
|
||||||
|
template<int NUM>
|
||||||
|
class SoundPwns
|
||||||
|
{
|
||||||
|
SoundPwn _sounds[NUM];
|
||||||
|
int _prev = 0;
|
||||||
|
|
||||||
|
public:
|
||||||
|
SoundPwns()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~SoundPwns()
|
||||||
|
{
|
||||||
|
Done();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Init(Sound::RcDesc desc)
|
||||||
|
{
|
||||||
|
char buffer[200];
|
||||||
|
VERUS_FOR(i, NUM)
|
||||||
|
{
|
||||||
|
sprintf_s(buffer, desc._url, i);
|
||||||
|
Sound::Desc descs = desc;
|
||||||
|
descs._url = buffer;
|
||||||
|
_sounds[i].Init(descs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Done()
|
||||||
|
{
|
||||||
|
VERUS_FOR(i, NUM)
|
||||||
|
_sounds[i].Done();
|
||||||
|
}
|
||||||
|
|
||||||
|
RSoundPtr operator[](int i)
|
||||||
|
{
|
||||||
|
if (i < 0)
|
||||||
|
i = Utils::I().GetRandom().Next() & 0xFF; // Only positive.
|
||||||
|
i %= NUM;
|
||||||
|
if (i == _prev)
|
||||||
|
i = (i + 1) % NUM;
|
||||||
|
_prev = i;
|
||||||
|
return _sounds[i];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,136 @@
|
||||||
|
#include "verus.h"
|
||||||
|
|
||||||
|
using namespace verus;
|
||||||
|
using namespace verus::Audio;
|
||||||
|
|
||||||
|
// Source:
|
||||||
|
|
||||||
|
Source::Source()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Source::~Source()
|
||||||
|
{
|
||||||
|
Done();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Source::Done()
|
||||||
|
{
|
||||||
|
if (_sid)
|
||||||
|
{
|
||||||
|
alDeleteSources(1, &_sid);
|
||||||
|
_sid = 0;
|
||||||
|
_pSound = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Source::Update()
|
||||||
|
{
|
||||||
|
if (!_sid)
|
||||||
|
return;
|
||||||
|
|
||||||
|
VERUS_QREF_TIMER;
|
||||||
|
|
||||||
|
int state;
|
||||||
|
alGetSourcei(_sid, AL_SOURCE_STATE, &state);
|
||||||
|
if (AL_INITIAL == state)
|
||||||
|
{
|
||||||
|
_travelDelay -= dt;
|
||||||
|
if (_travelDelay <= 0)
|
||||||
|
{
|
||||||
|
if (_pSound->HasRandomOffset())
|
||||||
|
alSourcef(_sid, AL_SEC_OFFSET, _pSound->GetRandomOffset());
|
||||||
|
alSourcePlay(_sid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Source::UpdateHRTF(bool is3D)
|
||||||
|
{
|
||||||
|
if (!_sid)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int state;
|
||||||
|
alGetSourcei(_sid, AL_SOURCE_STATE, &state);
|
||||||
|
if (AL_STOPPED == state)
|
||||||
|
{
|
||||||
|
alDeleteSources(1, &_sid);
|
||||||
|
_sid = 0;
|
||||||
|
}
|
||||||
|
else if (is3D)
|
||||||
|
{
|
||||||
|
alSourcefv(_sid, AL_POSITION, _position.ToPointer());
|
||||||
|
alSourcefv(_sid, AL_DIRECTION, _direction.ToPointer());
|
||||||
|
alSourcefv(_sid, AL_VELOCITY, _velocity.ToPointer());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Source::Play()
|
||||||
|
{
|
||||||
|
if (!this)
|
||||||
|
return; // For NewSource()-> pattern.
|
||||||
|
if (_pSound && _pSound->IsLoaded())
|
||||||
|
{
|
||||||
|
if (_pSound->HasRandomOffset())
|
||||||
|
alSourcef(_sid, AL_SEC_OFFSET, _pSound->GetRandomOffset());
|
||||||
|
alSourcePlay(_sid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Source::PlayAt(RcPoint3 pos, RcVector3 dir, RcVector3 vel, float delay)
|
||||||
|
{
|
||||||
|
if (!this)
|
||||||
|
return; // For NewSource()-> pattern.
|
||||||
|
VERUS_QREF_ASYS;
|
||||||
|
if (_pSound && _pSound->IsLoaded())
|
||||||
|
{
|
||||||
|
_travelDelay = asys.ComputeTravelDelay(pos) + delay;
|
||||||
|
MoveTo(pos, dir, vel);
|
||||||
|
UpdateHRTF(_pSound->IsFlagSet(SoundFlags::is3D));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Source::Stop()
|
||||||
|
{
|
||||||
|
if (_pSound && _pSound->IsLoaded())
|
||||||
|
alSourceStop(_sid);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Source::MoveTo(RcPoint3 pos, RcVector3 dir, RcVector3 vel)
|
||||||
|
{
|
||||||
|
if (_pSound && _pSound->IsLoaded())
|
||||||
|
{
|
||||||
|
_position = pos;
|
||||||
|
_direction = dir;
|
||||||
|
_velocity = vel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Source::SetGain(float gain)
|
||||||
|
{
|
||||||
|
if (_pSound && _pSound->IsLoaded())
|
||||||
|
alSourcef(_sid, AL_GAIN, gain*_pSound->GetGain().GetRandomValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Source::SetPitch(float pitch)
|
||||||
|
{
|
||||||
|
if (_pSound && _pSound->IsLoaded())
|
||||||
|
alSourcef(_sid, AL_PITCH, pitch*_pSound->GetPitch().GetRandomValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
// SourcePtr:
|
||||||
|
|
||||||
|
void SourcePtr::Attach(Source* pSource, Sound* pSound)
|
||||||
|
{
|
||||||
|
_p = pSource;
|
||||||
|
_p->_pSound = pSound;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SourcePtr::Done()
|
||||||
|
{
|
||||||
|
if (_p)
|
||||||
|
{
|
||||||
|
_p->Done();
|
||||||
|
_p = nullptr;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace verus
|
||||||
|
{
|
||||||
|
namespace Audio
|
||||||
|
{
|
||||||
|
class Source
|
||||||
|
{
|
||||||
|
friend class SourcePtr; // _pSound @ Attach().
|
||||||
|
friend class Sound; // _sid @ NewSource().
|
||||||
|
|
||||||
|
Point3 _position = Point3(0);
|
||||||
|
Vector3 _direction = Vector3(0);
|
||||||
|
Vector3 _velocity = Vector3(0);
|
||||||
|
Sound* _pSound = nullptr;
|
||||||
|
ALuint _sid = 0;
|
||||||
|
float _travelDelay = 0;
|
||||||
|
|
||||||
|
public:
|
||||||
|
struct Desc
|
||||||
|
{
|
||||||
|
float _secOffset = 0;
|
||||||
|
float _gain = 1;
|
||||||
|
float _pitch = 1;
|
||||||
|
bool _stopSource = true;
|
||||||
|
};
|
||||||
|
VERUS_TYPEDEFS(Desc);
|
||||||
|
|
||||||
|
Source();
|
||||||
|
~Source();
|
||||||
|
|
||||||
|
void Done();
|
||||||
|
|
||||||
|
void Update();
|
||||||
|
void UpdateHRTF(bool is3D);
|
||||||
|
|
||||||
|
void Play();
|
||||||
|
void PlayAt(RcPoint3 pos, RcVector3 dir = Vector3(0), RcVector3 vel = Vector3(0), float delay = 0);
|
||||||
|
void Stop();
|
||||||
|
void MoveTo(RcPoint3 pos, RcVector3 dir = Vector3(0), RcVector3 vel = Vector3(0));
|
||||||
|
|
||||||
|
void SetGain(float gain);
|
||||||
|
void SetPitch(float pitch);
|
||||||
|
};
|
||||||
|
VERUS_TYPEDEFS(Source);
|
||||||
|
|
||||||
|
class SourcePtr : public Ptr<Source>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void Attach(Source* pSource, Sound* pSound);
|
||||||
|
void Done();
|
||||||
|
};
|
||||||
|
VERUS_TYPEDEFS(SourcePtr);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,340 @@
|
||||||
|
#include "verus.h"
|
||||||
|
|
||||||
|
using namespace verus;
|
||||||
|
using namespace verus::Audio;
|
||||||
|
|
||||||
|
// Track:
|
||||||
|
|
||||||
|
Track::Track()
|
||||||
|
{
|
||||||
|
_loaded = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Track::~Track()
|
||||||
|
{
|
||||||
|
Done();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Track::Init(CSZ url)
|
||||||
|
{
|
||||||
|
IO::Async::I().Load(url, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Track::Done()
|
||||||
|
{
|
||||||
|
IO::Async::Cancel(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Track::Async_Run(CSZ url, RcBlob blob)
|
||||||
|
{
|
||||||
|
_vOggEncodedTrack.assign(blob._p, blob._p + blob._size);
|
||||||
|
|
||||||
|
_ds._p = _vOggEncodedTrack.data();
|
||||||
|
_ds._size = _vOggEncodedTrack.size();
|
||||||
|
_ds._cursor = 0;
|
||||||
|
|
||||||
|
_loaded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// StreamPlayer:
|
||||||
|
|
||||||
|
StreamPlayer::StreamPlayer()
|
||||||
|
{
|
||||||
|
VERUS_ZERO_MEM(_oggVorbisFile);
|
||||||
|
VERUS_ZERO_MEM(_buffers);
|
||||||
|
}
|
||||||
|
|
||||||
|
StreamPlayer::~StreamPlayer()
|
||||||
|
{
|
||||||
|
Done();
|
||||||
|
}
|
||||||
|
|
||||||
|
void StreamPlayer::Init()
|
||||||
|
{
|
||||||
|
VERUS_INIT();
|
||||||
|
|
||||||
|
_fade.Set(1, 0);
|
||||||
|
_fade.SetLimits(0, 1);
|
||||||
|
|
||||||
|
alGenBuffers(2, _buffers);
|
||||||
|
alGenSources(1, &_source);
|
||||||
|
|
||||||
|
alSourcei(_source, AL_SOURCE_RELATIVE, AL_TRUE);
|
||||||
|
alSource3f(_source, AL_POSITION, 0, 0, 0);
|
||||||
|
alSource3f(_source, AL_VELOCITY, 0, 0, 0);
|
||||||
|
alSourcef(_source, AL_GAIN, _gain);
|
||||||
|
alSourcef(_source, AL_ROLLOFF_FACTOR, 0);
|
||||||
|
|
||||||
|
_vSmallBuffer.resize(441 * 32);
|
||||||
|
_vMediumBuffer.resize(441 * 32 * 32);
|
||||||
|
_vTracks.reserve(8);
|
||||||
|
|
||||||
|
ResetFlag(StreamPlayerFlags::stopThread);
|
||||||
|
ResetFlag(StreamPlayerFlags::noLock);
|
||||||
|
_thread = std::thread(&StreamPlayer::ThreadProc, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void StreamPlayer::Done()
|
||||||
|
{
|
||||||
|
StopThread();
|
||||||
|
_nativeTrack.Done();
|
||||||
|
|
||||||
|
if (_source)
|
||||||
|
{
|
||||||
|
alDeleteSources(1, &_source);
|
||||||
|
_source = 0;
|
||||||
|
}
|
||||||
|
if (_buffers[0])
|
||||||
|
{
|
||||||
|
alDeleteBuffers(2, _buffers);
|
||||||
|
_buffers[0] = _buffers[1] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ov_clear(&_oggVorbisFile);
|
||||||
|
|
||||||
|
VERUS_DONE(StreamPlayer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void StreamPlayer::Update()
|
||||||
|
{
|
||||||
|
if (!IsInitialized())
|
||||||
|
return;
|
||||||
|
VERUS_UPDATE_ONCE_CHECK;
|
||||||
|
|
||||||
|
VERUS_QREF_TIMER;
|
||||||
|
|
||||||
|
_fade.UpdateClamped(dt);
|
||||||
|
|
||||||
|
const float level = Math::SmoothStep(0.f, 1.f, _fade.GetValue());
|
||||||
|
alSourcef(_source, AL_GAIN, _gain*level);
|
||||||
|
}
|
||||||
|
|
||||||
|
void StreamPlayer::AddTrack(PTrack pTrack)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
VERUS_LOCK(*this);
|
||||||
|
_vTracks.push_back(pTrack);
|
||||||
|
if (!_pTrack)
|
||||||
|
_pTrack = pTrack;
|
||||||
|
}
|
||||||
|
_cv.notify_one();
|
||||||
|
}
|
||||||
|
|
||||||
|
void StreamPlayer::DeleteTrack(PTrack pTrack)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
VERUS_LOCK(*this);
|
||||||
|
VERUS_WHILE(Vector<PTrack>, _vTracks, it)
|
||||||
|
{
|
||||||
|
if (*it == pTrack)
|
||||||
|
it = _vTracks.erase(it);
|
||||||
|
else
|
||||||
|
it++;
|
||||||
|
}
|
||||||
|
if (_pTrack == pTrack)
|
||||||
|
{
|
||||||
|
SetFlag(StreamPlayerFlags::noLock);
|
||||||
|
SwitchToTrack(nullptr);
|
||||||
|
ResetFlag(StreamPlayerFlags::noLock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_cv.notify_one();
|
||||||
|
}
|
||||||
|
|
||||||
|
void StreamPlayer::SwitchToTrack(PTrack pTrack)
|
||||||
|
{
|
||||||
|
VERUS_LOCK_EX(*this, IsFlagSet(StreamPlayerFlags::noLock));
|
||||||
|
|
||||||
|
VERUS_FOR(i, int(_vTracks.size()))
|
||||||
|
{
|
||||||
|
if (_vTracks[i] == pTrack)
|
||||||
|
{
|
||||||
|
_currentTrack = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_pTrack = pTrack;
|
||||||
|
_pVorbisInfo = nullptr;
|
||||||
|
ov_clear(&_oggVorbisFile);
|
||||||
|
|
||||||
|
if (!_pTrack || !_pTrack->IsLoaded()) // Possible to start decoding?
|
||||||
|
return;
|
||||||
|
|
||||||
|
const int ret = ov_open_callbacks(_pTrack->GetOggDataSource(), &_oggVorbisFile, 0, 0, g_oggCallbacks);
|
||||||
|
if (ret < 0)
|
||||||
|
throw VERUS_RUNTIME_ERROR << "ov_open_callbacks(), " << ret;
|
||||||
|
|
||||||
|
_pVorbisInfo = ov_info(&_oggVorbisFile, -1);
|
||||||
|
_format = (_pVorbisInfo->channels == 1) ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StreamPlayer::Play()
|
||||||
|
{
|
||||||
|
SetFlag(StreamPlayerFlags::play);
|
||||||
|
alSourcePlay(_source);
|
||||||
|
_cv.notify_one();
|
||||||
|
}
|
||||||
|
|
||||||
|
void StreamPlayer::Stop()
|
||||||
|
{
|
||||||
|
ResetFlag(StreamPlayerFlags::play);
|
||||||
|
alSourceStop(_source);
|
||||||
|
_cv.notify_one();
|
||||||
|
}
|
||||||
|
|
||||||
|
void StreamPlayer::Seek(int pos)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
VERUS_LOCK(*this);
|
||||||
|
|
||||||
|
if (!_pVorbisInfo)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int queued;
|
||||||
|
alGetSourcei(_source, AL_BUFFERS_QUEUED, &queued);
|
||||||
|
while (queued > 0)
|
||||||
|
{
|
||||||
|
ALuint buffer;
|
||||||
|
alSourceUnqueueBuffers(_source, 1, &buffer);
|
||||||
|
queued--;
|
||||||
|
}
|
||||||
|
ov_pcm_seek(&_oggVorbisFile, pos);
|
||||||
|
}
|
||||||
|
_cv.notify_one();
|
||||||
|
}
|
||||||
|
|
||||||
|
void StreamPlayer::ThreadProc()
|
||||||
|
{
|
||||||
|
VERUS_RT_ASSERT(IsInitialized());
|
||||||
|
try
|
||||||
|
{
|
||||||
|
SDL_SetThreadPriority(SDL_THREAD_PRIORITY_LOW);
|
||||||
|
while (!IsFlagSet(StreamPlayerFlags::stopThread))
|
||||||
|
{
|
||||||
|
VERUS_LOCK(*this);
|
||||||
|
|
||||||
|
_cv.wait_for(lock, std::chrono::milliseconds(530));
|
||||||
|
|
||||||
|
if (IsFlagSet(StreamPlayerFlags::play))
|
||||||
|
{
|
||||||
|
SetFlag(StreamPlayerFlags::noLock);
|
||||||
|
if (_pTrack)
|
||||||
|
{
|
||||||
|
if (_pTrack->IsLoaded() && !_pVorbisInfo) // Loaded but not started?
|
||||||
|
{
|
||||||
|
SwitchToTrack(_pTrack);
|
||||||
|
VERUS_RT_ASSERT(_pVorbisInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_pVorbisInfo) // Can get the data?
|
||||||
|
{
|
||||||
|
int queued;
|
||||||
|
alGetSourcei(_source, AL_BUFFERS_QUEUED, &queued);
|
||||||
|
if (!queued)
|
||||||
|
{
|
||||||
|
FillBuffer(_buffers[0]);
|
||||||
|
FillBuffer(_buffers[1]);
|
||||||
|
alSourceQueueBuffers(_source, 2, _buffers);
|
||||||
|
alSourcePlay(_source);
|
||||||
|
}
|
||||||
|
|
||||||
|
int processed;
|
||||||
|
alGetSourcei(_source, AL_BUFFERS_PROCESSED, &processed);
|
||||||
|
|
||||||
|
#ifdef VERUS_DEBUG
|
||||||
|
char debug[80];
|
||||||
|
sprintf_s(debug, "ThreadProc() processed=%d", processed);
|
||||||
|
VERUS_LOG_DEBUG(debug);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
while (processed > 0)
|
||||||
|
{
|
||||||
|
ALuint buffer;
|
||||||
|
alSourceUnqueueBuffers(_source, 1, &buffer);
|
||||||
|
FillBuffer(buffer);
|
||||||
|
alSourceQueueBuffers(_source, 1, &buffer);
|
||||||
|
processed--;
|
||||||
|
}
|
||||||
|
|
||||||
|
int state;
|
||||||
|
alGetSourcei(_source, AL_SOURCE_STATE, &state);
|
||||||
|
if (AL_STOPPED == state)
|
||||||
|
alSourcePlay(_source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // No track? Stop the music:
|
||||||
|
{
|
||||||
|
alSourceStop(_source);
|
||||||
|
}
|
||||||
|
ResetFlag(StreamPlayerFlags::noLock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
alSourceStop(_source);
|
||||||
|
}
|
||||||
|
catch (D::RcRuntimeError e)
|
||||||
|
{
|
||||||
|
//Utils::CLog::Error(e.what(), e.GetThreadID(), e.GetFile(), e.GetLine());
|
||||||
|
}
|
||||||
|
catch (const std::exception& e)
|
||||||
|
{
|
||||||
|
VERUS_LOG_ERROR(e.what());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void StreamPlayer::StopThread()
|
||||||
|
{
|
||||||
|
if (_thread.joinable())
|
||||||
|
{
|
||||||
|
SetFlag(StreamPlayerFlags::stopThread);
|
||||||
|
Stop();
|
||||||
|
_thread.join();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void StreamPlayer::FillBuffer(ALuint buffer)
|
||||||
|
{
|
||||||
|
VERUS_RT_ASSERT(IsInitialized());
|
||||||
|
int bitstream, oggCursor = 0, safeSize = Utils::Cast32(_vMediumBuffer.size() - _vSmallBuffer.size());
|
||||||
|
while (oggCursor < safeSize)
|
||||||
|
{
|
||||||
|
long num = -1;
|
||||||
|
if (_pTrack && _pTrack->IsLoaded())
|
||||||
|
num = ov_read(&_oggVorbisFile, reinterpret_cast<char*>(_vSmallBuffer.data()), Utils::Cast32(_vSmallBuffer.size()), 0, 2, 1, &bitstream);
|
||||||
|
if (num > 0)
|
||||||
|
{
|
||||||
|
memcpy(&_vMediumBuffer[oggCursor], _vSmallBuffer.data(), num);
|
||||||
|
oggCursor += num;
|
||||||
|
}
|
||||||
|
else if (0 == num) // No more data?
|
||||||
|
{
|
||||||
|
if (!_vTracks.empty()) // Next one in the playlist?
|
||||||
|
{
|
||||||
|
_currentTrack++;
|
||||||
|
_currentTrack %= _vTracks.size();
|
||||||
|
SwitchToTrack(_vTracks[_currentTrack]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ov_raw_seek(&_oggVorbisFile, 0); // Start from the beginning.
|
||||||
|
}
|
||||||
|
else
|
||||||
|
safeSize = 0; // Still loading? Exit.
|
||||||
|
}
|
||||||
|
if (_pVorbisInfo)
|
||||||
|
alBufferData(buffer, _format, _vMediumBuffer.data(), oggCursor, _pVorbisInfo->rate);
|
||||||
|
}
|
||||||
|
|
||||||
|
void StreamPlayer::FadeIn(float time)
|
||||||
|
{
|
||||||
|
_fade.Plan(1, time);
|
||||||
|
}
|
||||||
|
|
||||||
|
void StreamPlayer::FadeOut(float time)
|
||||||
|
{
|
||||||
|
_fade.Plan(0, time);
|
||||||
|
}
|
||||||
|
|
||||||
|
void StreamPlayer::Mute()
|
||||||
|
{
|
||||||
|
_fade.Set(0, 0);
|
||||||
|
}
|
|
@ -0,0 +1,81 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace verus
|
||||||
|
{
|
||||||
|
namespace Audio
|
||||||
|
{
|
||||||
|
class Track : public IO::AsyncCallback
|
||||||
|
{
|
||||||
|
Vector<BYTE> _vOggEncodedTrack;
|
||||||
|
OggDataSource _ds;
|
||||||
|
std::atomic_bool _loaded;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Track();
|
||||||
|
~Track();
|
||||||
|
|
||||||
|
POggDataSource GetOggDataSource() { return &_ds; }
|
||||||
|
void Init(CSZ url);
|
||||||
|
void Done();
|
||||||
|
|
||||||
|
virtual void Async_Run(CSZ url, RcBlob blob) override;
|
||||||
|
bool IsLoaded() const { return _loaded; }
|
||||||
|
};
|
||||||
|
VERUS_TYPEDEFS(Track);
|
||||||
|
|
||||||
|
struct StreamPlayerFlags
|
||||||
|
{
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
stopThread = (ObjectFlags::user << 0),
|
||||||
|
play = (ObjectFlags::user << 1),
|
||||||
|
noLock = (ObjectFlags::user << 2)
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
class StreamPlayer : public Object, public Lockable
|
||||||
|
{
|
||||||
|
Track _nativeTrack;
|
||||||
|
Vector<PTrack> _vTracks;
|
||||||
|
Vector<BYTE> _vSmallBuffer;
|
||||||
|
Vector<BYTE> _vMediumBuffer;
|
||||||
|
std::thread _thread;
|
||||||
|
std::condition_variable _cv;
|
||||||
|
vorbis_info* _pVorbisInfo = nullptr;
|
||||||
|
PTrack _pTrack = nullptr;
|
||||||
|
OggVorbis_File _oggVorbisFile;
|
||||||
|
ALuint _buffers[2];
|
||||||
|
ALuint _source = 0;
|
||||||
|
ALenum _format = 0;
|
||||||
|
Linear<float> _fade;
|
||||||
|
float _gain = 0.25f;
|
||||||
|
int _currentTrack = 0;
|
||||||
|
|
||||||
|
public:
|
||||||
|
StreamPlayer();
|
||||||
|
~StreamPlayer();
|
||||||
|
|
||||||
|
void Init();
|
||||||
|
void Done();
|
||||||
|
|
||||||
|
void Update();
|
||||||
|
|
||||||
|
void AddTrack(PTrack pTrack);
|
||||||
|
void DeleteTrack(PTrack pTrack);
|
||||||
|
void SwitchToTrack(PTrack pTrack);
|
||||||
|
|
||||||
|
void Play();
|
||||||
|
void Stop();
|
||||||
|
void Seek(int pos);
|
||||||
|
|
||||||
|
VERUS_P(void ThreadProc());
|
||||||
|
VERUS_P(void StopThread());
|
||||||
|
VERUS_P(void FillBuffer(ALuint buffer));
|
||||||
|
|
||||||
|
void FadeIn(float time);
|
||||||
|
void FadeOut(float time);
|
||||||
|
void Mute();
|
||||||
|
};
|
||||||
|
VERUS_TYPEDEFS(StreamPlayer);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
#include "verus.h"
|
||||||
|
|
||||||
|
using namespace verus;
|
||||||
|
using namespace verus::CGI;
|
|
@ -0,0 +1,11 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace verus
|
||||||
|
{
|
||||||
|
namespace CGI
|
||||||
|
{
|
||||||
|
class BaseGeometry
|
||||||
|
{
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
#include "verus.h"
|
||||||
|
|
||||||
|
using namespace verus;
|
||||||
|
using namespace verus::CGI;
|
|
@ -0,0 +1,11 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace verus
|
||||||
|
{
|
||||||
|
namespace CGI
|
||||||
|
{
|
||||||
|
class BasePipeline
|
||||||
|
{
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
#include "verus.h"
|
||||||
|
|
||||||
|
using namespace verus;
|
||||||
|
using namespace verus::CGI;
|
|
@ -0,0 +1,11 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace verus
|
||||||
|
{
|
||||||
|
namespace CGI
|
||||||
|
{
|
||||||
|
class BaseShader
|
||||||
|
{
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
#include "verus.h"
|
||||||
|
|
||||||
|
using namespace verus;
|
||||||
|
using namespace verus::CGI;
|
|
@ -0,0 +1,11 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace verus
|
||||||
|
{
|
||||||
|
namespace CGI
|
||||||
|
{
|
||||||
|
class BaseTexture
|
||||||
|
{
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "BaseGeometry.h"
|
||||||
|
#include "BasePipeline.h"
|
||||||
|
#include "BaseShader.h"
|
||||||
|
#include "BaseTexture.h"
|
|
@ -0,0 +1,3 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define VERUS_CT_ASSERT(x) static_assert(x, "VERUS_CT_ASSERT")
|
|
@ -0,0 +1,14 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
# define VERUS_RT_ASSERT(x) assert(x)
|
||||||
|
# define VERUS_RT_FAIL(x) assert(!x)
|
||||||
|
#else
|
||||||
|
# ifdef VERUS_RELEASE_DEBUG
|
||||||
|
# define VERUS_RT_ASSERT(x) SDL_assert_release(x)
|
||||||
|
# define VERUS_RT_FAIL(x) SDL_assert_release(!x)
|
||||||
|
# else
|
||||||
|
# define VERUS_RT_ASSERT(x)
|
||||||
|
# define VERUS_RT_FAIL(x)
|
||||||
|
# endif
|
||||||
|
#endif
|
|
@ -0,0 +1,7 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "AssertionRunTime.h"
|
||||||
|
#include "AssertionCompileTime.h"
|
||||||
|
#include "RuntimeError.h"
|
||||||
|
#include "Recoverable.h"
|
||||||
|
#include "Log.h"
|
|
@ -0,0 +1,134 @@
|
||||||
|
#include "verus.h"
|
||||||
|
|
||||||
|
using namespace verus;
|
||||||
|
using namespace verus::D;
|
||||||
|
|
||||||
|
std::mutex D::Log::s_mutex;
|
||||||
|
|
||||||
|
void Log::Error(CSZ txt, std::thread::id tid, CSZ filename, UINT32 line)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(s_mutex);
|
||||||
|
|
||||||
|
const time_t t = time(0);
|
||||||
|
const tm* pTM = localtime(&t);
|
||||||
|
char timestamp[80];
|
||||||
|
strftime(timestamp, sizeof(timestamp), "%Y.%m.%d %H:%M:%S", pTM);
|
||||||
|
|
||||||
|
CSZ p = strrchr(filename, '/');
|
||||||
|
if (!p)
|
||||||
|
p = strrchr(filename, '\\');
|
||||||
|
filename = p ? p + 1 : filename;
|
||||||
|
|
||||||
|
String pathName;
|
||||||
|
//if (Global::IsValidSingleton())
|
||||||
|
//{
|
||||||
|
// pathName = Global::I().GetWritablePath() + "/Errors.txt";
|
||||||
|
//}
|
||||||
|
//else
|
||||||
|
{
|
||||||
|
String temp = getenv("TEMP");
|
||||||
|
pathName = temp + "/CorrErrors.txt";
|
||||||
|
}
|
||||||
|
|
||||||
|
IO::File file;
|
||||||
|
if (file.Open(_C(pathName), "a"))
|
||||||
|
{
|
||||||
|
if (file.GetSize() > 100 * 1024)
|
||||||
|
{
|
||||||
|
file.Close();
|
||||||
|
file.Open(_C(pathName), "w");
|
||||||
|
}
|
||||||
|
StringStream ss;
|
||||||
|
ss << timestamp << " " << tid << " " << filename << ":" << line << " ERROR: " << txt << "\n";
|
||||||
|
file.Write(_C(ss.str()), ss.str().length());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Log::Session(CSZ txt)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
std::lock_guard<std::mutex> lock(s_mutex);
|
||||||
|
|
||||||
|
String pathName(Global::I().GetWritablePath());
|
||||||
|
pathName += "/SessionLog.txt";
|
||||||
|
IO::File file;
|
||||||
|
if (file.Create(_C(pathName), "a"))
|
||||||
|
{
|
||||||
|
StringStream ss;
|
||||||
|
ss.fill('0');
|
||||||
|
ss << '[';
|
||||||
|
ss.width(8);
|
||||||
|
ss << SDL_GetTicks() << "ms] " << txt << "\n";
|
||||||
|
file.Write(_C(ss.str()), ss.str().length());
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void Log::DebugString(CSZ txt)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
StringStream ss;
|
||||||
|
ss << verus::Global::GetNextCounterValue() << ": " << txt << "\n";
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
OutputDebugStringA(_C(ss.str()));
|
||||||
|
#endif
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void Log::Write(CSZ txt, std::thread::id tid, CSZ filename, UINT32 line, Severity severity)
|
||||||
|
{
|
||||||
|
char timestamp[40];
|
||||||
|
FormatTime(timestamp, sizeof(timestamp));
|
||||||
|
CSZ severityLetter = GetSeverityLetter(severity);
|
||||||
|
const String filenameEx = ExtractFilename(filename);
|
||||||
|
StringStream ss;
|
||||||
|
ss << timestamp << " [" << severityLetter << "] [" << tid << "] [" << filenameEx << ":" << line << "] " << txt << std::endl;
|
||||||
|
const String s = ss.str();
|
||||||
|
|
||||||
|
IO::File file;
|
||||||
|
if (file.Open("Log.txt", "a"))
|
||||||
|
{
|
||||||
|
if (file.GetSize() > 100 * 1024)
|
||||||
|
{
|
||||||
|
file.Close();
|
||||||
|
file.Open("Log.txt", "w");
|
||||||
|
}
|
||||||
|
file.Write(_C(s), s.length());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Log::FormatTime(char* buffer, size_t size)
|
||||||
|
{
|
||||||
|
const auto now = std::chrono::system_clock::now();
|
||||||
|
const time_t tnow = std::chrono::system_clock::to_time_t(now);
|
||||||
|
const auto trimmed = std::chrono::system_clock::from_time_t(tnow);
|
||||||
|
const int ms = static_cast<int>(std::chrono::duration_cast<std::chrono::microseconds>(now - trimmed).count());
|
||||||
|
char msText[16];
|
||||||
|
sprintf_s(msText, ".%06d", ms);
|
||||||
|
tm* pTM = localtime(&tnow);
|
||||||
|
strftime(buffer, size, "%Y-%m-%d %H:%M:%S", pTM);
|
||||||
|
strcat(buffer, msText);
|
||||||
|
}
|
||||||
|
|
||||||
|
CSZ Log::GetSeverityLetter(Severity severity)
|
||||||
|
{
|
||||||
|
switch (severity)
|
||||||
|
{
|
||||||
|
case Severity::error: return "E";
|
||||||
|
case Severity::warning: return "W";
|
||||||
|
case Severity::info: return "I";
|
||||||
|
case Severity::debug: return "D";
|
||||||
|
}
|
||||||
|
return "X";
|
||||||
|
}
|
||||||
|
|
||||||
|
String Log::ExtractFilename(CSZ filename)
|
||||||
|
{
|
||||||
|
CSZ p = strrchr(filename, '/');
|
||||||
|
if (!p)
|
||||||
|
p = strrchr(filename, '\\');
|
||||||
|
filename = p ? p + 1 : filename;
|
||||||
|
p = strrchr(filename, '.');
|
||||||
|
return p ? String(filename, p) : String(filename);
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
//#define VERUS_LOG_ERROR(txt) {verus::D::Log::Error(txt, std::this_thread::get_id(), __FILE__, __LINE__);}
|
||||||
|
//#define VERUS_LOG_ERROR_STREAM(txt) {StringStream ss; ss << txt; verus::D::Log::Error(_C(ss.str()), std::this_thread::get_id(), __FILE__, __LINE__);}
|
||||||
|
//#define VERUS_LOG_SESSION(txt) {verus::D::Log::Session(txt);}
|
||||||
|
//#define VERUS_LOG_SESSION_STREAM(txt) {StringStream ss; ss << txt; verus::D::Log::Session(_C(ss.str()));}
|
||||||
|
//#ifdef _DEBUG
|
||||||
|
//# define VERUS_LOG_DEBUG(x) {verus::D::Log::DebugString(x);}
|
||||||
|
//#else
|
||||||
|
//# define VERUS_LOG_DEBUG(x) {}
|
||||||
|
//#endif
|
||||||
|
|
||||||
|
#define VERUS_LOG_ERROR(txt) {StringStream ss; ss << txt; D::Log::I().Write(_C(ss.str()), std::this_thread::get_id(), __FILE__, __LINE__, D::Log::Severity::error);}
|
||||||
|
#define VERUS_LOG_WARN(txt) {StringStream ss; ss << txt; D::Log::I().Write(_C(ss.str()), std::this_thread::get_id(), __FILE__, __LINE__, D::Log::Severity::warning);}
|
||||||
|
#define VERUS_LOG_INFO(txt) {StringStream ss; ss << txt; D::Log::I().Write(_C(ss.str()), std::this_thread::get_id(), __FILE__, __LINE__, D::Log::Severity::info);}
|
||||||
|
#define VERUS_LOG_DEBUG(txt) {StringStream ss; ss << txt; D::Log::I().Write(_C(ss.str()), std::this_thread::get_id(), __FILE__, __LINE__, D::Log::Severity::debug);}
|
||||||
|
|
||||||
|
namespace verus
|
||||||
|
{
|
||||||
|
namespace D
|
||||||
|
{
|
||||||
|
class Log : public Singleton<Log>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum class Severity : int
|
||||||
|
{
|
||||||
|
error,
|
||||||
|
warning,
|
||||||
|
info,
|
||||||
|
debug
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
static std::mutex s_mutex;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static void Error(CSZ txt, std::thread::id tid, CSZ filename, UINT32 line);
|
||||||
|
static void Session(CSZ txt);
|
||||||
|
static void DebugString(CSZ txt);
|
||||||
|
|
||||||
|
void Write(CSZ txt, std::thread::id tid, CSZ filename, UINT32 line, Severity severity);
|
||||||
|
|
||||||
|
static void FormatTime(char* buffer, size_t size);
|
||||||
|
static CSZ GetSeverityLetter(Severity severity);
|
||||||
|
static String ExtractFilename(CSZ filename);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace verus
|
||||||
|
{
|
||||||
|
namespace D
|
||||||
|
{
|
||||||
|
class Recoverable : public RuntimeError
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Recoverable(std::thread::id tid = std::this_thread::get_id(), CSZ file = __FILE__, UINT32 line = __LINE__) : RuntimeError(tid, file, line) {}
|
||||||
|
Recoverable(const Recoverable& that)
|
||||||
|
{
|
||||||
|
*this = that;
|
||||||
|
}
|
||||||
|
Recoverable& operator=(const Recoverable& that)
|
||||||
|
{
|
||||||
|
RuntimeError::operator=(that);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
Recoverable& operator<<(const T& t)
|
||||||
|
{
|
||||||
|
RuntimeError::operator<<(t);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
VERUS_TYPEDEFS(Recoverable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define VERUS_RECOVERABLE verus::D::Recoverable(std::this_thread::get_id(), __FILE__, __LINE__)
|
|
@ -0,0 +1,67 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace verus
|
||||||
|
{
|
||||||
|
namespace D
|
||||||
|
{
|
||||||
|
//! See: https://marknelson.us/posts/2007/11/13/no-exceptions.html
|
||||||
|
class RuntimeError : public std::exception
|
||||||
|
{
|
||||||
|
mutable StringStream _ss;
|
||||||
|
mutable String _what;
|
||||||
|
std::thread::id _tid;
|
||||||
|
String _file;
|
||||||
|
UINT32 _line = 0;
|
||||||
|
|
||||||
|
public:
|
||||||
|
RuntimeError(std::thread::id tid = std::this_thread::get_id(), CSZ file = __FILE__, UINT32 line = __LINE__) :
|
||||||
|
_tid(tid), _line(line)
|
||||||
|
{
|
||||||
|
CSZ p = strrchr(file, '/');
|
||||||
|
if (!p)
|
||||||
|
p = strrchr(file, '\\');
|
||||||
|
_file = p ? p + 1 : file;
|
||||||
|
}
|
||||||
|
RuntimeError(const RuntimeError& that)
|
||||||
|
{
|
||||||
|
*this = that;
|
||||||
|
}
|
||||||
|
RuntimeError& operator=(const RuntimeError& that)
|
||||||
|
{
|
||||||
|
_what += that._what;
|
||||||
|
_what += that._ss.str();
|
||||||
|
_tid = that._tid;
|
||||||
|
_file = that._file;
|
||||||
|
_line = that._line;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
virtual ~RuntimeError() throw() {}
|
||||||
|
|
||||||
|
virtual CSZ what() const throw()
|
||||||
|
{
|
||||||
|
if (_ss.str().size())
|
||||||
|
{
|
||||||
|
_what += _ss.str();
|
||||||
|
_ss.str("");
|
||||||
|
}
|
||||||
|
return _C(_what);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::thread::id GetThreadID() const { return _tid; }
|
||||||
|
CSZ GetFile() const { return _C(_file); }
|
||||||
|
UINT32 GetLine() const { return _line; }
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
RuntimeError& operator<<(const T& t)
|
||||||
|
{
|
||||||
|
_ss << t;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsRaised() const { return !!strlen(what()); }
|
||||||
|
};
|
||||||
|
VERUS_TYPEDEFS(RuntimeError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define VERUS_RUNTIME_ERROR verus::D::RuntimeError(std::this_thread::get_id(), __FILE__, __LINE__)
|
|
@ -0,0 +1,316 @@
|
||||||
|
#include "verus.h"
|
||||||
|
|
||||||
|
using namespace verus;
|
||||||
|
using namespace verus::Game;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
struct MyRenderDelegate : CGL::CRenderDelegate
|
||||||
|
{
|
||||||
|
PBaseGame _p = nullptr;
|
||||||
|
|
||||||
|
MyRenderDelegate(PBaseGame p) : _p(p) {}
|
||||||
|
~MyRenderDelegate() {}
|
||||||
|
|
||||||
|
virtual void Render_OnDraw() override
|
||||||
|
{
|
||||||
|
VERUS_QREF_RENDER;
|
||||||
|
render.BindOffscreenRT();
|
||||||
|
_p->BaseGame_Draw();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void Render_OnDrawOverlay() override
|
||||||
|
{
|
||||||
|
_p->BaseGame_DrawOverlay();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void Render_OnPresent() override
|
||||||
|
{
|
||||||
|
VERUS_QREF_RENDER;
|
||||||
|
render->Present();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void Render_OnDrawCubeMap() override
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
VERUS_TYPEDEFS(MyRenderDelegate);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct BaseGame::Pimpl : AllocatorAware
|
||||||
|
{
|
||||||
|
PBaseGame _p = nullptr;
|
||||||
|
Scene::MainCamera _camera;
|
||||||
|
//CCharacter _cameraCharacter;
|
||||||
|
bool _defaultCameraMovement = true;
|
||||||
|
bool _showFPS = true;
|
||||||
|
bool _debugBullet = false;
|
||||||
|
bool _exitOnEscape = true;
|
||||||
|
|
||||||
|
Pimpl(PBaseGame p) : _p(p)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~Pimpl()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HandleUserEvents(SDL_Event* pEvent)
|
||||||
|
{
|
||||||
|
switch (pEvent->user.code)
|
||||||
|
{
|
||||||
|
case 0: return true; // Exit.
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
BaseGame::BaseGame()
|
||||||
|
{
|
||||||
|
Utils::MakeEx(&_alloc);
|
||||||
|
_p = new Pimpl(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseGame::~BaseGame()
|
||||||
|
{
|
||||||
|
delete _p;
|
||||||
|
|
||||||
|
_engineInit.Free();
|
||||||
|
|
||||||
|
Utils::FreeEx(&_alloc);
|
||||||
|
SDL_Quit();
|
||||||
|
//CGL::CRender::DoneWin32();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseGame::Initialize(VERUS_MAIN_DEFAULT_ARGS)
|
||||||
|
{
|
||||||
|
VERUS_SDL_CENTERED;
|
||||||
|
|
||||||
|
//Settings::Make();
|
||||||
|
//VERUS_QREF_SETTINGS;
|
||||||
|
//settings.ParseCommandLineArgs(argc, argv);
|
||||||
|
//settings.LoadValidateSave();
|
||||||
|
|
||||||
|
const int ret = SDL_Init(SDL_INIT_EVERYTHING);
|
||||||
|
if (ret)
|
||||||
|
throw VERUS_RUNTIME_ERROR << "SDL_Init(), " << ret;
|
||||||
|
|
||||||
|
// Allocate memory:
|
||||||
|
_engineInit.Make();
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
//Utils::TestAll();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Initialization:
|
||||||
|
//_engineInit.Init(this, new MyRenderDelegate(this), true);
|
||||||
|
|
||||||
|
// Configure:
|
||||||
|
//VERUS_QREF_RENDER;
|
||||||
|
//VERUS_QREF_SM;
|
||||||
|
//_p->_camera.SetAspectRatio(render.GetWindowAspectRatio());
|
||||||
|
//sm.SetCamera(&_p->_camera);
|
||||||
|
|
||||||
|
BaseGame_LoadContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseGame::Run()
|
||||||
|
{
|
||||||
|
VERUS_QREF_TIMER;
|
||||||
|
VERUS_QREF_KM;
|
||||||
|
//VERUS_QREF_BULLET;
|
||||||
|
//VERUS_QREF_RENDER;
|
||||||
|
VERUS_QREF_ASYNC;
|
||||||
|
VERUS_QREF_ASYS;
|
||||||
|
|
||||||
|
SDL_SetRelativeMouseMode(SDL_TRUE);
|
||||||
|
|
||||||
|
timer.Update();
|
||||||
|
|
||||||
|
SDL_Event event;
|
||||||
|
bool done = false;
|
||||||
|
|
||||||
|
do // The Game Loop.
|
||||||
|
{
|
||||||
|
if (_p->_exitOnEscape && km.IsKeyPressed(SDL_SCANCODE_ESCAPE))
|
||||||
|
Exit();
|
||||||
|
|
||||||
|
while (SDL_PollEvent(&event))
|
||||||
|
{
|
||||||
|
if (!km.HandleSdlEvent(event))
|
||||||
|
{
|
||||||
|
switch (event.type)
|
||||||
|
{
|
||||||
|
case SDL_QUIT:
|
||||||
|
{
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SDL_WINDOWEVENT:
|
||||||
|
{
|
||||||
|
switch (event.window.event)
|
||||||
|
{
|
||||||
|
case SDL_WINDOWEVENT_MINIMIZED:
|
||||||
|
BaseGame_OnDeactivated();
|
||||||
|
break;
|
||||||
|
case SDL_WINDOWEVENT_RESTORED:
|
||||||
|
BaseGame_OnActivated();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SDL_USEREVENT:
|
||||||
|
{
|
||||||
|
if (_p->HandleUserEvents(&event))
|
||||||
|
{
|
||||||
|
SDL_Delay(100);
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (done)
|
||||||
|
break;
|
||||||
|
|
||||||
|
//
|
||||||
|
// UPDATE
|
||||||
|
// At this point the user sees a frame drawn some time ago.
|
||||||
|
//
|
||||||
|
|
||||||
|
async.Update();
|
||||||
|
|
||||||
|
timer.Update(); // Now we know how much time has passed. Maybe 1 hour!
|
||||||
|
|
||||||
|
// Process input for simulation:
|
||||||
|
if (_p->_defaultCameraMovement)
|
||||||
|
{
|
||||||
|
const float speed = km.IsKeyPressed(SDL_SCANCODE_SPACE) ? 20.f : 2.f;
|
||||||
|
//if (km.IsKeyPressed(SDL_SCANCODE_W))
|
||||||
|
// _p->_cameraCharacter.MoveFront(speed);
|
||||||
|
//if (km.IsKeyPressed(SDL_SCANCODE_S))
|
||||||
|
// _p->_cameraCharacter.MoveFront(-speed);
|
||||||
|
//if (km.IsKeyPressed(SDL_SCANCODE_A))
|
||||||
|
// _p->_cameraCharacter.MoveSide(-speed);
|
||||||
|
//if (km.IsKeyPressed(SDL_SCANCODE_D))
|
||||||
|
// _p->_cameraCharacter.MoveSide(speed);
|
||||||
|
}
|
||||||
|
BaseGame_HandleInput();
|
||||||
|
|
||||||
|
//bullet.Simulate(); // x += v*dt.
|
||||||
|
|
||||||
|
// Update game state after simulation:
|
||||||
|
if (_p->_defaultCameraMovement)
|
||||||
|
{
|
||||||
|
//_p->_cameraCharacter.Update(); // Get position from Bullet.
|
||||||
|
//_p->_camera.MoveEyeTo(_p->_cameraCharacter.GetPosition());
|
||||||
|
//_p->_camera.MoveAtTo(_p->_cameraCharacter.GetPosition() + _p->_cameraCharacter.GetDirectionFront());
|
||||||
|
//if (Scene::CWater::IsValidSingleton())
|
||||||
|
{
|
||||||
|
// VERUS_QREF_WATER;
|
||||||
|
// if (water.IsInitialized())
|
||||||
|
// _p->_camera.ExcludeWaterLine();
|
||||||
|
}
|
||||||
|
_p->_camera.Update();
|
||||||
|
}
|
||||||
|
BaseGame_Update();
|
||||||
|
|
||||||
|
asys.Update();
|
||||||
|
|
||||||
|
// Draw current frame:
|
||||||
|
//if (render.Draw())
|
||||||
|
{
|
||||||
|
#ifdef VERUS_DEBUG
|
||||||
|
if (_p->_debugBullet)
|
||||||
|
bullet.DebugDraw();
|
||||||
|
#endif
|
||||||
|
//render.DrawToScreen();
|
||||||
|
}
|
||||||
|
km.ResetClickState();
|
||||||
|
//render.Present(); // This can take a while.
|
||||||
|
|
||||||
|
// Show FPS:
|
||||||
|
if (_p->_showFPS && timer.IsEventEvery(500))
|
||||||
|
{
|
||||||
|
char title[64];
|
||||||
|
CSZ renderer = "";
|
||||||
|
//switch (render.GetRenderer())
|
||||||
|
{
|
||||||
|
//case CGL::RENDERER_OPENGL: renderer = "OpenGL"; break;
|
||||||
|
//case CGL::RENDERER_DIRECT3D9: renderer = "Direct3D 9"; break;
|
||||||
|
//case CGL::RENDERER_DIRECT3D11: renderer = "Direct3D 11"; break;
|
||||||
|
//case CGL::RENDERER_DIRECT3D12: renderer = "Direct3D 12"; break;
|
||||||
|
}
|
||||||
|
//sprintf_s(title, "[%s] - %.1f FPS", renderer, render.GetFps());
|
||||||
|
//SDL_SetWindowTitle(render.GetWindow(), title);
|
||||||
|
}
|
||||||
|
} while (!done); // The Game Loop.
|
||||||
|
|
||||||
|
BaseGame_UnloadContent();
|
||||||
|
|
||||||
|
SDL_SetRelativeMouseMode(SDL_FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseGame::Exit()
|
||||||
|
{
|
||||||
|
Utils::ExitSdlLoop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseGame::KeyMapper_OnMouseMove(int x, int y)
|
||||||
|
{
|
||||||
|
//VERUS_QREF_CONST_SETTINGS;
|
||||||
|
|
||||||
|
//const float fx = x * 0.006f*settings.m_inputMouseSensitivity;
|
||||||
|
//const float fy = y * 0.006f*settings.m_inputMouseSensitivity;
|
||||||
|
|
||||||
|
if (_p->_defaultCameraMovement)
|
||||||
|
{
|
||||||
|
//_p->_cameraCharacter.TurnPitch(fy);
|
||||||
|
//_p->_cameraCharacter.TurnYaw(fx);
|
||||||
|
}
|
||||||
|
|
||||||
|
//BaseGame_OnMouseMove(fx, fy);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseGame::KeyMapper_OnKey(int scancode)
|
||||||
|
{
|
||||||
|
BaseGame_OnKey(scancode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseGame::KeyMapper_OnChar(wchar_t c)
|
||||||
|
{
|
||||||
|
BaseGame_OnChar(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
Scene::RCamera BaseGame::GetCamera()
|
||||||
|
{
|
||||||
|
return _p->_camera;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
RCharacter BaseGame::GetCameraCharacter()
|
||||||
|
{
|
||||||
|
return _p->_cameraCharacter;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void BaseGame::ActivateDefaultCameraMovement(bool b)
|
||||||
|
{
|
||||||
|
_p->_defaultCameraMovement = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseGame::ShowFPS(bool b)
|
||||||
|
{
|
||||||
|
_p->_showFPS = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseGame::DebugBullet(bool b)
|
||||||
|
{
|
||||||
|
_p->_debugBullet = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BaseGame::IsDebugBulletMode() const
|
||||||
|
{
|
||||||
|
return _p->_debugBullet;
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace verus
|
||||||
|
{
|
||||||
|
namespace Game
|
||||||
|
{
|
||||||
|
class BaseGame : public Input::KeyMapperDelegate
|
||||||
|
{
|
||||||
|
struct Pimpl;
|
||||||
|
Pimpl* _p = nullptr;
|
||||||
|
AlignedAllocator _alloc;
|
||||||
|
EngineInit _engineInit;
|
||||||
|
|
||||||
|
public:
|
||||||
|
BaseGame();
|
||||||
|
~BaseGame();
|
||||||
|
|
||||||
|
void Initialize(VERUS_MAIN_DEFAULT_ARGS);
|
||||||
|
void Run();
|
||||||
|
void Exit();
|
||||||
|
|
||||||
|
virtual void BaseGame_LoadContent() = 0;
|
||||||
|
virtual void BaseGame_UnloadContent() = 0;
|
||||||
|
virtual void BaseGame_HandleInput() = 0;
|
||||||
|
virtual void BaseGame_Update() = 0;
|
||||||
|
virtual void BaseGame_Draw() = 0;
|
||||||
|
virtual void BaseGame_DrawOverlay() = 0;
|
||||||
|
virtual void BaseGame_OnActivated() {}
|
||||||
|
virtual void BaseGame_OnDeactivated() {}
|
||||||
|
virtual void BaseGame_OnMouseMove(float x, float y) {}
|
||||||
|
virtual void BaseGame_OnKey(int scancode) {}
|
||||||
|
virtual void BaseGame_OnChar(wchar_t c) {}
|
||||||
|
|
||||||
|
virtual void KeyMapper_OnMouseMove(int x, int y) override;
|
||||||
|
virtual void KeyMapper_OnKey(int scancode) override;
|
||||||
|
virtual void KeyMapper_OnChar(wchar_t c) override;
|
||||||
|
|
||||||
|
// Internal objects:
|
||||||
|
Scene::RCamera GetCamera();
|
||||||
|
//RCharacter GetCameraCharacter();
|
||||||
|
|
||||||
|
// Configurations:
|
||||||
|
void ActivateDefaultCameraMovement(bool b);
|
||||||
|
void ShowFPS(bool b);
|
||||||
|
void DebugBullet(bool b);
|
||||||
|
bool IsDebugBulletMode() const;
|
||||||
|
};
|
||||||
|
VERUS_TYPEDEFS(BaseGame);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "State.h"
|
||||||
|
#include "StateMachine.h"
|
||||||
|
#include "BaseGame.h"
|
|
@ -0,0 +1,25 @@
|
||||||
|
#include "verus.h"
|
||||||
|
|
||||||
|
using namespace verus;
|
||||||
|
using namespace verus::Game;
|
||||||
|
|
||||||
|
bool State::IsValidNextState(PState p)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void State::OnEnter(PState pPrev)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void State::HandleInput()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void State::Update()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void State::OnExit(PState pNext)
|
||||||
|
{
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace verus
|
||||||
|
{
|
||||||
|
namespace Game
|
||||||
|
{
|
||||||
|
class StateMachine;
|
||||||
|
|
||||||
|
struct State
|
||||||
|
{
|
||||||
|
StateMachine* _pStateMachine = nullptr;
|
||||||
|
|
||||||
|
virtual bool IsValidNextState(State* p);
|
||||||
|
virtual void OnEnter(State* pPrev);
|
||||||
|
virtual void HandleInput();
|
||||||
|
virtual void Update();
|
||||||
|
virtual void OnExit(State* pNext);
|
||||||
|
};
|
||||||
|
VERUS_TYPEDEFS(State);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,100 @@
|
||||||
|
#include "verus.h"
|
||||||
|
|
||||||
|
using namespace verus;
|
||||||
|
using namespace verus::Game;
|
||||||
|
|
||||||
|
void StateMachine::HandleInput()
|
||||||
|
{
|
||||||
|
PcState pCheck = _pCurrentState;
|
||||||
|
_pCurrentState->_pStateMachine = this;
|
||||||
|
_pCurrentState->HandleInput();
|
||||||
|
_changed = (_pCurrentState != pCheck);
|
||||||
|
}
|
||||||
|
|
||||||
|
void StateMachine::Update()
|
||||||
|
{
|
||||||
|
VERUS_UPDATE_ONCE_CHECK;
|
||||||
|
|
||||||
|
PcState pCheck = _pCurrentState;
|
||||||
|
_pCurrentState->_pStateMachine = this;
|
||||||
|
_pCurrentState->Update();
|
||||||
|
_changed = (_pCurrentState != pCheck);
|
||||||
|
}
|
||||||
|
|
||||||
|
PState StateMachine::GetCurrentState() const
|
||||||
|
{
|
||||||
|
return _pCurrentState;
|
||||||
|
}
|
||||||
|
|
||||||
|
PState StateMachine::GetRequestedState() const
|
||||||
|
{
|
||||||
|
return _pRequestedState;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StateMachine::CanEnterState(RState state, bool allowSameState)
|
||||||
|
{
|
||||||
|
state._pStateMachine = this;
|
||||||
|
if (&state == _pCurrentState && !allowSameState)
|
||||||
|
return false;
|
||||||
|
return _pCurrentState ? _pCurrentState->IsValidNextState(&state) : true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StateMachine::EnterState(RState state, bool allowSameState)
|
||||||
|
{
|
||||||
|
state._pStateMachine = this;
|
||||||
|
if (!CanEnterState(state, allowSameState))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const UINT32 frame = /*CGL::CRender::I().GetNumFrames();*/ 0;
|
||||||
|
VERUS_RT_ASSERT(frame != _prevFrame); // Don't change state multiple times per frame!
|
||||||
|
_prevFrame = frame;
|
||||||
|
|
||||||
|
PState pPrevState = _pCurrentState;
|
||||||
|
if (_pCurrentState)
|
||||||
|
{
|
||||||
|
PcState pCheck = _pCurrentState;
|
||||||
|
_pCurrentState->OnExit(&state);
|
||||||
|
VERUS_RT_ASSERT(pCheck == _pCurrentState); // Don't change state while changing state!
|
||||||
|
}
|
||||||
|
_pCurrentState = &state;
|
||||||
|
{
|
||||||
|
PcState pCheck = _pCurrentState;
|
||||||
|
_pCurrentState->OnEnter(pPrevState);
|
||||||
|
VERUS_RT_ASSERT(pCheck == _pCurrentState); // Don't change state while changing state!
|
||||||
|
}
|
||||||
|
|
||||||
|
_pRequestedState = nullptr;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StateMachine::EnterRequestedState()
|
||||||
|
{
|
||||||
|
if (_pRequestedState == _pCurrentState)
|
||||||
|
_pRequestedState = nullptr;
|
||||||
|
if (_pRequestedState)
|
||||||
|
return EnterState(*_pRequestedState);
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StateMachine::ReenterState()
|
||||||
|
{
|
||||||
|
if (_pCurrentState)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
PcState pCheck = _pCurrentState;
|
||||||
|
_pCurrentState->OnExit(_pCurrentState);
|
||||||
|
VERUS_RT_ASSERT(pCheck == _pCurrentState);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
PcState pCheck = _pCurrentState;
|
||||||
|
_pCurrentState->OnEnter(_pCurrentState);
|
||||||
|
VERUS_RT_ASSERT(pCheck == _pCurrentState);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void StateMachine::RequestState(RState state)
|
||||||
|
{
|
||||||
|
_pRequestedState = &state;
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace verus
|
||||||
|
{
|
||||||
|
namespace Game
|
||||||
|
{
|
||||||
|
class StateMachine : public Object
|
||||||
|
{
|
||||||
|
PState _pCurrentState = nullptr;
|
||||||
|
PState _pRequestedState = nullptr;
|
||||||
|
UINT32 _prevFrame = -1;
|
||||||
|
bool _changed = false;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void HandleInput();
|
||||||
|
void Update();
|
||||||
|
PState GetCurrentState() const;
|
||||||
|
PState GetRequestedState() const;
|
||||||
|
bool CanEnterState(RState state, bool allowSameState = false);
|
||||||
|
bool EnterState(RState state, bool allowSameState = false);
|
||||||
|
bool EnterRequestedState();
|
||||||
|
void ReenterState();
|
||||||
|
void RequestState(RState state);
|
||||||
|
bool IsStateChanged() const { return _changed; }
|
||||||
|
};
|
||||||
|
VERUS_TYPEDEFS(StateMachine);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace verus
|
||||||
|
{
|
||||||
|
//! This allocator will reserve aligned memory blocks.
|
||||||
|
class AlignedAllocator : public BaseAllocator
|
||||||
|
{
|
||||||
|
INT64 _memUsedTotal = 0;
|
||||||
|
int _numMalloc = 0;
|
||||||
|
int _numFree = 0;
|
||||||
|
int _mallocDelta = 0;
|
||||||
|
|
||||||
|
public:
|
||||||
|
AlignedAllocator() {}
|
||||||
|
|
||||||
|
virtual void* malloc(size_t size) override
|
||||||
|
{
|
||||||
|
_memUsedTotal += size;
|
||||||
|
_numMalloc++;
|
||||||
|
_mallocDelta++;
|
||||||
|
return _mm_malloc(size, VERUS_MEMORY_ALIGNMENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void* realloc(void* memory, size_t size) override
|
||||||
|
{
|
||||||
|
void* p = _mm_malloc(size, VERUS_MEMORY_ALIGNMENT);
|
||||||
|
memcpy(p, memory, size);
|
||||||
|
_mm_free(memory);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void free(void* memory) override
|
||||||
|
{
|
||||||
|
_numFree++;
|
||||||
|
_mallocDelta--;
|
||||||
|
_mm_free(memory);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
#include "verus.h"
|
||||||
|
|
||||||
|
using namespace verus;
|
||||||
|
|
||||||
|
void* AllocatorAware::operator new(size_t size)
|
||||||
|
{
|
||||||
|
VERUS_QREF_UTILS;
|
||||||
|
return utils.GetAllocator()->malloc(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* AllocatorAware::operator new[](size_t size)
|
||||||
|
{
|
||||||
|
VERUS_QREF_UTILS;
|
||||||
|
return utils.GetAllocator()->malloc(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AllocatorAware::operator delete(void* p)
|
||||||
|
{
|
||||||
|
VERUS_QREF_UTILS;
|
||||||
|
utils.GetAllocator()->free(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AllocatorAware::operator delete[](void* p)
|
||||||
|
{
|
||||||
|
VERUS_QREF_UTILS;
|
||||||
|
utils.GetAllocator()->free(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* AllocatorAware::operator new(size_t size, void* place)
|
||||||
|
{
|
||||||
|
return place;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AllocatorAware::operator delete(void* p, void* place)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void* AllocatorAware::UtilsMalloc(size_t size)
|
||||||
|
{
|
||||||
|
if (Utils::IsValidSingleton())
|
||||||
|
{
|
||||||
|
VERUS_QREF_UTILS;
|
||||||
|
return utils.GetAllocator()->malloc(size);
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AllocatorAware::UtilsFree(void* p)
|
||||||
|
{
|
||||||
|
if (Utils::IsValidSingleton())
|
||||||
|
{
|
||||||
|
VERUS_QREF_UTILS;
|
||||||
|
utils.GetAllocator()->free(p);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace verus
|
||||||
|
{
|
||||||
|
//! Objects of this class will use the allocator provided by Utils.
|
||||||
|
class AllocatorAware
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void* operator new(size_t size);
|
||||||
|
void* operator new[](size_t size);
|
||||||
|
void operator delete(void* p);
|
||||||
|
void operator delete[](void* p);
|
||||||
|
// Placement:
|
||||||
|
void* operator new(size_t size, void* place);
|
||||||
|
void operator delete(void* p, void* place);
|
||||||
|
|
||||||
|
static void* UtilsMalloc(size_t size);
|
||||||
|
static bool UtilsFree(void* p);
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace verus
|
||||||
|
{
|
||||||
|
class BaseAllocator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void* malloc(size_t size) = 0;
|
||||||
|
virtual void* realloc(void* memory, size_t size) = 0;
|
||||||
|
virtual void free(void* memory) = 0;
|
||||||
|
};
|
||||||
|
VERUS_TYPEDEFS(BaseAllocator);
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Macros.h"
|
||||||
|
#include "Typedef.h"
|
||||||
|
#include "EnumClass.h"
|
||||||
|
#include "QuickRefs.h"
|
||||||
|
#include "AllocatorAware.h"
|
||||||
|
#include "Singleton.h"
|
|
@ -0,0 +1,13 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace verus
|
||||||
|
{
|
||||||
|
struct Blob
|
||||||
|
{
|
||||||
|
const BYTE* _p;
|
||||||
|
const INT64 _size;
|
||||||
|
|
||||||
|
Blob(const BYTE* p = nullptr, const INT64 size = 0) : _p(p), _size(size) {}
|
||||||
|
};
|
||||||
|
VERUS_TYPEDEFS(Blob);
|
||||||
|
}
|
|
@ -0,0 +1,359 @@
|
||||||
|
#include "verus.h"
|
||||||
|
|
||||||
|
using namespace verus;
|
||||||
|
|
||||||
|
// F to I:
|
||||||
|
BYTE Convert::UnormToUint8(float x) { return BYTE(x*UCHAR_MAX + 0.5f); }
|
||||||
|
UINT16 Convert::UnormToUint16(float x) { return UINT16(x*USHRT_MAX + 0.5f); }
|
||||||
|
char Convert::SnormToSint8(float x) { return char((x >= 0) ? x * SCHAR_MAX + 0.5f : x * SCHAR_MAX - 0.5f); }
|
||||||
|
short Convert::SnormToSint16(float x) { return short((x >= 0) ? x * SHRT_MAX + 0.5f : x * SHRT_MAX - 0.5f); }
|
||||||
|
|
||||||
|
// I to F:
|
||||||
|
float Convert::Uint8ToUnorm(BYTE x) { return x * (1.f / UCHAR_MAX); }
|
||||||
|
float Convert::Uint16ToUnorm(UINT16 x) { return x * (1.f / USHRT_MAX); }
|
||||||
|
float Convert::Sint8ToSnorm(char x) { if (x == SCHAR_MIN) x = SCHAR_MIN + 1; return x * (1.f / SCHAR_MAX); }
|
||||||
|
float Convert::Sint16ToSnorm(short x) { if (x == SHRT_MIN) x = SHRT_MIN + 1; return x * (1.f / SHRT_MAX); }
|
||||||
|
|
||||||
|
// AoF to AoI:
|
||||||
|
void Convert::UnormToUint8(const float* pIn, BYTE* pOut, int num) { VERUS_FOR(i, num) pOut[i] = UnormToUint8(pIn[i]); }
|
||||||
|
void Convert::UnormToUint16(const float* pIn, UINT16* pOut, int num) { VERUS_FOR(i, num) pOut[i] = UnormToUint16(pIn[i]); }
|
||||||
|
void Convert::SnormToSint8(const float* pIn, char* pOut, int num) { VERUS_FOR(i, num) pOut[i] = SnormToSint8(pIn[i]); }
|
||||||
|
void Convert::SnormToSint16(const float* pIn, short* pOut, int num) { VERUS_FOR(i, num) pOut[i] = SnormToSint16(pIn[i]); }
|
||||||
|
|
||||||
|
// AoI to AoF:
|
||||||
|
void Convert::Uint8ToUnorm(const BYTE* pIn, float* pOut, int num) { VERUS_FOR(i, num) pOut[i] = Uint8ToUnorm(pIn[i]); }
|
||||||
|
void Convert::Uint16ToUnorm(const UINT16* pIn, float* pOut, int num) { VERUS_FOR(i, num) pOut[i] = Uint16ToUnorm(pIn[i]); }
|
||||||
|
void Convert::Sint8ToSnorm(const char* pIn, float* pOut, int num) { VERUS_FOR(i, num) pOut[i] = Sint8ToSnorm(pIn[i]); }
|
||||||
|
void Convert::Sint16ToSnorm(const short* pIn, float* pOut, int num) { VERUS_FOR(i, num) pOut[i] = Sint16ToSnorm(pIn[i]); }
|
||||||
|
|
||||||
|
// I to I:
|
||||||
|
short Convert::Sint8ToSint16(char x) { return x * SHRT_MAX / SCHAR_MAX; }
|
||||||
|
char Convert::Sint16ToSint8(short x) { return x * SCHAR_MAX / SHRT_MAX; }
|
||||||
|
void Convert::Sint8ToSint16(const char* pIn, short* pOut, int num) { VERUS_FOR(i, num) pOut[i] = Sint8ToSint16(pIn[i]); }
|
||||||
|
void Convert::Sint16ToSint8(const short* pIn, char* pOut, int num) { VERUS_FOR(i, num) pOut[i] = Sint16ToSint8(pIn[i]); }
|
||||||
|
|
||||||
|
void Convert::ToDeviceNormal(const char* pIn, char* pOut)
|
||||||
|
{
|
||||||
|
// For UBYTE4 type normal:
|
||||||
|
// OpenGL glNormalPointer() only accepts signed bytes (GL_BYTE)
|
||||||
|
// Direct3D 9 only accepts unsigned bytes (D3DDECLTYPE_UBYTE4) So it goes.
|
||||||
|
//VERUS_QREF_RENDER;
|
||||||
|
//if (CGL::RENDERER_DIRECT3D9 == render.GetRenderer())
|
||||||
|
//{
|
||||||
|
// VERUS_FOR(i, 3)
|
||||||
|
// pOut[i] = pIn[i] + 127;
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT32 Convert::ToDeviceColor(UINT32 color)
|
||||||
|
{
|
||||||
|
// OpenGL stores color as RGBA. Direct3D 9 as BGRA.
|
||||||
|
// See also GL_EXT_vertex_array_bgra.
|
||||||
|
//VERUS_QREF_RENDER;
|
||||||
|
//return (CGL::RENDERER_DIRECT3D9 == render.GetRenderer()) ? VERUS_COLOR_TO_D3D(color) : color;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
float Convert::Byte256ToSFloat(BYTE in)
|
||||||
|
{
|
||||||
|
return float(in)*(1 / 128.f) - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT16 Convert::Uint8x4ToUint4x4(UINT32 in)
|
||||||
|
{
|
||||||
|
int x[4] =
|
||||||
|
{
|
||||||
|
(in >> 28) & 0xF,
|
||||||
|
(in >> 20) & 0xF,
|
||||||
|
(in >> 12) & 0xF,
|
||||||
|
(in >> 4) & 0xF
|
||||||
|
};
|
||||||
|
return (x[0] << 12) | (x[1] << 8) | (x[2] << 4) | (x[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT32 Convert::Uint4x4ToUint8x4(UINT16 in)
|
||||||
|
{
|
||||||
|
int x[4] =
|
||||||
|
{
|
||||||
|
(in >> 12) & 0xF,
|
||||||
|
(in >> 8) & 0xF,
|
||||||
|
(in >> 4) & 0xF,
|
||||||
|
(in >> 0) & 0xF
|
||||||
|
};
|
||||||
|
return (x[0] << 28) | (x[1] << 20) | (x[2] << 12) | (x[3] << 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT32 Convert::Color16To32(UINT16 in)
|
||||||
|
{
|
||||||
|
const int b = ((in >> 0) & 0x1F) << 3;
|
||||||
|
const int g = ((in >> 5) & 0x3F) << 2;
|
||||||
|
const int r = ((in >> 11) & 0x1F) << 3;
|
||||||
|
return VERUS_COLOR_RGBA(r, g, b, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Convert::ColorInt32ToFloat(UINT32 in, float* out, bool sRGB)
|
||||||
|
{
|
||||||
|
const float gamma = sRGB ? 2.2f : 1.f;
|
||||||
|
out[0] = pow(float(int((in >> 0) & 0xFF))*(1 / 255.f), gamma);
|
||||||
|
out[1] = pow(float(int((in >> 8) & 0xFF))*(1 / 255.f), gamma);
|
||||||
|
out[2] = pow(float(int((in >> 16) & 0xFF))*(1 / 255.f), gamma);
|
||||||
|
out[3] = float(int((in >> 24) & 0xFF))*(1 / 255.f);
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT32 Convert::ColorFloatToInt32(const float* in, bool sRGB)
|
||||||
|
{
|
||||||
|
const float gamma = sRGB ? 1 / 2.2f : 1.f;
|
||||||
|
const int r = Math::Clamp(int(pow(in[0], gamma)*255.5f), 0, 255);
|
||||||
|
const int g = Math::Clamp(int(pow(in[1], gamma)*255.5f), 0, 255);
|
||||||
|
const int b = Math::Clamp(int(pow(in[2], gamma)*255.5f), 0, 255);
|
||||||
|
const int a = Math::Clamp(int(in[3] * 255.5f), 0, 255);
|
||||||
|
return VERUS_COLOR_RGBA(r, g, b, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Convert::ColorTextToFloat4(CSZ sz, float* out, bool sRGB)
|
||||||
|
{
|
||||||
|
int color[4] = {};
|
||||||
|
if (!sz)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
else if (6 == strlen(sz) && !strchr(sz, ' '))
|
||||||
|
{
|
||||||
|
color[0] = Str::ByteFromHex(sz + 0);
|
||||||
|
color[1] = Str::ByteFromHex(sz + 2);
|
||||||
|
color[2] = Str::ByteFromHex(sz + 4);
|
||||||
|
color[3] = 255;
|
||||||
|
}
|
||||||
|
else if (8 == strlen(sz) && !strchr(sz, ' '))
|
||||||
|
{
|
||||||
|
color[0] = Str::ByteFromHex(sz + 0);
|
||||||
|
color[1] = Str::ByteFromHex(sz + 2);
|
||||||
|
color[2] = Str::ByteFromHex(sz + 4);
|
||||||
|
color[3] = Str::ByteFromHex(sz + 6);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const int num = sscanf(sz, "%d %d %d %d",
|
||||||
|
color + 0,
|
||||||
|
color + 1,
|
||||||
|
color + 2,
|
||||||
|
color + 3);
|
||||||
|
if (3 == num)
|
||||||
|
color[3] = 255;
|
||||||
|
}
|
||||||
|
const float gamma = sRGB ? 2.2f : 1.f;
|
||||||
|
out[0] = pow(float(color[0])*(1 / 255.f), gamma);
|
||||||
|
out[1] = pow(float(color[1])*(1 / 255.f), gamma);
|
||||||
|
out[2] = pow(float(color[2])*(1 / 255.f), gamma);
|
||||||
|
out[3] = float(color[3])*(1 / 255.f);
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT32 Convert::ColorTextToInt32(CSZ sz)
|
||||||
|
{
|
||||||
|
int color[4] = {};
|
||||||
|
if (6 == strlen(sz) && !strchr(sz, ' '))
|
||||||
|
{
|
||||||
|
color[0] = Str::ByteFromHex(sz + 0);
|
||||||
|
color[1] = Str::ByteFromHex(sz + 2);
|
||||||
|
color[2] = Str::ByteFromHex(sz + 4);
|
||||||
|
color[3] = 255;
|
||||||
|
}
|
||||||
|
else if (8 == strlen(sz) && !strchr(sz, ' '))
|
||||||
|
{
|
||||||
|
color[0] = Str::ByteFromHex(sz + 0);
|
||||||
|
color[1] = Str::ByteFromHex(sz + 2);
|
||||||
|
color[2] = Str::ByteFromHex(sz + 4);
|
||||||
|
color[3] = Str::ByteFromHex(sz + 6);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sscanf(sz, "%d %d %d %d",
|
||||||
|
color + 0,
|
||||||
|
color + 1,
|
||||||
|
color + 2,
|
||||||
|
color + 3);
|
||||||
|
}
|
||||||
|
return VERUS_COLOR_RGBA(color[0], color[1], color[2], color[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Convert::ToCorrectNormal(const char* in, char* out)
|
||||||
|
{
|
||||||
|
// For UBYTE4 type normal:
|
||||||
|
// OpenGL glNormalPointer() only accepts signed bytes (GL_BYTE)
|
||||||
|
// Direct3D only accepts unsigned bytes (D3DDECLTYPE_UBYTE4) So it goes.
|
||||||
|
//VERUS_QREF_RENDER;
|
||||||
|
//if (CGL::RENDERER_OPENGL != render.GetRenderer())
|
||||||
|
//{
|
||||||
|
// VERUS_FOR(i, 3)
|
||||||
|
// out[i] = in[i] + 125;
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT32 Convert::ToCorrectColor(UINT32 in)
|
||||||
|
{
|
||||||
|
// OpenGL stores color as RGBA. Direct3D 9 as BGRA.
|
||||||
|
// See also GL_EXT_vertex_array_bgra.
|
||||||
|
//VERUS_QREF_RENDER;
|
||||||
|
//return (CGL::RENDERER_DIRECT3D9 == render.GetRenderer()) ? VERUS_COLOR_TO_D3D(in) : in;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Convert::ByteToChar3(const BYTE* in, char* out)
|
||||||
|
{
|
||||||
|
VERUS_FOR(i, 3)
|
||||||
|
out[i] = int(in[i]) - 125;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Convert::ByteToShort3(const BYTE* in, short* out)
|
||||||
|
{
|
||||||
|
VERUS_FOR(i, 3)
|
||||||
|
out[i] = (int(in[i]) << 8) - 32000;
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT16 Convert::QuantizeFloat(float f, float mn, float mx)
|
||||||
|
{
|
||||||
|
const float range = mx - mn;
|
||||||
|
return UINT16(Math::Clamp((f - mn) / range * USHRT_MAX, 0.f, float(USHRT_MAX)));
|
||||||
|
}
|
||||||
|
|
||||||
|
float Convert::DequantizeFloat(UINT16 i, float mn, float mx)
|
||||||
|
{
|
||||||
|
const float range = mx - mn;
|
||||||
|
return float(i) / USHRT_MAX * range + mn;
|
||||||
|
}
|
||||||
|
|
||||||
|
BYTE Convert::QuantizeFloatToByte(float f, float mn, float mx)
|
||||||
|
{
|
||||||
|
const float range = mx - mn;
|
||||||
|
return BYTE(Math::Clamp((f - mn) / range * UCHAR_MAX, 0.f, float(UCHAR_MAX)));
|
||||||
|
}
|
||||||
|
|
||||||
|
float Convert::DequantizeFloatFromByte(BYTE i, float mn, float mx)
|
||||||
|
{
|
||||||
|
const float range = mx - mn;
|
||||||
|
return float(i) / UCHAR_MAX * range + mn;
|
||||||
|
}
|
||||||
|
|
||||||
|
String Convert::ToBase64(const Vector<BYTE>& vBin)
|
||||||
|
{
|
||||||
|
Vector<char> vBase64;
|
||||||
|
vBase64.resize(vBin.size() * 2);
|
||||||
|
base64_encodestate state;
|
||||||
|
base64_init_encodestate(&state);
|
||||||
|
const int len = base64_encode_block(reinterpret_cast<CSZ>(vBin.data()), Utils::Cast32(vBin.size()), vBase64.data(), &state);
|
||||||
|
const int len2 = base64_encode_blockend(&vBase64[len], &state);
|
||||||
|
vBase64.resize(len + len2);
|
||||||
|
return String(vBase64.begin(), vBase64.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector<BYTE> Convert::ToBinFromBase64(CSZ base64)
|
||||||
|
{
|
||||||
|
Vector<BYTE> vBin;
|
||||||
|
vBin.resize(strlen(base64));
|
||||||
|
base64_decodestate state;
|
||||||
|
base64_init_decodestate(&state);
|
||||||
|
const int len = base64_decode_block(base64, Utils::Cast32(strlen(base64)), reinterpret_cast<SZ>(vBin.data()), &state);
|
||||||
|
vBin.resize(len);
|
||||||
|
return vBin;
|
||||||
|
}
|
||||||
|
|
||||||
|
String Convert::ByteToHex(BYTE b)
|
||||||
|
{
|
||||||
|
static const char hexval[] = "0123456789ABCDEF";
|
||||||
|
char ret[3];
|
||||||
|
ret[0] = hexval[(b >> 4) & 0xF];
|
||||||
|
ret[1] = hexval[(b >> 0) & 0xF];
|
||||||
|
ret[2] = 0;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
String Convert::ToHex(const Vector<BYTE>& vBin)
|
||||||
|
{
|
||||||
|
static const char hexval[] = "0123456789ABCDEF";
|
||||||
|
const int num = Utils::Cast32(vBin.size());
|
||||||
|
Vector<char> vHex;
|
||||||
|
vHex.resize(num * 2);
|
||||||
|
VERUS_FOR(i, num)
|
||||||
|
{
|
||||||
|
vHex[(i << 1) + 0] = hexval[(vBin[i] >> 4) & 0xF];
|
||||||
|
vHex[(i << 1) + 1] = hexval[(vBin[i] >> 0) & 0xF];
|
||||||
|
}
|
||||||
|
return String(vHex.begin(), vHex.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector<BYTE> Convert::ToBinFromHex(CSZ hex)
|
||||||
|
{
|
||||||
|
Vector<BYTE> vBin;
|
||||||
|
const size_t len = strlen(hex);
|
||||||
|
if (0 == len || (len & 0x1))
|
||||||
|
return vBin;
|
||||||
|
const int lenBin = Utils::Cast32(len / 2);
|
||||||
|
vBin.resize(lenBin);
|
||||||
|
VERUS_FOR(i, lenBin)
|
||||||
|
{
|
||||||
|
const char hi = hex[(i << 1)];
|
||||||
|
const char lo = hex[(i << 1) + 1];
|
||||||
|
|
||||||
|
if /**/ (hi >= '0' && hi <= '9') vBin[i] = ((hi - '0')) << 4;
|
||||||
|
else if (hi >= 'a' && hi <= 'f') vBin[i] = ((hi - 'a') + 10) << 4;
|
||||||
|
else if (hi >= 'A' && hi <= 'F') vBin[i] = ((hi - 'A') + 10) << 4;
|
||||||
|
|
||||||
|
if /**/ (lo >= '0' && lo <= '9') vBin[i] |= (lo - '0');
|
||||||
|
else if (lo >= 'a' && lo <= 'f') vBin[i] |= (lo - 'a') + 10;
|
||||||
|
else if (lo >= 'A' && lo <= 'F') vBin[i] |= (lo - 'A') + 10;
|
||||||
|
}
|
||||||
|
return vBin;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector<BYTE> Convert::ToMd5(const Vector<BYTE>& vBin)
|
||||||
|
{
|
||||||
|
MD5Hash md5;
|
||||||
|
md5.update(vBin.data(), Utils::Cast32(vBin.size()));
|
||||||
|
md5.finalize();
|
||||||
|
|
||||||
|
Vector<BYTE> vOut = ToBinFromHex(_C(md5.hexdigest()));
|
||||||
|
return vOut;
|
||||||
|
}
|
||||||
|
|
||||||
|
String Convert::ToMd5String(const Vector<BYTE>& vBin)
|
||||||
|
{
|
||||||
|
return ToHex(ToMd5(vBin));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Convert::Test()
|
||||||
|
{
|
||||||
|
BYTE dataUint8[] = { 0, 127, 255 };
|
||||||
|
UINT16 dataUint16[] = { 0, 127, 65535, 65534 };
|
||||||
|
char dataSint8[] = { 64, -127, -128 };
|
||||||
|
short dataSint16[] = { 32767, -32766, -32768, -32767 };
|
||||||
|
float dataFloat[4];
|
||||||
|
|
||||||
|
Uint8ToUnorm(dataUint8, dataFloat, 3);
|
||||||
|
UnormToUint8(dataFloat, dataUint8, 3);
|
||||||
|
Uint16ToUnorm(dataUint16, dataFloat, 4);
|
||||||
|
UnormToUint16(dataFloat, dataUint16, 4);
|
||||||
|
Sint8ToSnorm(dataSint8, dataFloat, 3);
|
||||||
|
SnormToSint8(dataFloat, dataSint8, 3);
|
||||||
|
Sint16ToSnorm(dataSint16, dataFloat, 4);
|
||||||
|
SnormToSint16(dataFloat, dataSint16, 4);
|
||||||
|
|
||||||
|
Vector<BYTE> vBin;
|
||||||
|
vBin.resize(16);
|
||||||
|
|
||||||
|
Random random;
|
||||||
|
random.NextArray(vBin);
|
||||||
|
|
||||||
|
const String base64 = ToBase64(vBin);
|
||||||
|
const Vector<BYTE> vBinBase64 = ToBinFromBase64(_C(base64));
|
||||||
|
|
||||||
|
const String hex = ToHex(vBin);
|
||||||
|
const Vector<BYTE> vBinHex = ToBinFromHex(_C(hex));
|
||||||
|
|
||||||
|
VERUS_RT_ASSERT(std::equal(vBin.begin(), vBin.end(), vBinHex.begin()));
|
||||||
|
VERUS_RT_ASSERT(std::equal(vBin.begin(), vBin.end(), vBinBase64.begin()));
|
||||||
|
|
||||||
|
CSZ txt = "Hello World 1! Hello World 2! Hello World 3!";
|
||||||
|
vBin.assign(txt, txt + strlen(txt));
|
||||||
|
const Vector<BYTE> vMd5 = ToMd5(vBin);
|
||||||
|
const String md5 = ToMd5String(vBin);
|
||||||
|
VERUS_RT_ASSERT(md5 == "C84AAFD3D09E719514977BF3624F4D85");
|
||||||
|
}
|
|
@ -0,0 +1,82 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace verus
|
||||||
|
{
|
||||||
|
//! This class converts different data types.
|
||||||
|
class Convert
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Single floating-point to integer:
|
||||||
|
static BYTE UnormToUint8(float x);
|
||||||
|
static UINT16 UnormToUint16(float x);
|
||||||
|
static char SnormToSint8(float x);
|
||||||
|
static short SnormToSint16(float x);
|
||||||
|
|
||||||
|
// Single integer to Floating-point:
|
||||||
|
static float Uint8ToUnorm(BYTE x);
|
||||||
|
static float Uint16ToUnorm(UINT16 x);
|
||||||
|
static float Sint8ToSnorm(char x);
|
||||||
|
static float Sint16ToSnorm(short x);
|
||||||
|
|
||||||
|
// Array of floating-points to integers:
|
||||||
|
static void UnormToUint8(const float* pIn, BYTE* pOut, int num);
|
||||||
|
static void UnormToUint16(const float* pIn, UINT16* pOut, int num);
|
||||||
|
static void SnormToSint8(const float* pIn, char* pOut, int num);
|
||||||
|
static void SnormToSint16(const float* pIn, short* pOut, int num);
|
||||||
|
|
||||||
|
// Array of integers to floating-points:
|
||||||
|
static void Uint8ToUnorm(const BYTE* pIn, float* pOut, int num);
|
||||||
|
static void Uint16ToUnorm(const UINT16* pIn, float* pOut, int num);
|
||||||
|
static void Sint8ToSnorm(const char* pIn, float* pOut, int num);
|
||||||
|
static void Sint16ToSnorm(const short* pIn, float* pOut, int num);
|
||||||
|
|
||||||
|
// Integers to integers:
|
||||||
|
static short Sint8ToSint16(char x);
|
||||||
|
static char Sint16ToSint8(short x);
|
||||||
|
static void Sint8ToSint16(const char* pIn, short* pOut, int num);
|
||||||
|
static void Sint16ToSint8(const short* pIn, char* pOut, int num);
|
||||||
|
|
||||||
|
/* ??? */ static void ToDeviceNormal(const char* pIn, char* pOut);
|
||||||
|
/* ??? */ static UINT32 ToDeviceColor(UINT32 color);
|
||||||
|
|
||||||
|
/* ??? */ static float Byte256ToSFloat(BYTE in);
|
||||||
|
|
||||||
|
// 4 bits per channel:
|
||||||
|
static UINT16 Uint8x4ToUint4x4(UINT32 in);
|
||||||
|
static UINT32 Uint4x4ToUint8x4(UINT16 in);
|
||||||
|
|
||||||
|
// Colors:
|
||||||
|
static UINT32 Color16To32(UINT16 in);
|
||||||
|
static void ColorInt32ToFloat(UINT32 in, float* out, bool sRGB = true);
|
||||||
|
static UINT32 ColorFloatToInt32(const float* in, bool sRGB = true);
|
||||||
|
static void ColorTextToFloat4(CSZ sz, float* out, bool sRGB = true);
|
||||||
|
static UINT32 ColorTextToInt32(CSZ sz);
|
||||||
|
|
||||||
|
// Floating-point quantization:
|
||||||
|
static UINT16 QuantizeFloat(float f, float mn, float mx);
|
||||||
|
static float DequantizeFloat(UINT16 i, float mn, float mx);
|
||||||
|
static BYTE QuantizeFloatToByte(float f, float mn, float mx);
|
||||||
|
static float DequantizeFloatFromByte(BYTE i, float mn, float mx);
|
||||||
|
|
||||||
|
/* ??? */ static void ToCorrectNormal(const char* in, char* out);
|
||||||
|
/* ??? */ static UINT32 ToCorrectColor(UINT32 in);
|
||||||
|
|
||||||
|
/* ??? */ static void ByteToChar3(const BYTE* in, char* out);
|
||||||
|
/* ??? */ static void ByteToShort3(const BYTE* in, short* out);
|
||||||
|
|
||||||
|
// Base64:
|
||||||
|
static String ToBase64(const Vector<BYTE>& vBin);
|
||||||
|
static Vector<BYTE> ToBinFromBase64(CSZ base64);
|
||||||
|
|
||||||
|
// Hexadecimal:
|
||||||
|
static String ByteToHex(BYTE b);
|
||||||
|
static String ToHex(const Vector<BYTE>& vBin);
|
||||||
|
static Vector<BYTE> ToBinFromHex(CSZ hex);
|
||||||
|
|
||||||
|
// MD5:
|
||||||
|
static Vector<BYTE> ToMd5(const Vector<BYTE>& vBin);
|
||||||
|
static String ToMd5String(const Vector<BYTE>& vBin);
|
||||||
|
|
||||||
|
static void Test();
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,122 @@
|
||||||
|
#include "verus.h"
|
||||||
|
|
||||||
|
using namespace verus;
|
||||||
|
|
||||||
|
void EngineInit::Make()
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
if (_makeUtils)
|
||||||
|
Make_Utils();
|
||||||
|
if (_makeNet)
|
||||||
|
Make_Net();
|
||||||
|
if (_makeIO)
|
||||||
|
Make_IO();
|
||||||
|
if (_makeInput)
|
||||||
|
Make_Input();
|
||||||
|
if (_makeAudio)
|
||||||
|
Make_Audio();
|
||||||
|
if (_makeCGL)
|
||||||
|
Make_CGL();
|
||||||
|
if (_makePhysics)
|
||||||
|
Make_Physics();
|
||||||
|
if (_makeEffects)
|
||||||
|
Make_Effects();
|
||||||
|
if (_makeExtra)
|
||||||
|
Make_Extra();
|
||||||
|
if (_makeScene)
|
||||||
|
Make_Scene();
|
||||||
|
if (_makeGUI)
|
||||||
|
Make_GUI();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void EngineInit::Free()
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
if (_makeGUI)
|
||||||
|
Free_GUI();
|
||||||
|
if (_makeScene)
|
||||||
|
Free_Scene();
|
||||||
|
if (_makeExtra)
|
||||||
|
Free_Extra();
|
||||||
|
if (_makeEffects)
|
||||||
|
Free_Effects();
|
||||||
|
if (_makePhysics)
|
||||||
|
Free_Physics();
|
||||||
|
if (_makeCGL)
|
||||||
|
Free_CGL();
|
||||||
|
if (_makeAudio)
|
||||||
|
Free_Audio();
|
||||||
|
if (_makeInput)
|
||||||
|
Free_Input();
|
||||||
|
if (_makeIO)
|
||||||
|
Free_IO();
|
||||||
|
if (_makeNet)
|
||||||
|
Free_Net();
|
||||||
|
if (_makeUtils)
|
||||||
|
Free_Utils();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void EngineInit::Init(Input::PKeyMapperDelegate pKeyMapperDelegate, CGI::RenderDelegate* pRenderDelegate, bool createWindow)
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
if (_makeUtils)
|
||||||
|
Utils::CTimer::I().Init();
|
||||||
|
|
||||||
|
if (_makeIO)
|
||||||
|
IO::CAsync::I().Init();
|
||||||
|
|
||||||
|
// "A.P.I.":
|
||||||
|
if (_makeAudio)
|
||||||
|
Audio::CAudio::I().Init();
|
||||||
|
if (_makePhysics)
|
||||||
|
Physics::CBullet::I().Init();
|
||||||
|
if (_makeInput)
|
||||||
|
{
|
||||||
|
Input::CKeyMapper::I().Init();
|
||||||
|
Input::CKeyMapper::I().SetDelegate(pKeyMapperDelegate);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_makeCGL)
|
||||||
|
{
|
||||||
|
CGL::CRender::I().Init(pRenderDelegate, createWindow);
|
||||||
|
#ifdef _WIN32
|
||||||
|
CGL::CRender::InitWin32(_C(CUtils::I().GetWritablePath()), 101);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Static init:
|
||||||
|
if (_makeEffects)
|
||||||
|
Effects::CParticles::InitStatic();
|
||||||
|
if (_makeGUI)
|
||||||
|
GUI::CFont::InitStatic();
|
||||||
|
if (_makeScene)
|
||||||
|
{
|
||||||
|
Scene::CMesh::InitStatic();
|
||||||
|
Scene::CTerrain::InitStatic();
|
||||||
|
Scene::CForest::InitStatic();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helpers:
|
||||||
|
if (_makeCGL)
|
||||||
|
CGL::CDebugRender::I().Init();
|
||||||
|
if (_makeScene)
|
||||||
|
Scene::CHelpers::I().Init();
|
||||||
|
|
||||||
|
// Effects:
|
||||||
|
if (_makeEffects)
|
||||||
|
{
|
||||||
|
Effects::CBlur::I().Init();
|
||||||
|
Effects::CBloom::I().Init();
|
||||||
|
Effects::CSsao::I().Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Materials & textures:
|
||||||
|
if (_makeScene)
|
||||||
|
Scene::CMaterialManager::I().Init();
|
||||||
|
|
||||||
|
if (_makeGUI)
|
||||||
|
GUI::CGUI::I().Init();
|
||||||
|
#endif
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace verus
|
||||||
|
{
|
||||||
|
namespace Input
|
||||||
|
{
|
||||||
|
struct KeyMapperDelegate;
|
||||||
|
}
|
||||||
|
namespace CGI
|
||||||
|
{
|
||||||
|
struct RenderDelegate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace verus
|
||||||
|
{
|
||||||
|
class EngineInit
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool _makeUtils = true;
|
||||||
|
bool _makeNet = true;
|
||||||
|
bool _makeIO = true;
|
||||||
|
bool _makeInput = true;
|
||||||
|
bool _makeAudio = true;
|
||||||
|
bool _makeCGL = true;
|
||||||
|
bool _makePhysics = true;
|
||||||
|
bool _makeEffects = true;
|
||||||
|
bool _makeExtra = false;
|
||||||
|
bool _makeScene = true;
|
||||||
|
bool _makeGUI = true;
|
||||||
|
|
||||||
|
void Make();
|
||||||
|
void Free();
|
||||||
|
|
||||||
|
void Init(Input::KeyMapperDelegate* pKeyMapperDelegate, CGI::RenderDelegate* pRenderDelegate, bool createWindow);
|
||||||
|
};
|
||||||
|
VERUS_TYPEDEFS(EngineInit);
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace verus
|
||||||
|
{
|
||||||
|
template<typename T, typename = std::enable_if_t<std::is_enum<T>::value>, typename U = std::underlying_type_t<T>>
|
||||||
|
inline U operator&(T a, T b)
|
||||||
|
{
|
||||||
|
return static_cast<U>(a)&static_cast<U>(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, typename = std::enable_if_t<std::is_enum<T>::value>, typename U = std::underlying_type_t<T>>
|
||||||
|
inline T operator|(T a, T b)
|
||||||
|
{
|
||||||
|
return static_cast<T>(static_cast<U>(a) | static_cast<U>(b));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, typename = std::enable_if_t<std::is_enum<T>::value>, typename U = std::underlying_type_t<T>>
|
||||||
|
inline T& operator&=(T& a, T b)
|
||||||
|
{
|
||||||
|
a = static_cast<T>(static_cast<U>(a)&static_cast<U>(b));
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, typename = std::enable_if_t<std::is_enum<T>::value>, typename U = std::underlying_type_t<T>>
|
||||||
|
inline T& operator|=(T& a, T b)
|
||||||
|
{
|
||||||
|
a = static_cast<T>(static_cast<U>(a) | static_cast<U>(b));
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, typename = std::enable_if_t<std::is_enum<T>::value>, typename U = std::underlying_type_t<T>>
|
||||||
|
inline T operator~(T a)
|
||||||
|
{
|
||||||
|
return static_cast<T>(~static_cast<U>(a));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, typename = std::enable_if_t<std::is_enum<T>::value>, typename U = std::underlying_type_t<T>>
|
||||||
|
inline U operator+(T a)
|
||||||
|
{
|
||||||
|
return static_cast<U>(a);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
#include "verus.h"
|
||||||
|
|
||||||
|
int g_numSingletonAlloc;
|
||||||
|
|
||||||
|
namespace verus
|
||||||
|
{
|
||||||
|
void Make_Global()
|
||||||
|
{
|
||||||
|
Timer::Make();
|
||||||
|
}
|
||||||
|
void Free_Global()
|
||||||
|
{
|
||||||
|
Timer::Free();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define VERUS_MEMORY_ALIGNMENT 16
|
||||||
|
|
||||||
|
#include "BaseAllocator.h"
|
||||||
|
#include "AlignedAllocator.h"
|
||||||
|
#include "STL.h"
|
||||||
|
#include "Store.h"
|
||||||
|
#include "Blob.h"
|
||||||
|
#include "Random.h"
|
||||||
|
#include "Utils.h"
|
||||||
|
#include "Parallel.h"
|
||||||
|
#include "Range.h"
|
||||||
|
#include "Object.h"
|
||||||
|
#include "Lockable.h"
|
||||||
|
#include "Linear.h"
|
||||||
|
#include "Str.h"
|
||||||
|
#include "Convert.h"
|
||||||
|
#include "Timer.h"
|
||||||
|
#include "EngineInit.h"
|
||||||
|
|
||||||
|
namespace verus
|
||||||
|
{
|
||||||
|
void Make_Global();
|
||||||
|
void Free_Global();
|
||||||
|
}
|
|
@ -0,0 +1,103 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace verus
|
||||||
|
{
|
||||||
|
template<typename T>
|
||||||
|
class Linear
|
||||||
|
{
|
||||||
|
T _value;
|
||||||
|
T _speed;
|
||||||
|
T _min;
|
||||||
|
T _max;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Linear() : _value(0), _speed(0), _min(0), _max(1) {}
|
||||||
|
|
||||||
|
T& GetValue() { return _value; }
|
||||||
|
const T& GetValue() const { return _value; }
|
||||||
|
|
||||||
|
T& GetSpeed() { return _speed; }
|
||||||
|
const T& GetSpeed() const { return _speed; }
|
||||||
|
|
||||||
|
void Set(const T& value, const T& speed)
|
||||||
|
{
|
||||||
|
_value = value;
|
||||||
|
_speed = speed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetValue(const T& value)
|
||||||
|
{
|
||||||
|
_value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetSpeed(const T& speed)
|
||||||
|
{
|
||||||
|
_speed = speed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetLimits(const T& mn, const T& mx)
|
||||||
|
{
|
||||||
|
_min = mn;
|
||||||
|
_max = mx;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Plan(const T& value, float time)
|
||||||
|
{
|
||||||
|
const T delta = value - _value;
|
||||||
|
_speed = delta / time;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpinTo(const T& value, float speed)
|
||||||
|
{
|
||||||
|
if (value >= _value)
|
||||||
|
{
|
||||||
|
_speed = speed;
|
||||||
|
_min = _value;
|
||||||
|
_max = value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_speed = -speed;
|
||||||
|
_min = value;
|
||||||
|
_max = _value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Reverse()
|
||||||
|
{
|
||||||
|
_speed = -_speed;
|
||||||
|
if (_speed >= 0)
|
||||||
|
{
|
||||||
|
_max = -_min;
|
||||||
|
_min = _value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_min = -_max;
|
||||||
|
_max = _value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateUnlimited(float dt)
|
||||||
|
{
|
||||||
|
_value += _speed * dt;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateClamped(float dt)
|
||||||
|
{
|
||||||
|
_value += _speed * dt;
|
||||||
|
_value = Math::Clamp(_value, _min, _max);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateClampedV(float dt)
|
||||||
|
{
|
||||||
|
_value += _speed * dt;
|
||||||
|
_value = _value.Clamp(_min, _max);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WrapFloatV()
|
||||||
|
{
|
||||||
|
_value = _value.Mod(1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define VERUS_LOCK(o) std::unique_lock<std::mutex> lock = std::unique_lock<std::mutex>((o).GetMutex())
|
||||||
|
#define VERUS_LOCK_EX(o, no) std::unique_lock<std::mutex> lock = no ?\
|
||||||
|
std::unique_lock<std::mutex>((o).GetMutex(), std::defer_lock) : std::unique_lock<std::mutex>((o).GetMutex())
|
||||||
|
|
||||||
|
namespace verus
|
||||||
|
{
|
||||||
|
class Lockable
|
||||||
|
{
|
||||||
|
std::mutex _mutex;
|
||||||
|
|
||||||
|
public:
|
||||||
|
std::mutex& GetMutex() { return _mutex; }
|
||||||
|
};
|
||||||
|
VERUS_TYPEDEFS(Lockable);
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define VERUS_CRNL "\r\n"
|
||||||
|
#define VERUS_WHITESPACE " \t\r\n"
|
||||||
|
|
||||||
|
#define VERUS_ARRAY_LENGTH(x) (sizeof(x)/sizeof(x[0]))
|
||||||
|
#define VERUS_LITERAL_LENGTH(x) (sizeof(x)-1)
|
||||||
|
#define VERUS_ZERO_MEM(x) memset(&x, 0, sizeof(x))
|
||||||
|
|
||||||
|
#define VERUS_BUFFER_OFFSET(x) ((char*)nullptr+(x))
|
||||||
|
|
||||||
|
#define VERUS_BITMASK_SET(flags, mask) ((flags) |= (mask))
|
||||||
|
#define VERUS_BITMASK_UNSET(flags, mask) ((flags) &= ~(mask))
|
||||||
|
|
||||||
|
#define VERUS_MAIN_DEFAULT_ARGS int argc, char* argv[]
|
||||||
|
|
||||||
|
#define VERUS_P(x) private: x; public:
|
||||||
|
#define VERUS_PD(x) protected: x; private:
|
||||||
|
#define VERUS_FRIEND(c, type) friend c type; type
|
||||||
|
|
||||||
|
#define VERUS_SMART_DELETE(p) {if(p) {delete p; p = nullptr;}}
|
||||||
|
#define VERUS_SMART_DELETE_ARRAY(p) {if(p) {delete [] p; p = nullptr;}}
|
||||||
|
|
||||||
|
#define _C(x) ((x).c_str())
|
||||||
|
|
||||||
|
#define VERUS_P_FOR(i, to) Parallel::For(0, to, [&](int i)
|
||||||
|
#define VERUS_FOR(i, to) for(int i = 0; i < to; ++i)
|
||||||
|
#define VERUS_FOREACH(T, v, it) for(T::iterator it=(v).begin(), itEnd=(v).end(); it!=itEnd; ++it)
|
||||||
|
#define VERUS_FOREACH_CONST(T, v, it) for(T::const_iterator it=(v).begin(), itEnd=(v).end(); it!=itEnd; ++it)
|
||||||
|
#define VERUS_FOREACH_REVERSE(T, v, it) for(T::reverse_iterator it=(v).rbegin(), itEnd=(v).rend(); it!=itEnd; ++it)
|
||||||
|
#define VERUS_FOREACH_REVERSE_CONST(T, v, it) for(T::const_reverse_iterator it=(v).rbegin(), itEnd=(v).rend(); it!=itEnd; ++it)
|
||||||
|
#define VERUS_FOREACH_X(T, v, it) for(T::iterator it=(v).begin(), itEnd=(v).end(); it!=itEnd;)
|
||||||
|
#define VERUS_FOREACH_X_CONST(T, v, it) for(T::const_iterator it=(v).begin(), itEnd=(v).end(); it!=itEnd;)
|
||||||
|
#define VERUS_FOREACH_X_REVERSE(T, v, it) for(T::reverse_iterator it=(v).rbegin(), itEnd=(v).rend(); it!=itEnd;)
|
||||||
|
#define VERUS_FOREACH_X_REVERSE_CONST(T, v, it) for(T::const_reverse_iterator it=(v).rbegin(), itEnd=(v).rend(); it!=itEnd;)
|
||||||
|
// For loops with erase() use this:
|
||||||
|
#define VERUS_WHILE(T, v, it) T::iterator it=(v).begin(); while(it!=(v).end())
|
||||||
|
|
||||||
|
#define VERUS_IF_FOUND_IN(T, map, x, it)\
|
||||||
|
auto it = map.find(x);\
|
||||||
|
if(it != map.end())
|
||||||
|
|
||||||
|
#define VERUS_TYPEDEFS(x)\
|
||||||
|
typedef x& R##x;\
|
||||||
|
typedef const x& Rc##x;\
|
||||||
|
typedef x* P##x;\
|
||||||
|
typedef const x* Pc##x
|
||||||
|
|
||||||
|
// Circular buffer's size must be power of two:
|
||||||
|
#define VERUS_CIRCULAR_ADD(x, mx)\
|
||||||
|
x++;\
|
||||||
|
x &= mx-1
|
||||||
|
#define VERUS_CIRCULAR_IS_FULL(r, w, mx)\
|
||||||
|
(((w+1)&(mx-1)) == r)
|
||||||
|
|
||||||
|
// Colors:
|
||||||
|
#define VERUS_COLOR_RGBA(r,g,b,a) ((UINT32)((((a)&0xFF)<<24)|(((b)&0xFF)<<16)|(((g)&0xFF)<<8)|((r)&0xFF)))
|
||||||
|
#define VERUS_COLOR_TO_D3D(color) (((color)&0xFF00FF00)|(((color)>>16)&0xFF)|(((color)&0xFF)<<16))
|
||||||
|
#define VERUS_COLOR_WHITE VERUS_COLOR_RGBA(255, 255, 255, 255)
|
||||||
|
#define VERUS_COLOR_BLACK VERUS_COLOR_RGBA(0, 0, 0, 255)
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
# define VERUS_SDL_CENTERED _putenv("SDL_VIDEO_WINDOW_POS"); _putenv("SDL_VIDEO_CENTERED=1")
|
||||||
|
#else
|
||||||
|
# define VERUS_SDL_CENTERED putenv("SDL_VIDEO_WINDOW_POS"); putenv("SDL_VIDEO_CENTERED=1")
|
||||||
|
#endif
|
|
@ -0,0 +1,39 @@
|
||||||
|
#include "verus.h"
|
||||||
|
|
||||||
|
using namespace verus;
|
||||||
|
|
||||||
|
Object::Object()
|
||||||
|
{
|
||||||
|
_flags = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Object::~Object()
|
||||||
|
{
|
||||||
|
VERUS_RT_ASSERT(!IsInitialized());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Object::Init()
|
||||||
|
{
|
||||||
|
VERUS_RT_ASSERT(!IsInitialized());
|
||||||
|
SetFlag(ObjectFlags::init);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Object::Done()
|
||||||
|
{
|
||||||
|
_flags = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef VERUS_DEBUG
|
||||||
|
void Object::UpdateOnceCheck()
|
||||||
|
{
|
||||||
|
const UINT32 numFrames = CGL::CRender::I().GetNumFrames();
|
||||||
|
VERUS_RT_ASSERT(_updateOnceFrame <= numFrames);
|
||||||
|
_updateOnceFrame = numFrames + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Object::UpdateOnceCheckDraw()
|
||||||
|
{
|
||||||
|
const UINT32 numFrames = CGL::CRender::I().GetNumFrames();
|
||||||
|
VERUS_RT_ASSERT(_updateOnceFrame > numFrames);
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -0,0 +1,57 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef VERUS_DEBUG
|
||||||
|
# define VERUS_UPDATE_ONCE_CHECK UpdateOnceCheck()
|
||||||
|
# define VERUS_UPDATE_ONCE_CHECK_DRAW UpdateOnceCheckDraw()
|
||||||
|
#else
|
||||||
|
# define VERUS_UPDATE_ONCE_CHECK
|
||||||
|
# define VERUS_UPDATE_ONCE_CHECK_DRAW
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define VERUS_INIT()\
|
||||||
|
Object::Init();
|
||||||
|
|
||||||
|
#define VERUS_DONE(x)\
|
||||||
|
if(Object::IsInitialized()) {\
|
||||||
|
Object::Done();\
|
||||||
|
this->~x();\
|
||||||
|
new(this) x();}
|
||||||
|
|
||||||
|
namespace verus
|
||||||
|
{
|
||||||
|
struct ObjectFlags
|
||||||
|
{
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
init = (1 << 0),
|
||||||
|
user = (1 << 1)
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
class Object
|
||||||
|
{
|
||||||
|
std::atomic_uint _flags;
|
||||||
|
#ifdef VERUS_DEBUG
|
||||||
|
UINT32 _updateOnceFrame = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Object();
|
||||||
|
virtual ~Object();
|
||||||
|
|
||||||
|
void Init();
|
||||||
|
void Done();
|
||||||
|
|
||||||
|
#ifdef VERUS_DEBUG
|
||||||
|
void UpdateOnceCheck();
|
||||||
|
void UpdateOnceCheckDraw();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool IsInitialized() const { return _flags & ObjectFlags::init; }
|
||||||
|
|
||||||
|
bool IsFlagSet(UINT32 mask) const { return !!(_flags&mask); }
|
||||||
|
void SetFlag(UINT32 mask) { _flags |= mask; }
|
||||||
|
void ResetFlag(UINT32 mask) { _flags &= ~mask; }
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace verus
|
||||||
|
{
|
||||||
|
class Parallel
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
template<typename TFunc>
|
||||||
|
static void For(int from, int to, TFunc func, int minTime = 10, int minShare = 1)
|
||||||
|
{
|
||||||
|
const int total = to - from;
|
||||||
|
VERUS_RT_ASSERT(minShare <= total);
|
||||||
|
const UINT32 numCoresLimit = total / minShare;
|
||||||
|
const int numCores = Math::Min(std::thread::hardware_concurrency(), numCoresLimit);
|
||||||
|
const int numExThreads = numCores - 1;
|
||||||
|
const int share = total / numCores;
|
||||||
|
const int extra = total - share * numExThreads;
|
||||||
|
std::vector<std::thread> v;
|
||||||
|
v.reserve(numExThreads);
|
||||||
|
const std::chrono::high_resolution_clock::time_point t0 = std::chrono::high_resolution_clock::now();
|
||||||
|
VERUS_FOR(i, numExThreads)
|
||||||
|
{
|
||||||
|
v.push_back(std::thread([i, share, func]()
|
||||||
|
{
|
||||||
|
const int from = share * i;
|
||||||
|
const int to = from + share;
|
||||||
|
for (int j = from; j < to; ++j)
|
||||||
|
func(j);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const int from = share * numExThreads;
|
||||||
|
const int to = from + extra;
|
||||||
|
for (int j = from; j < to; ++j)
|
||||||
|
func(j);
|
||||||
|
}
|
||||||
|
VERUS_FOREACH(std::vector<std::thread>, v, it)
|
||||||
|
it->join();
|
||||||
|
const std::chrono::high_resolution_clock::time_point t1 = std::chrono::high_resolution_clock::now();
|
||||||
|
const std::chrono::milliseconds d = std::chrono::duration_cast<std::chrono::milliseconds>(t1 - t0);
|
||||||
|
//VERUS_RT_ASSERT(d.count() >= minTime);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define VERUS_QREF_ASYNC IO::RAsync async = IO::Async::I()
|
||||||
|
#define VERUS_QREF_ASYS Audio::RAudioSystem asys = Audio::AudioSystem::I()
|
||||||
|
#define VERUS_QREF_ATMO Scene::RAtmosphere atmo = Scene::Atmosphere::I()
|
||||||
|
#define VERUS_QREF_BLOOM Effects::RBloom bloom = Effects::Bloom::I()
|
||||||
|
#define VERUS_QREF_BLUR Effects::RBlur blur = Effects::Blur::I()
|
||||||
|
#define VERUS_QREF_BULLET Physics::RBullet bullet = Physics::Bullet::I()
|
||||||
|
#define VERUS_QREF_CONST_SETTINGS RcSettings settings = CSettings::IConst()
|
||||||
|
#define VERUS_QREF_DEPTH Effects::RDepth depth = Effects::Depth::I()
|
||||||
|
#define VERUS_QREF_DR CGL::RDebugRender dr = CGL::DebugRender::I()
|
||||||
|
#define VERUS_QREF_FSYS IO::RFileSys fsys = IO::FileSys::I()
|
||||||
|
#define VERUS_QREF_GAME Game::RGame game = Game::Game::I()
|
||||||
|
#define VERUS_QREF_GRASS Scene::RGrass grass = Scene::Grass::I()
|
||||||
|
#define VERUS_QREF_GUI GUI::RGUI gui = GUI::GUI::I()
|
||||||
|
#define VERUS_QREF_HELPERS Scene::RHelpers helpers = Scene::Helpers::I()
|
||||||
|
#define VERUS_QREF_KM Input::RKeyMapper km = Input::KeyMapper::I()
|
||||||
|
#define VERUS_QREF_LS Scene::RLandscape ls = Scene::Landscape::I()
|
||||||
|
#define VERUS_QREF_MM Scene::RMaterialManager mm = Scene::MaterialManager::I()
|
||||||
|
#define VERUS_QREF_MP Net::RMultiplayer mp = Net::Multiplayer::I()
|
||||||
|
#define VERUS_QREF_PHYSICS Physics::RPhysics physics = Physics::Physics::I()
|
||||||
|
#define VERUS_QREF_RENDER CGL::RRender render = CGL::Render::I()
|
||||||
|
#define VERUS_QREF_SETTINGS App::RSettings settings = App::Settings::I()
|
||||||
|
#define VERUS_QREF_SM Scene::RSceneManager sm = Scene::SceneManager::I()
|
||||||
|
#define VERUS_QREF_SSAO Effects::RSsao ssao = Effects::Ssao::I()
|
||||||
|
#define VERUS_QREF_TIMER RTimer timer = Timer::I(); const float dt = timer.GetDeltaTime()
|
||||||
|
#define VERUS_QREF_TIMER_GUI RTimer timer = Timer::I(); const float dt = timer.GetDeltaTime(Timer::Type::gui)
|
||||||
|
#define VERUS_QREF_UTILS RUtils utils = Utils::I()
|
||||||
|
#define VERUS_QREF_WATER Scene::RWater water = Scene::Water::I()
|
|
@ -0,0 +1,56 @@
|
||||||
|
#include "verus.h"
|
||||||
|
|
||||||
|
using namespace verus;
|
||||||
|
|
||||||
|
Random::Random()
|
||||||
|
{
|
||||||
|
std::random_device rd;
|
||||||
|
Seed(rd());
|
||||||
|
}
|
||||||
|
|
||||||
|
Random::Random(UINT32 seed) :
|
||||||
|
_mt(seed)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Random::~Random()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT32 Random::Next()
|
||||||
|
{
|
||||||
|
return _mt();
|
||||||
|
}
|
||||||
|
|
||||||
|
double Random::NextDouble()
|
||||||
|
{
|
||||||
|
return static_cast<double>(Next()) / std::numeric_limits<UINT32>::max();
|
||||||
|
}
|
||||||
|
|
||||||
|
float Random::NextFloat()
|
||||||
|
{
|
||||||
|
return static_cast<float>(Next()) / std::numeric_limits<UINT32>::max();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Random::NextArray(UINT32* p, int num)
|
||||||
|
{
|
||||||
|
VERUS_FOR(i, num)
|
||||||
|
p[i] = Next();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Random::NextArray(float* p, int num)
|
||||||
|
{
|
||||||
|
VERUS_FOR(i, num)
|
||||||
|
p[i] = NextFloat();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Random::NextArray(Vector<BYTE>& v)
|
||||||
|
{
|
||||||
|
VERUS_FOREACH(Vector<BYTE>, v, it)
|
||||||
|
*it = Next();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Random::Seed(UINT32 seed)
|
||||||
|
{
|
||||||
|
_mt.seed(seed);
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace verus
|
||||||
|
{
|
||||||
|
class Random
|
||||||
|
{
|
||||||
|
std::mt19937 _mt;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Random();
|
||||||
|
Random(UINT32 seed);
|
||||||
|
~Random();
|
||||||
|
|
||||||
|
UINT32 Next();
|
||||||
|
double NextDouble();
|
||||||
|
float NextFloat();
|
||||||
|
|
||||||
|
void NextArray(UINT32* p, int num);
|
||||||
|
void NextArray(float* p, int num);
|
||||||
|
void NextArray(Vector<BYTE>& v);
|
||||||
|
|
||||||
|
std::mt19937& GetGenerator() { return _mt; }
|
||||||
|
|
||||||
|
void Seed(UINT32 seed);
|
||||||
|
};
|
||||||
|
VERUS_TYPEDEFS(Random);
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace verus
|
||||||
|
{
|
||||||
|
template<typename T>
|
||||||
|
class Range
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
T _min;
|
||||||
|
T _max;
|
||||||
|
|
||||||
|
Range() : _min(0), _max(0) {}
|
||||||
|
Range(T x) : _min(x), _max(x) {}
|
||||||
|
Range(T mn, T mx) : _min(mn), _max(mx) { VERUS_RT_ASSERT(_min <= _max); }
|
||||||
|
|
||||||
|
T GetRange() const { return _max - _min; }
|
||||||
|
T GetRandomValue() const { return _min + Utils::I().GetRandom().NextFloat()*GetRange(); }
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,112 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace verus
|
||||||
|
{
|
||||||
|
//! Custom allocator for the Standard Template Library. Will try to use the allocator provided by Utils.
|
||||||
|
template<typename T>
|
||||||
|
class AllocatorAwareSTL
|
||||||
|
{
|
||||||
|
void operator=(const AllocatorAwareSTL&);
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef T value_type;
|
||||||
|
typedef size_t size_type;
|
||||||
|
typedef ptrdiff_t difference_type;
|
||||||
|
typedef T* pointer;
|
||||||
|
typedef const T* const_pointer;
|
||||||
|
typedef T& reference;
|
||||||
|
typedef const T& const_reference;
|
||||||
|
|
||||||
|
AllocatorAwareSTL() {}
|
||||||
|
AllocatorAwareSTL(const AllocatorAwareSTL&) {}
|
||||||
|
~AllocatorAwareSTL() {}
|
||||||
|
|
||||||
|
template<typename _Other>
|
||||||
|
AllocatorAwareSTL(const AllocatorAwareSTL<_Other>& other) {}
|
||||||
|
|
||||||
|
template<typename U>
|
||||||
|
struct rebind
|
||||||
|
{
|
||||||
|
typedef AllocatorAwareSTL<U> other;
|
||||||
|
};
|
||||||
|
|
||||||
|
pointer address(reference r) const
|
||||||
|
{
|
||||||
|
return &r;
|
||||||
|
}
|
||||||
|
|
||||||
|
const_pointer address(const_reference r) const
|
||||||
|
{
|
||||||
|
return &r;
|
||||||
|
}
|
||||||
|
|
||||||
|
pointer allocate(size_type n)
|
||||||
|
{
|
||||||
|
pointer p = static_cast<pointer>(AllocatorAware::UtilsMalloc(n * sizeof(value_type)));
|
||||||
|
if (p)
|
||||||
|
{
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p = static_cast<pointer>(malloc(n * sizeof(value_type)));
|
||||||
|
char txt[80];
|
||||||
|
sprintf_s(txt, "allocate(), malloc() 0x%p", p);
|
||||||
|
VERUS_LOG_DEBUG(txt);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void deallocate(pointer p, size_type)
|
||||||
|
{
|
||||||
|
if (!AllocatorAware::UtilsFree(p))
|
||||||
|
{
|
||||||
|
char txt[80];
|
||||||
|
sprintf_s(txt, "deallocate(), free() 0x%p", p);
|
||||||
|
VERUS_LOG_DEBUG(txt);
|
||||||
|
free(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void construct(pointer p, const value_type& val)
|
||||||
|
{
|
||||||
|
new(p)value_type(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
void destroy(pointer p)
|
||||||
|
{
|
||||||
|
p->~value_type();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_type max_size() const
|
||||||
|
{
|
||||||
|
return ULONG_MAX / sizeof(value_type);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//! This function will compare two allocators.
|
||||||
|
template<typename T>
|
||||||
|
bool operator==(const AllocatorAwareSTL<T>& l, const AllocatorAwareSTL<T>& r)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! This function will compare two allocators.
|
||||||
|
template<typename T>
|
||||||
|
bool operator!=(const AllocatorAwareSTL<T>& l, const AllocatorAwareSTL<T>& r)
|
||||||
|
{
|
||||||
|
return !(l == r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace verus
|
||||||
|
{
|
||||||
|
template<typename T> using Vector = std::vector <T, AllocatorAwareSTL<T>>;
|
||||||
|
template<typename T> using List = std::list <T, AllocatorAwareSTL<T>>;
|
||||||
|
template<typename T> using Set = std::set <T, std::less<T>, AllocatorAwareSTL<T>>;
|
||||||
|
template<typename T> using MultiSet = std::multiset <T, std::less<T>, AllocatorAwareSTL<T>>;
|
||||||
|
template<typename T> using HashSet = std::unordered_set <T, std::hash<T>, std::equal_to<T>, AllocatorAwareSTL<T>>;
|
||||||
|
template<typename T, typename U> using Map = std::map <T, U, std::less<T>, AllocatorAwareSTL<T>>;
|
||||||
|
template<typename T, typename U> using MultiMap = std::multimap <T, U, std::less<T>, AllocatorAwareSTL<T>>;
|
||||||
|
template<typename T, typename U> using HashMap = std::unordered_map <T, U, std::hash<T>, std::equal_to<T>, AllocatorAwareSTL<T>>;
|
||||||
|
}
|
|
@ -0,0 +1,74 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
extern int g_numSingletonAlloc;
|
||||||
|
|
||||||
|
namespace verus
|
||||||
|
{
|
||||||
|
//! Restricts the instantiation of a class to one object.
|
||||||
|
template<typename T>
|
||||||
|
class Singleton : public AllocatorAware
|
||||||
|
{
|
||||||
|
static T* s_pSingleton;
|
||||||
|
|
||||||
|
Singleton(const Singleton& that);
|
||||||
|
Singleton& operator=(const Singleton& that);
|
||||||
|
|
||||||
|
public:
|
||||||
|
Singleton()
|
||||||
|
{
|
||||||
|
s_pSingleton = static_cast<T*>(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~Singleton()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void Make()
|
||||||
|
{
|
||||||
|
if (s_pSingleton)
|
||||||
|
return;
|
||||||
|
new T();
|
||||||
|
g_numSingletonAlloc++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void Free()
|
||||||
|
{
|
||||||
|
if (s_pSingleton)
|
||||||
|
{
|
||||||
|
g_numSingletonAlloc--;
|
||||||
|
delete s_pSingleton;
|
||||||
|
}
|
||||||
|
s_pSingleton = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline T& I() { Test(); return *s_pSingleton; }
|
||||||
|
static inline T* P() { Test(); return s_pSingleton; }
|
||||||
|
|
||||||
|
static inline const T& IConst() { Test(); return *s_pSingleton; }
|
||||||
|
static inline const T* PConst() { Test(); return s_pSingleton; }
|
||||||
|
|
||||||
|
static inline bool IsValidSingleton()
|
||||||
|
{
|
||||||
|
return s_pSingleton != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void Assign(T* p) { s_pSingleton = p; }
|
||||||
|
|
||||||
|
static inline void Test()
|
||||||
|
{
|
||||||
|
#ifdef _DEBUG
|
||||||
|
//if (!IsValidSingleton())
|
||||||
|
// VERUS_LOG_DEBUG(T::GetSingletonFailMessage());
|
||||||
|
//VERUS_RT_ASSERT(s_pSingleton);
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline CSZ GetSingletonFailMessage() { return "Singleton FAIL.\r\n"; }
|
||||||
|
|
||||||
|
static inline void TestAllocCount()
|
||||||
|
{
|
||||||
|
//VERUS_RT_ASSERT(!g_numSingletonAlloc);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
template<typename T> T* Singleton<T>::s_pSingleton = nullptr;
|
||||||
|
}
|
|
@ -0,0 +1,177 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace verus
|
||||||
|
{
|
||||||
|
//! A convenient way to store a collection of objects.
|
||||||
|
|
||||||
|
//! It's a good idea not to use new/delete explicitly. Use STL allocator.
|
||||||
|
//! 'Unique' class uses map and supports reference counting.
|
||||||
|
//! The Insert method returns a raw pointer which should be wrapped inside a Ptr.
|
||||||
|
//!
|
||||||
|
//! Types of pointers:
|
||||||
|
//! - raw pointer - very dumb, no automatic initialization.
|
||||||
|
//! - Ptr wrapper - like a smart pointer, but even smarter.
|
||||||
|
//! - Pwn wrapper - owning Ptr, basically calls Done in destructor.
|
||||||
|
//! Use Ptr for function parameters. Use Pwn for class members.
|
||||||
|
//!
|
||||||
|
template<typename TValue>
|
||||||
|
class Store
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
typedef List<TValue> TList;
|
||||||
|
|
||||||
|
TList _list;
|
||||||
|
|
||||||
|
public:
|
||||||
|
TValue* Insert()
|
||||||
|
{
|
||||||
|
_list.emplace_back();
|
||||||
|
return &_list.back();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Delete(TValue* p)
|
||||||
|
{
|
||||||
|
_list.remove_if([p](const TValue& v)
|
||||||
|
{
|
||||||
|
return p == &v;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeleteAll()
|
||||||
|
{
|
||||||
|
_list.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
TValue& GetStoredAt(int index)
|
||||||
|
{
|
||||||
|
auto it = _list.begin();
|
||||||
|
std::advance(it, index);
|
||||||
|
return *it;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetNumStored() const
|
||||||
|
{
|
||||||
|
return _list.size();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename TKey, typename TValue>
|
||||||
|
class StoreUnique
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
typedef Map<TKey, TValue> TMap;
|
||||||
|
|
||||||
|
TMap _map;
|
||||||
|
|
||||||
|
public:
|
||||||
|
TValue* Insert(const TKey& key)
|
||||||
|
{
|
||||||
|
VERUS_IF_FOUND_IN(TMap, _map, key, it)
|
||||||
|
{
|
||||||
|
it->second.AddRef();
|
||||||
|
return &it->second;
|
||||||
|
}
|
||||||
|
return &_map[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
TValue* Find(const TKey& key)
|
||||||
|
{
|
||||||
|
VERUS_IF_FOUND_IN(TMap, _map, key, it)
|
||||||
|
return &it->second;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Delete(const TKey& key)
|
||||||
|
{
|
||||||
|
VERUS_IF_FOUND_IN(TMap, _map, key, it)
|
||||||
|
{
|
||||||
|
if (it->second.Done())
|
||||||
|
_map.erase(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeleteAll()
|
||||||
|
{
|
||||||
|
for (auto& x : _map)
|
||||||
|
{
|
||||||
|
while (!x.second.Done());
|
||||||
|
}
|
||||||
|
_map.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
TValue& GetStoredAt(int index)
|
||||||
|
{
|
||||||
|
auto it = _map.begin();
|
||||||
|
std::advance(it, index);
|
||||||
|
return *it;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetNumStored() const
|
||||||
|
{
|
||||||
|
return _map.size();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class Ptr
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
T* _p;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Ptr(T* p = nullptr) : _p(p) {}
|
||||||
|
~Ptr() {}
|
||||||
|
|
||||||
|
T& operator*() const { return *_p; }
|
||||||
|
T* operator->() const { return _p; }
|
||||||
|
explicit operator bool() const { return !!_p; }
|
||||||
|
bool operator==(const Ptr<T>& that) const { return _p == that._p; }
|
||||||
|
bool operator!=(const Ptr<T>& that) const { return _p != that._p; }
|
||||||
|
bool operator<(const Ptr<T>& that) const { return _p < that._p; }
|
||||||
|
T* Attach(T* ptr)
|
||||||
|
{
|
||||||
|
T* p = _p;
|
||||||
|
_p = ptr;
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
T* Detach()
|
||||||
|
{
|
||||||
|
T* p = _p;
|
||||||
|
_p = nullptr;
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T, int NUM>
|
||||||
|
class Pwns
|
||||||
|
{
|
||||||
|
T _t[NUM];
|
||||||
|
|
||||||
|
public:
|
||||||
|
Pwns()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~Pwns()
|
||||||
|
{
|
||||||
|
Done();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Done()
|
||||||
|
{
|
||||||
|
VERUS_FOR(i, NUM)
|
||||||
|
_t[i].Done();
|
||||||
|
}
|
||||||
|
|
||||||
|
const T& operator[](int i) const
|
||||||
|
{
|
||||||
|
VERUS_RT_ASSERT(i >= 0 && i < NUM);
|
||||||
|
return _t[i];
|
||||||
|
}
|
||||||
|
T& operator[](int i)
|
||||||
|
{
|
||||||
|
VERUS_RT_ASSERT(i >= 0 && i < NUM);
|
||||||
|
return _t[i];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue