Start CMake modernization scaffold

This commit is contained in:
2026-05-31 23:40:43 +02:00
parent ee027984b7
commit c38ff8209b
36 changed files with 2118 additions and 1556 deletions

2
.gitignore vendored
View File

@@ -53,3 +53,5 @@ linux/Makefile
webgl/build
webgl/.vscode
out/

164
CMakeLists.txt Normal file
View File

@@ -0,0 +1,164 @@
cmake_minimum_required(VERSION 3.29)
project(PanoPainter
VERSION 0.0.0
DESCRIPTION "Panoramic painting and animation application"
LANGUAGES C CXX)
if(POLICY CMP0091)
cmake_policy(SET CMP0091 NEW)
endif()
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>DLL")
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
include(PanoPainterOptions)
include(PanoPainterWarnings)
include(PanoPainterSources)
include(PanoPainterVersion)
if(PP_ENABLE_CLANG_TIDY)
find_program(PP_CLANG_TIDY_EXE NAMES clang-tidy)
if(PP_CLANG_TIDY_EXE)
set(CMAKE_CXX_CLANG_TIDY "${PP_CLANG_TIDY_EXE}")
else()
message(WARNING "PP_ENABLE_CLANG_TIDY is ON but clang-tidy was not found.")
endif()
endif()
if(PP_ENABLE_CPPCHECK)
find_program(PP_CPPCHECK_EXE NAMES cppcheck)
if(PP_CPPCHECK_EXE)
set(CMAKE_CXX_CPPCHECK
"${PP_CPPCHECK_EXE}"
"--enable=warning,style,performance,portability"
"--inline-suppr"
"--suppress=missingIncludeSystem")
else()
message(WARNING "PP_ENABLE_CPPCHECK is ON but cppcheck was not found.")
endif()
endif()
add_library(pp_project_options INTERFACE)
target_compile_features(pp_project_options INTERFACE cxx_std_23)
add_library(pp_project_warnings INTERFACE)
pp_configure_project_warnings(pp_project_warnings)
add_custom_target(panopainter_modernization_status
COMMAND "${CMAKE_COMMAND}" -E echo "PanoPainter modernization scaffold configured."
COMMAND "${CMAKE_COMMAND}" -E echo "Roadmap: docs/modernization/roadmap.md"
COMMAND "${CMAKE_COMMAND}" -E echo "Debt log: docs/modernization/debt.md"
VERBATIM)
add_library(pp_foundation STATIC
src/foundation/binary_stream.cpp)
target_include_directories(pp_foundation
PUBLIC
"${CMAKE_CURRENT_SOURCE_DIR}/src")
target_link_libraries(pp_foundation
PUBLIC
pp_project_options
PRIVATE
pp_project_warnings)
if(PP_BUILD_TOOLS)
add_subdirectory(tools/pano_cli)
endif()
if(PP_BUILD_TESTS)
enable_testing()
add_subdirectory(tests)
endif()
if(PP_BUILD_APP)
if(WIN32)
add_library(pp_legacy_app STATIC
${PP_LEGACY_APP_SOURCES}
${PP_VENDOR_SOURCES})
target_link_libraries(pp_legacy_app
PUBLIC
pp_project_options
PRIVATE
pp_project_warnings)
target_include_directories(pp_legacy_app
PUBLIC
${PP_LEGACY_INCLUDE_DIRS})
target_compile_definitions(pp_legacy_app
PUBLIC
ENUM_BITFIELDS_NOT_SUPPORTED
UNICODE
_UNICODE
_CRT_SECURE_NO_WARNINGS
_SCL_SECURE_NO_WARNINGS
_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING
_SILENCE_STDEXT_ARR_ITERS_DEPRECATION_WARNING
_CONSOLE
WITH_CURL=1)
set_target_properties(pp_legacy_app PROPERTIES
VS_GLOBAL_CharacterSet "Unicode")
target_precompile_headers(pp_legacy_app PRIVATE src/pch.h)
set_source_files_properties(${PP_VENDOR_SOURCES}
PROPERTIES SKIP_PRECOMPILE_HEADERS ON)
set_source_files_properties(src/version.cpp
PROPERTIES SKIP_PRECOMPILE_HEADERS ON)
add_executable(PanoPainter WIN32
${PP_WINDOWS_APP_SOURCES})
target_link_libraries(PanoPainter
PRIVATE
pp_project_options
pp_project_warnings
pp_legacy_app
"${CMAKE_CURRENT_SOURCE_DIR}/libs/bugtrap-client/lib/BugTrapU-x64.lib"
"$<$<CONFIG:Debug>:${CMAKE_CURRENT_SOURCE_DIR}/libs/curl-win/lib/dll-debug-x64/libcurl_debug.lib>"
"$<$<NOT:$<CONFIG:Debug>>:${CMAKE_CURRENT_SOURCE_DIR}/libs/curl-win/lib/dll-release-x64/libcurl.lib>"
"${CMAKE_CURRENT_SOURCE_DIR}/libs/libyuv/lib/win/yuv.lib"
"${CMAKE_CURRENT_SOURCE_DIR}/libs/mp4v2/lib/win/libmp4v2.lib"
"${CMAKE_CURRENT_SOURCE_DIR}/libs/openh264/lib/openh264-2.0.0-win64.lib"
"${CMAKE_CURRENT_SOURCE_DIR}/libs/openvr/lib/win64/openvr_api.lib"
comdlg32
gdi32
opengl32
ole32
shell32
shlwapi
user32
wbemuuid)
target_precompile_headers(PanoPainter REUSE_FROM pp_legacy_app)
set_target_properties(PanoPainter PROPERTIES
VS_GLOBAL_CharacterSet "Unicode")
pp_add_version_generation(PanoPainter "$<IF:$<CONFIG:Debug>,debug,release>")
add_custom_command(TARGET PanoPainter POST_BUILD
COMMAND "${CMAKE_COMMAND}" -E copy_directory
"${CMAKE_CURRENT_SOURCE_DIR}/data"
"$<TARGET_FILE_DIR:PanoPainter>/data"
COMMAND "${CMAKE_COMMAND}" -E copy_if_different
"${CMAKE_CURRENT_SOURCE_DIR}/libs/bugtrap-client/lib/BugTrapU-x64.dll"
"$<TARGET_FILE_DIR:PanoPainter>/BugTrapU-x64.dll"
COMMAND "${CMAKE_COMMAND}" -E copy_if_different
"$<$<CONFIG:Debug>:${CMAKE_CURRENT_SOURCE_DIR}/libs/curl-win/lib/dll-debug-x64/libcurl_debug.dll>$<$<NOT:$<CONFIG:Debug>>:${CMAKE_CURRENT_SOURCE_DIR}/libs/curl-win/lib/dll-release-x64/libcurl.dll>"
"$<TARGET_FILE_DIR:PanoPainter>/"
COMMAND "${CMAKE_COMMAND}" -E copy_if_different
"${CMAKE_CURRENT_SOURCE_DIR}/libs/libyuv/lib/win/libyuv.dll"
"$<TARGET_FILE_DIR:PanoPainter>/libyuv.dll"
COMMAND "${CMAKE_COMMAND}" -E copy_if_different
"${CMAKE_CURRENT_SOURCE_DIR}/libs/mp4v2/lib/win/libmp4v2.dll"
"$<TARGET_FILE_DIR:PanoPainter>/libmp4v2.dll"
COMMAND "${CMAKE_COMMAND}" -E copy_if_different
"${CMAKE_CURRENT_SOURCE_DIR}/libs/openh264/lib/openh264-2.0.0-win64.dll"
"$<TARGET_FILE_DIR:PanoPainter>/openh264-2.0.0-win64.dll"
VERBATIM)
else()
message(WARNING "PP_BUILD_APP is enabled, but the root CMake app target is currently Windows-only. Platform alignment is tracked in Phase 6.")
endif()
endif()

174
CMakePresets.json Normal file
View File

@@ -0,0 +1,174 @@
{
"version": 8,
"cmakeMinimumRequired": {
"major": 3,
"minor": 29,
"patch": 0
},
"configurePresets": [
{
"name": "base",
"hidden": true,
"binaryDir": "${sourceDir}/out/build/${presetName}",
"cacheVariables": {
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON",
"PP_BUILD_APP": "ON",
"PP_BUILD_TESTS": "ON",
"PP_BUILD_TOOLS": "ON",
"PP_ENABLE_OPENGL": "ON",
"PP_ENABLE_VULKAN_EXPERIMENTAL": "OFF",
"PP_ENABLE_VR": "ON",
"PP_ENABLE_CLOUD": "ON",
"PP_ENABLE_VIDEO": "ON"
}
},
{
"name": "windows-vs2026-x64",
"inherits": "base",
"displayName": "Windows VS 2026 x64",
"generator": "Visual Studio 18 2026",
"architecture": "x64"
},
{
"name": "windows-msvc-default",
"inherits": "base",
"displayName": "Windows MSVC default generator",
"architecture": "x64"
},
{
"name": "windows-clangcl-asan",
"inherits": "base",
"displayName": "Windows clang-cl ASan",
"generator": "Ninja",
"toolset": "ClangCL",
"cacheVariables": {
"CMAKE_C_COMPILER": "clang-cl",
"CMAKE_CXX_COMPILER": "clang-cl",
"PP_ENABLE_ASAN": "ON",
"PP_ENABLE_UBSAN": "OFF"
}
},
{
"name": "linux-clang",
"inherits": "base",
"displayName": "Linux clang",
"generator": "Ninja",
"cacheVariables": {
"CMAKE_C_COMPILER": "clang",
"CMAKE_CXX_COMPILER": "clang++"
}
},
{
"name": "android-arm64",
"inherits": "base",
"displayName": "Android arm64-v8a",
"generator": "Ninja",
"cacheVariables": {
"ANDROID_ABI": "arm64-v8a",
"ANDROID_PLATFORM": "android-26"
}
},
{
"name": "android-x64",
"inherits": "base",
"displayName": "Android x86_64",
"generator": "Ninja",
"cacheVariables": {
"ANDROID_ABI": "x86_64",
"ANDROID_PLATFORM": "android-26"
}
},
{
"name": "emscripten",
"inherits": "base",
"displayName": "Emscripten WebGL",
"generator": "Ninja",
"cacheVariables": {
"PP_ENABLE_VR": "OFF",
"PP_ENABLE_VIDEO": "OFF"
}
},
{
"name": "macos",
"inherits": "base",
"displayName": "macOS",
"generator": "Ninja"
},
{
"name": "ios-device",
"inherits": "base",
"displayName": "iOS device",
"generator": "Xcode",
"cacheVariables": {
"CMAKE_SYSTEM_NAME": "iOS",
"CMAKE_OSX_SYSROOT": "iphoneos"
}
},
{
"name": "ios-simulator",
"inherits": "base",
"displayName": "iOS simulator",
"generator": "Xcode",
"cacheVariables": {
"CMAKE_SYSTEM_NAME": "iOS",
"CMAKE_OSX_SYSROOT": "iphonesimulator"
}
}
],
"buildPresets": [
{
"name": "windows-vs2026-x64",
"configurePreset": "windows-vs2026-x64"
},
{
"name": "windows-msvc-default",
"configurePreset": "windows-msvc-default"
},
{
"name": "windows-clangcl-asan",
"configurePreset": "windows-clangcl-asan"
},
{
"name": "linux-clang",
"configurePreset": "linux-clang"
}
],
"testPresets": [
{
"name": "desktop-fast",
"configurePreset": "windows-msvc-default",
"output": {
"outputOnFailure": true
},
"filter": {
"exclude": {
"label": "gpu|slow|platform"
}
}
},
{
"name": "desktop-fast-vs2026",
"configurePreset": "windows-vs2026-x64",
"output": {
"outputOnFailure": true
},
"filter": {
"exclude": {
"label": "gpu|slow|platform"
}
}
},
{
"name": "desktop-gpu",
"configurePreset": "windows-msvc-default",
"output": {
"outputOnFailure": true
},
"filter": {
"include": {
"label": "gpu"
}
}
}
]
}

View File

@@ -1,57 +0,0 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.28010.2026
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PanoPainter", "PanoPainter.vcxproj", "{6D5028CE-4D76-4B6A-A7C2-DE5A3268D433}"
EndProject
Project("{C7167F0D-BC9F-4E6E-AFE1-012C56B48DB5}") = "PanoPainterPackage", "PanoPainterPackage\PanoPainterPackage.wapproj", "{3A716FB6-DE62-439F-83B6-3C40915D6678}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{6D5028CE-4D76-4B6A-A7C2-DE5A3268D433}.Debug|Any CPU.ActiveCfg = Debug|Win32
{6D5028CE-4D76-4B6A-A7C2-DE5A3268D433}.Debug|x64.ActiveCfg = Debug|x64
{6D5028CE-4D76-4B6A-A7C2-DE5A3268D433}.Debug|x64.Build.0 = Debug|x64
{6D5028CE-4D76-4B6A-A7C2-DE5A3268D433}.Debug|x64.Deploy.0 = Debug|x64
{6D5028CE-4D76-4B6A-A7C2-DE5A3268D433}.Debug|x86.ActiveCfg = Debug|Win32
{6D5028CE-4D76-4B6A-A7C2-DE5A3268D433}.Debug|x86.Build.0 = Debug|Win32
{6D5028CE-4D76-4B6A-A7C2-DE5A3268D433}.Release|Any CPU.ActiveCfg = Release|Win32
{6D5028CE-4D76-4B6A-A7C2-DE5A3268D433}.Release|x64.ActiveCfg = Release|x64
{6D5028CE-4D76-4B6A-A7C2-DE5A3268D433}.Release|x64.Build.0 = Release|x64
{6D5028CE-4D76-4B6A-A7C2-DE5A3268D433}.Release|x64.Deploy.0 = Release|x64
{6D5028CE-4D76-4B6A-A7C2-DE5A3268D433}.Release|x86.ActiveCfg = Release|Win32
{6D5028CE-4D76-4B6A-A7C2-DE5A3268D433}.Release|x86.Build.0 = Release|Win32
{3A716FB6-DE62-439F-83B6-3C40915D6678}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3A716FB6-DE62-439F-83B6-3C40915D6678}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3A716FB6-DE62-439F-83B6-3C40915D6678}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
{3A716FB6-DE62-439F-83B6-3C40915D6678}.Debug|x64.ActiveCfg = Debug|x64
{3A716FB6-DE62-439F-83B6-3C40915D6678}.Debug|x64.Build.0 = Debug|x64
{3A716FB6-DE62-439F-83B6-3C40915D6678}.Debug|x64.Deploy.0 = Debug|x64
{3A716FB6-DE62-439F-83B6-3C40915D6678}.Debug|x86.ActiveCfg = Debug|x86
{3A716FB6-DE62-439F-83B6-3C40915D6678}.Debug|x86.Build.0 = Debug|x86
{3A716FB6-DE62-439F-83B6-3C40915D6678}.Debug|x86.Deploy.0 = Debug|x86
{3A716FB6-DE62-439F-83B6-3C40915D6678}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3A716FB6-DE62-439F-83B6-3C40915D6678}.Release|Any CPU.Build.0 = Release|Any CPU
{3A716FB6-DE62-439F-83B6-3C40915D6678}.Release|Any CPU.Deploy.0 = Release|Any CPU
{3A716FB6-DE62-439F-83B6-3C40915D6678}.Release|x64.ActiveCfg = Release|x64
{3A716FB6-DE62-439F-83B6-3C40915D6678}.Release|x64.Build.0 = Release|x64
{3A716FB6-DE62-439F-83B6-3C40915D6678}.Release|x64.Deploy.0 = Release|x64
{3A716FB6-DE62-439F-83B6-3C40915D6678}.Release|x86.ActiveCfg = Release|x86
{3A716FB6-DE62-439F-83B6-3C40915D6678}.Release|x86.Build.0 = Release|x86
{3A716FB6-DE62-439F-83B6-3C40915D6678}.Release|x86.Deploy.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {3E8EFC4B-CEA1-4408-8628-7D2C0F6C43C8}
EndGlobalSection
EndGlobal

View File

@@ -1,634 +0,0 @@
<?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|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<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">
<ProjectGuid>{6D5028CE-4D76-4B6A-A7C2-DE5A3268D433}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>PanoPainter</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
<ProjectName>PanoPainter</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</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|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<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|Win32'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>libs\glm;libs\glew-2.0.0\include;libs\stb;libs\tinyxml2;libs\yoga;libs\curl-win\include;libs\jpeg;libs\wacom;C:\Users\omar\Downloads\BugTrap-master\BugTrap-master\source\Client;$(IncludePath)</IncludePath>
<LibraryPath>libs\curl-win\lib\dll-$(Configuration)-$(PlatformShortName);libs\glew-2.0.0\lib\Release\$(Platform);C:\Users\omar\Downloads\BugTrap-master\BugTrap-master\bin;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>libs\glm;libs\glew-2.0.0\include;libs\stb;libs\tinyxml2;libs\yoga;libs\curl-win\include;libs\jpeg;libs\wacom;libs\bugtrap-client\include;libs\poly2tri\poly2tri;libs\base64;libs\sqlite3;libs\openvr\headers;libs\nanort;libs\hash-library;libs\fmt\include;libs\glad\include;libs\openh264\include;libs\mp4v2\include;libs\libyuv\include;C:\Program Files\RenderDoc;$(IncludePath)</IncludePath>
<LibraryPath>libs\curl-win\lib\dll-$(Configuration)-$(PlatformShortName);libs\glew-2.0.0\lib\Release\$(Platform);libs\bugtrap-client\lib;libs\openvr\lib\win64;libs\openh264\lib;libs\mp4v2\lib\win;libs\libyuv\lib\win;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<IncludePath>libs\glm;libs\glew-2.0.0\include;libs\stb;libs\tinyxml2;libs\yoga;libs\curl-win\include;libs\jpeg;libs\wacom;C:\Users\omar\Downloads\BugTrap-master\BugTrap-master\source\Client;$(IncludePath)</IncludePath>
<LibraryPath>libs\curl-win\lib\dll-$(Configuration)-$(PlatformShortName);libs\glew-2.0.0\lib\Release\$(Platform);C:\Users\omar\Downloads\BugTrap-master\BugTrap-master\bin;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<IncludePath>libs\glm;libs\glew-2.0.0\include;libs\stb;libs\tinyxml2;libs\yoga;libs\curl-win\include;libs\jpeg;libs\wacom;libs\bugtrap-client\include;libs\poly2tri\poly2tri;libs\base64;libs\sqlite3;libs\openvr\headers;libs\nanort;libs\hash-library;libs\fmt\include;libs\glad\include;libs\openh264\include;libs\mp4v2\include;libs\libyuv\include;C:\Program Files\RenderDoc;$(IncludePath)</IncludePath>
<LibraryPath>libs\curl-win\lib\dll-$(Configuration)-$(PlatformShortName);libs\glew-2.0.0\lib\Release\$(Platform);libs\bugtrap-client\lib;libs\openvr\lib\win64;libs\openh264\lib;libs\mp4v2\lib\win;libs\libyuv\lib\win;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
<PreBuildEvent>
<Command>
</Command>
</PreBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>ENUM_BITFIELDS_NOT_SUPPORTED;DEBUG;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<ExceptionHandling>false</ExceptionHandling>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
<PreBuildEvent>
<Command>python .\scripts\pre-build.py debug</Command>
</PreBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>Use</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
<PreBuildEvent>
<Command>
</Command>
</PreBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>Use</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>ENUM_BITFIELDS_NOT_SUPPORTED;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<ExceptionHandling>false</ExceptionHandling>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
<PreBuildEvent>
<Command>python .\scripts\pre-build.py release</Command>
</PreBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="libs\fmt\src\format.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="libs\fmt\src\posix.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="libs\glad\src\glad.c">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="libs\glad\src\glad_wgl.c">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="libs\hash-library\md5.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="libs\nanort\nanort.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="libs\sqlite3\sqlite3.c">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="libs\yoga\yoga\event\event.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
<AssemblerListingLocation Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(IntDir)yoga\</AssemblerListingLocation>
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(IntDir)yoga\</ObjectFileName>
<XMLDocumentationFileName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(IntDir)yoga\</XMLDocumentationFileName>
<AssemblerListingLocation Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(IntDir)yoga\</AssemblerListingLocation>
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(IntDir)yoga\</ObjectFileName>
<XMLDocumentationFileName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(IntDir)yoga\</XMLDocumentationFileName>
</ClCompile>
<ClCompile Include="libs\yoga\yoga\internal\experiments.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
<AssemblerListingLocation Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(IntDir)yoga\</AssemblerListingLocation>
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(IntDir)yoga\</ObjectFileName>
<XMLDocumentationFileName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(IntDir)yoga\</XMLDocumentationFileName>
<AssemblerListingLocation Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(IntDir)yoga\</AssemblerListingLocation>
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(IntDir)yoga\</ObjectFileName>
<XMLDocumentationFileName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(IntDir)yoga\</XMLDocumentationFileName>
</ClCompile>
<ClCompile Include="libs\yoga\yoga\log.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
<AssemblerListingLocation Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(IntDir)yoga\</AssemblerListingLocation>
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(IntDir)yoga\</ObjectFileName>
<XMLDocumentationFileName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(IntDir)yoga\</XMLDocumentationFileName>
<AssemblerListingLocation Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(IntDir)yoga\</AssemblerListingLocation>
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(IntDir)yoga\</ObjectFileName>
<XMLDocumentationFileName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(IntDir)yoga\</XMLDocumentationFileName>
</ClCompile>
<ClCompile Include="libs\yoga\yoga\Utils.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
<AssemblerListingLocation Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(IntDir)yoga\</AssemblerListingLocation>
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(IntDir)yoga\</ObjectFileName>
<XMLDocumentationFileName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(IntDir)yoga\</XMLDocumentationFileName>
<AssemblerListingLocation Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(IntDir)yoga\</AssemblerListingLocation>
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(IntDir)yoga\</ObjectFileName>
<XMLDocumentationFileName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(IntDir)yoga\</XMLDocumentationFileName>
</ClCompile>
<ClCompile Include="libs\yoga\yoga\YGConfig.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
<AssemblerListingLocation Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(IntDir)yoga\</AssemblerListingLocation>
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(IntDir)yoga\</ObjectFileName>
<XMLDocumentationFileName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(IntDir)yoga\</XMLDocumentationFileName>
<AssemblerListingLocation Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(IntDir)yoga\</AssemblerListingLocation>
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(IntDir)yoga\</ObjectFileName>
<XMLDocumentationFileName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(IntDir)yoga\</XMLDocumentationFileName>
</ClCompile>
<ClCompile Include="libs\yoga\yoga\YGEnums.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
<AssemblerListingLocation Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(IntDir)yoga\</AssemblerListingLocation>
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(IntDir)yoga\</ObjectFileName>
<XMLDocumentationFileName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(IntDir)yoga\</XMLDocumentationFileName>
<AssemblerListingLocation Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(IntDir)yoga\</AssemblerListingLocation>
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(IntDir)yoga\</ObjectFileName>
<XMLDocumentationFileName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(IntDir)yoga\</XMLDocumentationFileName>
</ClCompile>
<ClCompile Include="libs\yoga\yoga\YGLayout.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
<AssemblerListingLocation Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(IntDir)yoga\</AssemblerListingLocation>
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(IntDir)yoga\</ObjectFileName>
<XMLDocumentationFileName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(IntDir)yoga\</XMLDocumentationFileName>
<AssemblerListingLocation Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(IntDir)yoga\</AssemblerListingLocation>
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(IntDir)yoga\</ObjectFileName>
<XMLDocumentationFileName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(IntDir)yoga\</XMLDocumentationFileName>
</ClCompile>
<ClCompile Include="libs\yoga\yoga\YGNode.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
<AssemblerListingLocation Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(IntDir)yoga\</AssemblerListingLocation>
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(IntDir)yoga\</ObjectFileName>
<XMLDocumentationFileName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(IntDir)yoga\</XMLDocumentationFileName>
<AssemblerListingLocation Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(IntDir)yoga\</AssemblerListingLocation>
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(IntDir)yoga\</ObjectFileName>
<XMLDocumentationFileName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(IntDir)yoga\</XMLDocumentationFileName>
</ClCompile>
<ClCompile Include="libs\yoga\yoga\YGNodePrint.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
<AssemblerListingLocation Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(IntDir)yoga\</AssemblerListingLocation>
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(IntDir)yoga\</ObjectFileName>
<XMLDocumentationFileName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(IntDir)yoga\</XMLDocumentationFileName>
<AssemblerListingLocation Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(IntDir)yoga\</AssemblerListingLocation>
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(IntDir)yoga\</ObjectFileName>
<XMLDocumentationFileName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(IntDir)yoga\</XMLDocumentationFileName>
</ClCompile>
<ClCompile Include="libs\yoga\yoga\YGStyle.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
<AssemblerListingLocation Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(IntDir)yoga\</AssemblerListingLocation>
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(IntDir)yoga\</ObjectFileName>
<XMLDocumentationFileName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(IntDir)yoga\</XMLDocumentationFileName>
<AssemblerListingLocation Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(IntDir)yoga\</AssemblerListingLocation>
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(IntDir)yoga\</ObjectFileName>
<XMLDocumentationFileName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(IntDir)yoga\</XMLDocumentationFileName>
</ClCompile>
<ClCompile Include="libs\yoga\yoga\YGValue.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
<AssemblerListingLocation Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(IntDir)yoga\</AssemblerListingLocation>
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(IntDir)yoga\</ObjectFileName>
<XMLDocumentationFileName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(IntDir)yoga\</XMLDocumentationFileName>
<AssemblerListingLocation Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(IntDir)yoga\</AssemblerListingLocation>
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(IntDir)yoga\</ObjectFileName>
<XMLDocumentationFileName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(IntDir)yoga\</XMLDocumentationFileName>
</ClCompile>
<ClCompile Include="libs\yoga\yoga\Yoga.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
<AssemblerListingLocation Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(IntDir)yoga\</AssemblerListingLocation>
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(IntDir)yoga\</ObjectFileName>
<XMLDocumentationFileName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(IntDir)yoga\</XMLDocumentationFileName>
<AssemblerListingLocation Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(IntDir)yoga\</AssemblerListingLocation>
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(IntDir)yoga\</ObjectFileName>
<XMLDocumentationFileName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(IntDir)yoga\</XMLDocumentationFileName>
</ClCompile>
<ClCompile Include="src\abr.cpp" />
<ClCompile Include="src\action.cpp" />
<ClCompile Include="src\app.cpp" />
<ClCompile Include="src\app_cloud.cpp" />
<ClCompile Include="src\app_commands.cpp" />
<ClCompile Include="src\app_dialogs.cpp" />
<ClCompile Include="src\app_events.cpp" />
<ClCompile Include="src\app_layout.cpp" />
<ClCompile Include="src\app_shaders.cpp" />
<ClCompile Include="src\app_vr.cpp" />
<ClCompile Include="src\asset.cpp" />
<ClCompile Include="src\bezier.cpp" />
<ClCompile Include="src\binary_stream.cpp" />
<ClCompile Include="src\brush.cpp" />
<ClCompile Include="src\canvas.cpp" />
<ClCompile Include="src\canvas_actions.cpp" />
<ClCompile Include="src\canvas_layer.cpp" />
<ClCompile Include="src\canvas_modes.cpp" />
<ClCompile Include="src\event.cpp" />
<ClCompile Include="src\font.cpp" />
<ClCompile Include="src\hmd.cpp" />
<ClCompile Include="src\image.cpp" />
<ClCompile Include="src\layout.cpp" />
<ClCompile Include="src\log.cpp" />
<ClCompile Include="src\main.cpp" />
<ClCompile Include="src\mp4enc.cpp" />
<ClCompile Include="src\node.cpp" />
<ClCompile Include="src\node_about.cpp" />
<ClCompile Include="src\node_border.cpp" />
<ClCompile Include="src\node_button.cpp" />
<ClCompile Include="src\node_button_custom.cpp" />
<ClCompile Include="src\node_canvas.cpp" />
<ClCompile Include="src\node_changelog.cpp" />
<ClCompile Include="src\node_checkbox.cpp" />
<ClCompile Include="src\node_colorwheel.cpp" />
<ClCompile Include="src\node_color_quad.cpp" />
<ClCompile Include="src\node_combobox.cpp" />
<ClCompile Include="src\node_dialog_browse.cpp" />
<ClCompile Include="src\node_dialog_cloud.cpp" />
<ClCompile Include="src\node_dialog_export_ppbr.cpp" />
<ClCompile Include="src\node_dialog_layer_rename.cpp" />
<ClCompile Include="src\node_dialog_open.cpp" />
<ClCompile Include="src\node_dialog_picker.cpp" />
<ClCompile Include="src\node_dialog_resize.cpp" />
<ClCompile Include="src\node_icon.cpp" />
<ClCompile Include="src\node_image.cpp" />
<ClCompile Include="src\node_image_texture.cpp" />
<ClCompile Include="src\node_input_box.cpp" />
<ClCompile Include="src\node_message_box.cpp" />
<ClCompile Include="src\node_metadata.cpp" />
<ClCompile Include="src\node_panel_brush.cpp" />
<ClCompile Include="src\node_panel_color.cpp" />
<ClCompile Include="src\node_panel_floating.cpp" />
<ClCompile Include="src\node_panel_grid.cpp" />
<ClCompile Include="src\node_panel_layer.cpp" />
<ClCompile Include="src\node_panel_quick.cpp" />
<ClCompile Include="src\node_panel_stroke.cpp" />
<ClCompile Include="src\node_panel_animation.cpp" />
<ClCompile Include="src\node_popup_menu.cpp" />
<ClCompile Include="src\node_progress_bar.cpp" />
<ClCompile Include="src\node_remote_page.cpp" />
<ClCompile Include="src\node_scroll.cpp" />
<ClCompile Include="src\node_settings.cpp" />
<ClCompile Include="src\node_shorcuts.cpp" />
<ClCompile Include="src\node_slider.cpp" />
<ClCompile Include="src\node_stroke_preview.cpp" />
<ClCompile Include="src\node_text.cpp" />
<ClCompile Include="src\node_text_input.cpp" />
<ClCompile Include="src\node_tool_bucket.cpp" />
<ClCompile Include="src\node_usermanual.cpp" />
<ClCompile Include="src\node_viewport.cpp" />
<ClCompile Include="src\pch.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="src\rtt.cpp" />
<ClCompile Include="src\serializer.cpp" />
<ClCompile Include="src\settings.cpp" />
<ClCompile Include="src\shader.cpp" />
<ClCompile Include="src\shape.cpp" />
<ClCompile Include="src\texture.cpp" />
<ClCompile Include="src\util.cpp" />
<ClCompile Include="src\version.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="src\wacom.cpp" />
<ClCompile Include="libs\jpeg\jpgd.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="libs\jpeg\jpge.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="libs\poly2tri\poly2tri\common\shapes.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="libs\poly2tri\poly2tri\sweep\advancing_front.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="libs\poly2tri\poly2tri\sweep\cdt.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="libs\poly2tri\poly2tri\sweep\sweep.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="libs\poly2tri\poly2tri\sweep\sweep_context.cc">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="libs\tinyxml2\tinyxml2.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="libs\wacom\WinTab\Utils.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Use</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Use</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Use</PrecompiledHeader>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="libs\hash-library\md5.h" />
<ClInclude Include="libs\nanort\nanort.h" />
<ClInclude Include="libs\sqlite3\sqlite3.h" />
<ClInclude Include="libs\sqlite3\sqlite3ext.h" />
<ClInclude Include="resource.h" />
<ClInclude Include="src\abr.h" />
<ClInclude Include="src\action.h" />
<ClInclude Include="src\app.h" />
<ClInclude Include="src\asset.h" />
<ClInclude Include="src\bezier.h" />
<ClInclude Include="src\binary_stream.h" />
<ClInclude Include="src\brush.h" />
<ClInclude Include="src\canvas.h" />
<ClInclude Include="src\canvas_actions.h" />
<ClInclude Include="src\canvas_layer.h" />
<ClInclude Include="src\canvas_modes.h" />
<ClInclude Include="src\event.h" />
<ClInclude Include="src\font.h" />
<ClInclude Include="src\hmd.h" />
<ClInclude Include="src\image.h" />
<ClInclude Include="src\keymap.h" />
<ClInclude Include="src\layout.h" />
<ClInclude Include="src\log.h" />
<ClInclude Include="src\mp4enc.h" />
<ClInclude Include="src\node.h" />
<ClInclude Include="src\node_about.h" />
<ClInclude Include="src\node_border.h" />
<ClInclude Include="src\node_button.h" />
<ClInclude Include="src\node_button_custom.h" />
<ClInclude Include="src\node_canvas.h" />
<ClInclude Include="src\node_changelog.h" />
<ClInclude Include="src\node_checkbox.h" />
<ClInclude Include="src\node_colorwheel.h" />
<ClInclude Include="src\node_color_quad.h" />
<ClInclude Include="src\node_combobox.h" />
<ClInclude Include="src\node_dialog_browse.h" />
<ClInclude Include="src\node_dialog_cloud.h" />
<ClInclude Include="src\node_dialog_export_ppbr.h" />
<ClInclude Include="src\node_dialog_layer_rename.h" />
<ClInclude Include="src\node_dialog_open.h" />
<ClInclude Include="src\node_dialog_picker.h" />
<ClInclude Include="src\node_dialog_resize.h" />
<ClInclude Include="src\node_icon.h" />
<ClInclude Include="src\node_image.h" />
<ClInclude Include="src\node_image_texture.h" />
<ClInclude Include="src\node_input_box.h" />
<ClInclude Include="src\node_message_box.h" />
<ClInclude Include="src\node_metadata.h" />
<ClInclude Include="src\node_panel_brush.h" />
<ClInclude Include="src\node_panel_color.h" />
<ClInclude Include="src\node_panel_floating.h" />
<ClInclude Include="src\node_panel_grid.h" />
<ClInclude Include="src\node_panel_layer.h" />
<ClInclude Include="src\node_panel_quick.h" />
<ClInclude Include="src\node_panel_stroke.h" />
<ClInclude Include="src\node_panel_animation.h" />
<ClInclude Include="src\node_popup_menu.h" />
<ClInclude Include="src\node_progress_bar.h" />
<ClInclude Include="src\node_remote_page.h" />
<ClInclude Include="src\node_scroll.h" />
<ClInclude Include="src\node_settings.h" />
<ClInclude Include="src\node_shorcuts.h" />
<ClInclude Include="src\node_slider.h" />
<ClInclude Include="src\node_stroke_preview.h" />
<ClInclude Include="src\node_text.h" />
<ClInclude Include="src\node_text_input.h" />
<ClInclude Include="src\node_tool_bucket.h" />
<ClInclude Include="src\node_usermanual.h" />
<ClInclude Include="src\node_viewport.h" />
<ClInclude Include="src\pch.h" />
<ClInclude Include="src\rtt.h" />
<ClInclude Include="src\serializer.h" />
<ClInclude Include="src\settings.h" />
<ClInclude Include="src\shader.h" />
<ClInclude Include="src\shape.h" />
<ClInclude Include="src\texture.h" />
<ClInclude Include="src\util.h" />
<ClInclude Include="src\version.gen.h" />
<ClInclude Include="src\version.h" />
<ClInclude Include="src\wacom.h" />
<ClInclude Include="libs\jpeg\jpgd.h" />
<ClInclude Include="libs\jpeg\jpge.h" />
<ClInclude Include="libs\tinyxml2\tinyxml2.h" />
<ClInclude Include="libs\wacom\WinTab\MSGPACK.H" />
<ClInclude Include="libs\wacom\WinTab\PKTDEF.H" />
<ClInclude Include="libs\wacom\WinTab\Utils.h" />
<ClInclude Include="libs\wacom\WinTab\WINTAB.H" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="PanoPainter.rc" />
</ItemGroup>
<ItemGroup>
<Natvis Include="libs\glm\util\glm.natvis" />
</ItemGroup>
<ItemGroup>
<Xml Include="data\dialogs\about.xml" />
<Xml Include="data\dialogs\brush-export.xml" />
<Xml Include="data\dialogs\changelog.xml" />
<Xml Include="data\dialogs\cloud-browse.xml" />
<Xml Include="data\dialogs\color-picker.xml" />
<Xml Include="data\dialogs\doc-browse.xml" />
<Xml Include="data\dialogs\doc-new.xml" />
<Xml Include="data\dialogs\doc-open.xml" />
<Xml Include="data\dialogs\doc-resize.xml" />
<Xml Include="data\dialogs\doc-save.xml" />
<Xml Include="data\dialogs\input-box.xml" />
<Xml Include="data\dialogs\layer-rename.xml" />
<Xml Include="data\dialogs\message-box.xml" />
<Xml Include="data\dialogs\panel-animation.xml" />
<Xml Include="data\dialogs\panel-floating.xml" />
<Xml Include="data\dialogs\panel-grid.xml" />
<Xml Include="data\dialogs\panel-layers.xml" />
<Xml Include="data\dialogs\panel-brushes.xml" />
<Xml Include="data\dialogs\panel-presets.xml" />
<Xml Include="data\dialogs\panel-quick.xml" />
<Xml Include="data\dialogs\panel-stroke.xml" />
<Xml Include="data\dialogs\progress-bar.xml" />
<Xml Include="data\dialogs\remote-page.xml" />
<Xml Include="data\dialogs\settings.xml" />
<Xml Include="data\dialogs\shortcuts.xml" />
<Xml Include="data\dialogs\usermanual.xml" />
<Xml Include="data\layout.xml">
<SubType>Designer</SubType>
<DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
</DeploymentContent>
</Xml>
</ItemGroup>
<ItemGroup>
<None Include="data\shaders\atlas.glsl" />
<None Include="data\shaders\bake-uv.glsl" />
<None Include="data\shaders\checkerboard.glsl" />
<None Include="data\shaders\color-hue.glsl" />
<None Include="data\shaders\color-quad.glsl" />
<None Include="data\shaders\color-tri.glsl" />
<None Include="data\shaders\color.glsl" />
<None Include="data\shaders\comp-draw.glsl" />
<None Include="data\shaders\comp-erase.glsl" />
<None Include="data\shaders\equirect.glsl" />
<None Include="data\shaders\font.glsl" />
<None Include="data\shaders\include\blend-stroke.glsl" />
<None Include="data\shaders\include\blend.glsl" />
<None Include="data\shaders\include\blur.glsl" />
<None Include="data\shaders\include\color.glsl" />
<None Include="data\shaders\include\ext-fb-fetch.glsl" />
<None Include="data\shaders\include\hsv.glsl" />
<None Include="data\shaders\include\rand.glsl" />
<None Include="data\shaders\lambert.glsl" />
<None Include="data\shaders\lightmap.glsl" />
<None Include="data\shaders\stroke-dilate.glsl" />
<None Include="data\shaders\stroke-instanced.glsl" />
<None Include="data\shaders\stroke-pad.glsl" />
<None Include="data\shaders\stroke-preview.glsl" />
<None Include="data\shaders\stroke.glsl" />
<None Include="data\shaders\texture-alpha.glsl" />
<None Include="data\shaders\texture-blend.glsl" />
<None Include="data\shaders\texture-colorize.glsl" />
<None Include="data\shaders\texture-mask.glsl" />
<None Include="data\shaders\texture.glsl" />
<None Include="data\shaders\uvs.glsl" />
<None Include="data\shaders\vertex-color.glsl" />
</ItemGroup>
<ItemGroup>
<Image Include="icon.ico" />
</ItemGroup>
<ItemGroup>
<Xsd Include="extra\layout.xsd">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</Xsd>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -1,854 +0,0 @@
<?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="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="Source Files\ui">
<UniqueIdentifier>{600b8daa-4234-4c37-b4ba-c22cad7d1dc3}</UniqueIdentifier>
</Filter>
<Filter Include="libs">
<UniqueIdentifier>{6d64b115-02d1-43e0-86c8-c8212f51162d}</UniqueIdentifier>
</Filter>
<Filter Include="libs\jpeg">
<UniqueIdentifier>{dc178d53-6a6d-4a18-a93c-d4994340515f}</UniqueIdentifier>
</Filter>
<Filter Include="libs\WinTab">
<UniqueIdentifier>{54dc9f46-d2e0-466c-90d2-eb5d72d5799d}</UniqueIdentifier>
</Filter>
<Filter Include="libs\yoga">
<UniqueIdentifier>{a4a12057-835e-47ff-be4d-ce58b36cecf5}</UniqueIdentifier>
</Filter>
<Filter Include="libs\tinyxml2">
<UniqueIdentifier>{6fe315aa-e2b9-4f01-8291-683a5fda123b}</UniqueIdentifier>
</Filter>
<Filter Include="libs\poly2tri">
<UniqueIdentifier>{bda6fa93-a186-41ca-9bd9-49b7e0fd1ca4}</UniqueIdentifier>
</Filter>
<Filter Include="extras">
<UniqueIdentifier>{e631ac80-1b9b-424f-8adf-e2bab71a566d}</UniqueIdentifier>
</Filter>
<Filter Include="libs\sqlite3">
<UniqueIdentifier>{ef44d179-f28b-458c-b3df-be2895553149}</UniqueIdentifier>
</Filter>
<Filter Include="libs\nanort">
<UniqueIdentifier>{be0c0053-abd8-4e2d-a294-7c54511b05a6}</UniqueIdentifier>
</Filter>
<Filter Include="libs\hash">
<UniqueIdentifier>{2a784067-6741-47a3-b668-cc45f2224286}</UniqueIdentifier>
</Filter>
<Filter Include="libs\fmt">
<UniqueIdentifier>{7b4f5b47-7a8b-4e4c-9e82-399bb5047ffc}</UniqueIdentifier>
</Filter>
<Filter Include="shaders">
<UniqueIdentifier>{b55fb692-a845-4ef2-9b0e-5b2dd8bd125f}</UniqueIdentifier>
</Filter>
<Filter Include="shaders\include">
<UniqueIdentifier>{a2cacb13-2854-44ee-9511-6cb8ac587428}</UniqueIdentifier>
</Filter>
<Filter Include="libs\glad">
<UniqueIdentifier>{ca37521b-213f-4bcf-acfd-eda1483a30b2}</UniqueIdentifier>
</Filter>
<Filter Include="extras\dialogs">
<UniqueIdentifier>{5ecb54ed-7c3d-46fd-9b5d-227abdbc5954}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\app.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\image.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\main.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\shader.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\shape.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\texture.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\pch.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\font.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\util.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\asset.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\rtt.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\bezier.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\canvas.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\brush.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\log.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\action.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\event.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\canvas_modes.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\node.cpp">
<Filter>Source Files\ui</Filter>
</ClCompile>
<ClCompile Include="src\node_border.cpp">
<Filter>Source Files\ui</Filter>
</ClCompile>
<ClCompile Include="src\node_button.cpp">
<Filter>Source Files\ui</Filter>
</ClCompile>
<ClCompile Include="src\node_button_custom.cpp">
<Filter>Source Files\ui</Filter>
</ClCompile>
<ClCompile Include="src\node_canvas.cpp">
<Filter>Source Files\ui</Filter>
</ClCompile>
<ClCompile Include="src\node_checkbox.cpp">
<Filter>Source Files\ui</Filter>
</ClCompile>
<ClCompile Include="src\node_color_quad.cpp">
<Filter>Source Files\ui</Filter>
</ClCompile>
<ClCompile Include="src\node_dialog_open.cpp">
<Filter>Source Files\ui</Filter>
</ClCompile>
<ClCompile Include="src\node_icon.cpp">
<Filter>Source Files\ui</Filter>
</ClCompile>
<ClCompile Include="src\node_image.cpp">
<Filter>Source Files\ui</Filter>
</ClCompile>
<ClCompile Include="src\node_image_texture.cpp">
<Filter>Source Files\ui</Filter>
</ClCompile>
<ClCompile Include="src\node_message_box.cpp">
<Filter>Source Files\ui</Filter>
</ClCompile>
<ClCompile Include="src\node_panel_brush.cpp">
<Filter>Source Files\ui</Filter>
</ClCompile>
<ClCompile Include="src\node_panel_color.cpp">
<Filter>Source Files\ui</Filter>
</ClCompile>
<ClCompile Include="src\node_panel_layer.cpp">
<Filter>Source Files\ui</Filter>
</ClCompile>
<ClCompile Include="src\node_panel_stroke.cpp">
<Filter>Source Files\ui</Filter>
</ClCompile>
<ClCompile Include="src\node_popup_menu.cpp">
<Filter>Source Files\ui</Filter>
</ClCompile>
<ClCompile Include="src\node_settings.cpp">
<Filter>Source Files\ui</Filter>
</ClCompile>
<ClCompile Include="src\node_slider.cpp">
<Filter>Source Files\ui</Filter>
</ClCompile>
<ClCompile Include="src\node_stroke_preview.cpp">
<Filter>Source Files\ui</Filter>
</ClCompile>
<ClCompile Include="src\node_text.cpp">
<Filter>Source Files\ui</Filter>
</ClCompile>
<ClCompile Include="src\node_text_input.cpp">
<Filter>Source Files\ui</Filter>
</ClCompile>
<ClCompile Include="src\node_viewport.cpp">
<Filter>Source Files\ui</Filter>
</ClCompile>
<ClCompile Include="src\layout.cpp">
<Filter>Source Files\ui</Filter>
</ClCompile>
<ClCompile Include="src\node_scroll.cpp">
<Filter>Source Files\ui</Filter>
</ClCompile>
<ClCompile Include="src\app_shaders.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\app_layout.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\app_events.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="libs\jpeg\jpgd.cpp">
<Filter>libs\jpeg</Filter>
</ClCompile>
<ClCompile Include="libs\jpeg\jpge.cpp">
<Filter>libs\jpeg</Filter>
</ClCompile>
<ClCompile Include="libs\tinyxml2\tinyxml2.cpp">
<Filter>libs\tinyxml2</Filter>
</ClCompile>
<ClCompile Include="src\wacom.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="libs\wacom\WinTab\Utils.cpp">
<Filter>libs\WinTab</Filter>
</ClCompile>
<ClCompile Include="src\node_dialog_layer_rename.cpp">
<Filter>Source Files\ui</Filter>
</ClCompile>
<ClCompile Include="src\app_dialogs.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="libs\poly2tri\poly2tri\common\shapes.cc">
<Filter>libs\poly2tri</Filter>
</ClCompile>
<ClCompile Include="libs\poly2tri\poly2tri\sweep\advancing_front.cc">
<Filter>libs\poly2tri</Filter>
</ClCompile>
<ClCompile Include="libs\poly2tri\poly2tri\sweep\cdt.cc">
<Filter>libs\poly2tri</Filter>
</ClCompile>
<ClCompile Include="libs\poly2tri\poly2tri\sweep\sweep.cc">
<Filter>libs\poly2tri</Filter>
</ClCompile>
<ClCompile Include="libs\poly2tri\poly2tri\sweep\sweep_context.cc">
<Filter>libs\poly2tri</Filter>
</ClCompile>
<ClCompile Include="src\node_progress_bar.cpp">
<Filter>Source Files\ui</Filter>
</ClCompile>
<ClCompile Include="src\node_dialog_browse.cpp">
<Filter>Source Files\ui</Filter>
</ClCompile>
<ClCompile Include="src\app_commands.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\node_dialog_cloud.cpp">
<Filter>Source Files\ui</Filter>
</ClCompile>
<ClCompile Include="src\app_cloud.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\node_combobox.cpp">
<Filter>Source Files\ui</Filter>
</ClCompile>
<ClCompile Include="src\node_dialog_picker.cpp">
<Filter>Source Files\ui</Filter>
</ClCompile>
<ClCompile Include="src\node_colorwheel.cpp">
<Filter>Source Files\ui</Filter>
</ClCompile>
<ClCompile Include="src\node_panel_grid.cpp">
<Filter>Source Files\ui</Filter>
</ClCompile>
<ClCompile Include="src\version.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\node_about.cpp">
<Filter>Source Files\ui</Filter>
</ClCompile>
<ClCompile Include="src\node_changelog.cpp">
<Filter>Source Files\ui</Filter>
</ClCompile>
<ClCompile Include="src\node_usermanual.cpp">
<Filter>Source Files\ui</Filter>
</ClCompile>
<ClCompile Include="src\node_dialog_resize.cpp">
<Filter>Source Files\ui</Filter>
</ClCompile>
<ClCompile Include="libs\sqlite3\sqlite3.c">
<Filter>libs\sqlite3</Filter>
</ClCompile>
<ClCompile Include="src\hmd.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\app_vr.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="libs\nanort\nanort.cc">
<Filter>libs\nanort</Filter>
</ClCompile>
<ClCompile Include="libs\hash-library\md5.cpp">
<Filter>libs\hash</Filter>
</ClCompile>
<ClCompile Include="src\abr.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="libs\fmt\src\format.cc">
<Filter>libs\fmt</Filter>
</ClCompile>
<ClCompile Include="libs\fmt\src\posix.cc">
<Filter>libs\fmt</Filter>
</ClCompile>
<ClCompile Include="src\node_panel_quick.cpp">
<Filter>Source Files\ui</Filter>
</ClCompile>
<ClCompile Include="src\binary_stream.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\serializer.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="libs\yoga\yoga\YGConfig.cpp">
<Filter>libs\yoga</Filter>
</ClCompile>
<ClCompile Include="libs\yoga\yoga\YGEnums.cpp">
<Filter>libs\yoga</Filter>
</ClCompile>
<ClCompile Include="libs\yoga\yoga\YGLayout.cpp">
<Filter>libs\yoga</Filter>
</ClCompile>
<ClCompile Include="libs\yoga\yoga\YGNode.cpp">
<Filter>libs\yoga</Filter>
</ClCompile>
<ClCompile Include="libs\yoga\yoga\YGNodePrint.cpp">
<Filter>libs\yoga</Filter>
</ClCompile>
<ClCompile Include="libs\yoga\yoga\YGStyle.cpp">
<Filter>libs\yoga</Filter>
</ClCompile>
<ClCompile Include="libs\yoga\yoga\YGValue.cpp">
<Filter>libs\yoga</Filter>
</ClCompile>
<ClCompile Include="libs\yoga\yoga\Yoga.cpp">
<Filter>libs\yoga</Filter>
</ClCompile>
<ClCompile Include="libs\yoga\yoga\log.cpp">
<Filter>libs\yoga</Filter>
</ClCompile>
<ClCompile Include="libs\yoga\yoga\Utils.cpp">
<Filter>libs\yoga</Filter>
</ClCompile>
<ClCompile Include="src\node_panel_floating.cpp">
<Filter>Source Files\ui</Filter>
</ClCompile>
<ClCompile Include="src\settings.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\canvas_actions.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\canvas_layer.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\node_tool_bucket.cpp">
<Filter>Source Files\ui</Filter>
</ClCompile>
<ClCompile Include="libs\glad\src\glad.c">
<Filter>libs\glad</Filter>
</ClCompile>
<ClCompile Include="libs\glad\src\glad_wgl.c">
<Filter>libs\glad</Filter>
</ClCompile>
<ClCompile Include="src\node_dialog_export_ppbr.cpp">
<Filter>Source Files\ui</Filter>
</ClCompile>
<ClCompile Include="src\node_input_box.cpp">
<Filter>Source Files\ui</Filter>
</ClCompile>
<ClCompile Include="src\node_panel_animation.cpp">
<Filter>Source Files\ui</Filter>
</ClCompile>
<ClCompile Include="libs\yoga\yoga\internal\experiments.cpp">
<Filter>libs\yoga</Filter>
</ClCompile>
<ClCompile Include="libs\yoga\yoga\event\event.cpp">
<Filter>libs\yoga</Filter>
</ClCompile>
<ClCompile Include="src\mp4enc.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\node_remote_page.cpp">
<Filter>Source Files\ui</Filter>
</ClCompile>
<ClCompile Include="src\node_metadata.cpp">
<Filter>Source Files\ui</Filter>
</ClCompile>
<ClCompile Include="src\node_shorcuts.cpp">
<Filter>Source Files\ui</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="libs\jpeg\jpgd.h">
<Filter>libs\jpeg</Filter>
</ClInclude>
<ClInclude Include="libs\jpeg\jpge.h">
<Filter>libs\jpeg</Filter>
</ClInclude>
<ClInclude Include="libs\tinyxml2\tinyxml2.h">
<Filter>libs\tinyxml2</Filter>
</ClInclude>
<ClInclude Include="libs\wacom\WinTab\PKTDEF.H">
<Filter>libs\WinTab</Filter>
</ClInclude>
<ClInclude Include="libs\wacom\WinTab\Utils.h">
<Filter>libs\WinTab</Filter>
</ClInclude>
<ClInclude Include="libs\wacom\WinTab\WINTAB.H">
<Filter>libs\WinTab</Filter>
</ClInclude>
<ClInclude Include="libs\wacom\WinTab\MSGPACK.H">
<Filter>libs\WinTab</Filter>
</ClInclude>
<ClInclude Include="libs\sqlite3\sqlite3.h">
<Filter>libs\sqlite3</Filter>
</ClInclude>
<ClInclude Include="libs\sqlite3\sqlite3ext.h">
<Filter>libs\sqlite3</Filter>
</ClInclude>
<ClInclude Include="libs\nanort\nanort.h">
<Filter>libs\nanort</Filter>
</ClInclude>
<ClInclude Include="libs\hash-library\md5.h">
<Filter>libs\hash</Filter>
</ClInclude>
<ClInclude Include="src\abr.h">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="src\action.h">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="src\app.h">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="src\asset.h">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="src\bezier.h">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="src\binary_stream.h">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="src\brush.h">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="src\canvas.h">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="src\canvas_actions.h">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="src\canvas_layer.h">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="src\canvas_modes.h">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="src\event.h">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="src\font.h">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="src\hmd.h">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="src\image.h">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="src\keymap.h">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="src\log.h">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="src\pch.h">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="resource.h">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="src\rtt.h">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="src\serializer.h">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="src\settings.h">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="src\shader.h">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="src\shape.h">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="src\texture.h">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="src\util.h">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="src\version.gen.h">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="src\version.h">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="src\wacom.h">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="src\layout.h">
<Filter>Source Files\ui</Filter>
</ClInclude>
<ClInclude Include="src\node.h">
<Filter>Source Files\ui</Filter>
</ClInclude>
<ClInclude Include="src\node_about.h">
<Filter>Source Files\ui</Filter>
</ClInclude>
<ClInclude Include="src\node_border.h">
<Filter>Source Files\ui</Filter>
</ClInclude>
<ClInclude Include="src\node_button.h">
<Filter>Source Files\ui</Filter>
</ClInclude>
<ClInclude Include="src\node_button_custom.h">
<Filter>Source Files\ui</Filter>
</ClInclude>
<ClInclude Include="src\node_canvas.h">
<Filter>Source Files\ui</Filter>
</ClInclude>
<ClInclude Include="src\node_changelog.h">
<Filter>Source Files\ui</Filter>
</ClInclude>
<ClInclude Include="src\node_checkbox.h">
<Filter>Source Files\ui</Filter>
</ClInclude>
<ClInclude Include="src\node_color_quad.h">
<Filter>Source Files\ui</Filter>
</ClInclude>
<ClInclude Include="src\node_colorwheel.h">
<Filter>Source Files\ui</Filter>
</ClInclude>
<ClInclude Include="src\node_combobox.h">
<Filter>Source Files\ui</Filter>
</ClInclude>
<ClInclude Include="src\node_dialog_browse.h">
<Filter>Source Files\ui</Filter>
</ClInclude>
<ClInclude Include="src\node_dialog_cloud.h">
<Filter>Source Files\ui</Filter>
</ClInclude>
<ClInclude Include="src\node_dialog_export_ppbr.h">
<Filter>Source Files\ui</Filter>
</ClInclude>
<ClInclude Include="src\node_dialog_layer_rename.h">
<Filter>Source Files\ui</Filter>
</ClInclude>
<ClInclude Include="src\node_dialog_open.h">
<Filter>Source Files\ui</Filter>
</ClInclude>
<ClInclude Include="src\node_dialog_picker.h">
<Filter>Source Files\ui</Filter>
</ClInclude>
<ClInclude Include="src\node_dialog_resize.h">
<Filter>Source Files\ui</Filter>
</ClInclude>
<ClInclude Include="src\node_icon.h">
<Filter>Source Files\ui</Filter>
</ClInclude>
<ClInclude Include="src\node_image.h">
<Filter>Source Files\ui</Filter>
</ClInclude>
<ClInclude Include="src\node_image_texture.h">
<Filter>Source Files\ui</Filter>
</ClInclude>
<ClInclude Include="src\node_input_box.h">
<Filter>Source Files\ui</Filter>
</ClInclude>
<ClInclude Include="src\node_message_box.h">
<Filter>Source Files\ui</Filter>
</ClInclude>
<ClInclude Include="src\node_panel_brush.h">
<Filter>Source Files\ui</Filter>
</ClInclude>
<ClInclude Include="src\node_panel_color.h">
<Filter>Source Files\ui</Filter>
</ClInclude>
<ClInclude Include="src\node_panel_floating.h">
<Filter>Source Files\ui</Filter>
</ClInclude>
<ClInclude Include="src\node_panel_grid.h">
<Filter>Source Files\ui</Filter>
</ClInclude>
<ClInclude Include="src\node_panel_layer.h">
<Filter>Source Files\ui</Filter>
</ClInclude>
<ClInclude Include="src\node_panel_quick.h">
<Filter>Source Files\ui</Filter>
</ClInclude>
<ClInclude Include="src\node_panel_stroke.h">
<Filter>Source Files\ui</Filter>
</ClInclude>
<ClInclude Include="src\node_popup_menu.h">
<Filter>Source Files\ui</Filter>
</ClInclude>
<ClInclude Include="src\node_progress_bar.h">
<Filter>Source Files\ui</Filter>
</ClInclude>
<ClInclude Include="src\node_scroll.h">
<Filter>Source Files\ui</Filter>
</ClInclude>
<ClInclude Include="src\node_settings.h">
<Filter>Source Files\ui</Filter>
</ClInclude>
<ClInclude Include="src\node_slider.h">
<Filter>Source Files\ui</Filter>
</ClInclude>
<ClInclude Include="src\node_stroke_preview.h">
<Filter>Source Files\ui</Filter>
</ClInclude>
<ClInclude Include="src\node_text.h">
<Filter>Source Files\ui</Filter>
</ClInclude>
<ClInclude Include="src\node_text_input.h">
<Filter>Source Files\ui</Filter>
</ClInclude>
<ClInclude Include="src\node_tool_bucket.h">
<Filter>Source Files\ui</Filter>
</ClInclude>
<ClInclude Include="src\node_usermanual.h">
<Filter>Source Files\ui</Filter>
</ClInclude>
<ClInclude Include="src\node_viewport.h">
<Filter>Source Files\ui</Filter>
</ClInclude>
<ClInclude Include="src\node_panel_animation.h">
<Filter>Source Files\ui</Filter>
</ClInclude>
<ClInclude Include="src\node_remote_page.h">
<Filter>Source Files\ui</Filter>
</ClInclude>
<ClInclude Include="src\node_metadata.h">
<Filter>Source Files\ui</Filter>
</ClInclude>
<ClInclude Include="src\node_shorcuts.h">
<Filter>Source Files\ui</Filter>
</ClInclude>
<ClInclude Include="src\mp4enc.h">
<Filter>Source Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="PanoPainter.rc">
<Filter>Resource Files</Filter>
</ResourceCompile>
</ItemGroup>
<ItemGroup>
<Natvis Include="libs\glm\util\glm.natvis">
<Filter>extras</Filter>
</Natvis>
</ItemGroup>
<ItemGroup>
<Xml Include="data\layout.xml">
<Filter>extras</Filter>
</Xml>
<Xml Include="data\dialogs\changelog.xml">
<Filter>extras\dialogs</Filter>
</Xml>
<Xml Include="data\dialogs\about.xml">
<Filter>extras\dialogs</Filter>
</Xml>
<Xml Include="data\dialogs\usermanual.xml">
<Filter>extras\dialogs</Filter>
</Xml>
<Xml Include="data\dialogs\brush-export.xml">
<Filter>extras\dialogs</Filter>
</Xml>
<Xml Include="data\dialogs\panel-layers.xml">
<Filter>extras\dialogs</Filter>
</Xml>
<Xml Include="data\dialogs\panel-brushes.xml">
<Filter>extras\dialogs</Filter>
</Xml>
<Xml Include="data\dialogs\panel-stroke.xml">
<Filter>extras\dialogs</Filter>
</Xml>
<Xml Include="data\dialogs\panel-grid.xml">
<Filter>extras\dialogs</Filter>
</Xml>
<Xml Include="data\dialogs\panel-quick.xml">
<Filter>extras\dialogs</Filter>
</Xml>
<Xml Include="data\dialogs\color-picker.xml">
<Filter>extras\dialogs</Filter>
</Xml>
<Xml Include="data\dialogs\input-box.xml">
<Filter>extras\dialogs</Filter>
</Xml>
<Xml Include="data\dialogs\message-box.xml">
<Filter>extras\dialogs</Filter>
</Xml>
<Xml Include="data\dialogs\progress-bar.xml">
<Filter>extras\dialogs</Filter>
</Xml>
<Xml Include="data\dialogs\layer-rename.xml">
<Filter>extras\dialogs</Filter>
</Xml>
<Xml Include="data\dialogs\doc-resize.xml">
<Filter>extras\dialogs</Filter>
</Xml>
<Xml Include="data\dialogs\doc-browse.xml">
<Filter>extras\dialogs</Filter>
</Xml>
<Xml Include="data\dialogs\doc-new.xml">
<Filter>extras\dialogs</Filter>
</Xml>
<Xml Include="data\dialogs\doc-save.xml">
<Filter>extras\dialogs</Filter>
</Xml>
<Xml Include="data\dialogs\cloud-browse.xml">
<Filter>extras\dialogs</Filter>
</Xml>
<Xml Include="data\dialogs\settings.xml">
<Filter>extras\dialogs</Filter>
</Xml>
<Xml Include="data\dialogs\doc-open.xml">
<Filter>extras\dialogs</Filter>
</Xml>
<Xml Include="data\dialogs\panel-floating.xml">
<Filter>extras\dialogs</Filter>
</Xml>
<Xml Include="data\dialogs\panel-presets.xml">
<Filter>extras\dialogs</Filter>
</Xml>
<Xml Include="data\dialogs\panel-animation.xml">
<Filter>extras\dialogs</Filter>
</Xml>
<Xml Include="data\dialogs\remote-page.xml">
<Filter>extras\dialogs</Filter>
</Xml>
<Xml Include="data\dialogs\shortcuts.xml">
<Filter>extras\dialogs</Filter>
</Xml>
</ItemGroup>
<ItemGroup>
<None Include="data\shaders\texture.glsl">
<Filter>shaders</Filter>
</None>
<None Include="data\shaders\include\blend-stroke.glsl">
<Filter>shaders\include</Filter>
</None>
<None Include="data\shaders\include\blur.glsl">
<Filter>shaders\include</Filter>
</None>
<None Include="data\shaders\include\color.glsl">
<Filter>shaders\include</Filter>
</None>
<None Include="data\shaders\include\ext-fb-fetch.glsl">
<Filter>shaders\include</Filter>
</None>
<None Include="data\shaders\include\hsv.glsl">
<Filter>shaders\include</Filter>
</None>
<None Include="data\shaders\include\rand.glsl">
<Filter>shaders\include</Filter>
</None>
<None Include="data\shaders\include\blend.glsl">
<Filter>shaders\include</Filter>
</None>
<None Include="data\shaders\comp-draw.glsl">
<Filter>shaders</Filter>
</None>
<None Include="data\shaders\comp-erase.glsl">
<Filter>shaders</Filter>
</None>
<None Include="data\shaders\equirect.glsl">
<Filter>shaders</Filter>
</None>
<None Include="data\shaders\font.glsl">
<Filter>shaders</Filter>
</None>
<None Include="data\shaders\lambert.glsl">
<Filter>shaders</Filter>
</None>
<None Include="data\shaders\lightmap.glsl">
<Filter>shaders</Filter>
</None>
<None Include="data\shaders\stroke.glsl">
<Filter>shaders</Filter>
</None>
<None Include="data\shaders\stroke-instanced.glsl">
<Filter>shaders</Filter>
</None>
<None Include="data\shaders\stroke-preview.glsl">
<Filter>shaders</Filter>
</None>
<None Include="data\shaders\texture-alpha.glsl">
<Filter>shaders</Filter>
</None>
<None Include="data\shaders\texture-blend.glsl">
<Filter>shaders</Filter>
</None>
<None Include="data\shaders\uvs.glsl">
<Filter>shaders</Filter>
</None>
<None Include="data\shaders\vertex-color.glsl">
<Filter>shaders</Filter>
</None>
<None Include="data\shaders\atlas.glsl">
<Filter>shaders</Filter>
</None>
<None Include="data\shaders\bake-uv.glsl">
<Filter>shaders</Filter>
</None>
<None Include="data\shaders\checkerboard.glsl">
<Filter>shaders</Filter>
</None>
<None Include="data\shaders\color.glsl">
<Filter>shaders</Filter>
</None>
<None Include="data\shaders\color-hue.glsl">
<Filter>shaders</Filter>
</None>
<None Include="data\shaders\color-quad.glsl">
<Filter>shaders</Filter>
</None>
<None Include="data\shaders\color-tri.glsl">
<Filter>shaders</Filter>
</None>
<None Include="data\shaders\texture-colorize.glsl">
<Filter>shaders</Filter>
</None>
<None Include="data\shaders\texture-mask.glsl">
<Filter>shaders</Filter>
</None>
<None Include="data\shaders\stroke-dilate.glsl">
<Filter>shaders</Filter>
</None>
<None Include="data\shaders\stroke-pad.glsl">
<Filter>shaders</Filter>
</None>
</ItemGroup>
<ItemGroup>
<Image Include="icon.ico">
<Filter>Resource Files</Filter>
</Image>
</ItemGroup>
<ItemGroup>
<Xsd Include="extra\layout.xsd">
<Filter>extras</Filter>
</Xsd>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,16 @@
option(PP_BUILD_APP "Build the PanoPainter application target from root CMake." ON)
option(PP_BUILD_TESTS "Build PanoPainter tests." ON)
option(PP_BUILD_TOOLS "Build PanoPainter automation tools." ON)
option(PP_ENABLE_OPENGL "Enable the OpenGL renderer backend." ON)
option(PP_ENABLE_VULKAN_EXPERIMENTAL "Enable non-production Vulkan experiments." OFF)
option(PP_ENABLE_VR "Enable VR support." ON)
option(PP_ENABLE_CLOUD "Enable cloud/network features." ON)
option(PP_ENABLE_VIDEO "Enable MP4/timelapse video features." ON)
option(PP_ENABLE_ASAN "Enable AddressSanitizer where supported." OFF)
option(PP_ENABLE_UBSAN "Enable UndefinedBehaviorSanitizer where supported." OFF)
option(PP_ENABLE_TSAN "Enable ThreadSanitizer for headless targets where supported." OFF)
option(PP_ENABLE_MSVC_ANALYZE "Enable MSVC static analysis." OFF)
option(PP_ENABLE_CLANG_TIDY "Enable clang-tidy integration." OFF)
option(PP_ENABLE_CPPCHECK "Enable cppcheck integration." OFF)

View File

@@ -0,0 +1,143 @@
set(PP_LEGACY_APP_SOURCES
src/abr.cpp
src/action.cpp
src/app.cpp
src/app_cloud.cpp
src/app_commands.cpp
src/app_dialogs.cpp
src/app_events.cpp
src/app_layout.cpp
src/app_shaders.cpp
src/app_vr.cpp
src/asset.cpp
src/bezier.cpp
src/binary_stream.cpp
src/brush.cpp
src/canvas.cpp
src/canvas_actions.cpp
src/canvas_layer.cpp
src/canvas_modes.cpp
src/event.cpp
src/font.cpp
src/hmd.cpp
src/image.cpp
src/layout.cpp
src/log.cpp
src/mp4enc.cpp
src/node.cpp
src/node_about.cpp
src/node_border.cpp
src/node_button.cpp
src/node_button_custom.cpp
src/node_canvas.cpp
src/node_changelog.cpp
src/node_checkbox.cpp
src/node_color_quad.cpp
src/node_colorwheel.cpp
src/node_combobox.cpp
src/node_dialog_browse.cpp
src/node_dialog_cloud.cpp
src/node_dialog_export_ppbr.cpp
src/node_dialog_layer_rename.cpp
src/node_dialog_open.cpp
src/node_dialog_picker.cpp
src/node_dialog_resize.cpp
src/node_icon.cpp
src/node_image.cpp
src/node_image_texture.cpp
src/node_input_box.cpp
src/node_message_box.cpp
src/node_metadata.cpp
src/node_panel_animation.cpp
src/node_panel_brush.cpp
src/node_panel_color.cpp
src/node_panel_floating.cpp
src/node_panel_grid.cpp
src/node_panel_layer.cpp
src/node_panel_quick.cpp
src/node_panel_stroke.cpp
src/node_popup_menu.cpp
src/node_progress_bar.cpp
src/node_remote_page.cpp
src/node_scroll.cpp
src/node_settings.cpp
src/node_shorcuts.cpp
src/node_slider.cpp
src/node_stroke_preview.cpp
src/node_text.cpp
src/node_text_input.cpp
src/node_tool_bucket.cpp
src/node_usermanual.cpp
src/node_viewport.cpp
src/pch.cpp
src/rtt.cpp
src/serializer.cpp
src/settings.cpp
src/shader.cpp
src/shape.cpp
src/texture.cpp
src/util.cpp
src/version.cpp
src/wacom.cpp
)
set(PP_WINDOWS_APP_SOURCES
src/main.cpp
PanoPainter.rc
)
set(PP_VENDOR_SOURCES
libs/fmt/src/format.cc
libs/fmt/src/posix.cc
libs/glad/src/glad.c
libs/glad/src/glad_wgl.c
libs/hash-library/md5.cpp
libs/jpeg/jpgd.cpp
libs/jpeg/jpge.cpp
libs/nanort/nanort.cc
libs/poly2tri/poly2tri/common/shapes.cc
libs/poly2tri/poly2tri/sweep/advancing_front.cc
libs/poly2tri/poly2tri/sweep/cdt.cc
libs/poly2tri/poly2tri/sweep/sweep.cc
libs/poly2tri/poly2tri/sweep/sweep_context.cc
libs/sqlite3/sqlite3.c
libs/tinyxml2/tinyxml2.cpp
libs/wacom/WinTab/Utils.cpp
libs/yoga/yoga/event/event.cpp
libs/yoga/yoga/internal/experiments.cpp
libs/yoga/yoga/log.cpp
libs/yoga/yoga/Utils.cpp
libs/yoga/yoga/YGConfig.cpp
libs/yoga/yoga/YGEnums.cpp
libs/yoga/yoga/YGLayout.cpp
libs/yoga/yoga/YGNode.cpp
libs/yoga/yoga/YGNodePrint.cpp
libs/yoga/yoga/YGStyle.cpp
libs/yoga/yoga/YGValue.cpp
libs/yoga/yoga/Yoga.cpp
)
set(PP_LEGACY_INCLUDE_DIRS
"${CMAKE_CURRENT_SOURCE_DIR}/src"
"${CMAKE_CURRENT_SOURCE_DIR}"
"${CMAKE_CURRENT_SOURCE_DIR}/libs/base64"
"${CMAKE_CURRENT_SOURCE_DIR}/libs/bugtrap-client/include"
"${CMAKE_CURRENT_SOURCE_DIR}/libs/curl-win/include"
"${CMAKE_CURRENT_SOURCE_DIR}/libs/fmt/include"
"${CMAKE_CURRENT_SOURCE_DIR}/libs/glad/include"
"${CMAKE_CURRENT_SOURCE_DIR}/libs/glm"
"${CMAKE_CURRENT_SOURCE_DIR}/libs/hash-library"
"${CMAKE_CURRENT_SOURCE_DIR}/libs/jpeg"
"${CMAKE_CURRENT_SOURCE_DIR}/libs/libyuv/include"
"${CMAKE_CURRENT_SOURCE_DIR}/libs/mp4v2/include"
"${CMAKE_CURRENT_SOURCE_DIR}/libs/nanort"
"${CMAKE_CURRENT_SOURCE_DIR}/libs/openh264/include"
"${CMAKE_CURRENT_SOURCE_DIR}/libs/openvr/headers"
"${CMAKE_CURRENT_SOURCE_DIR}/libs/poly2tri/poly2tri"
"${CMAKE_CURRENT_SOURCE_DIR}/libs/sqlite3"
"${CMAKE_CURRENT_SOURCE_DIR}/libs/stb"
"${CMAKE_CURRENT_SOURCE_DIR}/libs/tinyxml2"
"${CMAKE_CURRENT_SOURCE_DIR}/libs/wacom"
"${CMAKE_CURRENT_SOURCE_DIR}/libs/yoga"
)

View File

@@ -0,0 +1,17 @@
function(pp_add_version_generation target config_name)
find_package(Python3 COMPONENTS Interpreter REQUIRED)
add_custom_command(
OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/src/version.gen.h"
COMMAND "${Python3_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/scripts/pre-build.py" "${config_name}"
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/scripts/pre-build.py"
COMMENT "Generating src/version.gen.h"
VERBATIM)
add_custom_target(pp_generate_version
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/src/version.gen.h")
add_dependencies(${target} pp_generate_version)
endfunction()

View File

@@ -0,0 +1,40 @@
function(pp_configure_project_warnings target)
if(MSVC)
target_compile_options(${target} INTERFACE
/W4
/permissive-
/Zc:__cplusplus
/Zc:preprocessor)
if(PP_ENABLE_MSVC_ANALYZE)
target_compile_options(${target} INTERFACE /analyze)
endif()
else()
target_compile_options(${target} INTERFACE
-Wall
-Wextra
-Wpedantic
-Wconversion
-Wshadow
-Wnull-dereference)
endif()
if(PP_ENABLE_ASAN)
if(MSVC)
target_compile_options(${target} INTERFACE /fsanitize=address)
target_link_options(${target} INTERFACE /fsanitize=address)
else()
target_compile_options(${target} INTERFACE -fsanitize=address)
target_link_options(${target} INTERFACE -fsanitize=address)
endif()
endif()
if(PP_ENABLE_UBSAN AND NOT MSVC)
target_compile_options(${target} INTERFACE -fsanitize=undefined)
target_link_options(${target} INTERFACE -fsanitize=undefined)
endif()
if(PP_ENABLE_TSAN AND NOT MSVC)
target_compile_options(${target} INTERFACE -fsanitize=thread)
target_link_options(${target} INTERFACE -fsanitize=thread)
endif()
endfunction()

View File

@@ -0,0 +1,49 @@
# ADR 0001: Incremental Component Boundaries
Status: accepted
Date: 2026-05-31
## Context
PanoPainter currently has a flat `src/` layout with broad dependencies through
`pch.h`, global singletons such as `App::I` and `Canvas::I`, OpenGL types in
high-level painting/document headers, and duplicated platform source lists.
The modernization work must retain existing behavior across Windows desktop
and AppX, macOS, iOS, Android standard, Quest, Focus/Wave, Linux, and WebGL.
## Decision
Modernization will proceed incrementally. OpenGL remains the production
renderer while component boundaries and tests are introduced. Vulkan, Metal,
and WebGPU-related work must stay out of the production path until OpenGL
parity tests exist.
The target dependency direction is:
```text
pp_foundation
-> pp_assets
-> pp_paint
-> pp_document
-> pp_renderer_api
-> pp_renderer_gl
-> pp_paint_renderer
-> pp_ui_core
-> pp_panopainter_ui
-> pp_platform_*
-> panopainter_app
```
Pure component headers must not include platform SDK headers or graphics API
headers. Temporary shims are allowed only when recorded in
`docs/modernization/debt.md`.
## Consequences
- The first implementation steps are documentation, inventory, CMake skeleton,
diagnostics, and tests, not a renderer rewrite.
- Existing project files remain until the shared CMake targets are validated.
- Refactors should prefer additive compatibility layers before moving behavior.
- Every extracted component must gain its own tests before the next component
boundary is extracted.

View File

@@ -0,0 +1,83 @@
# Build And Platform Inventory
Status: live
Last updated: 2026-05-31
This inventory records the known build surfaces during the CMake migration.
Keep it updated as platform paths move to shared CMake targets.
## Existing Build Entrypoints
| Platform/Target | Current Entrypoint | Notes |
| --- | --- | --- |
| Windows desktop | Root `CMakeLists.txt`, preset `windows-msvc-default`; target preset `windows-vs2026-x64` retained for VS 2026 | Raw `.sln/.vcxproj` files removed on 2026-05-31; local machine currently uses Visual Studio 17 2022 |
| Windows AppX | `PanoPainterPackage/Package.appxmanifest`, `.wapproj` referenced by solution | Distribution packaging |
| macOS | `PanoPainter-OSX/` project files and `Info.plist` | Uses `NSOpenGLView` today |
| iOS | `PanoPainter/Info.plist`, related Apple sources | Uses OpenGL ES today |
| Android standard | `android/android/build.gradle`, `android/android/CMakeLists.txt` | Native library target `native-lib` |
| Android Quest | `android/quest/build.gradle`, `android/quest/CMakeLists.txt` | OVR SDK imported libraries |
| Android Focus/Wave | `android/focus/build.gradle`, `android/focus/CMakeLists.txt` | Wave SDK imported libraries |
| Linux | `linux/CMakeLists.txt` | Old CMake 3.4, C++14 flag |
| WebGL/Emscripten | `webgl/CMakeLists.txt` | Old CMake 3.4, WebGL2 flags |
## Existing Version Generation
- Script: `scripts/pre-build.py`
- Output: `src/version.gen.h`
- Current behavior: derives version from git branch, latest tag, short hash,
commit count, and configuration argument.
- Migration requirement: root CMake should call this script through a custom
command and avoid unnecessary tracked-file churn where possible.
## Existing Dependency Sources
Hybrid policy: migrate reliable packages to vcpkg and retain SDK/patched
dependencies until each platform triplet is proven.
| Dependency | Current Source | Initial Policy |
| --- | --- | --- |
| fmt | `libs/fmt` | Move to vcpkg |
| GLM | `libs/glm` | Move to vcpkg |
| tinyxml2 | `libs/tinyxml2` | Move to vcpkg |
| stb | `libs/stb` | Move to vcpkg or interface target if package friction |
| CURL | `libs/curl-win`, `libs/curl-android-ios` | Move to vcpkg where triplets work |
| SQLite | `libs/sqlite3` | Move to vcpkg |
| GLAD | `libs/glad` | Move to vcpkg or generated backend target |
| Catch2 | none yet | Add through vcpkg |
| OpenVR | `libs/openvr` | Retain initially |
| OVR Platform/Mobile | `libs/ovr_platform`, `libs/ovr_mobile` | Retain initially |
| Wave SDK | `libs/wave_sdk` | Retain initially |
| Wacom WinTab | `libs/wacom` | Retain initially |
| AppCenter Apple | `libs/appcenter-apple` | Retain initially |
| openh264/mp4v2/libyuv | `libs/openh264`, `libs/mp4v2`, `libs/libyuv` | Retain initially |
| jpeg helpers | `libs/jpeg` | Evaluate after image tests exist |
| poly2tri/nanort/base64/hash-library | `libs/*` | Evaluate after component split |
## Current Validation Commands
These commands are the current local baseline.
```powershell
cmake --preset windows-msvc-default
cmake --build --preset windows-msvc-default --config Debug --target PanoPainter
ctest --preset desktop-fast --build-config Debug
powershell -ExecutionPolicy Bypass -File scripts\automation\test.ps1 -Preset desktop-fast -Configuration Debug
powershell -ExecutionPolicy Bypass -File scripts\automation\build.ps1 -Preset windows-msvc-default -Configuration Debug -Target pano_cli
```
Known local toolchain state:
- CMake: 4.0.0-rc4
- Local Visual Studio generator selected by CMake: Visual Studio 17 2022
- Android SDK: `C:\Users\omara\AppData\Local\Android\Sdk`
- Android NDK: `C:\Users\omara\AppData\Local\Android\Sdk\ndk\29.0.14206865`
- `vcpkg` is not on PATH yet; see DEBT-0007.
Known warnings after the current CMake app build:
- Legacy code/vendor warnings under `/W4`.
- Visual Studio vcpkg manifest warning because manifest mode is not enabled.
- `LNK4099` missing `yuv.pdb` for retained libyuv binaries.
- `LNK4098` runtime library conflict from retained vendor binaries.
Platform-specific commands should be added here when verified locally.

View File

@@ -0,0 +1,83 @@
# PanoPainter Capability Map
Status: live
Last updated: 2026-05-31
This map is the preservation checklist for the modernization. When a component
is extracted, update the relevant rows with the owning component, test label,
and validation command.
## Project And Documents
| Capability | Current Area | Target Owner | Required Tests |
| --- | --- | --- | --- |
| PPI open/save | `Canvas`, serializer, dialogs | `pp_document`, `pp_assets`, `pano_cli` | Round-trip tiny project, old-version fixture, corrupt/truncated fixture |
| Version metadata | `scripts/pre-build.py`, `version.*` | build system, `pp_foundation` | Generated header smoke test, missing-tag behavior |
| Thumbnail generation/read | `Canvas`, `Image` | `pp_assets`, `pp_paint_renderer` | Golden thumbnail, corrupt input |
| Save-as, overwrite prompts | App/dialogs | `pp_panopainter_ui`, `pp_platform_*` | UI automation and platform smoke |
## Image And Export
| Capability | Current Area | Target Owner | Required Tests |
| --- | --- | --- | --- |
| PNG/JPEG import | `Image`, `Canvas` import paths | `pp_assets`, `pp_document` | Fixture import, malformed file |
| PNG/JPEG export | `Canvas`, `Image` | `pp_assets`, `pp_paint_renderer` | Golden output tolerance |
| Equirectangular import/export | `Canvas`, shaders, RTT | `pp_paint_renderer` | Tiny cube/equirect golden |
| Cube face export | `Canvas` | `pp_paint_renderer` | Six-face golden set |
| Depth export | `Canvas`, grid tools | `pp_paint_renderer` | Float/readback validation |
## Brush And Painting
| Capability | Current Area | Target Owner | Required Tests |
| --- | --- | --- | --- |
| Brush settings serialization | `Brush`, `Serializer` | `pp_paint`, `pp_assets` | Round-trip and boundary values |
| ABR import | `ABR`, `Brush` | `pp_assets`, `pp_paint` | Sample ABR and malformed ABR |
| PPBR import/export | brush panel/dialog | `pp_assets`, `pp_panopainter_ui` | Round-trip fixture |
| Stroke sampling | `Stroke`, `Canvas` | `pp_paint` | Property tests for spacing, pressure, jitter |
| Dual brush/pattern behavior | `Brush`, shaders | `pp_paint`, `pp_paint_renderer` | CPU reference and GPU golden |
| Blend modes | GLSL include files, layer rendering | `pp_paint`, `pp_paint_renderer` | CPU reference vectors and GPU parity |
| Erase/flood fill/masks | `Canvas`, modes, shaders | `pp_document`, `pp_paint_renderer` | Edge masks, alpha lock, dirty rects |
## Layers And Animation
| Capability | Current Area | Target Owner | Required Tests |
| --- | --- | --- | --- |
| Layer add/remove/move/merge | `Canvas`, `Layer`, actions | `pp_document` | Undo/redo invariant tests |
| Blend/opacity/visibility/alpha lock | `Layer`, UI panels, shaders | `pp_document`, `pp_paint_renderer` | CPU model and render golden |
| Selection mask | `Canvas` mask layer | `pp_document`, `pp_paint_renderer` | Mask apply/clear edge cases |
| Animation frames | `LayerFrame`, animation panel | `pp_document`, `pp_panopainter_ui` | Duration, duplicate, remove, seek |
| MP4/timelapse export | `MP4Encoder`, recording thread | `pp_assets`, `pp_paint_renderer`, app | Smoke export and cancellation |
## UI And Workflow
| Capability | Current Area | Target Owner | Required Tests |
| --- | --- | --- | --- |
| XML layout parsing | `LayoutManager`, `Node` | `pp_ui_core` | Layout fixtures and malformed XML |
| Yoga layout | `Node` | `pp_ui_core` | Deterministic geometry fixtures |
| Generic controls | `NodeButton`, sliders, text, images | `pp_ui_core` | Event dispatch and layout tests |
| PanoPainter panels/dialogs | `NodePanel*`, `NodeDialog*` | `pp_panopainter_ui` | UI automation scripts |
| Canvas viewport UI | `NodeCanvas` | `pp_panopainter_ui`, `pp_paint_renderer` | Input-to-command automation |
| Settings UI | `Settings`, `NodeSettings` | `pp_assets`, `pp_panopainter_ui` | Round-trip settings |
## Input, Platform, And Devices
| Capability | Current Area | Target Owner | Required Tests |
| --- | --- | --- | --- |
| Mouse/keyboard/touch/gestures | `App`, platform entrypoints | `pp_platform_*`, app | Synthetic event playback |
| Wacom pressure | `WacomTablet` | `pp_platform_windows` | Adapter smoke with fallback |
| Clipboard/file picker/share | `App` platform methods | `pp_platform_*` | Platform smoke or mocked service |
| Virtual keyboard | platform entrypoints | `pp_platform_*` | Platform smoke |
| OpenVR desktop | `HMD`, `Vive`, `app_vr` | `pp_platform_vr`, app | Compile gate and mocked pose tests |
| Quest/OVR | Android Quest files | `pp_platform_android_quest` | Compile/package gate |
| Focus/Wave | Android Focus files | `pp_platform_android_wave` | Compile/package gate |
## Cloud, Logging, And Automation
| Capability | Current Area | Target Owner | Required Tests |
| --- | --- | --- | --- |
| Upload/download/browse | `app_cloud`, CURL helpers | app service, `pp_platform_*` | Mocked HTTP and timeout tests |
| License/check flows | app/cloud code | app service | Mocked response tests |
| Logging/crash reporting | `log`, BugTrap/AppCenter | `pp_foundation`, platform wrappers | Log formatting and platform compile |
| Headless automation | none yet | `tools/pano_cli` | JSON command fixtures |
| Tracing | none yet | `pp_foundation` | Span nesting/timing tests |

View File

@@ -0,0 +1,34 @@
# Modernization Debt Log
Status: live
Last updated: 2026-05-31
Every shortcut, temporary adapter, retained vendored dependency, skipped
platform gate, compatibility shim, or incomplete automation path must be
recorded here before it lands. Entries must be specific enough for a future
agent or engineer to remove them without reconstructing context from chat.
## Entry Rules
- Add an entry before merging the shortcut.
- Reference the debt id in code comments, TODOs, ADRs, or roadmap notes.
- Include an owner, reason, validation command, and removal condition.
- Do not close an entry until the removal condition is met and validated.
- Prefer deleting shortcuts over expanding this log.
## Open Debt
| ID | Status | Owner | Item | Reason | Validation | Removal Condition |
| --- | --- | --- | --- | --- | --- | --- |
| DEBT-0001 | Open | Modernization | Existing platform build files remain alongside new CMake | Required for incremental migration without losing platform coverage | Existing platform builds plus new CMake configure | Remove after all platform builds consume shared CMake targets |
| DEBT-0002 | Open | Modernization | Vendored SDK and patched libraries retained initially | Some dependencies are SDK-only, patched, or have platform-specific binaries | Dependency inventory and platform build smoke tests | Replace with vcpkg packages or document permanent vendored status after triplet evaluation |
| DEBT-0003 | Open | Modernization | Existing singletons remain during initial split | Avoid behavior changes while introducing component boundaries | App launch and component tests | Replace singleton reaches with context/service injection at component boundaries |
| DEBT-0004 | Open | Modernization | Android, Linux, WebGL, Apple, and AppX build files remain platform-specific until root CMake alignment reaches them | Prevent platform regressions during incremental migration; raw Windows `.sln/.vcxproj` files were removed on 2026-05-31 by user decision | `cmake --preset windows-msvc-default`; platform-specific configure/build smoke checks as each platform is migrated | Root CMake owns every platform source list and package path |
| DEBT-0005 | Open | Modernization | Temporary local CTest harness is used before Catch2 is wired through vcpkg | `vcpkg` is not currently on PATH, but headless tests need to run now | `ctest --preset desktop-fast --build-config Debug` | Replace `tests/test_harness.h` tests with Catch2 tests once vcpkg toolchain/presets are validated |
| DEBT-0006 | Open | Modernization | `pano_cli create-document` validates and emits JSON command contracts but does not yet invoke the legacy document/app model | The document model has not been extracted from `Canvas`/`App` yet | `pano_cli create-document --width 64 --height 32 --layers 2`; CTest `pano_cli_create_document_smoke` | Replace command contract implementation with real `pp_document` creation once Phase 4 extracts the document model |
| DEBT-0007 | Open | Modernization | `vcpkg.json` exists but CMake is not yet using a validated vcpkg toolchain on this machine | `vcpkg` is not available on PATH and Visual Studio reports manifest mode is disabled | `cmake --preset windows-msvc-default` currently configures with vendored dependencies | Add validated vcpkg toolchain/preset integration for desktop, Android, and Apple triplets |
| DEBT-0008 | Open | Modernization | `windows-msvc-default` preset is used for local validation because the VS 2026 generator is not installed here | The target VS 2026 preset must remain, but this machine configures with Visual Studio 17 2022 | `cmake --preset windows-msvc-default`; `ctest --preset desktop-fast --build-config Debug` | Validate `windows-vs2026-x64` on a machine with Visual Studio 2026 installed and make it the default Windows validation preset |
## Closed Debt
None yet.

View File

@@ -0,0 +1,553 @@
# PanoPainter Modernization Roadmap
Status: live
Last updated: 2026-05-31
This is the living roadmap for modernizing PanoPainter into independently
testable C++23 components while retaining all existing functionality. Keep this
file current as phases are implemented. Do not let shortcuts, skipped platforms,
or temporary adapters live only in chat history.
## How To Keep This Roadmap Live
- Update the phase status before and after each implementation pass.
- When a shortcut is introduced, add it to the debt log section in this file
until `docs/modernization/debt.md` exists, then move debt entries there.
- When a major architectural decision is made, add an ADR under `docs/adr/`
once that directory exists.
- Every phase must preserve old behavior unless the roadmap explicitly says
otherwise.
- Each phase must leave the repo in a buildable and testable state.
- Do not add stubs without a debt entry, validation command, and removal
condition.
## Locked Decisions
- Graphics path: keep OpenGL working first; add Vulkan and Metal after the
renderer boundary exists.
- Required platforms at phase gates: Windows desktop/AppX, macOS, iOS,
Android standard, Quest, Focus/Wave, Linux, and WebGL.
- Dependency policy: use vcpkg where reliable; keep SDK, patched, or
vendor-only dependencies with documented reasons.
- Test stack: Catch2, golden/approval tests, and fuzz/property tests where
useful.
- Automation: local reproducible matrix first; hosted CI can be added later.
- Documentation: ADRs, debt log, and this living roadmap.
- "vkpkg" in older notes means `vcpkg`.
- Target C++ standard: C++23.
- Initial Windows CMake generator target: Visual Studio 2026 when available.
## Phase Status
| Phase | Name | Status | Gate |
| --- | --- | --- | --- |
| 0 | Inventory, Safety Rails, And Memory | Complete | No behavior changes; old builds still work |
| 1 | Unified CMake Skeleton | In progress | Root CMake builds the Windows app and owns the source list |
| 2 | Toolchain, Diagnostics, And Dependencies | In progress | Strict desktop library builds compile cleanly |
| 3 | Test Harness And Agent-Ready Automation | In progress | `ctest --preset desktop-fast` runs headlessly |
| 4 | Component Split Without Behavior Change | Started | Each extracted target builds and tests |
| 5 | Renderer Boundary And OpenGL Parity | Not started | OpenGL output matches golden readbacks |
| 6 | Platform Alignment | Not started | Every supported platform has named validation |
| 7 | Hardening, Coverage, And Breaking-Point Tests | Not started | Each component has edge/failure tests |
| 8 | Future Backend Readiness | Not started | Vulkan/Metal lab targets remain non-default |
## Target Component Architecture
The refactor should move toward one-way dependencies:
```text
pp_foundation
-> pp_assets
-> pp_paint
-> pp_document
-> pp_renderer_api
-> pp_renderer_gl
-> pp_paint_renderer
-> pp_ui_core
-> pp_panopainter_ui
-> pp_platform_*
-> panopainter_app
```
Intended responsibilities:
- `pp_foundation`: logging facade, math/util helpers, events, task queues,
binary streams.
- `pp_assets`: `Asset`, `Image`, `Settings`, serialization, ABR, PPBR, and PPI
helpers.
- `pp_paint`: pure `Brush`, `Stroke`, stroke sampling, and CPU reference blend
math.
- `pp_document`: canvas document model, layers, animation frames, and undo/redo
model.
- `pp_renderer_api`: renderer-neutral interfaces for textures, render targets,
shaders, meshes, readback, frame capture, and tracing.
- `pp_renderer_gl`: current OpenGL implementation behind renderer interfaces.
- `pp_paint_renderer`: stroke rasterization, layer compositing, cube/equirect
export using `pp_renderer_api`.
- `pp_ui_core`: `Node`, layout, generic controls, text/image primitives.
- `pp_panopainter_ui`: panels, dialogs, `NodeCanvas`, and app-specific
workflows.
- `pp_platform_*`: Windows, macOS/iOS, Android, Linux, and WebGL shells.
- `panopainter_app`: composition root only.
Rules:
- Component headers must not include platform SDK or graphics API headers unless
the component name includes that backend or platform.
- Pure libraries must build and test without a window, GL context, network,
tablet, VR headset, or filesystem outside test temp directories.
- Public APIs should return explicit status/result objects. PanoPainter app
code keeps exceptions disabled unless isolated SDK wrappers require them.
- Singleton access should be replaced at component boundaries with context or
service objects. Temporary facade shims require debt entries.
## Phase 0: Inventory, Safety Rails, And Memory
Status: complete on 2026-05-31. Created this roadmap,
`docs/modernization/debt.md`, `docs/modernization/capability-map.md`,
`docs/modernization/build-inventory.md`, and ADR 0001.
Goal: create durable project memory and prevent silent shortcuts before large
refactors begin.
Implementation tasks:
- Add `docs/modernization/roadmap.md`, `docs/modernization/debt.md`, and
`docs/adr/`.
- Add a shortcut rule: every temporary adapter, fallback, skipped platform, or
retained vendored dependency must have owner, reason, validation command, and
removal condition.
- Generate a current capability map covering:
- project open/save and PPI compatibility
- image import/export and thumbnails
- brush presets, ABR import, PPBR export/import
- layers, blend modes, alpha lock, selection mask
- animation frames and MP4/timelapse recording
- VR, tablet, touch, mouse, keyboard, gestures
- cloud upload/download/browse
- UI dialogs, panels, layout XML, settings
- Windows/AppX, macOS, iOS, Android standard, Quest, Focus/Wave, Linux, WebGL
- Record current build commands and known platform prerequisites.
Gate:
- No behavior changes.
- Existing Visual Studio, platform CMake, Gradle, Apple, Linux, and WebGL paths
are not removed.
## Phase 1: Unified CMake Skeleton
Goal: make CMake the canonical source list without breaking existing projects.
Status: in progress. Root `CMakeLists.txt`, `CMakePresets.json`, and project
option targets exist. The Windows desktop app builds through CMake as
`PanoPainter`; the raw Visual Studio solution/project files were removed on
2026-05-31 by user decision. Non-Windows platform build files remain during
Phase 6 alignment.
Implementation tasks:
- Add root `CMakeLists.txt` and shared CMake modules under `cmake/`.
- Add `CMakePresets.json` with at least:
- `windows-vs2026-x64`
- `windows-clangcl-asan`
- `linux-clang`
- `android-arm64`
- `android-x64`
- `emscripten`
- `macos`
- `ios-device`
- `ios-simulator`
- Keep Android CMake, Linux CMake, WebGL CMake, Apple project files, and AppX
packaging during the transition until each consumes shared component targets.
- Move version generation into a CMake custom command using
`scripts/pre-build.py`.
- Fix `scripts/pre-build.py` only if required to avoid unnecessary rewrites or
missing-tag failures.
- Add CMake options:
- `PP_BUILD_APP`
- `PP_BUILD_TESTS`
- `PP_BUILD_TOOLS`
- `PP_ENABLE_OPENGL`
- `PP_ENABLE_VULKAN_EXPERIMENTAL=OFF`
- `PP_ENABLE_VR`
- `PP_ENABLE_CLOUD`
- `PP_ENABLE_VIDEO`
- Define source-list helper targets so per-platform source duplication can be
reduced incrementally.
Gate:
- Windows desktop app builds through CMake.
- New CMake can configure on Windows.
- Source list differences are understood and documented.
- Non-Windows platform migration is debt-tracked until Phase 6.
## Phase 2: Toolchain, Diagnostics, And Dependencies
Goal: turn the build into an error-finding system before deep refactors.
Status: in progress. Initial warning/sanitizer option targets and `vcpkg.json`
exist. Dependency migration is not complete until component targets consume
vcpkg packages and platform triplets are validated.
Implementation tasks:
- Set C++23 through target features, not raw compiler flags.
- Add warning profiles:
- MSVC: `/W4 /permissive- /Zc:__cplusplus /Zc:preprocessor`.
- Optional MSVC analysis preset: `/analyze`.
- Clang/GCC: `-Wall -Wextra -Wpedantic -Wconversion -Wshadow
-Wnull-dereference`.
- Keep exceptions disabled for PanoPainter targets, except isolated SDK wrapper
targets when unavoidable.
- Add sanitizer presets:
- Clang/GCC ASan and UBSan for headless libraries.
- MSVC ASan where supported.
- TSan only for pure/headless targets.
- Add tooling hooks:
- `clang-tidy`
- `cppcheck`
- shader validation or compile checks
- CTest dashboard output
- Add `vcpkg.json`.
- Move reliable dependencies to vcpkg first:
- `fmt`
- `glm`
- `tinyxml2`
- `stb`
- `curl`
- `sqlite3`
- `glad`
- `Catch2`
- Keep vendored until proven:
- OpenVR
- OVR/Wave SDKs
- Wacom WinTab
- AppCenter
- openh264
- mp4v2
- libyuv
- patched or SDK-specific libraries
Gate:
- Desktop library targets compile with strict diagnostics.
- New warnings caused by refactor are fixed or locally justified.
- No global blanket warning suppression for project code.
## Phase 3: Test Harness And Agent-Ready Automation
Goal: make each component reachable by automated tools and future agents.
Status: in progress. `tests/` exists, `desktop-fast` runs headlessly, and
PowerShell/bash wrappers exist for configure/build/test/analyze. `pano_cli`
exists with a first JSON automation command for validating create-document
inputs; full document/app integration is debt-tracked as DEBT-0006.
Implementation tasks:
- Add `tests/` with one executable per component.
- Register CTest labels:
- `foundation`
- `assets`
- `paint`
- `document`
- `renderer`
- `ui`
- `platform`
- `integration`
- `fuzz`
- `slow`
- `gpu`
- Add `tools/pano_cli` for headless automation.
- `pano_cli` should support:
- create document
- load project
- save project
- apply scripted strokes
- import/export images
- inspect layers
- run layout parse
- emit JSON results
- Add local automation wrappers under `scripts/automation/`:
- configure
- build
- test
- analyze
- package smoke
- All wrappers must return machine-readable logs or summaries.
- Establish `tests/data/` fixtures:
- tiny PPI files
- corrupt/truncated PPI cases
- PNG/JPEG fixtures
- ABR/PPBR samples
- layout XML
- shader snippets
- brush stroke scripts
Gate:
- `ctest --preset desktop-fast --build-config Debug` runs without a GL
context.
- Non-render components can be tested on a headless machine.
## Phase 4: Component Split Without Behavior Change
Goal: split libraries while keeping current app behavior.
Status: started. `pp_foundation` exists with binary stream utilities and
boundary/overread tests. Continue extracting legacy-safe utilities before
moving assets, paint, or document behavior.
Implementation tasks:
- Extract components in this order:
1. `pp_foundation`
2. `pp_assets`
3. `pp_paint`
4. `pp_document`
5. `pp_renderer_api`
6. `pp_renderer_gl`
7. `pp_paint_renderer`
8. `pp_ui_core`
9. `pp_panopainter_ui`
10. `pp_platform_*`
11. `panopainter_app`
- Remove renderer/platform dependencies from pure headers first, especially:
- `Brush`
- document/layer model
- serializer
- UI core headers
- Keep facade shims where needed, but debt-track every shim.
- Avoid large behavioral rewrites during extraction.
- Each extracted component gets a focused test suite before moving to the next.
Gate:
- Old app still launches.
- Component tests pass after every extraction.
- No undocumented stubs or shortcuts.
## Phase 5: Renderer Boundary And OpenGL Parity
Goal: make OpenGL an implementation detail and establish parity tests before
adding new backends.
Implementation tasks:
- Introduce renderer interfaces:
- `IRenderDevice`
- `ITexture2D`
- `IRenderTarget`
- `IShaderProgram`
- `IMesh`
- `ICommandContext`
- `IReadbackBuffer`
- `IRenderTrace`
- Port current renderer classes behind OpenGL backend types:
- `RTT`
- `Texture2D`
- `Sampler`
- `ShaderManager`
- `Shape`
- Preserve current shader behavior and asset paths.
- Add deterministic GPU tests:
- clear
- blit
- texture upload/download
- stroke composite
- erase
- layer blend
- equirect export
- readback bounds
- Add CPU reference tests for blend modes.
- Compare GPU output to golden/reference data with explicit tolerances.
Gate:
- OpenGL readbacks match golden data on Windows and Linux.
- Mobile/WebGL compile gates remain green.
## Phase 6: Platform Alignment
Goal: every supported platform consumes the same component targets.
Implementation tasks:
- Convert these builds to shared component targets:
- Windows desktop
- Windows AppX
- macOS
- iOS
- Android standard
- Android Quest
- Android Focus/Wave
- Linux
- WebGL/Emscripten
- Keep platform entrypoints thin:
- window lifecycle
- input dispatch
- clipboard
- file picker/share
- GL context creation
- VR SDK bridge
- packaging only
- Add or refine CMake toolchain/preset support for:
- Android NDK ABIs
- iOS device
- iOS simulator
- macOS
- Emscripten
- Keep SDK-only imported libraries documented until vcpkg triplets are proven.
Gate:
- Every platform has a named configure/build command.
- Missing local prerequisites are documented.
- Each platform has at least compile or package validation.
## Phase 7: Hardening, Coverage, And Breaking-Point Tests
Goal: tests should try to break components, not only confirm current happy
paths.
Implementation tasks:
- Add property/fuzz tests for:
- binary streams
- serializers
- PPI parsing
- ABR parsing
- layout XML parsing
- image metadata parsing
- brush parameter extremes
- layer/frame operations
- undo/redo invariants
- Add stress tests for:
- thousands of stroke samples
- extreme resolutions guarded by memory limits
- rapid layer/frame edits
- corrupt assets
- cancellation during export
- concurrent render/UI task scheduling
- Add coverage for headless libraries on Clang/GCC.
- Require coverage reports for changed components first; do not set a global
threshold until the baseline is meaningful.
- Add tracing spans around:
- project load/save
- render passes
- stroke commit
- readback
- export
- UI layout
- platform I/O
- Logs must include component, thread, frame/stroke id, and timing.
Gate:
- No shortcut remains undocumented.
- Every component has unit tests and at least one failure or edge test.
## Phase 8: Future Backend Readiness
Goal: prepare Vulkan and Metal without destabilizing the OpenGL parity path.
Implementation tasks:
- Create non-default targets only after OpenGL backend parity:
- `pp_renderer_vulkan_lab`
- `pp_renderer_metal_lab`
- Use `D:\Dev\vkpaint` as reference material for Vulkan painting experiments,
not as direct production code.
- Before integration, prove:
- ping-pong compositing path
- input-attachment/subpass path where applicable
- feedback-loop or framebuffer-fetch-style path where supported
- synchronization and layout correctness under validation layers
- Keep WebGPU as an optional future portability backend, not the core renderer
contract.
Gate:
- Vulkan/Metal lab targets are opt-in.
- OpenGL production backend remains stable.
## Test Matrix
| Preset/Label | Purpose | Requires |
| --- | --- | --- |
| `desktop-fast` | Pure component unit tests | No GPU/window |
| `desktop-gpu` | OpenGL backend golden/readback tests | GPU/GL context |
| `fuzz` | Parser and serializer fuzzing | Fuzzer-capable compiler |
| `stress` | Large and adversarial scenarios | Longer runtime |
| `platform-build` | Configure/build each supported platform | Local toolchains |
| `package-smoke` | AppX/APK/Apple/WebGL package smoke | Platform SDKs |
Acceptance for each phase:
- Previous phase tests still pass.
- New component has its own tests.
- No undocumented stubs.
- No skipped platform without a debt entry.
- Automation command is recorded in this roadmap or linked docs.
## Verified Commands
Last verified on 2026-05-31:
```powershell
cmake --preset windows-msvc-default
cmake --build --preset windows-msvc-default --config Debug --target pp_foundation_tests pano_cli PanoPainter
ctest --preset desktop-fast --build-config Debug
powershell -ExecutionPolicy Bypass -File scripts\automation\test.ps1 -Preset desktop-fast -Configuration Debug
powershell -ExecutionPolicy Bypass -File scripts\automation\build.ps1 -Preset windows-msvc-default -Configuration Debug -Target pano_cli
```
Results:
- `pp_foundation_tests` passed.
- `pano_cli_create_document_smoke` passed.
- `PanoPainter.exe` built through CMake at
`out/build/windows-msvc-default/Debug/PanoPainter.exe`.
- PowerShell build/test automation wrappers return JSON summaries and passed
local smoke checks.
- Known remaining warnings: legacy project/vendor diagnostics, Visual Studio
vcpkg-manifest warning, `LNK4099` missing libyuv PDBs, and `LNK4098` runtime
library conflict from retained vendor binaries.
## Current Debt Log
The canonical debt log is now `docs/modernization/debt.md`. Keep this section
as a reminder only; do not add new debt entries here.
| ID | Status | Owner | Item | Reason | Validation | Removal Condition |
| --- | --- | --- | --- | --- | --- | --- |
| DEBT-0001 | Open | TBD | Existing platform build files remain alongside new CMake | Required for incremental migration | Existing platform builds plus new CMake configure | Remove after all platform builds consume shared CMake targets |
| DEBT-0002 | Open | TBD | Vendored SDK and patched libraries retained initially | Some dependencies are SDK-only or have platform-specific binaries | Dependency inventory and platform build smoke tests | Replace or document permanent vendored status after vcpkg triplet evaluation |
| DEBT-0003 | Open | TBD | Existing singletons remain during initial split | Avoid behavior changes while introducing boundaries | App launch and component tests | Replace singleton reaches with context/service injection at component boundaries |
## Current Capability Map Seed
Use this as the starting checklist for Phase 0 inventory.
- Project I/O: PPI open/save, thumbnails, version metadata, autosave/save-as
flows.
- Image I/O: JPEG/PNG import/export, cube faces, equirectangular export,
depth export.
- Brush system: ABR import, PPBR import/export, presets, tip/pattern/dual brush,
pressure, jitter, blend modes.
- Painting: six cube faces, temporary stroke buffers, erase, flood fill, masks,
alpha lock, layer compositing.
- Layers and animation: layer add/remove/move/merge, blend/opacity/visibility,
frame add/remove/duplicate/duration, MP4/timelapse export.
- UI: XML layout, Yoga layout, panels, dialogs, color tools, brush tools,
layers, animation timeline, settings, shortcuts, manual/changelog/about.
- Input: mouse, keyboard, touch, gestures, Wacom tablet, stylus pressure,
VR controllers.
- Platform services: clipboard, file picker, save picker, directory picker,
share/display file, keyboard show/hide.
- VR/platform variants: OpenVR desktop, Quest, Focus/Wave, Android standard,
iOS/macOS, Linux, WebGL.
- Cloud/network: upload, download, browse, license/check flows.
- Recording/export: PBO readbacks, MP4 encoder, timelapse frames.

View File

@@ -62,7 +62,7 @@ BOOL LoadWintab( void )
// ghWintab = LoadLibraryA( "C:\\dev\\mainline\\Wacom\\Win\\Win32\\Debug\\Wacom_Tablet.dll" );
// ghWintab = LoadLibraryA( "C:\\dev\\mainline\\Wacom\\Win\\Win32\\Debug\\Wintab32.dll" );
LOG("calling LoadLibrary");
ghWintab = LoadLibrary(L"Wintab32.dll");
ghWintab = LoadLibraryW(L"Wintab32.dll");
LOG("LoadLibrary called");
if ( !ghWintab )

View File

@@ -0,0 +1,30 @@
[CmdletBinding()]
param(
[string]$Preset = "windows-msvc-default",
[switch]$NoApp
)
$ErrorActionPreference = "Stop"
$started = Get-Date
$argsList = @(
"--preset", $Preset,
"-DPP_ENABLE_MSVC_ANALYZE=ON",
"-DPP_ENABLE_CLANG_TIDY=ON",
"-DPP_ENABLE_CPPCHECK=ON"
)
if ($NoApp) {
$argsList += "-DPP_BUILD_APP=OFF"
}
& cmake @argsList
$exitCode = $LASTEXITCODE
$elapsed = [int]((Get-Date) - $started).TotalMilliseconds
[ordered]@{
command = "analyze-configure"
preset = $Preset
exitCode = $exitCode
elapsedMs = $elapsed
} | ConvertTo-Json -Compress
exit $exitCode

View File

@@ -0,0 +1,11 @@
#!/usr/bin/env sh
set -u
preset="${1:-linux-clang}"
start="$(date +%s)"
cmake --preset "$preset" -DPP_ENABLE_CLANG_TIDY=ON -DPP_ENABLE_CPPCHECK=ON
exit_code="$?"
end="$(date +%s)"
elapsed_ms="$(( (end - start) * 1000 ))"
printf '{"command":"analyze-configure","preset":"%s","exitCode":%s,"elapsedMs":%s}\n' "$preset" "$exit_code" "$elapsed_ms"
exit "$exit_code"

View File

@@ -0,0 +1,28 @@
[CmdletBinding()]
param(
[string]$Preset = "windows-msvc-default",
[string]$Configuration = "Debug",
[string]$Target = ""
)
$ErrorActionPreference = "Stop"
$started = Get-Date
$argsList = @("--build", "--preset", $Preset, "--config", $Configuration)
if ($Target.Length -gt 0) {
$argsList += @("--target", $Target)
}
& cmake @argsList
$exitCode = $LASTEXITCODE
$elapsed = [int]((Get-Date) - $started).TotalMilliseconds
[ordered]@{
command = "build"
preset = $Preset
configuration = $Configuration
target = $Target
exitCode = $exitCode
elapsedMs = $elapsed
} | ConvertTo-Json -Compress
exit $exitCode

View File

@@ -0,0 +1,17 @@
#!/usr/bin/env sh
set -u
preset="${1:-linux-clang}"
configuration="${2:-Debug}"
target="${3:-}"
start="$(date +%s)"
if [ -n "$target" ]; then
cmake --build --preset "$preset" --config "$configuration" --target "$target"
else
cmake --build --preset "$preset" --config "$configuration"
fi
exit_code="$?"
end="$(date +%s)"
elapsed_ms="$(( (end - start) * 1000 ))"
printf '{"command":"build","preset":"%s","configuration":"%s","target":"%s","exitCode":%s,"elapsedMs":%s}\n' "$preset" "$configuration" "$target" "$exit_code" "$elapsed_ms"
exit "$exit_code"

View File

@@ -0,0 +1,25 @@
[CmdletBinding()]
param(
[string]$Preset = "windows-msvc-default",
[switch]$NoApp
)
$ErrorActionPreference = "Stop"
$started = Get-Date
$argsList = @("--preset", $Preset)
if ($NoApp) {
$argsList += "-DPP_BUILD_APP=OFF"
}
& cmake @argsList
$exitCode = $LASTEXITCODE
$elapsed = [int]((Get-Date) - $started).TotalMilliseconds
[ordered]@{
command = "configure"
preset = $Preset
exitCode = $exitCode
elapsedMs = $elapsed
} | ConvertTo-Json -Compress
exit $exitCode

View File

@@ -0,0 +1,11 @@
#!/usr/bin/env sh
set -u
preset="${1:-linux-clang}"
start="$(date +%s)"
cmake --preset "$preset"
exit_code="$?"
end="$(date +%s)"
elapsed_ms="$(( (end - start) * 1000 ))"
printf '{"command":"configure","preset":"%s","exitCode":%s,"elapsedMs":%s}\n' "$preset" "$exit_code" "$elapsed_ms"
exit "$exit_code"

View File

@@ -0,0 +1,22 @@
[CmdletBinding()]
param(
[string]$Preset = "desktop-fast",
[string]$Configuration = "Debug"
)
$ErrorActionPreference = "Stop"
$started = Get-Date
& ctest --preset $Preset --build-config $Configuration
$exitCode = $LASTEXITCODE
$elapsed = [int]((Get-Date) - $started).TotalMilliseconds
[ordered]@{
command = "test"
preset = $Preset
configuration = $Configuration
exitCode = $exitCode
elapsedMs = $elapsed
} | ConvertTo-Json -Compress
exit $exitCode

View File

@@ -0,0 +1,12 @@
#!/usr/bin/env sh
set -u
preset="${1:-desktop-fast}"
configuration="${2:-Debug}"
start="$(date +%s)"
ctest --preset "$preset" --build-config "$configuration"
exit_code="$?"
end="$(date +%s)"
elapsed_ms="$(( (end - start) * 1000 ))"
printf '{"command":"test","preset":"%s","configuration":"%s","exitCode":%s,"elapsedMs":%s}\n' "$preset" "$configuration" "$exit_code" "$elapsed_ms"
exit "$exit_code"

View File

@@ -0,0 +1,142 @@
#include "foundation/binary_stream.h"
namespace pp::foundation {
ByteReader::ByteReader(std::span<const std::byte> bytes) noexcept
: bytes_(bytes)
{
}
std::size_t ByteReader::position() const noexcept
{
return position_;
}
std::size_t ByteReader::size() const noexcept
{
return bytes_.size();
}
std::size_t ByteReader::remaining() const noexcept
{
return bytes_.size() - position_;
}
bool ByteReader::empty() const noexcept
{
return remaining() == 0;
}
Status ByteReader::seek(std::size_t position) noexcept
{
if (position > bytes_.size()) {
return Status::out_of_range("seek position is outside the stream");
}
position_ = position;
return Status::success();
}
Result<std::uint8_t> ByteReader::read_u8() noexcept
{
const auto bytes = read_bytes(1);
if (!bytes) {
return Result<std::uint8_t>::failure(bytes.status());
}
return Result<std::uint8_t>::success(static_cast<std::uint8_t>(bytes.value()[0]));
}
Result<std::uint16_t> ByteReader::read_u16_le() noexcept
{
const auto bytes = read_bytes(2);
if (!bytes) {
return Result<std::uint16_t>::failure(bytes.status());
}
const auto b0 = static_cast<std::uint16_t>(bytes.value()[0]);
const auto b1 = static_cast<std::uint16_t>(bytes.value()[1]);
return Result<std::uint16_t>::success(static_cast<std::uint16_t>(b0 | (b1 << 8U)));
}
Result<std::uint32_t> ByteReader::read_u32_le() noexcept
{
const auto bytes = read_bytes(4);
if (!bytes) {
return Result<std::uint32_t>::failure(bytes.status());
}
const auto b0 = static_cast<std::uint32_t>(bytes.value()[0]);
const auto b1 = static_cast<std::uint32_t>(bytes.value()[1]);
const auto b2 = static_cast<std::uint32_t>(bytes.value()[2]);
const auto b3 = static_cast<std::uint32_t>(bytes.value()[3]);
return Result<std::uint32_t>::success(b0 | (b1 << 8U) | (b2 << 16U) | (b3 << 24U));
}
Result<std::span<const std::byte>> ByteReader::read_bytes(std::size_t count) noexcept
{
if (count > remaining()) {
return Result<std::span<const std::byte>>::failure(
Status::out_of_range("read would move beyond the end of the stream"));
}
const auto start = position_;
position_ += count;
return Result<std::span<const std::byte>>::success(bytes_.subspan(start, count));
}
ByteWriter::ByteWriter(std::vector<std::byte>& bytes) noexcept
: bytes_(&bytes)
{
}
std::size_t ByteWriter::size() const noexcept
{
return bytes_ == nullptr ? 0 : bytes_->size();
}
Status ByteWriter::write_u8(std::uint8_t value)
{
if (bytes_ == nullptr) {
return Status::invalid_argument("writer has no backing storage");
}
bytes_->push_back(static_cast<std::byte>(value));
return Status::success();
}
Status ByteWriter::write_u16_le(std::uint16_t value)
{
if (bytes_ == nullptr) {
return Status::invalid_argument("writer has no backing storage");
}
bytes_->push_back(static_cast<std::byte>(value & 0xffU));
bytes_->push_back(static_cast<std::byte>((value >> 8U) & 0xffU));
return Status::success();
}
Status ByteWriter::write_u32_le(std::uint32_t value)
{
if (bytes_ == nullptr) {
return Status::invalid_argument("writer has no backing storage");
}
bytes_->push_back(static_cast<std::byte>(value & 0xffU));
bytes_->push_back(static_cast<std::byte>((value >> 8U) & 0xffU));
bytes_->push_back(static_cast<std::byte>((value >> 16U) & 0xffU));
bytes_->push_back(static_cast<std::byte>((value >> 24U) & 0xffU));
return Status::success();
}
Status ByteWriter::write_bytes(std::span<const std::byte> bytes)
{
if (bytes_ == nullptr) {
return Status::invalid_argument("writer has no backing storage");
}
bytes_->insert(bytes_->end(), bytes.begin(), bytes.end());
return Status::success();
}
}

View File

@@ -0,0 +1,46 @@
#pragma once
#include "foundation/result.h"
#include <cstddef>
#include <cstdint>
#include <span>
#include <vector>
namespace pp::foundation {
class ByteReader {
public:
explicit ByteReader(std::span<const std::byte> bytes) noexcept;
[[nodiscard]] std::size_t position() const noexcept;
[[nodiscard]] std::size_t size() const noexcept;
[[nodiscard]] std::size_t remaining() const noexcept;
[[nodiscard]] bool empty() const noexcept;
[[nodiscard]] Status seek(std::size_t position) noexcept;
[[nodiscard]] Result<std::uint8_t> read_u8() noexcept;
[[nodiscard]] Result<std::uint16_t> read_u16_le() noexcept;
[[nodiscard]] Result<std::uint32_t> read_u32_le() noexcept;
[[nodiscard]] Result<std::span<const std::byte>> read_bytes(std::size_t count) noexcept;
private:
std::span<const std::byte> bytes_;
std::size_t position_ = 0;
};
class ByteWriter {
public:
explicit ByteWriter(std::vector<std::byte>& bytes) noexcept;
[[nodiscard]] std::size_t size() const noexcept;
[[nodiscard]] Status write_u8(std::uint8_t value);
[[nodiscard]] Status write_u16_le(std::uint16_t value);
[[nodiscard]] Status write_u32_le(std::uint32_t value);
[[nodiscard]] Status write_bytes(std::span<const std::byte> bytes);
private:
std::vector<std::byte>* bytes_ = nullptr;
};
}

80
src/foundation/result.h Normal file
View File

@@ -0,0 +1,80 @@
#pragma once
namespace pp::foundation {
enum class StatusCode {
ok,
invalid_argument,
out_of_range,
};
struct Status {
StatusCode code = StatusCode::ok;
const char* message = "ok";
[[nodiscard]] constexpr bool ok() const noexcept
{
return code == StatusCode::ok;
}
[[nodiscard]] static constexpr Status success() noexcept
{
return {};
}
[[nodiscard]] static constexpr Status invalid_argument(const char* message) noexcept
{
return { StatusCode::invalid_argument, message };
}
[[nodiscard]] static constexpr Status out_of_range(const char* message) noexcept
{
return { StatusCode::out_of_range, message };
}
};
template <typename T>
class Result {
public:
[[nodiscard]] static constexpr Result success(T value) noexcept
{
return Result(value, Status::success());
}
[[nodiscard]] static constexpr Result failure(Status status) noexcept
{
return Result(T{}, status);
}
[[nodiscard]] constexpr bool ok() const noexcept
{
return status_.ok();
}
[[nodiscard]] constexpr explicit operator bool() const noexcept
{
return ok();
}
[[nodiscard]] constexpr const T& value() const noexcept
{
return value_;
}
[[nodiscard]] constexpr Status status() const noexcept
{
return status_;
}
private:
constexpr Result(T value, Status status) noexcept
: value_(value)
, status_(status)
{
}
T value_{};
Status status_{};
};
}

View File

@@ -19,7 +19,10 @@
#include "abr.h"
#include "settings.h"
#if __has_include(<renderdoc_app.h>)
#include <renderdoc_app.h>
#define USE_RENDERDOC
#endif
#include <iomanip>
#include <ctime>
@@ -33,7 +36,7 @@ HINSTANCE hInst;
HWND hWnd;
HDC hDC;
HGLRC hRC;
wchar_t* className;
const wchar_t* className;
bool keys[256];
std::mutex gl_mutex;
std::mutex async_mutex;
@@ -54,6 +57,7 @@ float timer_ink_touch = 0;
float timer_ink_pen = 0;
bool sandboxed = false;
#ifdef USE_RENDERDOC
RENDERDOC_API_1_4_0* rdoc_api = NULL;
bool win32_renderdoc_init()
{
@@ -78,6 +82,10 @@ void win32_renderdoc_frame_end()
if (rdoc_api)
rdoc_api->EndFrameCapture(NULL, NULL);
}
#else
void win32_renderdoc_frame_start() { }
void win32_renderdoc_frame_end() { }
#endif
HRESULT(*GetDpiForMonitor_fn)(HMONITOR hmonitor, MONITOR_DPI_TYPE dpiType, UINT* dpiX, UINT* dpiY);
HRESULT(*SetProcessDpiAwareness_fn)(PROCESS_DPI_AWARENESS value);
@@ -367,7 +375,7 @@ int read_WMI_info()
}
IWbemServices* pService = NULL;
if (FAILED(hRes = pLocator->ConnectServer(L"root\\CIMV2", NULL, NULL, NULL, WBEM_FLAG_CONNECT_USE_MAX_WAIT, NULL, NULL, &pService)))
if (FAILED(hRes = pLocator->ConnectServer(BSTR(L"root\\CIMV2"), NULL, NULL, NULL, WBEM_FLAG_CONNECT_USE_MAX_WAIT, NULL, NULL, &pService)))
{
pLocator->Release();
LOG("Unable to connect to \"CIMV2\": %x", hRes);
@@ -411,7 +419,7 @@ int read_WMI_info()
// GET DEVICE INFO
{
IEnumWbemClassObject* pEnumerator = NULL;
if (FAILED(hRes = pService->ExecQuery(L"WQL", L"SELECT * FROM Win32_ComputerSystem", WBEM_FLAG_FORWARD_ONLY, NULL, &pEnumerator)))
if (FAILED(hRes = pService->ExecQuery(BSTR(L"WQL"), BSTR(L"SELECT * FROM Win32_ComputerSystem"), WBEM_FLAG_FORWARD_ONLY, NULL, &pEnumerator)))
{
pLocator->Release();
pService->Release();
@@ -438,7 +446,7 @@ int read_WMI_info()
// GET OS INFO
{
IEnumWbemClassObject* pEnumerator = NULL;
if (FAILED(hRes = pService->ExecQuery(L"WQL", L"SELECT * FROM Win32_OperatingSystem", WBEM_FLAG_FORWARD_ONLY, NULL, &pEnumerator)))
if (FAILED(hRes = pService->ExecQuery(BSTR(L"WQL"), BSTR(L"SELECT * FROM Win32_OperatingSystem"), WBEM_FLAG_FORWARD_ONLY, NULL, &pEnumerator)))
{
pLocator->Release();
pService->Release();
@@ -468,7 +476,7 @@ int read_WMI_info()
pService->Release();
pService = NULL;
if (FAILED(hRes = pLocator->ConnectServer(L"root\\Microsoft\\Windows\\DeviceGuard", NULL, NULL, NULL, WBEM_FLAG_CONNECT_USE_MAX_WAIT, NULL, NULL, &pService)))
if (FAILED(hRes = pLocator->ConnectServer(BSTR(L"root\\Microsoft\\Windows\\DeviceGuard"), NULL, NULL, NULL, WBEM_FLAG_CONNECT_USE_MAX_WAIT, NULL, NULL, &pService)))
{
pLocator->Release();
LOG("Unable to connect to \"DeviceGuard\": %x", hRes);
@@ -478,7 +486,7 @@ int read_WMI_info()
// GET DEVICE GUARD
{
IEnumWbemClassObject* pEnumerator = NULL;
if (FAILED(hRes = pService->ExecQuery(L"WQL", L"SELECT * FROM Win32_DeviceGuard", WBEM_FLAG_FORWARD_ONLY, NULL, &pEnumerator)))
if (FAILED(hRes = pService->ExecQuery(BSTR(L"WQL"), BSTR(L"SELECT * FROM Win32_DeviceGuard"), WBEM_FLAG_FORWARD_ONLY, NULL, &pEnumerator)))
{
pLocator->Release();
pService->Release();
@@ -954,8 +962,10 @@ int main(int argc, char** argv)
LOG("GL vendor: %s", glGetString(GL_VENDOR));
LOG("GL renderer: %s", glGetString(GL_RENDERER));
#ifdef USE_RENDERDOC
if (!win32_renderdoc_init())
LOG("Renderdoc not started");
#endif // USE_RENDERDOC
swprintf_s(window_title, L"PanoPainter %s (%s)", g_version_number_w,
str2wstr((char*)glGetString(GL_RENDERER)).c_str());

View File

@@ -64,8 +64,12 @@
#elif _WIN32
#define _USE_MATH_DEFINES
#ifndef _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#endif
#ifndef _SCL_SECURE_NO_WARNINGS
#define _SCL_SECURE_NO_WARNINGS
#endif
#include <windows.h>
#include <windowsx.h>
#include <tchar.h>
@@ -138,6 +142,7 @@
#include <regex>
#include <mutex>
#include <queue>
#include <chrono>
#include <memory>
#include <string>
#include <vector>
@@ -181,4 +186,4 @@
#ifndef EMSCRIPTEN
#include <curl/curl.h>
#endif
#endif

View File

@@ -11,7 +11,9 @@ const int g_version_build = PP_VERSION_BUILD;
#ifdef _WIN32
#include <windows.h>
const wchar_t* g_version_w = TEXT(PP_VERSION_STRING);
const wchar_t* g_version_number_w = TEXT(PP_VERSION_NUMBER_STRING);
const wchar_t* g_window_title_w = L"PanoPainter " TEXT(PP_VERSION_NUMBER_STRING);
#define PP_WIDEN2(x) L##x
#define PP_WIDEN(x) PP_WIDEN2(x)
const wchar_t* g_version_w = PP_WIDEN(PP_VERSION_STRING);
const wchar_t* g_version_number_w = PP_WIDEN(PP_VERSION_NUMBER_STRING);
const wchar_t* g_window_title_w = L"PanoPainter " PP_WIDEN(PP_VERSION_NUMBER_STRING);
#endif

23
tests/CMakeLists.txt Normal file
View File

@@ -0,0 +1,23 @@
add_library(pp_test_harness INTERFACE)
target_include_directories(pp_test_harness INTERFACE
"${CMAKE_CURRENT_SOURCE_DIR}")
target_link_libraries(pp_test_harness INTERFACE
pp_project_options
pp_project_warnings)
add_executable(pp_foundation_tests
foundation/binary_stream_tests.cpp)
target_link_libraries(pp_foundation_tests PRIVATE
pp_foundation
pp_test_harness)
add_test(NAME pp_foundation_tests COMMAND pp_foundation_tests)
set_tests_properties(pp_foundation_tests PROPERTIES
LABELS "foundation;desktop-fast")
if(TARGET pano_cli)
add_test(NAME pano_cli_create_document_smoke
COMMAND pano_cli create-document --width 64 --height 32 --layers 2)
set_tests_properties(pano_cli_create_document_smoke PROPERTIES
LABELS "integration;desktop-fast")
endif()

View File

@@ -0,0 +1,100 @@
#include "foundation/binary_stream.h"
#include "test_harness.h"
#include <array>
#include <cstddef>
#include <cstdint>
#include <vector>
using pp::foundation::ByteReader;
using pp::foundation::ByteWriter;
namespace {
void round_trips_little_endian_values(pp::tests::Harness& h)
{
std::vector<std::byte> bytes;
ByteWriter writer(bytes);
PP_EXPECT(h, writer.write_u8(0x12U).ok());
PP_EXPECT(h, writer.write_u16_le(0x3456U).ok());
PP_EXPECT(h, writer.write_u32_le(0x789abcdeU).ok());
PP_EXPECT(h, writer.size() == 7U);
ByteReader reader(bytes);
const auto u8 = reader.read_u8();
const auto u16 = reader.read_u16_le();
const auto u32 = reader.read_u32_le();
PP_EXPECT(h, u8.ok());
PP_EXPECT(h, u8.value() == 0x12U);
PP_EXPECT(h, u16.ok());
PP_EXPECT(h, u16.value() == 0x3456U);
PP_EXPECT(h, u32.ok());
PP_EXPECT(h, u32.value() == 0x789abcdeU);
PP_EXPECT(h, reader.empty());
}
void rejects_overread_without_moving_cursor(pp::tests::Harness& h)
{
const std::array bytes {
std::byte { 0x01 },
std::byte { 0x02 },
std::byte { 0x03 },
};
ByteReader reader(bytes);
PP_EXPECT(h, reader.seek(2).ok());
const auto before = reader.position();
const auto value = reader.read_u32_le();
PP_EXPECT(h, !value.ok());
PP_EXPECT(h, reader.position() == before);
PP_EXPECT(h, reader.remaining() == 1U);
}
void rejects_out_of_range_seek(pp::tests::Harness& h)
{
const std::array bytes {
std::byte { 0x01 },
std::byte { 0x02 },
};
ByteReader reader(bytes);
PP_EXPECT(h, !reader.seek(3).ok());
PP_EXPECT(h, reader.position() == 0U);
PP_EXPECT(h, reader.seek(2).ok());
PP_EXPECT(h, reader.empty());
}
void boundary_reads_are_consistent(pp::tests::Harness& h)
{
std::array<std::byte, 16> bytes {};
for (std::size_t i = 0; i < bytes.size(); ++i) {
bytes[i] = static_cast<std::byte>(i);
}
for (std::size_t length = 0; length <= bytes.size(); ++length) {
ByteReader reader(std::span<const std::byte>(bytes.data(), length));
const auto exact = reader.read_bytes(length);
PP_EXPECT(h, exact.ok());
PP_EXPECT(h, exact.value().size() == length);
PP_EXPECT(h, reader.empty());
const auto too_much = reader.read_u8();
PP_EXPECT(h, !too_much.ok());
PP_EXPECT(h, reader.position() == length);
}
}
}
int main()
{
pp::tests::Harness harness;
harness.run("round_trips_little_endian_values", round_trips_little_endian_values);
harness.run("rejects_overread_without_moving_cursor", rejects_overread_without_moving_cursor);
harness.run("rejects_out_of_range_seek", rejects_out_of_range_seek);
harness.run("boundary_reads_are_consistent", boundary_reads_are_consistent);
return harness.finish();
}

50
tests/test_harness.h Normal file
View File

@@ -0,0 +1,50 @@
#pragma once
#include <cstdlib>
#include <iostream>
#include <string_view>
namespace pp::tests {
class Harness {
public:
void expect(bool condition, std::string_view expression, std::string_view file, int line)
{
++assertions_;
if (!condition) {
++failures_;
std::cerr << file << ":" << line << ": expectation failed: " << expression << "\n";
}
}
template <typename Callback>
void run(std::string_view name, Callback callback)
{
const auto failures_before = failures_;
callback(*this);
++tests_;
if (failures_ == failures_before) {
std::cout << "[pass] " << name << "\n";
} else {
std::cout << "[fail] " << name << "\n";
}
}
[[nodiscard]] int finish() const
{
std::cout << "{\"tests\":" << tests_
<< ",\"assertions\":" << assertions_
<< ",\"failures\":" << failures_ << "}\n";
return failures_ == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}
private:
int tests_ = 0;
int assertions_ = 0;
int failures_ = 0;
};
}
#define PP_EXPECT(harness, expression) \
(harness).expect(static_cast<bool>(expression), #expression, __FILE__, __LINE__)

View File

@@ -0,0 +1,6 @@
add_executable(pano_cli
main.cpp)
target_link_libraries(pano_cli PRIVATE
pp_project_options
pp_project_warnings
pp_foundation)

113
tools/pano_cli/main.cpp Normal file
View File

@@ -0,0 +1,113 @@
#include "foundation/result.h"
#include <charconv>
#include <cstdint>
#include <iostream>
#include <string_view>
namespace {
struct DocumentArgs {
std::uint32_t width = 0;
std::uint32_t height = 0;
std::uint32_t layers = 1;
};
bool parse_u32(std::string_view text, std::uint32_t& value)
{
const auto* begin = text.data();
const auto* end = text.data() + text.size();
const auto [ptr, ec] = std::from_chars(begin, end, value);
return ec == std::errc {} && ptr == end;
}
void print_error(std::string_view command, std::string_view message)
{
std::cout << "{\"ok\":false,\"command\":\"" << command
<< "\",\"error\":\"" << message << "\"}\n";
}
void print_help()
{
std::cout
<< "pano_cli commands:\n"
<< " create-document --width N --height N [--layers N]\n"
<< " --help\n";
}
pp::foundation::Status parse_document_args(int argc, char** argv, DocumentArgs& args)
{
for (int i = 2; i < argc; ++i) {
const std::string_view key(argv[i]);
if (key == "--width" || key == "--height" || key == "--layers") {
if (i + 1 >= argc) {
return pp::foundation::Status::invalid_argument("missing value for option");
}
std::uint32_t value = 0;
if (!parse_u32(argv[++i], value)) {
return pp::foundation::Status::invalid_argument("option value must be an unsigned integer");
}
if (key == "--width") {
args.width = value;
} else if (key == "--height") {
args.height = value;
} else {
args.layers = value;
}
} else {
return pp::foundation::Status::invalid_argument("unknown option");
}
}
if (args.width == 0 || args.height == 0) {
return pp::foundation::Status::invalid_argument("width and height must be greater than zero");
}
if (args.layers == 0) {
return pp::foundation::Status::invalid_argument("layer count must be greater than zero");
}
return pp::foundation::Status::success();
}
int create_document(int argc, char** argv)
{
DocumentArgs args;
const auto status = parse_document_args(argc, argv, args);
if (!status.ok()) {
print_error("create-document", status.message);
return 2;
}
std::cout << "{\"ok\":true,\"command\":\"create-document\",\"document\":{"
<< "\"width\":" << args.width
<< ",\"height\":" << args.height
<< ",\"layers\":" << args.layers
<< "}}\n";
return 0;
}
}
int main(int argc, char** argv)
{
if (argc < 2) {
print_help();
return 1;
}
const std::string_view command(argv[1]);
if (command == "--help" || command == "-h") {
print_help();
return 0;
}
if (command == "create-document") {
return create_document(argc, argv);
}
print_error(command, "unknown command");
return 2;
}

16
vcpkg.json Normal file
View File

@@ -0,0 +1,16 @@
{
"name": "panopainter",
"version-string": "0.0.0-modernization",
"description": "PanoPainter modernization dependency manifest.",
"dependencies": [
"catch2",
"curl",
"fmt",
"glad",
"glm",
"sqlite3",
"stb",
"tinyxml2"
]
}